1 /* Test mpz_cmp_d and mpz_cmpabs_d. 2 3 Copyright 2001, 2002, 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 http://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 static void 68 mpz_set_str_or_abort (mpz_ptr z, const char *str, int base) 69 { 70 if (mpz_set_str (z, str, base) != 0) 71 { 72 fprintf (stderr, "ERROR: mpz_set_str failed\n"); 73 fprintf (stderr, " str = \"%s\"\n", str); 74 fprintf (stderr, " base = %d\n", base); 75 abort(); 76 } 77 } 78 79 void 80 check_data (void) 81 { 82 static const struct { 83 const char *x; 84 double y; 85 int cmp, cmpabs; 86 87 } data[] = { 88 89 { "0", 0.0, 0, 0 }, 90 91 { "1", 0.0, 1, 1 }, 92 { "-1", 0.0, -1, 1 }, 93 94 { "1", 0.5, 1, 1 }, 95 { "-1", -0.5, -1, 1 }, 96 97 { "0", 1.0, -1, -1 }, 98 { "0", -1.0, 1, -1 }, 99 100 { "0x1000000000000000000000000000000000000000000000000", 1.0, 1, 1 }, 101 { "-0x1000000000000000000000000000000000000000000000000", 1.0, -1, 1 }, 102 103 { "0", 1e100, -1, -1 }, 104 { "0", -1e100, 1, -1 }, 105 106 { "2", 1.5, 1, 1 }, 107 { "2", -1.5, 1, 1 }, 108 { "-2", 1.5, -1, 1 }, 109 { "-2", -1.5, -1, 1 }, 110 }; 111 112 mpz_t x; 113 int i; 114 115 mpz_init (x); 116 117 for (i = 0; i < numberof (data); i++) 118 { 119 mpz_set_str_or_abort (x, data[i].x, 0); 120 check_one ("check_data", x, data[i].y, data[i].cmp, data[i].cmpabs); 121 } 122 123 mpz_clear (x); 124 } 125 126 127 /* Equality of integers with up to 53 bits */ 128 void 129 check_onebits (void) 130 { 131 mpz_t x, x2; 132 double y; 133 int i; 134 135 mpz_init_set_ui (x, 0L); 136 mpz_init (x2); 137 138 for (i = 0; i < 512; i++) 139 { 140 mpz_mul_2exp (x, x, 1); 141 mpz_add_ui (x, x, 1L); 142 143 y = mpz_get_d (x); 144 mpz_set_d (x2, y); 145 146 /* stop if any truncation is occurring */ 147 if (mpz_cmp (x, x2) != 0) 148 break; 149 150 check_one ("check_onebits", x, y, 0, 0); 151 check_one ("check_onebits", x, -y, 1, 0); 152 mpz_neg (x, x); 153 check_one ("check_onebits", x, y, -1, 0); 154 check_one ("check_onebits", x, -y, 0, 0); 155 mpz_neg (x, x); 156 } 157 158 mpz_clear (x); 159 mpz_clear (x2); 160 } 161 162 163 /* With the mpz differing by 1, in a limb position possibly below the double */ 164 void 165 check_low_z_one (void) 166 { 167 mpz_t x; 168 double y; 169 unsigned long i; 170 171 mpz_init (x); 172 173 /* FIXME: It'd be better to base this on the float format. */ 174 #if defined (__vax) || defined (__vax__) 175 #define LIM 127 /* vax fp numbers have limited range */ 176 #else 177 #define LIM 512 178 #endif 179 180 for (i = 1; i < LIM; i++) 181 { 182 mpz_set_ui (x, 1L); 183 mpz_mul_2exp (x, x, i); 184 y = mpz_get_d (x); 185 186 check_one ("check_low_z_one", x, y, 0, 0); 187 check_one ("check_low_z_one", x, -y, 1, 0); 188 mpz_neg (x, x); 189 check_one ("check_low_z_one", x, y, -1, 0); 190 check_one ("check_low_z_one", x, -y, 0, 0); 191 mpz_neg (x, x); 192 193 mpz_sub_ui (x, x, 1); 194 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 check_one ("check_low_z_one", x, y, -1, -1); 199 check_one ("check_low_z_one", x, -y, 1, -1); 200 mpz_neg (x, x); 201 202 mpz_add_ui (x, x, 2); 203 204 check_one ("check_low_z_one", x, y, 1, 1); 205 check_one ("check_low_z_one", x, -y, 1, 1); 206 mpz_neg (x, x); 207 check_one ("check_low_z_one", x, y, -1, 1); 208 check_one ("check_low_z_one", x, -y, -1, 1); 209 mpz_neg (x, x); 210 } 211 212 mpz_clear (x); 213 } 214 215 /* Comparing 1 and 1+2^-n. "y" is volatile to make gcc store and fetch it, 216 which forces it to a 64-bit double, whereas on x86 it would otherwise 217 remain on the float stack as an 80-bit long double. */ 218 void 219 check_one_2exp (void) 220 { 221 double e; 222 mpz_t x; 223 volatile double y; 224 int i; 225 226 mpz_init (x); 227 228 e = 1.0; 229 for (i = 0; i < 128; i++) 230 { 231 e /= 2.0; 232 y = 1.0 + e; 233 if (y == 1.0) 234 break; 235 236 mpz_set_ui (x, 1L); 237 check_one ("check_one_2exp", x, y, -1, -1); 238 check_one ("check_one_2exp", x, -y, 1, -1); 239 240 mpz_set_si (x, -1L); 241 check_one ("check_one_2exp", x, y, -1, -1); 242 check_one ("check_one_2exp", x, -y, 1, -1); 243 } 244 245 mpz_clear (x); 246 } 247 248 void 249 check_infinity (void) 250 { 251 mpz_t x; 252 double y = HUGE_VAL; 253 if (y != 2*y) 254 return; 255 256 mpz_init (x); 257 258 /* 0 cmp inf */ 259 mpz_set_ui (x, 0L); 260 check_one ("check_infinity", x, y, -1, -1); 261 check_one ("check_infinity", x, -y, 1, -1); 262 263 /* 123 cmp inf */ 264 mpz_set_ui (x, 123L); 265 check_one ("check_infinity", x, y, -1, -1); 266 check_one ("check_infinity", x, -y, 1, -1); 267 268 /* -123 cmp inf */ 269 mpz_set_si (x, -123L); 270 check_one ("check_infinity", x, y, -1, -1); 271 check_one ("check_infinity", x, -y, 1, -1); 272 273 /* 2^5000 cmp inf */ 274 mpz_set_ui (x, 1L); 275 mpz_mul_2exp (x, x, 5000L); 276 check_one ("check_infinity", x, y, -1, -1); 277 check_one ("check_infinity", x, -y, 1, -1); 278 279 /* -2^5000 cmp inf */ 280 mpz_neg (x, x); 281 check_one ("check_infinity", x, y, -1, -1); 282 check_one ("check_infinity", x, -y, 1, -1); 283 284 mpz_clear (x); 285 } 286 287 void 288 testmain (int argc, char *argv[]) 289 { 290 check_data (); 291 check_onebits (); 292 check_low_z_one (); 293 check_one_2exp (); 294 check_infinity (); 295 } 296