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 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 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 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 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 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 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 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