1 /* Test file for mpfr_log10.
2
3 Copyright 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 #ifdef CHECK_EXTERNAL
26 static int
test_log10(mpfr_ptr a,mpfr_srcptr b,mpfr_rnd_t rnd_mode)27 test_log10 (mpfr_ptr a, mpfr_srcptr b, mpfr_rnd_t rnd_mode)
28 {
29 int res;
30 int ok = rnd_mode == MPFR_RNDN && mpfr_number_p (b) && mpfr_get_prec (a)>=53;
31 if (ok)
32 {
33 mpfr_print_raw (b);
34 }
35 res = mpfr_log10 (a, b, rnd_mode);
36 if (ok)
37 {
38 printf (" ");
39 mpfr_print_raw (a);
40 printf ("\n");
41 }
42 return res;
43 }
44 #else
45 #define test_log10 mpfr_log10
46 #endif
47
48 #define TEST_FUNCTION test_log10
49 #define TEST_RANDOM_POS 8
50 #include "tgeneric.c"
51
52 /* On 2023-02-13, one gets an infinite loop in mpfr_log10 on both
53 32-bit and 64-bit hosts when the precision is not large enough
54 (precision 12 and below). */
55 static void
bug20230213(void)56 bug20230213 (void)
57 {
58 mpfr_exp_t old_emin, old_emax, e;
59 mpfr_t t, x, y0, y1, y2;
60 int prec;
61
62 old_emin = mpfr_get_emin ();
63 old_emax = mpfr_get_emax ();
64
65 set_emin (MPFR_EMIN_MIN);
66 set_emax (MPFR_EMAX_MAX);
67 e = mpfr_get_emax () - 1;
68
69 /* The precisions of t and y0 should be large enough to avoid
70 a hard-to-round case for the target precisions. */
71 mpfr_inits2 (64, t, y0, (mpfr_ptr) 0);
72 mpfr_set_exp_t (y0, e, MPFR_RNDN);
73 mpfr_log_ui (t, 10, MPFR_RNDN);
74 mpfr_div (y0, y0, t, MPFR_RNDN);
75 mpfr_log_ui (t, 2, MPFR_RNDN);
76 mpfr_mul (y0, y0, t, MPFR_RNDN);
77
78 for (prec = 16; prec >= MPFR_PREC_MIN; prec--)
79 {
80 mpfr_inits2 (prec, x, y1, y2, (mpfr_ptr) 0);
81 mpfr_set (y1, y0, MPFR_RNDN);
82
83 mpfr_set_ui_2exp (x, 1, e, MPFR_RNDN);
84 mpfr_log10 (y2, x, MPFR_RNDN);
85 MPFR_ASSERTN (MPFR_IS_PURE_FP (y2));
86 MPFR_ASSERTN (MPFR_IS_POS (y2));
87
88 if (! mpfr_equal_p (y1, y2))
89 {
90 printf ("Error in bug20230213.\n");
91 printf ("Expected ");
92 mpfr_dump (y1);
93 printf ("Got ");
94 mpfr_dump (y2);
95 exit (1);
96 }
97 mpfr_clears (x, y1, y2, (mpfr_ptr) 0);
98 }
99
100 mpfr_clears (t, y0, (mpfr_ptr) 0);
101
102 set_emin (old_emin);
103 set_emax (old_emax);
104 }
105
106 int
main(int argc,char * argv[])107 main (int argc, char *argv[])
108 {
109 mpfr_t x, y;
110 unsigned int n;
111 int inex, r;
112
113 tests_start_mpfr ();
114
115 test_generic (MPFR_PREC_MIN, 100, 20);
116
117 mpfr_init2 (x, 53);
118 mpfr_init2 (y, 53);
119
120 RND_LOOP (r)
121 {
122 /* check NaN */
123 mpfr_set_nan (x);
124 inex = test_log10 (y, x, (mpfr_rnd_t) r);
125 MPFR_ASSERTN (mpfr_nan_p (y) && inex == 0);
126
127 /* check Inf */
128 mpfr_set_inf (x, -1);
129 inex = test_log10 (y, x, (mpfr_rnd_t) r);
130 MPFR_ASSERTN (mpfr_nan_p (y) && inex == 0);
131
132 mpfr_set_inf (x, 1);
133 inex = test_log10 (y, x, (mpfr_rnd_t) r);
134 MPFR_ASSERTN (mpfr_inf_p (y) && mpfr_sgn (y) > 0 && inex == 0);
135
136 mpfr_set_ui (x, 0, MPFR_RNDN);
137 inex = test_log10 (x, x, (mpfr_rnd_t) r);
138 MPFR_ASSERTN (mpfr_inf_p (x) && mpfr_sgn (x) < 0 && inex == 0);
139 mpfr_set_ui (x, 0, MPFR_RNDN);
140 mpfr_neg (x, x, MPFR_RNDN);
141 inex = test_log10 (x, x, (mpfr_rnd_t) r);
142 MPFR_ASSERTN (mpfr_inf_p (x) && mpfr_sgn (x) < 0 && inex == 0);
143
144 /* check negative argument */
145 mpfr_set_si (x, -1, MPFR_RNDN);
146 inex = test_log10 (y, x, (mpfr_rnd_t) r);
147 MPFR_ASSERTN (mpfr_nan_p (y) && inex == 0);
148
149 /* check log10(1) = 0 */
150 mpfr_set_ui (x, 1, MPFR_RNDN);
151 inex = test_log10 (y, x, (mpfr_rnd_t) r);
152 MPFR_ASSERTN (MPFR_IS_ZERO (y) && MPFR_IS_POS (y) && inex == 0);
153
154 /* check log10(10^n)=n */
155 mpfr_set_ui (x, 1, MPFR_RNDN);
156 for (n = 1; n <= 15; n++)
157 {
158 mpfr_mul_ui (x, x, 10, MPFR_RNDN); /* x = 10^n */
159 inex = test_log10 (y, x, (mpfr_rnd_t) r);
160 if (mpfr_cmp_ui (y, n))
161 {
162 printf ("log10(10^n) <> n for n=%u\n", n);
163 exit (1);
164 }
165 MPFR_ASSERTN (inex == 0);
166 }
167 }
168
169 mpfr_clear (x);
170 mpfr_clear (y);
171
172 bug20230213 ();
173
174 data_check ("data/log10", mpfr_log10, "mpfr_log10");
175 bad_cases (mpfr_log10, mpfr_exp10, "mpfr_log10",
176 256, -30, 30, 4, 128, 800, 50);
177
178 tests_end_mpfr ();
179 return 0;
180 }
181