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
check_data(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
check_round(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
main(void)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