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