1 1.1 mrg /* Test mpf_get_d_2exp. 2 1.1 mrg 3 1.1.1.5 mrg Copyright 2002, 2003, 2017, 2020 Free Software Foundation, Inc. 4 1.1 mrg 5 1.1.1.2 mrg This file is part of the GNU MP Library test suite. 6 1.1 mrg 7 1.1.1.2 mrg The GNU MP Library test suite is free software; you can redistribute it 8 1.1.1.2 mrg and/or modify it under the terms of the GNU General Public License as 9 1.1.1.2 mrg published by the Free Software Foundation; either version 3 of the License, 10 1.1.1.2 mrg or (at your option) any later version. 11 1.1.1.2 mrg 12 1.1.1.2 mrg The GNU MP Library test suite is distributed in the hope that it will be 13 1.1.1.2 mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1.1.2 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15 1.1.1.2 mrg Public License for more details. 16 1.1 mrg 17 1.1.1.2 mrg You should have received a copy of the GNU General Public License along with 18 1.1.1.3 mrg the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 19 1.1 mrg 20 1.1 mrg #include <stdio.h> 21 1.1 mrg #include <stdlib.h> 22 1.1 mrg #include "gmp-impl.h" 23 1.1 mrg #include "tests.h" 24 1.1 mrg 25 1.1 mrg 26 1.1 mrg static void 27 1.1.1.4 mrg check_data (void) 28 1.1 mrg { 29 1.1 mrg mpf_t f; 30 1.1 mrg double got, want; 31 1.1.1.4 mrg long got_exp; 32 1.1.1.4 mrg long exp; 33 1.1.1.4 mrg struct { 34 1.1.1.4 mrg int base; 35 1.1.1.4 mrg int shift; 36 1.1.1.4 mrg } data[] = { 37 1.1.1.4 mrg {-1, 1}, {-3, 2}, {-5, 3}, {-7, 3}, { 1, 1}, { 3, 2}, { 5, 3}, { 7, 3} 38 1.1.1.4 mrg }; 39 1.1 mrg 40 1.1.1.4 mrg mpf_init2 (f, 3); 41 1.1 mrg 42 1.1.1.5 mrg got = mpf_get_d_2exp (&got_exp, f); 43 1.1.1.5 mrg if (got != 0 || got_exp != 0) 44 1.1.1.5 mrg { 45 1.1.1.5 mrg printf ("mpf_get_d_2exp wrong on zero\n"); 46 1.1.1.5 mrg mpf_trace (" f ", f); 47 1.1.1.5 mrg d_trace (" got ", got); 48 1.1.1.5 mrg printf (" got exp %ld\n", got_exp); 49 1.1.1.5 mrg abort(); 50 1.1.1.5 mrg } 51 1.1.1.5 mrg 52 1.1.1.4 mrg for (exp = -513; exp <= 513; exp++) 53 1.1 mrg { 54 1.1.1.4 mrg size_t i; 55 1.1.1.4 mrg for (i = 0; i < numberof (data); i++) 56 1.1.1.4 mrg { 57 1.1.1.4 mrg want = (double) data[i].base / (1 << data[i].shift); 58 1.1.1.4 mrg mpf_set_d (f, want); 59 1.1.1.4 mrg 60 1.1.1.4 mrg if (exp >= 0) 61 1.1.1.4 mrg mpf_mul_2exp (f, f, exp); 62 1.1.1.4 mrg else 63 1.1.1.4 mrg mpf_div_2exp (f, f, -exp); 64 1.1.1.4 mrg 65 1.1.1.4 mrg got = mpf_get_d_2exp (&got_exp, f); 66 1.1.1.4 mrg if (got != want || got_exp != exp) 67 1.1.1.4 mrg { 68 1.1.1.4 mrg printf ("mpf_get_d_2exp wrong on 2**%ld\n", exp); 69 1.1.1.4 mrg mpf_trace (" f ", f); 70 1.1.1.4 mrg d_trace (" want ", want); 71 1.1.1.4 mrg d_trace (" got ", got); 72 1.1.1.4 mrg printf (" want exp %ld\n", exp); 73 1.1.1.4 mrg printf (" got exp %ld\n", got_exp); 74 1.1.1.4 mrg abort(); 75 1.1.1.4 mrg } 76 1.1.1.4 mrg } 77 1.1 mrg } 78 1.1 mrg mpf_clear (f); 79 1.1 mrg } 80 1.1 mrg 81 1.1 mrg /* Check that hardware rounding doesn't make mpf_get_d_2exp return a value 82 1.1 mrg outside its defined range. */ 83 1.1 mrg static void 84 1.1 mrg check_round (void) 85 1.1 mrg { 86 1.1 mrg static const unsigned long data[] = { 1, 32, 53, 54, 64, 128, 256, 512 }; 87 1.1 mrg mpf_t f; 88 1.1 mrg double got; 89 1.1 mrg long got_exp; 90 1.1 mrg int i, rnd_mode, old_rnd_mode; 91 1.1 mrg 92 1.1 mrg mpf_init2 (f, 1024L); 93 1.1 mrg old_rnd_mode = tests_hardware_getround (); 94 1.1 mrg 95 1.1 mrg for (rnd_mode = 0; rnd_mode < 4; rnd_mode++) 96 1.1 mrg { 97 1.1 mrg tests_hardware_setround (rnd_mode); 98 1.1 mrg 99 1.1 mrg for (i = 0; i < numberof (data); i++) 100 1.1 mrg { 101 1.1 mrg mpf_set_ui (f, 1L); 102 1.1 mrg mpf_mul_2exp (f, f, data[i]); 103 1.1 mrg mpf_sub_ui (f, f, 1L); 104 1.1 mrg 105 1.1 mrg got = mpf_get_d_2exp (&got_exp, f); 106 1.1 mrg if (got < 0.5 || got >= 1.0) 107 1.1 mrg { 108 1.1 mrg printf ("mpf_get_d_2exp bad on 2**%lu-1\n", data[i]); 109 1.1 mrg printf ("result out of range, expect 0.5 <= got < 1.0\n"); 110 1.1 mrg printf (" rnd_mode = %d\n", rnd_mode); 111 1.1 mrg printf (" data[i] = %lu\n", data[i]); 112 1.1 mrg mpf_trace (" f ", f); 113 1.1 mrg d_trace (" got ", got); 114 1.1 mrg printf (" got exp %ld\n", got_exp); 115 1.1 mrg abort(); 116 1.1 mrg } 117 1.1 mrg } 118 1.1 mrg } 119 1.1 mrg 120 1.1 mrg mpf_clear (f); 121 1.1 mrg tests_hardware_setround (old_rnd_mode); 122 1.1 mrg } 123 1.1 mrg 124 1.1 mrg 125 1.1 mrg int 126 1.1 mrg main (void) 127 1.1 mrg { 128 1.1 mrg tests_start (); 129 1.1 mrg mp_trace_base = 16; 130 1.1 mrg 131 1.1.1.4 mrg check_data (); 132 1.1 mrg check_round (); 133 1.1 mrg 134 1.1 mrg tests_end (); 135 1.1 mrg exit (0); 136 1.1 mrg } 137