Imported Upstream version 6.0.0
[platform/upstream/gmp.git] / tests / mpz / t-cmp_d.c
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 }