1 /* Test mpfr_get_ld_2exp.
2
3 Copyright 2006-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5
6 This file is part of the GNU MPFR Library.
7
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23 #include <float.h>
24
25 #include "mpfr-test.h"
26
27 /* Check that hardware rounding doesn't make mpfr_get_ld_2exp return a value
28 outside its defined range. */
29 static void
check_round(void)30 check_round (void)
31 {
32 static const unsigned long data[] = {1, 32, 53, 54, 63, 64, 65, 127, 128, 256, 512 };
33 mpfr_t f;
34 long double got;
35 long got_exp;
36 int i, rnd_mode, neg;
37
38 mpfr_init2 (f, 1024L);
39
40 RND_LOOP (rnd_mode)
41 {
42 for (i = 0; i < (int) numberof (data); i++)
43 {
44 mpfr_set_ui (f, 1L, MPFR_RNDZ);
45 mpfr_mul_2ui (f, f, data[i], MPFR_RNDZ);
46 mpfr_sub_ui (f, f, 1L, MPFR_RNDZ);
47
48 for (neg = 0; neg <= 1; neg++)
49 {
50 got = mpfr_get_ld_2exp (&got_exp, f, (mpfr_rnd_t) rnd_mode);
51
52 if (neg == 0
53 ? (got < 0.5 || got >= 1.0)
54 : (got <= -1.0 || got > -0.5))
55 {
56 printf ("mpfr_get_ld_2exp wrong on 2**%lu-1\n", data[i]);
57 printf ("result out of range, expect 0.5 <= got < 1.0\n");
58 printf (" rnd_mode = %d\n", rnd_mode);
59 printf (" data[i] = %lu\n", data[i]);
60 printf (" f ");
61 mpfr_out_str (stdout, 2, 0, f, MPFR_RNDN);
62 printf ("\n");
63 ld_trace (" got ", got);
64 printf (" got exp %ld\n", got_exp);
65 exit(1);
66 }
67
68 mpfr_neg (f, f, MPFR_RNDZ);
69 }
70 }
71 }
72
73 mpfr_clear (f);
74 }
75
76
77 static void
check_inf_nan(void)78 check_inf_nan (void)
79 {
80 #if !defined(MPFR_ERRDIVZERO)
81 mpfr_t x;
82 double d;
83 long exp;
84
85 mpfr_init2 (x, 123);
86
87 mpfr_set_inf (x, 1);
88 d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ);
89 MPFR_ASSERTN (d > 0);
90 MPFR_ASSERTN (DOUBLE_ISINF (d));
91
92 mpfr_set_inf (x, -1);
93 d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ);
94 MPFR_ASSERTN (d < 0);
95 MPFR_ASSERTN (DOUBLE_ISINF (d));
96
97 mpfr_set_nan (x);
98 d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ);
99 MPFR_ASSERTN (DOUBLE_ISNAN (d));
100
101 mpfr_clear (x);
102 #endif
103 }
104
105 static void
bug20090520(void)106 bug20090520 (void)
107 {
108 mpfr_t x;
109 long double d, e;
110 int i;
111
112 mpfr_init (x);
113 mpfr_set_ui (x, 1, MPFR_RNDN);
114 d = 1.0;
115 mpfr_div_2ui (x, x, 16383, MPFR_RNDN);
116 for (i = 0; i < 16383; i++)
117 d *= 0.5;
118 e = mpfr_get_ld (x, MPFR_RNDN);
119 if (e != d)
120 {
121 printf ("mpfr_get_ld(1e-16383) failed\n");
122 printf ("expected %.20Le\n", d);
123 printf ("got %.20Le\n", e);
124 exit (1);
125 }
126 mpfr_clear (x);
127 }
128
129 static void
bug20180904(void)130 bug20180904 (void)
131 {
132 #if defined(HAVE_LDOUBLE_IEEE_EXT_LITTLE) || \
133 defined(HAVE_LDOUBLE_IEEE_EXT_BIG)
134 mpfr_t x;
135 long double d = 5.450797408381041489264061250159e-4937L;
136 long double e;
137
138 mpfr_init2 (x, 64);
139 mpfr_set_str_binary (x, "0.1000100000000000000000000000000000000000000000000000000000000000E-16397");
140 e = mpfr_get_ld (x, MPFR_RNDN);
141 if (e != d)
142 {
143 printf ("Error in bug20180904:\n");
144 printf ("expected %.30Le\n", d);
145 printf ("got %.30Le\n", e);
146 exit (1);
147 }
148 mpfr_clear (x);
149 #endif
150 }
151
152 int
main(void)153 main (void)
154 {
155 tests_start_mpfr ();
156 mpfr_test_init ();
157
158 bug20180904 ();
159 bug20090520 ();
160
161 check_round ();
162 check_inf_nan ();
163
164 tests_end_mpfr ();
165 return 0;
166 }
167