1 /* Test that routines allow reusing a source variable as destination.
2 
3 Copyright 1996, 2000-2002, 2012 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library test suite.
6 
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11 
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "gmp-impl.h"
25 #include "tests.h"
26 
27 #if __GMP_LIBGMP_DLL
28 
29 /* FIXME: When linking to a DLL libgmp, mpf_add etc can't be used as
30    initializers for global variables because they're effectively global
31    variables (function pointers) themselves.  Perhaps calling a test
32    function successively with mpf_add etc would be better.  */
33 
34 int
main(void)35 main (void)
36 {
37   printf ("Test suppressed for windows DLL\n");
38   exit (0);
39 }
40 
41 
42 #else /* ! DLL_EXPORT */
43 
44 #ifndef SIZE
45 #define SIZE 16
46 #endif
47 
48 #ifndef EXPO
49 #define EXPO 32
50 #endif
51 
52 void dump_abort (const char *, mpf_t, mpf_t);
53 
54 typedef void (*dss_func) (mpf_ptr, mpf_srcptr, mpf_srcptr);
55 
56 dss_func dss_funcs[] =
57 {
58   mpf_div, mpf_add, mpf_mul, mpf_sub,
59 };
60 
61 const char *dss_func_names[] =
62 {
63   "mpf_div", "mpf_add", "mpf_mul", "mpf_sub",
64 };
65 
66 typedef void (*dsi_func) (mpf_ptr, mpf_srcptr, unsigned long int);
67 
68 dsi_func dsi_funcs[] =
69 {
70   mpf_div_ui, mpf_add_ui, mpf_mul_ui, mpf_sub_ui,
71   mpf_mul_2exp, mpf_div_2exp, mpf_pow_ui
72 };
73 
74 const char *dsi_func_names[] =
75 {
76   "mpf_div_ui", "mpf_add_ui", "mpf_mul_ui", "mpf_sub_ui",
77   "mpf_mul_2exp", "mpf_div_2exp", "mpf_pow_ui"
78 };
79 
80 typedef void (*dis_func) (mpf_ptr, unsigned long int, mpf_srcptr);
81 
82 dis_func dis_funcs[] =
83 {
84   mpf_ui_div, mpf_ui_sub,
85 };
86 
87 const char *dis_func_names[] =
88 {
89   "mpf_ui_div", "mpf_ui_sub",
90 };
91 
92 int
main(int argc,char ** argv)93 main (int argc, char **argv)
94 {
95   int i;
96   int pass, reps = 10000;
97   mpf_t in1, in2, out1;
98   unsigned long int in1i, in2i;
99   mpf_t res1, res2, res3;
100   mp_size_t bprec = 100;
101 
102   tests_start ();
103 
104   if (argc > 1)
105     {
106       reps = strtol (argv[1], 0, 0);
107       if (argc > 2)
108           bprec = strtol (argv[2], 0, 0);
109     }
110 
111   mpf_set_default_prec (bprec);
112 
113   mpf_init (in1);
114   mpf_init (in2);
115   mpf_init (out1);
116   mpf_init (res1);
117   mpf_init (res2);
118   mpf_init (res3);
119 
120   for (pass = 1; pass <= reps; pass++)
121     {
122       mpf_random2 (in1, urandom () % SIZE - SIZE/2, urandom () % EXPO);
123       mpf_random2 (in2, urandom () % SIZE - SIZE/2, urandom () % EXPO);
124 
125       for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++)
126           {
127             /* Don't divide by 0.  */
128             if (i == 0 && mpf_cmp_ui (in2, 0) == 0)
129               continue;
130 
131             (dss_funcs[i]) (res1, in1, in2);
132 
133             mpf_set (out1, in1);
134             (dss_funcs[i]) (out1, out1, in2);
135             mpf_set (res2, out1);
136 
137             mpf_set (out1, in2);
138             (dss_funcs[i]) (out1, in1, out1);
139             mpf_set (res3, out1);
140 
141             if (mpf_cmp (res1, res2) != 0)
142               dump_abort (dss_func_names[i], res1, res2);
143             if (mpf_cmp (res1, res3) != 0)
144               dump_abort (dss_func_names[i], res1, res3);
145           }
146 
147       in2i = urandom ();
148       for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++)
149           {
150             unsigned long this_in2i = in2i;
151 
152             /* Don't divide by 0.  */
153             if (dsi_funcs[i] == mpf_div_ui && this_in2i == 0)
154               continue;
155 
156             /* Avoid overflow/underflow in the exponent.  */
157             if (dsi_funcs[i] == mpf_mul_2exp || dsi_funcs[i] == mpf_div_2exp)
158               this_in2i %= 0x100000;
159             else if (dsi_funcs[i] == mpf_pow_ui)
160               this_in2i %= 0x1000;
161 
162             (dsi_funcs[i]) (res1, in1, this_in2i);
163 
164             mpf_set (out1, in1);
165             (dsi_funcs[i]) (out1, out1, this_in2i);
166             mpf_set (res2, out1);
167 
168             if (mpf_cmp (res1, res2) != 0)
169               dump_abort (dsi_func_names[i], res1, res2);
170           }
171 
172       in1i = urandom ();
173       for (i = 0; i < sizeof (dis_funcs) / sizeof (dis_func); i++)
174           {
175             /* Don't divide by 0.  */
176             if (dis_funcs[i] == mpf_ui_div
177                 && mpf_cmp_ui (in2, 0) == 0)
178               continue;
179 
180             (dis_funcs[i]) (res1, in1i, in2);
181 
182             mpf_set (out1, in2);
183             (dis_funcs[i]) (out1, in1i, out1);
184             mpf_set (res2, out1);
185 
186             if (mpf_cmp (res1, res2) != 0)
187               dump_abort (dis_func_names[i], res1, res2);
188           }
189 
190     }
191 
192   mpf_clear (in1);
193   mpf_clear (in2);
194   mpf_clear (out1);
195   mpf_clear (res1);
196   mpf_clear (res2);
197   mpf_clear (res3);
198 
199   tests_end ();
200   exit (0);
201 }
202 
203 void
dump_abort(const char * name,mpf_t res1,mpf_t res2)204 dump_abort (const char *name, mpf_t res1, mpf_t res2)
205 {
206   printf ("failure in %s:\n", name);
207   mpf_dump (res1);
208   mpf_dump (res2);
209   abort ();
210 }
211 
212 #if 0
213 void mpf_abs                  (mpf_ptr, mpf_srcptr);
214 void mpf_sqrt                 (mpf_ptr, mpf_srcptr);
215 void mpf_neg                  (mpf_ptr, mpf_srcptr);
216 #endif
217 
218 #endif /* ! DLL_EXPORT */
219