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