Upload Tizen:Base source
[external/gmp.git] / tests / mpz / t-cmp_d.c
1 /* Test mpz_cmp_d and mpz_cmpabs_d.
2
3 Copyright 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library.  If not, see http://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     {  "0",  1.0, -1, -1 },
88     {  "0", -1.0,  1, -1 },
89
90     {  "0x1000000000000000000000000000000000000000000000000", 0.0,  1, 1 },
91     { "-0x1000000000000000000000000000000000000000000000000", 0.0, -1, 1 },
92
93     {  "0",  1e100, -1, -1 },
94     {  "0", -1e100,  1, -1 },
95
96     {  "2",  1.5,   1,  1 },
97     {  "2", -1.5,   1,  1 },
98     { "-2",  1.5,  -1,  1 },
99     { "-2", -1.5,  -1,  1 },
100   };
101
102   mpz_t  x;
103   int    i;
104
105   mpz_init (x);
106
107   for (i = 0; i < numberof (data); i++)
108     {
109       mpz_set_str_or_abort (x, data[i].x, 0);
110       check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs);
111     }
112
113   mpz_clear (x);
114 }
115
116
117 /* Equality of integers with up to 53 bits */
118 void
119 check_onebits (void)
120 {
121   mpz_t   x, x2;
122   double  y;
123   int     i;
124
125   mpz_init_set_ui (x, 0L);
126   mpz_init (x2);
127
128   for (i = 0; i < 512; i++)
129     {
130       mpz_mul_2exp (x, x, 1);
131       mpz_add_ui (x, x, 1L);
132
133       y = mpz_get_d (x);
134       mpz_set_d (x2, y);
135
136       /* stop if any truncation is occurring */
137       if (mpz_cmp (x, x2) != 0)
138         break;
139
140       check_one ("check_onebits", x, y, 0, 0);
141       check_one ("check_onebits", x, -y, 1, 0);
142       mpz_neg (x, x);
143       check_one ("check_onebits", x, y, -1, 0);
144       check_one ("check_onebits", x, -y, 0, 0);
145       mpz_neg (x, x);
146     }
147
148   mpz_clear (x);
149   mpz_clear (x2);
150 }
151
152
153 /* With the mpz differing by 1, in a limb position possibly below the double */
154 void
155 check_low_z_one (void)
156 {
157   mpz_t          x;
158   double         y;
159   unsigned long  i;
160
161   mpz_init (x);
162
163   /* FIXME: It'd be better to base this on the float format. */
164 #ifdef __vax
165 #define LIM 127                 /* vax fp numbers have limited range */
166 #else
167 #define LIM 512
168 #endif
169
170   for (i = 1; i < LIM; i++)
171     {
172       mpz_set_ui (x, 1L);
173       mpz_mul_2exp (x, x, i);
174       y = mpz_get_d (x);
175
176       check_one ("check_low_z_one", x, y,   0, 0);
177       check_one ("check_low_z_one", x, -y,  1, 0);
178       mpz_neg (x, x);
179       check_one ("check_low_z_one", x, y,  -1, 0);
180       check_one ("check_low_z_one", x, -y,  0, 0);
181       mpz_neg (x, x);
182
183       mpz_sub_ui (x, x, 1);
184
185       check_one ("check_low_z_one", x, y,  -1, -1);
186       check_one ("check_low_z_one", x, -y,  1, -1);
187       mpz_neg (x, x);
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
192       mpz_add_ui (x, x, 2);
193
194       check_one ("check_low_z_one", x, y,   1, 1);
195       check_one ("check_low_z_one", x, -y,  1, 1);
196       mpz_neg (x, x);
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     }
201
202   mpz_clear (x);
203 }
204
205 /* Comparing 1 and 1+2^-n.  "y" is volatile to make gcc store and fetch it,
206    which forces it to a 64-bit double, whereas on x86 it would otherwise
207    remain on the float stack as an 80-bit long double.  */
208 void
209 check_one_2exp (void)
210 {
211   double           e;
212   mpz_t            x;
213   volatile double  y;
214   int              i;
215
216   mpz_init (x);
217
218   e = 1.0;
219   for (i = 0; i < 128; i++)
220     {
221       e /= 2.0;
222       y = 1.0 + e;
223       if (y == 1.0)
224         break;
225
226       mpz_set_ui (x, 1L);
227       check_one ("check_one_2exp", x,  y, -1, -1);
228       check_one ("check_one_2exp", x, -y,  1, -1);
229
230       mpz_set_si (x, -1L);
231       check_one ("check_one_2exp", x,  y, -1, -1);
232       check_one ("check_one_2exp", x, -y,  1, -1);
233     }
234
235   mpz_clear (x);
236 }
237
238 void
239 check_infinity (void)
240 {
241   mpz_t   x;
242   double  y = tests_infinity_d ();
243   if (y == 0.0)
244     return;
245
246   mpz_init (x);
247
248   /* 0 cmp inf */
249   mpz_set_ui (x, 0L);
250   check_one ("check_infinity", x,  y, -1, -1);
251   check_one ("check_infinity", x, -y,  1, -1);
252
253   /* 123 cmp inf */
254   mpz_set_ui (x, 123L);
255   check_one ("check_infinity", x,  y, -1, -1);
256   check_one ("check_infinity", x, -y,  1, -1);
257
258   /* -123 cmp inf */
259   mpz_set_si (x, -123L);
260   check_one ("check_infinity", x,  y, -1, -1);
261   check_one ("check_infinity", x, -y,  1, -1);
262
263   /* 2^5000 cmp inf */
264   mpz_set_ui (x, 1L);
265   mpz_mul_2exp (x, x, 5000L);
266   check_one ("check_infinity", x,  y, -1, -1);
267   check_one ("check_infinity", x, -y,  1, -1);
268
269   /* -2^5000 cmp inf */
270   mpz_neg (x, x);
271   check_one ("check_infinity", x,  y, -1, -1);
272   check_one ("check_infinity", x, -y,  1, -1);
273
274   mpz_clear (x);
275 }
276
277 int
278 main (int argc, char *argv[])
279 {
280   tests_start ();
281
282   check_data ();
283   check_onebits ();
284   check_low_z_one ();
285   check_one_2exp ();
286   check_infinity ();
287
288   tests_end ();
289   exit (0);
290 }