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