github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpq/t-get_d.c (about) 1 /* Test mpq_get_d and mpq_set_d 2 3 Copyright 1991, 1993, 1994, 1996, 2000-2003, 2012, 2013 Free Software 4 Foundation, Inc. 5 6 This file is part of the GNU MP Library test suite. 7 8 The GNU MP Library test suite is free software; you can redistribute it 9 and/or modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 3 of the License, 11 or (at your option) any later version. 12 13 The GNU MP Library test suite is distributed in the hope that it will be 14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 16 Public License for more details. 17 18 You should have received a copy of the GNU General Public License along with 19 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 24 #include "gmp.h" 25 #include "gmp-impl.h" 26 #include "tests.h" 27 28 #ifndef SIZE 29 #define SIZE 8 30 #endif 31 32 /* VAX D floats only have an 8 bit signed exponent, so anything 2^128 or 33 bigger will overflow, that being 4 limbs. */ 34 #if defined (__vax) || defined (__vax__) && SIZE > 4 35 #undef SIZE 36 #define SIZE 4 37 #define EPSIZE 3 38 #else 39 #define EPSIZE SIZE 40 #endif 41 42 void dump (mpq_t); 43 44 void 45 check_monotonic (int argc, char **argv) 46 { 47 mpq_t a; 48 mp_size_t size; 49 int reps = 100; 50 int i, j; 51 double last_d, new_d; 52 mpq_t qlast_d, qnew_d; 53 mpq_t eps; 54 55 if (argc == 2) 56 reps = atoi (argv[1]); 57 58 /* The idea here is to test the monotonousness of mpq_get_d by adding 59 numbers to the numerator and denominator. */ 60 61 mpq_init (a); 62 mpq_init (eps); 63 mpq_init (qlast_d); 64 mpq_init (qnew_d); 65 66 for (i = 0; i < reps; i++) 67 { 68 size = urandom () % SIZE - SIZE/2; 69 mpz_random2 (mpq_numref (a), size); 70 do 71 { 72 size = urandom () % SIZE - SIZE/2; 73 mpz_random2 (mpq_denref (a), size); 74 } 75 while (mpz_cmp_ui (mpq_denref (a), 0) == 0); 76 77 mpq_canonicalize (a); 78 79 last_d = mpq_get_d (a); 80 mpq_set_d (qlast_d, last_d); 81 for (j = 0; j < 10; j++) 82 { 83 size = urandom () % EPSIZE + 1; 84 mpz_random2 (mpq_numref (eps), size); 85 size = urandom () % EPSIZE + 1; 86 mpz_random2 (mpq_denref (eps), size); 87 mpq_canonicalize (eps); 88 89 mpq_add (a, a, eps); 90 mpq_canonicalize (a); 91 new_d = mpq_get_d (a); 92 if (last_d > new_d) 93 { 94 printf ("\nERROR (test %d/%d): bad mpq_get_d results\n", i, j); 95 printf ("last: %.16g\n", last_d); 96 printf (" new: %.16g\n", new_d); dump (a); 97 abort (); 98 } 99 mpq_set_d (qnew_d, new_d); 100 MPQ_CHECK_FORMAT (qnew_d); 101 if (mpq_cmp (qlast_d, qnew_d) > 0) 102 { 103 printf ("ERROR (test %d/%d): bad mpq_set_d results\n", i, j); 104 printf ("last: %.16g\n", last_d); dump (qlast_d); 105 printf (" new: %.16g\n", new_d); dump (qnew_d); 106 abort (); 107 } 108 last_d = new_d; 109 mpq_set (qlast_d, qnew_d); 110 } 111 } 112 113 mpq_clear (a); 114 mpq_clear (eps); 115 mpq_clear (qlast_d); 116 mpq_clear (qnew_d); 117 } 118 119 double 120 my_ldexp (double d, int e) 121 { 122 for (;;) 123 { 124 if (e > 0) 125 { 126 if (e >= 16) 127 { 128 d *= 65536.0; 129 e -= 16; 130 } 131 else 132 { 133 d *= 2.0; 134 e -= 1; 135 } 136 } 137 else if (e < 0) 138 { 139 140 if (e <= -16) 141 { 142 d /= 65536.0; 143 e += 16; 144 } 145 else 146 { 147 d /= 2.0; 148 e += 1; 149 } 150 } 151 else 152 return d; 153 } 154 } 155 156 #define MAXEXP 500 157 158 #if defined (__vax) || defined (__vax__) 159 #undef MAXEXP 160 #define MAXEXP 30 161 #endif 162 163 void 164 check_random (int argc, char **argv) 165 { 166 gmp_randstate_ptr rands = RANDS; 167 168 double d; 169 mpq_t q; 170 mpz_t a, t; 171 int exp; 172 173 int test, reps = 100000; 174 175 if (argc == 2) 176 reps = 100 * atoi (argv[1]); 177 178 mpq_init (q); 179 mpz_init (a); 180 mpz_init (t); 181 182 for (test = 0; test < reps; test++) 183 { 184 mpz_rrandomb (a, rands, 53); 185 mpz_urandomb (t, rands, 32); 186 exp = mpz_get_ui (t) % (2*MAXEXP) - MAXEXP; 187 188 d = my_ldexp (mpz_get_d (a), exp); 189 mpq_set_d (q, d); 190 /* Check that n/d = a * 2^exp, or 191 d*a 2^{exp} = n */ 192 mpz_mul (t, a, mpq_denref (q)); 193 if (exp > 0) 194 mpz_mul_2exp (t, t, exp); 195 else 196 { 197 if (!mpz_divisible_2exp_p (t, -exp)) 198 goto fail; 199 mpz_div_2exp (t, t, -exp); 200 } 201 if (mpz_cmp (t, mpq_numref (q)) != 0) 202 { 203 fail: 204 printf ("ERROR (check_random test %d): bad mpq_set_d results\n", test); 205 printf ("%.16g\n", d); 206 gmp_printf ("%Qd\n", q); 207 abort (); 208 } 209 } 210 mpq_clear (q); 211 mpz_clear (t); 212 mpz_clear (a); 213 } 214 215 void 216 dump (mpq_t x) 217 { 218 mpz_out_str (stdout, 10, mpq_numref (x)); 219 printf ("/"); 220 mpz_out_str (stdout, 10, mpq_denref (x)); 221 printf ("\n"); 222 } 223 224 /* Check various values 2^n and 1/2^n. */ 225 void 226 check_onebit (void) 227 { 228 static const long data[] = { 229 -3*GMP_NUMB_BITS-1, -3*GMP_NUMB_BITS, -3*GMP_NUMB_BITS+1, 230 -2*GMP_NUMB_BITS-1, -2*GMP_NUMB_BITS, -2*GMP_NUMB_BITS+1, 231 -GMP_NUMB_BITS-1, -GMP_NUMB_BITS, -GMP_NUMB_BITS+1, 232 -5, -2, -1, 0, 1, 2, 5, 233 GMP_NUMB_BITS-1, GMP_NUMB_BITS, GMP_NUMB_BITS+1, 234 2*GMP_NUMB_BITS-1, 2*GMP_NUMB_BITS, 2*GMP_NUMB_BITS+1, 235 3*GMP_NUMB_BITS-1, 3*GMP_NUMB_BITS, 3*GMP_NUMB_BITS+1, 236 }; 237 238 int i, neg; 239 long exp, l; 240 mpq_t q; 241 double got, want; 242 243 mpq_init (q); 244 245 for (i = 0; i < numberof (data); i++) 246 { 247 exp = data[i]; 248 249 mpq_set_ui (q, 1L, 1L); 250 if (exp >= 0) 251 mpq_mul_2exp (q, q, exp); 252 else 253 mpq_div_2exp (q, q, -exp); 254 255 want = 1.0; 256 for (l = 0; l < exp; l++) 257 want *= 2.0; 258 for (l = 0; l > exp; l--) 259 want /= 2.0; 260 261 for (neg = 0; neg <= 1; neg++) 262 { 263 if (neg) 264 { 265 mpq_neg (q, q); 266 want = -want; 267 } 268 269 got = mpq_get_d (q); 270 271 if (got != want) 272 { 273 printf ("mpq_get_d wrong on %s2**%ld\n", neg ? "-" : "", exp); 274 mpq_trace (" q ", q); 275 d_trace (" want ", want); 276 d_trace (" got ", got); 277 abort(); 278 } 279 } 280 } 281 mpq_clear (q); 282 } 283 284 int 285 main (int argc, char **argv) 286 { 287 tests_start (); 288 289 check_onebit (); 290 check_monotonic (argc, argv); 291 check_random (argc, argv); 292 293 tests_end (); 294 exit (0); 295 }