t-cmp_d.c revision 1.1.1.4
1/* Test mpz_cmp_d and mpz_cmpabs_d. 2 3Copyright 2001-2003, 2005 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library test suite. 6 7The GNU MP Library test suite is free software; you can redistribute it 8and/or modify it under the terms of the GNU General Public License as 9published by the Free Software Foundation; either version 3 of the License, 10or (at your option) any later version. 11 12The GNU MP Library test suite is distributed in the hope that it will be 13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15Public License for more details. 16 17You should have received a copy of the GNU General Public License along with 18the 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 35void 36check_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 71void 72check_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 */ 120void 121check_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 */ 156void 157check_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. */ 210void 211check_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 240void 241check_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 279int 280main (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