xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tlog10.c (revision ec6772edaf0cdcb5f52a48f4aca5e33a8fb8ecfd)
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