xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/t-cmp_d.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
1 /* Test mpz_cmp_d and mpz_cmpabs_d.
2 
3 Copyright 2001-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 https://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       unsigned 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 void
68 check_data (void)
69 {
70   static const struct {
71     const char  *x;
72     double      y;
73     int         cmp, cmpabs;
74 
75   } data[] = {
76 
77     {  "0",  0.0,  0,  0 },
78 
79     {  "1",  0.0,  1,  1 },
80     { "-1",  0.0, -1,  1 },
81 
82     {  "1",  0.5,  1,  1 },
83     { "-1", -0.5, -1,  1 },
84 
85     {  "0",  1.0, -1, -1 },
86     {  "0", -1.0,  1, -1 },
87 
88     {  "0x1000000000000000000000000000000000000000000000000", 1.0,  1, 1 },
89     { "-0x1000000000000000000000000000000000000000000000000", 1.0, -1, 1 },
90 
91     {  "0",  1e100, -1, -1 },
92     {  "0", -1e100,  1, -1 },
93 
94     {  "2",  1.5,   1,  1 },
95     {  "2", -1.5,   1,  1 },
96     { "-2",  1.5,  -1,  1 },
97     { "-2", -1.5,  -1,  1 },
98   };
99 
100   mpz_t    x;
101   unsigned i;
102 
103   mpz_init (x);
104 
105   for (i = 0; i < numberof (data); i++)
106     {
107       mpz_set_str_or_abort (x, data[i].x, 0);
108       check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs);
109     }
110 
111   mpz_clear (x);
112 }
113 
114 
115 /* Equality of integers with up to 53 bits */
116 void
117 check_onebits (void)
118 {
119   mpz_t   x, x2;
120   double  y;
121   int     i;
122 
123   mpz_init_set_ui (x, 0L);
124   mpz_init (x2);
125 
126   for (i = 0; i < 512; i++)
127     {
128       mpz_mul_2exp (x, x, 1);
129       mpz_add_ui (x, x, 1L);
130 
131       y = mpz_get_d (x);
132       mpz_set_d (x2, y);
133 
134       /* stop if any truncation is occurring */
135       if (mpz_cmp (x, x2) != 0)
136         break;
137 
138       check_one ("check_onebits", x, y, 0, 0);
139       check_one ("check_onebits", x, -y, 1, 0);
140       mpz_neg (x, x);
141       check_one ("check_onebits", x, y, -1, 0);
142       check_one ("check_onebits", x, -y, 0, 0);
143       mpz_neg (x, x);
144     }
145 
146   mpz_clear (x);
147   mpz_clear (x2);
148 }
149 
150 
151 /* With the mpz differing by 1, in a limb position possibly below the double */
152 void
153 check_low_z_one (void)
154 {
155   mpz_t          x;
156   double         y;
157   unsigned long  i;
158 
159   mpz_init (x);
160 
161   /* FIXME: It'd be better to base this on the float format. */
162 #if defined (__vax) || defined (__vax__)
163 #define LIM 127			/* vax fp numbers have limited range */
164 #else
165 #define LIM 512
166 #endif
167 
168   for (i = 1; i < LIM; i++)
169     {
170       mpz_set_ui (x, 1L);
171       mpz_mul_2exp (x, x, i);
172       y = mpz_get_d (x);
173 
174       check_one ("check_low_z_one", x, y,   0, 0);
175       check_one ("check_low_z_one", x, -y,  1, 0);
176       mpz_neg (x, x);
177       check_one ("check_low_z_one", x, y,  -1, 0);
178       check_one ("check_low_z_one", x, -y,  0, 0);
179       mpz_neg (x, x);
180 
181       mpz_sub_ui (x, x, 1);
182 
183       check_one ("check_low_z_one", x, y,  -1, -1);
184       check_one ("check_low_z_one", x, -y,  1, -1);
185       mpz_neg (x, x);
186       check_one ("check_low_z_one", x, y,  -1, -1);
187       check_one ("check_low_z_one", x, -y,  1, -1);
188       mpz_neg (x, x);
189 
190       mpz_add_ui (x, x, 2);
191 
192       check_one ("check_low_z_one", x, y,   1, 1);
193       check_one ("check_low_z_one", x, -y,  1, 1);
194       mpz_neg (x, x);
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     }
199 
200   mpz_clear (x);
201 }
202 
203 /* Comparing 1 and 1+2^-n.  "y" is volatile to make gcc store and fetch it,
204    which forces it to a 64-bit double, whereas on x86 it would otherwise
205    remain on the float stack as an 80-bit long double.  */
206 void
207 check_one_2exp (void)
208 {
209   double           e;
210   mpz_t            x;
211   volatile double  y;
212   int              i;
213 
214   mpz_init (x);
215 
216   e = 1.0;
217   for (i = 0; i < 128; i++)
218     {
219       e /= 2.0;
220       y = 1.0 + e;
221       if (y == 1.0)
222         break;
223 
224       mpz_set_ui (x, 1L);
225       check_one ("check_one_2exp", x,  y, -1, -1);
226       check_one ("check_one_2exp", x, -y,  1, -1);
227 
228       mpz_set_si (x, -1L);
229       check_one ("check_one_2exp", x,  y, -1, -1);
230       check_one ("check_one_2exp", x, -y,  1, -1);
231     }
232 
233   mpz_clear (x);
234 }
235 
236 void
237 check_infinity (void)
238 {
239   mpz_t   x;
240   double  y = HUGE_VAL;
241   if (y != 2*y)
242     return;
243 
244   mpz_init (x);
245 
246   /* 0 cmp inf */
247   mpz_set_ui (x, 0L);
248   check_one ("check_infinity", x,  y, -1, -1);
249   check_one ("check_infinity", x, -y,  1, -1);
250 
251   /* 123 cmp inf */
252   mpz_set_ui (x, 123L);
253   check_one ("check_infinity", x,  y, -1, -1);
254   check_one ("check_infinity", x, -y,  1, -1);
255 
256   /* -123 cmp inf */
257   mpz_set_si (x, -123L);
258   check_one ("check_infinity", x,  y, -1, -1);
259   check_one ("check_infinity", x, -y,  1, -1);
260 
261   /* 2^5000 cmp inf */
262   mpz_set_ui (x, 1L);
263   mpz_mul_2exp (x, x, 5000L);
264   check_one ("check_infinity", x,  y, -1, -1);
265   check_one ("check_infinity", x, -y,  1, -1);
266 
267   /* -2^5000 cmp inf */
268   mpz_neg (x, x);
269   check_one ("check_infinity", x,  y, -1, -1);
270   check_one ("check_infinity", x, -y,  1, -1);
271 
272   mpz_clear (x);
273 }
274 
275 void
276 testmain (int argc, char *argv[])
277 {
278   check_data ();
279   check_onebits ();
280   check_low_z_one ();
281   check_one_2exp ();
282   check_infinity ();
283 }
284