1/* Test mpz_cmp_d and mpz_cmpabs_d. 2 3Copyright 2001, 2002, 2003, 2005 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library. 6 7The GNU MP Library is free software; you can redistribute it and/or modify 8it under the terms of the GNU Lesser General Public License as published by 9the Free Software Foundation; either version 3 of the License, or (at your 10option) any later version. 11 12The GNU MP Library is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15License for more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along 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 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 { "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 */ 118void 119check_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 */ 154void 155check_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. */ 208void 209check_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 238void 239check_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 277int 278main (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} 291