1 /* Test mpf_get_d_2exp. 2 3 Copyright 2002, 2003, 2017, 2020 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-impl.h" 23 #include "tests.h" 24 25 26 static void 27 check_data (void) 28 { 29 mpf_t f; 30 double got, want; 31 long got_exp; 32 long exp; 33 struct { 34 int base; 35 int shift; 36 } data[] = { 37 {-1, 1}, {-3, 2}, {-5, 3}, {-7, 3}, { 1, 1}, { 3, 2}, { 5, 3}, { 7, 3} 38 }; 39 40 mpf_init2 (f, 3); 41 42 got = mpf_get_d_2exp (&got_exp, f); 43 if (got != 0 || got_exp != 0) 44 { 45 printf ("mpf_get_d_2exp wrong on zero\n"); 46 mpf_trace (" f ", f); 47 d_trace (" got ", got); 48 printf (" got exp %ld\n", got_exp); 49 abort(); 50 } 51 52 for (exp = -513; exp <= 513; exp++) 53 { 54 size_t i; 55 for (i = 0; i < numberof (data); i++) 56 { 57 want = (double) data[i].base / (1 << data[i].shift); 58 mpf_set_d (f, want); 59 60 if (exp >= 0) 61 mpf_mul_2exp (f, f, exp); 62 else 63 mpf_div_2exp (f, f, -exp); 64 65 got = mpf_get_d_2exp (&got_exp, f); 66 if (got != want || got_exp != exp) 67 { 68 printf ("mpf_get_d_2exp wrong on 2**%ld\n", exp); 69 mpf_trace (" f ", f); 70 d_trace (" want ", want); 71 d_trace (" got ", got); 72 printf (" want exp %ld\n", exp); 73 printf (" got exp %ld\n", got_exp); 74 abort(); 75 } 76 } 77 } 78 mpf_clear (f); 79 } 80 81 /* Check that hardware rounding doesn't make mpf_get_d_2exp return a value 82 outside its defined range. */ 83 static void 84 check_round (void) 85 { 86 static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 }; 87 mpf_t f; 88 double got; 89 long got_exp; 90 int i, rnd_mode, old_rnd_mode; 91 92 mpf_init2 (f, 1024L); 93 old_rnd_mode = tests_hardware_getround (); 94 95 for (rnd_mode = 0; rnd_mode < 4; rnd_mode++) 96 { 97 tests_hardware_setround (rnd_mode); 98 99 for (i = 0; i < numberof (data); i++) 100 { 101 mpf_set_ui (f, 1L); 102 mpf_mul_2exp (f, f, data[i]); 103 mpf_sub_ui (f, f, 1L); 104 105 got = mpf_get_d_2exp (&got_exp, f); 106 if (got < 0.5 || got >= 1.0) 107 { 108 printf ("mpf_get_d_2exp bad on 2**%lu-1\n", data[i]); 109 printf ("result out of range, expect 0.5 <= got < 1.0\n"); 110 printf (" rnd_mode = %d\n", rnd_mode); 111 printf (" data[i] = %lu\n", data[i]); 112 mpf_trace (" f ", f); 113 d_trace (" got ", got); 114 printf (" got exp %ld\n", got_exp); 115 abort(); 116 } 117 } 118 } 119 120 mpf_clear (f); 121 tests_hardware_setround (old_rnd_mode); 122 } 123 124 125 int 126 main (void) 127 { 128 tests_start (); 129 mp_trace_base = 16; 130 131 check_data (); 132 check_round (); 133 134 tests_end (); 135 exit (0); 136 } 137