github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpz/t-get_d_2exp.c (about) 1 /* Test mpz_get_d_2exp. 2 3 Copyright 2002, 2003, 2012 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 "gmp.h" 23 #include "gmp-impl.h" 24 #include "tests.h" 25 26 27 static void 28 check_zero (void) 29 { 30 mpz_t z; 31 double got, want; 32 long got_exp, want_exp; 33 34 mpz_init_set_ui (z, 0); 35 36 want = 0.0; 37 want_exp = 0; 38 got = mpz_get_d_2exp (&got_exp, z); 39 if (got != want || got_exp != want_exp) 40 { 41 printf ("mpz_get_d_2exp wrong on zero\n"); 42 mpz_trace (" z ", z); 43 d_trace (" want ", want); 44 d_trace (" got ", got); 45 printf (" want exp %ld\n", want_exp); 46 printf (" got exp %ld\n", got_exp); 47 abort(); 48 } 49 50 mpz_clear (z); 51 } 52 53 static void 54 check_onebit (void) 55 { 56 static const unsigned long data[] = { 57 1, 32, 52, 53, 54, 63, 64, 65, 128, 256, 511, 512, 513 58 }; 59 mpz_t z; 60 double got, want; 61 long got_exp, want_exp; 62 int i; 63 64 mpz_init (z); 65 66 for (i = 0; i < numberof (data); i++) 67 { 68 mpz_set_ui (z, 1L); 69 mpz_mul_2exp (z, z, data[i]); 70 want = 0.5; 71 want_exp = data[i] + 1; 72 got = mpz_get_d_2exp (&got_exp, z); 73 if (got != want || got_exp != want_exp) 74 { 75 printf ("mpz_get_d_2exp wrong on 2**%ld\n", data[i]); 76 mpz_trace (" z ", z); 77 d_trace (" want ", want); 78 d_trace (" got ", got); 79 printf (" want exp %ld\n", want_exp); 80 printf (" got exp %ld\n", got_exp); 81 abort(); 82 } 83 84 mpz_set_si (z, -1L); 85 mpz_mul_2exp (z, z, data[i]); 86 want = -0.5; 87 want_exp = data[i] + 1; 88 got = mpz_get_d_2exp (&got_exp, z); 89 if (got != want || got_exp != want_exp) 90 { 91 printf ("mpz_get_d_2exp wrong on -2**%ld\n", data[i]); 92 mpz_trace (" z ", z); 93 d_trace (" want ", want); 94 d_trace (" got ", got); 95 printf (" want exp %ld\n", want_exp); 96 printf (" got exp %ld\n", got_exp); 97 abort(); 98 } 99 } 100 mpz_clear (z); 101 } 102 103 /* Check that hardware rounding doesn't make mpz_get_d_2exp return a value 104 outside its defined range. */ 105 static void 106 check_round (void) 107 { 108 static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 }; 109 mpz_t z; 110 double got; 111 long got_exp; 112 int i, rnd_mode, old_rnd_mode; 113 114 mpz_init (z); 115 old_rnd_mode = tests_hardware_getround (); 116 117 for (rnd_mode = 0; rnd_mode < 4; rnd_mode++) 118 { 119 tests_hardware_setround (rnd_mode); 120 121 for (i = 0; i < numberof (data); i++) 122 { 123 mpz_set_ui (z, 1L); 124 mpz_mul_2exp (z, z, data[i]); 125 mpz_sub_ui (z, z, 1L); 126 127 got = mpz_get_d_2exp (&got_exp, z); 128 if (got < 0.5 || got >= 1.0) 129 { 130 printf ("mpz_get_d_2exp wrong on 2**%lu-1\n", data[i]); 131 printf ("result out of range, expect 0.5 <= got < 1.0\n"); 132 printf (" rnd_mode = %d\n", rnd_mode); 133 printf (" data[i] = %lu\n", data[i]); 134 mpz_trace (" z ", z); 135 d_trace (" got ", got); 136 printf (" got exp %ld\n", got_exp); 137 abort(); 138 } 139 140 mpz_neg (z, z); 141 got = mpz_get_d_2exp (&got_exp, z); 142 if (got <= -1.0 || got > -0.5) 143 { 144 printf ("mpz_get_d_2exp wrong on -2**%lu-1\n", data[i]); 145 printf ("result out of range, expect -1.0 < got <= -0.5\n"); 146 printf (" rnd_mode = %d\n", rnd_mode); 147 printf (" data[i] = %lu\n", data[i]); 148 mpz_trace (" z ", z); 149 d_trace (" got ", got); 150 printf (" got exp %ld\n", got_exp); 151 abort(); 152 } 153 } 154 } 155 156 mpz_clear (z); 157 tests_hardware_setround (old_rnd_mode); 158 } 159 160 static void 161 check_rand (void) 162 { 163 gmp_randstate_ptr rands = RANDS; 164 int i; 165 mpz_t z; 166 double got; 167 long got_exp; 168 unsigned long bits; 169 170 mpz_init (z); 171 172 for (i = 0; i < 200; i++) 173 { 174 bits = gmp_urandomm_ui (rands, 512L); 175 mpz_urandomb (z, rands, bits); 176 177 got = mpz_get_d_2exp (&got_exp, z); 178 if (mpz_sgn (z) == 0) 179 continue; 180 bits = mpz_sizeinbase (z, 2); 181 182 if (got < 0.5 || got >= 1.0) 183 { 184 printf ("mpz_get_d_2exp out of range, expect 0.5 <= got < 1.0\n"); 185 mpz_trace (" z ", z); 186 d_trace (" got ", got); 187 printf (" got exp %ld\n", got_exp); 188 abort(); 189 } 190 191 /* FIXME: If mpz_get_d_2exp rounds upwards we might have got_exp == 192 bits+1, so leave this test disabled until we decide if that's what 193 should happen, or not. */ 194 #if 0 195 if (got_exp != bits) 196 { 197 printf ("mpz_get_d_2exp wrong exponent\n", i); 198 mpz_trace (" z ", z); 199 d_trace (" bits ", bits); 200 d_trace (" got ", got); 201 printf (" got exp %ld\n", got_exp); 202 abort(); 203 } 204 #endif 205 } 206 mpz_clear (z); 207 } 208 209 210 int 211 main (void) 212 { 213 tests_start (); 214 mp_trace_base = -16; 215 216 check_zero (); 217 check_onebit (); 218 check_round (); 219 check_rand (); 220 221 tests_end (); 222 exit (0); 223 }