1 /* Test mpz_get_d_2exp. 2 3 Copyright 2002, 2003 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library. 6 7 The GNU MP Library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU Lesser General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or (at your 10 option) any later version. 11 12 The GNU MP Library is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 License for more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with the GNU MP Library. If not, see http://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_onebit (void) 29 { 30 static const unsigned long data[] = { 31 1, 32, 52, 53, 54, 63, 64, 65, 128, 256, 511, 512, 513 32 }; 33 mpz_t z; 34 double got, want; 35 long got_exp, want_exp; 36 int i; 37 38 mpz_init (z); 39 40 for (i = 0; i < numberof (data); i++) 41 { 42 mpz_set_ui (z, 1L); 43 mpz_mul_2exp (z, z, data[i]); 44 want = 0.5; 45 want_exp = data[i] + 1; 46 got = mpz_get_d_2exp (&got_exp, z); 47 if (got != want || got_exp != want_exp) 48 { 49 printf ("mpz_get_d_2exp wrong on 2**%ld\n", data[i]); 50 mpz_trace (" z ", z); 51 d_trace (" want ", want); 52 d_trace (" got ", got); 53 printf (" want exp %ld\n", want_exp); 54 printf (" got exp %ld\n", got_exp); 55 abort(); 56 } 57 58 mpz_set_si (z, -1L); 59 mpz_mul_2exp (z, z, data[i]); 60 want = -0.5; 61 want_exp = data[i] + 1; 62 got = mpz_get_d_2exp (&got_exp, z); 63 if (got != want || got_exp != want_exp) 64 { 65 printf ("mpz_get_d_2exp wrong on -2**%ld\n", data[i]); 66 mpz_trace (" z ", z); 67 d_trace (" want ", want); 68 d_trace (" got ", got); 69 printf (" want exp %ld\n", want_exp); 70 printf (" got exp %ld\n", got_exp); 71 abort(); 72 } 73 } 74 mpz_clear (z); 75 } 76 77 /* Check that hardware rounding doesn't make mpz_get_d_2exp return a value 78 outside its defined range. */ 79 static void 80 check_round (void) 81 { 82 static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 }; 83 mpz_t z; 84 double got; 85 long got_exp; 86 int i, rnd_mode, old_rnd_mode; 87 88 mpz_init (z); 89 old_rnd_mode = tests_hardware_getround (); 90 91 for (rnd_mode = 0; rnd_mode < 4; rnd_mode++) 92 { 93 tests_hardware_setround (rnd_mode); 94 95 for (i = 0; i < numberof (data); i++) 96 { 97 mpz_set_ui (z, 1L); 98 mpz_mul_2exp (z, z, data[i]); 99 mpz_sub_ui (z, z, 1L); 100 101 got = mpz_get_d_2exp (&got_exp, z); 102 if (got < 0.5 || got >= 1.0) 103 { 104 printf ("mpz_get_d_2exp wrong on 2**%lu-1\n", data[i]); 105 printf ("result out of range, expect 0.5 <= got < 1.0\n"); 106 printf (" rnd_mode = %d\n", rnd_mode); 107 printf (" data[i] = %lu\n", data[i]); 108 mpz_trace (" z ", z); 109 d_trace (" got ", got); 110 printf (" got exp %ld\n", got_exp); 111 abort(); 112 } 113 114 mpz_neg (z, z); 115 got = mpz_get_d_2exp (&got_exp, z); 116 if (got <= -1.0 || got > -0.5) 117 { 118 printf ("mpz_get_d_2exp wrong on -2**%lu-1\n", data[i]); 119 printf ("result out of range, expect -1.0 < got <= -0.5\n"); 120 printf (" rnd_mode = %d\n", rnd_mode); 121 printf (" data[i] = %lu\n", data[i]); 122 mpz_trace (" z ", z); 123 d_trace (" got ", got); 124 printf (" got exp %ld\n", got_exp); 125 abort(); 126 } 127 } 128 } 129 130 mpz_clear (z); 131 tests_hardware_setround (old_rnd_mode); 132 } 133 134 static void 135 check_rand (void) 136 { 137 gmp_randstate_ptr rands = RANDS; 138 int i; 139 mpz_t z; 140 double got; 141 long got_exp; 142 unsigned long bits; 143 144 mpz_init (z); 145 146 for (i = 0; i < 200; i++) 147 { 148 bits = gmp_urandomm_ui (rands, 512L); 149 mpz_urandomb (z, rands, bits); 150 151 got = mpz_get_d_2exp (&got_exp, z); 152 if (mpz_sgn (z) == 0) 153 continue; 154 bits = mpz_sizeinbase (z, 2); 155 156 if (got < 0.5 || got >= 1.0) 157 { 158 printf ("mpz_get_d_2exp out of range, expect 0.5 <= got < 1.0\n"); 159 mpz_trace (" z ", z); 160 d_trace (" got ", got); 161 printf (" got exp %ld\n", got_exp); 162 abort(); 163 } 164 165 /* FIXME: If mpz_get_d_2exp rounds upwards we might have got_exp == 166 bits+1, so leave this test disabled until we decide if that's what 167 should happen, or not. */ 168 #if 0 169 if (got_exp != bits) 170 { 171 printf ("mpz_get_d_2exp wrong exponent\n", i); 172 mpz_trace (" z ", z); 173 d_trace (" bits ", bits); 174 d_trace (" got ", got); 175 printf (" got exp %ld\n", got_exp); 176 abort(); 177 } 178 #endif 179 } 180 mpz_clear (z); 181 } 182 183 184 int 185 main (void) 186 { 187 tests_start (); 188 mp_trace_base = -16; 189 190 check_onebit (); 191 check_round (); 192 check_rand (); 193 194 tests_end (); 195 exit (0); 196 } 197