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