1 /* Test file for mpfr_const_log2.
2
3 Copyright 1999, 2001-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 "mpfr-test.h"
24
25 /* tlog2 [prec] [rnd] [0 = no print] */
26
27 static void
check(mpfr_prec_t p0,mpfr_prec_t p1)28 check (mpfr_prec_t p0, mpfr_prec_t p1)
29 {
30 mpfr_t x, y, z;
31 int i, inex, inex_ref;
32
33 mpfr_init (x);
34 mpfr_init (y);
35 mpfr_init2 (z, p1 + 10);
36 mpfr_const_log2 (z, MPFR_RNDN);
37 mpfr_clear_cache (__gmpfr_cache_const_log2);
38
39 for (; p0 <= p1; p0++)
40 {
41 mpfr_set_prec (x, p0);
42 mpfr_set_prec (y, p0);
43 RND_LOOP_NO_RNDF (i)
44 {
45 mpfr_rnd_t rnd = (mpfr_rnd_t) i;
46 inex = mpfr_const_log2 (x, rnd);
47 inex_ref = mpfr_set (y, z, rnd);
48 if (! mpfr_can_round (z, mpfr_get_prec (z), MPFR_RNDN, rnd, p0))
49 {
50 printf ("increase guard precision in check()\n");
51 exit (1);
52 }
53 if (mpfr_cmp (x, y) || inex != inex_ref)
54 {
55 printf ("mpfr_const_log2 fails for prec=%u, rnd=%s\n",
56 (unsigned int) p0, mpfr_print_rnd_mode (rnd));
57 printf ("expected "), mpfr_dump (y);
58 printf ("got "), mpfr_dump (x);
59 printf ("expected inex = %d\n", inex_ref);
60 printf ("got inex = %d\n", inex);
61 exit (1);
62 }
63 }
64 }
65
66 mpfr_clear (x);
67 mpfr_clear (y);
68 mpfr_clear (z);
69 }
70
71 static void
check_large(void)72 check_large (void)
73 {
74 mpfr_t x, y, z;
75
76 mpfr_init2 (x, 25000);
77 mpfr_init2 (y, 26000);
78 mpfr_init2 (z, 26000);
79 (mpfr_const_log2) (x, MPFR_RNDN); /* First one ! */
80 (mpfr_const_log2) (y, MPFR_RNDN); /* Then the other - cache - */
81 mpfr_set (z, y, MPFR_RNDN);
82 mpfr_prec_round (y, 25000, MPFR_RNDN);
83 if (mpfr_cmp (x, y) != 0)
84 {
85 printf ("const_log2: error for large prec\n");
86 printf ("x = ");
87 mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN);
88 printf ("\n");
89 printf ("y = ");
90 mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
91 printf ("\n");
92 printf ("z = ");
93 mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
94 printf ("\n");
95 exit (1);
96 }
97
98 /* worst-case with 15 successive ones after last bit,
99 to exercise can_round loop */
100 mpfr_set_prec (x, 26249);
101 mpfr_const_log2 (x, MPFR_RNDZ);
102
103 mpfr_clears (x, y, z, (mpfr_ptr) 0);
104 }
105
106 static void
check_cache(void)107 check_cache (void)
108 {
109 mpfr_t x;
110 int i;
111
112 mpfr_init2 (x, 195);
113 mpfr_free_cache ();
114 i = mpfr_const_log2 (x, MPFR_RNDN);
115 if (i == 0)
116 {
117 printf("Error for log2. Invalid ternary value (1).\n");
118 exit (1);
119 }
120 mpfr_set_prec (x, 194);
121 i = mpfr_const_log2 (x, MPFR_RNDN);
122 if (i == 0)
123 {
124 printf("Error for log2. Invalid ternary value (2).\n");
125 exit (1);
126 }
127
128 mpfr_free_cache ();
129 mpfr_set_prec (x, 9);
130 mpfr_const_log2 (x, MPFR_RNDN);
131 mpfr_set_prec (x, 8);
132 mpfr_const_log2 (x, MPFR_RNDN);
133 if (mpfr_cmp_str (x, "0.10110001E0", 2, MPFR_RNDN))
134 {
135 printf("Error for log2. Wrong rounding.\n");
136 exit (1);
137 }
138
139 mpfr_clear (x);
140 }
141
142 /* Wrapper for tgeneric */
143 static int
my_const_log2(mpfr_ptr x,mpfr_srcptr y,mpfr_rnd_t r)144 my_const_log2 (mpfr_ptr x, mpfr_srcptr y, mpfr_rnd_t r)
145 {
146 return mpfr_const_log2 (x, r);
147 }
148
149 #define RAND_FUNCTION(x) mpfr_set_ui ((x), 0, MPFR_RNDN)
150 #define TEST_FUNCTION my_const_log2
151 #include "tgeneric.c"
152
153 static void
exercise_Ziv(void)154 exercise_Ziv (void)
155 {
156 mpfr_t x, y;
157 int inex;
158
159 mpfr_init2 (x, 92);
160 mpfr_init2 (y, 92);
161 inex = mpfr_const_log2 (x, MPFR_RNDN);
162 mpfr_set_str_binary (y, "0.1011000101110010000101111111011111010001110011110111100110101011110010011110001110110011101");
163 MPFR_ASSERTN(mpfr_equal_p (x, y));
164 MPFR_ASSERTN(inex > 0);
165 mpfr_clear (x);
166 mpfr_clear (y);
167 }
168
169 int
main(int argc,char * argv[])170 main (int argc, char *argv[])
171 {
172 mpfr_t x;
173 int p;
174 mpfr_rnd_t rnd;
175
176 tests_start_mpfr ();
177
178 p = (argc>1) ? atoi(argv[1]) : 53;
179 rnd = (argc>2) ? (mpfr_rnd_t) atoi(argv[2]) : MPFR_RNDN;
180
181 mpfr_init (x);
182
183 /* increase the 2nd argument to say 300000 to perform the exhaustive search
184 in src/const_log2.c */
185 check (MPFR_PREC_MIN, 1000);
186
187 /* check precision of 2 bits */
188 mpfr_set_prec (x, 2);
189 mpfr_const_log2 (x, MPFR_RNDN);
190 if (mpfr_cmp_ui_2exp(x, 3, -2)) /* 3*2^-2 */
191 {
192 printf ("mpfr_const_log2 failed for prec=2, rnd=MPFR_RNDN\n"
193 "expected 0.75, got ");
194 mpfr_out_str(stdout, 10, 0, x, MPFR_RNDN);
195 putchar('\n');
196 exit (1);
197 }
198
199 if (argc >= 2)
200 {
201 mpfr_set_prec (x, p);
202 mpfr_const_log2 (x, rnd);
203 mpfr_out_str (stdout, 10, 0, x, rnd);
204 puts ("");
205 }
206
207 exercise_Ziv ();
208
209 mpfr_set_prec (x, 53);
210 mpfr_const_log2 (x, MPFR_RNDZ);
211 if (mpfr_cmp_str1 (x, "6.9314718055994530941e-1") )
212 {
213 printf ("mpfr_const_log2 failed for prec=53\n");
214 exit (1);
215 }
216
217 mpfr_set_prec (x, 32);
218 mpfr_const_log2 (x, MPFR_RNDN);
219 if (mpfr_cmp_str1 (x, "0.69314718060195446"))
220 {
221 printf ("mpfr_const_log2 failed for prec=32\n");
222 exit (1);
223 }
224
225 mpfr_clear (x);
226
227 check_large ();
228 check_cache ();
229
230 test_generic (MPFR_PREC_MIN, 200, 1);
231
232 tests_end_mpfr ();
233 return 0;
234 }
235