t-get_d_2exp.c revision 1.1.1.2
1/* Test mpz_get_d_2exp. 2 3Copyright 2002, 2003, 2012 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 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 27static void 28check_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 53static void 54check_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. */ 105static void 106check_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 160static void 161check_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 210int 211main (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} 224