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