1/* Test mpz_get_d_2exp. 2 3Copyright 2002, 2003 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 "gmp.h" 23#include "gmp-impl.h" 24#include "tests.h" 25 26 27static void 28check_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. */ 79static void 80check_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 134static void 135check_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 184int 185main (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