xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/t-cmp_d.c (revision c34236556bea94afcaca1782d7d228301edc3ea0)
1 /* Test mpz_cmp_d and mpz_cmpabs_d.
2 
3 Copyright 2001, 2002, 2003, 2005, 2013 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 http://www.gnu.org/licenses/.  */
19 
20 #include <math.h>
21 
22 #include "testutils.h"
23 
24 /* FIXME: Not sure if the tests here are exhaustive.  Ought to try to get
25    each possible exit from mpz_cmp_d (and mpz_cmpabs_d) exercised.  */
26 
27 
28 #define SGN(n)  ((n) > 0 ? 1 : (n) < 0 ? -1 : 0)
29 
30 
31 void
32 check_one (const char *name, mpz_srcptr x, double y, int cmp, int cmpabs)
33 {
34   int   got;
35 
36   got = mpz_cmp_d (x, y);
37   if (SGN(got) != cmp)
38     {
39       int i;
40       printf    ("mpz_cmp_d wrong (from %s)\n", name);
41       printf    ("  got  %d\n", got);
42       printf    ("  want %d\n", cmp);
43     fail:
44       printf ("  x=");
45       mpz_out_str (stdout, 10, x);
46       printf    ("\n  y %g\n", y);
47       printf ("  x=0x");
48       mpz_out_str (stdout, -16, x);
49       printf    ("\n  y %g\n", y);
50       printf    ("  y");
51       for (i = 0; i < sizeof(y); i++)
52         printf (" %02X", (unsigned) ((unsigned char *) &y)[i]);
53       printf ("\n");
54       abort ();
55     }
56 
57   got = mpz_cmpabs_d (x, y);
58   if (SGN(got) != cmpabs)
59     {
60       printf    ("mpz_cmpabs_d wrong\n");
61       printf    ("  got  %d\n", got);
62       printf    ("  want %d\n", cmpabs);
63       goto fail;
64     }
65 }
66 
67 static void
68 mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
69 {
70   if (mpz_set_str (z, str, base) != 0)
71     {
72       fprintf (stderr, "ERROR: mpz_set_str failed\n");
73       fprintf (stderr, "   str  = \"%s\"\n", str);
74       fprintf (stderr, "   base = %d\n", base);
75       abort();
76     }
77 }
78 
79 void
80 check_data (void)
81 {
82   static const struct {
83     const char  *x;
84     double      y;
85     int         cmp, cmpabs;
86 
87   } data[] = {
88 
89     {  "0",  0.0,  0,  0 },
90 
91     {  "1",  0.0,  1,  1 },
92     { "-1",  0.0, -1,  1 },
93 
94     {  "1",  0.5,  1,  1 },
95     { "-1", -0.5, -1,  1 },
96 
97     {  "0",  1.0, -1, -1 },
98     {  "0", -1.0,  1, -1 },
99 
100     {  "0x1000000000000000000000000000000000000000000000000", 1.0,  1, 1 },
101     { "-0x1000000000000000000000000000000000000000000000000", 1.0, -1, 1 },
102 
103     {  "0",  1e100, -1, -1 },
104     {  "0", -1e100,  1, -1 },
105 
106     {  "2",  1.5,   1,  1 },
107     {  "2", -1.5,   1,  1 },
108     { "-2",  1.5,  -1,  1 },
109     { "-2", -1.5,  -1,  1 },
110   };
111 
112   mpz_t  x;
113   int    i;
114 
115   mpz_init (x);
116 
117   for (i = 0; i < numberof (data); i++)
118     {
119       mpz_set_str_or_abort (x, data[i].x, 0);
120       check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs);
121     }
122 
123   mpz_clear (x);
124 }
125 
126 
127 /* Equality of integers with up to 53 bits */
128 void
129 check_onebits (void)
130 {
131   mpz_t   x, x2;
132   double  y;
133   int     i;
134 
135   mpz_init_set_ui (x, 0L);
136   mpz_init (x2);
137 
138   for (i = 0; i < 512; i++)
139     {
140       mpz_mul_2exp (x, x, 1);
141       mpz_add_ui (x, x, 1L);
142 
143       y = mpz_get_d (x);
144       mpz_set_d (x2, y);
145 
146       /* stop if any truncation is occurring */
147       if (mpz_cmp (x, x2) != 0)
148         break;
149 
150       check_one ("check_onebits", x, y, 0, 0);
151       check_one ("check_onebits", x, -y, 1, 0);
152       mpz_neg (x, x);
153       check_one ("check_onebits", x, y, -1, 0);
154       check_one ("check_onebits", x, -y, 0, 0);
155       mpz_neg (x, x);
156     }
157 
158   mpz_clear (x);
159   mpz_clear (x2);
160 }
161 
162 
163 /* With the mpz differing by 1, in a limb position possibly below the double */
164 void
165 check_low_z_one (void)
166 {
167   mpz_t          x;
168   double         y;
169   unsigned long  i;
170 
171   mpz_init (x);
172 
173   /* FIXME: It'd be better to base this on the float format. */
174 #if defined (__vax) || defined (__vax__)
175 #define LIM 127			/* vax fp numbers have limited range */
176 #else
177 #define LIM 512
178 #endif
179 
180   for (i = 1; i < LIM; i++)
181     {
182       mpz_set_ui (x, 1L);
183       mpz_mul_2exp (x, x, i);
184       y = mpz_get_d (x);
185 
186       check_one ("check_low_z_one", x, y,   0, 0);
187       check_one ("check_low_z_one", x, -y,  1, 0);
188       mpz_neg (x, x);
189       check_one ("check_low_z_one", x, y,  -1, 0);
190       check_one ("check_low_z_one", x, -y,  0, 0);
191       mpz_neg (x, x);
192 
193       mpz_sub_ui (x, x, 1);
194 
195       check_one ("check_low_z_one", x, y,  -1, -1);
196       check_one ("check_low_z_one", x, -y,  1, -1);
197       mpz_neg (x, x);
198       check_one ("check_low_z_one", x, y,  -1, -1);
199       check_one ("check_low_z_one", x, -y,  1, -1);
200       mpz_neg (x, x);
201 
202       mpz_add_ui (x, x, 2);
203 
204       check_one ("check_low_z_one", x, y,   1, 1);
205       check_one ("check_low_z_one", x, -y,  1, 1);
206       mpz_neg (x, x);
207       check_one ("check_low_z_one", x, y,  -1, 1);
208       check_one ("check_low_z_one", x, -y, -1, 1);
209       mpz_neg (x, x);
210     }
211 
212   mpz_clear (x);
213 }
214 
215 /* Comparing 1 and 1+2^-n.  "y" is volatile to make gcc store and fetch it,
216    which forces it to a 64-bit double, whereas on x86 it would otherwise
217    remain on the float stack as an 80-bit long double.  */
218 void
219 check_one_2exp (void)
220 {
221   double           e;
222   mpz_t            x;
223   volatile double  y;
224   int              i;
225 
226   mpz_init (x);
227 
228   e = 1.0;
229   for (i = 0; i < 128; i++)
230     {
231       e /= 2.0;
232       y = 1.0 + e;
233       if (y == 1.0)
234         break;
235 
236       mpz_set_ui (x, 1L);
237       check_one ("check_one_2exp", x,  y, -1, -1);
238       check_one ("check_one_2exp", x, -y,  1, -1);
239 
240       mpz_set_si (x, -1L);
241       check_one ("check_one_2exp", x,  y, -1, -1);
242       check_one ("check_one_2exp", x, -y,  1, -1);
243     }
244 
245   mpz_clear (x);
246 }
247 
248 void
249 check_infinity (void)
250 {
251   mpz_t   x;
252   double  y = HUGE_VAL;
253   if (y != 2*y)
254     return;
255 
256   mpz_init (x);
257 
258   /* 0 cmp inf */
259   mpz_set_ui (x, 0L);
260   check_one ("check_infinity", x,  y, -1, -1);
261   check_one ("check_infinity", x, -y,  1, -1);
262 
263   /* 123 cmp inf */
264   mpz_set_ui (x, 123L);
265   check_one ("check_infinity", x,  y, -1, -1);
266   check_one ("check_infinity", x, -y,  1, -1);
267 
268   /* -123 cmp inf */
269   mpz_set_si (x, -123L);
270   check_one ("check_infinity", x,  y, -1, -1);
271   check_one ("check_infinity", x, -y,  1, -1);
272 
273   /* 2^5000 cmp inf */
274   mpz_set_ui (x, 1L);
275   mpz_mul_2exp (x, x, 5000L);
276   check_one ("check_infinity", x,  y, -1, -1);
277   check_one ("check_infinity", x, -y,  1, -1);
278 
279   /* -2^5000 cmp inf */
280   mpz_neg (x, x);
281   check_one ("check_infinity", x,  y, -1, -1);
282   check_one ("check_infinity", x, -y,  1, -1);
283 
284   mpz_clear (x);
285 }
286 
287 void
288 testmain (int argc, char *argv[])
289 {
290   check_data ();
291   check_onebits ();
292   check_low_z_one ();
293   check_one_2exp ();
294   check_infinity ();
295 }
296