xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/mpfr-test.h (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* auxiliary functions for MPFR tests.
2 
3 Copyright 1999-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 #ifndef __MPFR_TEST_H__
24 #define __MPFR_TEST_H__
25 
26 /* Include config.h before using ANY configure macros if needed. */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 /* The no assertion request doesn't apply to the tests */
32 #if defined(MPFR_WANT_ASSERT)
33 # if MPFR_WANT_ASSERT < 0
34 #  undef MPFR_WANT_ASSERT
35 # endif
36 #endif
37 
38 #include "mpfr-impl.h"
39 
40 /* Avoid a GCC bug on Sparc, at least when using TLS. The MPFR library
41  * itself is not affected, only a particular test. Normal code using
42  * the MPFR library should not be affected either, as the bug occurs
43  * when accessing __gmpfr_flags directly (and the public mpfr.h header
44  * file does not provide any macro that accesses an internal variable
45  * directly). So a workaround for the tests is the best solution.
46  *
47  * This bug, which could be observed under Debian with GCC 4.5.3 and
48  * sparc-sun-solaris2.10 with GCC 5.5.0 when TLS and optimizations
49  * are used[*], makes test programs using bad_cases() crash (SIGSEGV)
50  * in this function at:
51  *
52  *   if (mpfr_nanflag_p () || mpfr_overflow_p () || mpfr_underflow_p ())
53  *
54  * Debugging shows that any attempt to access __gmpfr_flags directly
55  * in the loop makes the program crash at this moment. This bug is not
56  * present in the assembly code generated by -S, but is visible after a
57  * normal compilation + link, when tracing the assembly code with gdb.
58  * The workaround is to disable the macros from mpfr-impl.h that access
59  * __gmpfr_flags directly. This bug may have been fixed in more recent
60  * GCC versions, but it is safe to enable this workaround in all GCC
61  * versions.
62  *
63  * [*] This is the default. Disabling TLS or recompiling the tests
64  * without optimizations (-O0) makes the crash disappear.
65  *
66  * Mentions of these crashes:
67  *   https://sympa.inria.fr/sympa/arc/mpfr/2011-10/msg00045.html [Debian]
68  *   https://sympa.inria.fr/sympa/arc/mpfr/2011-10/msg00055.html [Debian]
69  *   https://sympa.inria.fr/sympa/arc/mpfr/2011-12/msg00000.html [Solaris 10]
70  *   https://sympa.inria.fr/sympa/arc/mpfr/2011-12/msg00001.html [Solaris 10]
71  *   https://sympa.inria.fr/sympa/arc/mpfr/2011-12/msg00002.html
72  *   https://sympa.inria.fr/sympa/arc/mpfr/2016-03/msg00061.html [Solaris 10]
73  *   https://sympa.inria.fr/sympa/arc/mpfr/2016-03/msg00063.html
74  *   https://sympa.inria.fr/sympa/arc/mpfr/2020-06/msg00015.html [Solaris 10]
75  *   https://sympa.inria.fr/sympa/arc/mpfr/2020-06/msg00020.html
76  */
77 #if defined(__GNUC__) && defined (__sparc__)
78 # undef mpfr_underflow_p
79 # undef mpfr_overflow_p
80 # undef mpfr_nanflag_p
81 # undef mpfr_inexflag_p
82 # undef mpfr_erangeflag_p
83 # undef mpfr_divby0_p
84 #endif
85 
86 #ifdef MPFR_TESTS_ABORT
87 # undef exit
88 # define exit(C) ((C) != 1 ? (exit)(C) : \
89                   (fflush (stdout), fflush (stderr), abort ()))
90 #endif
91 
92 #define STRINGIZE(S) #S
93 #define MAKE_STR(S) STRINGIZE(S)
94 
95 /* In C (but not C++), mpfr_ptr and mpfr_srcptr arguments can be provided
96    in a different pointer type, such as void *. For functions implemented
97    as macros, the type conversion for the function parameters will not be
98    done by the compiler, which means potential bugs in these implementations
99    if we forget to take these unusual cases into account. So we need to test
100    such arguments, in order to make sure that the arguments are converted to
101    the expected type when needed.
102 
103    However, at least when the function is not implemented as a macro (which
104    is the case when MPFR_USE_NO_MACRO is defined), such tests with void *
105    arguments are not valid in C++; therefore, we will not do the cast to
106    void * if the __cplusplus macro is defined. And with GCC 4.6+ compilers
107    (and compatible), we will ignore the -Wc++-compat option around these
108    tests.
109 
110    Note: in the future, inline functions could be used instead of macros,
111    and such tests would become useless (except to detect compiler bugs).
112 */
113 #if defined (__cplusplus)
114 #define VOIDP_CAST(X) (X)
115 #else
116 #define VOIDP_CAST(X) ((void *) (X))
117 /* Define IGNORE_CPP_COMPAT only for the GCC and Clang versions that
118    support it.
119    Note: GCC versions < 4.6 do not allow "#pragma GCC diagnostic" inside
120    functions, and Clang on Windows (clang-cl) does not define __GNUC__.
121    See https://sympa.inria.fr/sympa/arc/mpfr/2022-12/msg00007.html */
122 #if __MPFR_GNUC(4,6) || defined (__clang__)
123 #define IGNORE_CPP_COMPAT
124 #endif
125 #endif
126 
127 #if defined (__cplusplus)
128 extern "C" {
129 #endif
130 
131 /* generates a random long int, a random double,
132    and corresponding seed initializing */
133 #define DBL_RAND() ((double) randlimb() / (double) MPFR_LIMB_MAX)
134 
135 #define MINNORM 2.2250738585072013831e-308 /* 2^(-1022), smallest normalized */
136 #define MAXNORM 1.7976931348623157081e308 /* 2^(1023)*(2-2^(-52)) */
137 
138 /* Generates a random rounding mode */
139 #define RND_RAND() ((mpfr_rnd_t) (randlimb() % MPFR_RND_MAX))
140 
141 /* Ditto, excluding RNDF, assumed to be the last rounding mode */
142 #define RND_RAND_NO_RNDF() ((mpfr_rnd_t) (randlimb() % MPFR_RNDF))
143 
144 /* Generates a random boolean (with type int, thanks to the "!= 0" test).
145    Note: "& 1" is better than "% 2" for compilers with limited optimization,
146    such as tcc 0.9.27. */
147 #define RAND_BOOL() ((randlimb() & 1) != 0)
148 
149 /* Generates a random sign */
150 #define RAND_SIGN() (RAND_BOOL() ? MPFR_SIGN_POS : MPFR_SIGN_NEG)
151 
152 /* Loop for all rounding modes */
153 #define RND_LOOP(_r) for((_r) = 0 ; (_r) < MPFR_RND_MAX ; (_r)++)
154 
155 /* Loop for all rounding modes except RNDF (assumed to be the last one),
156    which must be excluded from tests that rely on deterministic results. */
157 #define RND_LOOP_NO_RNDF(_r) for((_r) = 0 ; (_r) < MPFR_RNDF ; (_r)++)
158 
159 /* Test whether two floating-point data have the same value,
160    seen as an element of the set of the floating-point data
161    (Level 2 in the IEEE 754-2008 standard). */
162 #define SAME_VAL(X,Y)                                                   \
163   ((MPFR_IS_NAN (X) && MPFR_IS_NAN (Y)) ||                              \
164    (mpfr_equal_p ((X), (Y)) && MPFR_INT_SIGN (X) == MPFR_INT_SIGN (Y)))
165 
166 /* In the tests, mpfr_sgn was sometimes used incorrectly, for instance:
167  *
168  *   if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0)
169  *
170  * to check that y is +0. This does not make sense since on 0, mpfr_sgn
171  * yields 0, so that -0 would not be detected as an error. To make sure
172  * that mpfr_sgn is not used incorrectly, we choose to fail when this
173  * macro is used on a datum whose mathematical sign is not +1 or -1.
174  * This feature is disabled when MPFR_TESTS_TSGN is defined, typically
175  * in tsgn (to test mpfr_sgn itself).
176  */
177 #ifndef MPFR_TESTS_TSGN
178 # undef mpfr_sgn
179 # define mpfr_sgn(x)                   \
180   (MPFR_ASSERTN (! MPFR_IS_NAN (x)),   \
181    MPFR_ASSERTN (! MPFR_IS_ZERO (x)),  \
182    MPFR_SIGN (x))
183 #endif
184 
185 #define FLIST mpfr_ptr, mpfr_srcptr, mpfr_rnd_t
186 
187 int test_version (void);
188 
189 /* Memory handling */
190 #define DEFAULT_MEMORY_LIMIT (1UL << 22)
191 extern size_t tests_memory_limit;
192 void tests_memory_start (void);
193 void tests_memory_end (void);
194 
195 void tests_start_mpfr (void);
196 void tests_end_mpfr (void);
197 
198 void tests_expect_abort (void);
199 int tests_run_within_valgrind (void);
200 
201 int mpfr_set_machine_rnd_mode (mpfr_rnd_t);
202 int have_subnorm_dbl (void);
203 int have_subnorm_flt (void);
204 void mpfr_test_init (void);
205 mp_limb_t randlimb (void);
206 unsigned long randulong (void);
207 long randlong (void);
208 void randseed (unsigned int);
209 void mpfr_random2 (mpfr_ptr, mp_size_t, mpfr_exp_t, gmp_randstate_t);
210 int ulp (double, double);
211 double dbl (double, int);
212 double Ulp (double);
213 int Isnan (double);
214 void d_trace (const char *, double);
215 void ld_trace (const char *, long double);
216 void n_trace (const char *, mp_limb_t *, mp_size_t);
217 
218 FILE *src_fopen (const char *, const char *);
219 void set_emin (mpfr_exp_t);
220 void set_emax (mpfr_exp_t);
221 void tests_default_random (mpfr_ptr, int, mpfr_exp_t, mpfr_exp_t,
222                            int);
223 void data_check (const char *, int (*) (FLIST), const char *);
224 void bad_cases (int (*)(FLIST), int (*)(FLIST),
225                 const char *, int, mpfr_exp_t, mpfr_exp_t,
226                 mpfr_prec_t, mpfr_prec_t, mpfr_prec_t, int);
227 void flags_out (unsigned int);
228 
229 int mpfr_cmp_str (mpfr_srcptr x, const char *, int, mpfr_rnd_t);
230 #define mpfr_cmp_str1(x,s) mpfr_cmp_str(x,s,10,MPFR_RNDN)
231 #define mpfr_set_str1(x,s) mpfr_set_str(x,s,10,MPFR_RNDN)
232 
233 #define mpfr_cmp0(x,y) (MPFR_ASSERTN (!MPFR_IS_NAN (x) && !MPFR_IS_NAN (y)), mpfr_cmp (x,y))
234 #define mpfr_cmp_ui0(x,i) (MPFR_ASSERTN (!MPFR_IS_NAN (x)), mpfr_cmp_ui (x,i))
235 #define mpfr_cmp_si0(x,i) (MPFR_ASSERTN (!MPFR_IS_NAN (x)), mpfr_cmp_si (x,i))
236 #define mpfr_cmp_si_2exp0(x,i,e) (MPFR_ASSERTN (!MPFR_IS_NAN (x)), \
237                                   mpfr_cmp_si_2exp (x,i,e))
238 
239 /* define CHECK_EXTERNAL if you want to check mpfr against another library
240    with correct rounding. You'll probably have to modify mpfr_print_raw()
241    and/or test_add() below:
242    * mpfr_print_raw() prints each number as "p m e" where p is the precision,
243      m the mantissa (as a binary integer with sign), and e the exponent.
244      The corresponding number is m*2^e. Example: "2 10 -6" represents
245      2*2^(-6) with a precision of 2 bits.
246    * test_add() outputs "b c a" on one line, for each addition a <- b + c.
247      Currently it only prints such a line for rounding to nearest, when
248      the inputs b and c are not NaN and/or Inf.
249 */
250 #ifdef CHECK_EXTERNAL
251 static void
mpfr_print_raw(mpfr_srcptr x)252 mpfr_print_raw (mpfr_srcptr x)
253 {
254   printf ("%lu ", MPFR_PREC (x));
255   if (MPFR_IS_NAN (x))
256     {
257       printf ("@NaN@");
258       return;
259     }
260 
261   if (MPFR_IS_NEG (x))
262     printf ("-");
263 
264   if (MPFR_IS_INF (x))
265     printf ("@Inf@");
266   else if (MPFR_IS_ZERO (x))
267     printf ("0 0");
268   else
269     {
270       mp_limb_t *mx;
271       mpfr_prec_t px;
272       mp_size_t n;
273 
274       mx = MPFR_MANT (x);
275       px = MPFR_PREC (x);
276 
277       for (n = (px - 1) / GMP_NUMB_BITS; ; n--)
278         {
279           mp_limb_t wd, t;
280 
281           MPFR_ASSERTN (n >= 0);
282           wd = mx[n];
283           for (t = MPFR_LIMB_HIGHBIT; t != 0; t >>= 1)
284             {
285               printf ((wd & t) == 0 ? "0" : "1");
286               if (--px == 0)
287                 {
288                   mpfr_exp_t ex;
289 
290                   ex = MPFR_GET_EXP (x);
291                   MPFR_ASSERTN (ex >= LONG_MIN && ex <= LONG_MAX);
292                   printf (" %ld", (long) ex - (long) MPFR_PREC (x));
293                   return;
294                 }
295             }
296         }
297     }
298 }
299 #endif
300 
301 extern char *locale;
302 
303 /* Random */
304 extern char             mpfr_rands_initialized;
305 extern gmp_randstate_t  mpfr_rands;
306 
307 #undef RANDS
308 #define RANDS                                   \
309   ((mpfr_rands_initialized ? 0                 \
310     : (mpfr_rands_initialized = 1,             \
311        gmp_randinit_default (mpfr_rands), 0)), \
312    mpfr_rands)
313 
314 #undef RANDS_CLEAR
315 #define RANDS_CLEAR()                   \
316   do {                                  \
317     if (mpfr_rands_initialized)        \
318       {                                 \
319         mpfr_rands_initialized = 0;    \
320         gmp_randclear (mpfr_rands);    \
321       }                                 \
322   } while (0)
323 
324 /* Memory Allocation */
325 extern int tests_memory_disabled;
326 void *tests_allocate (size_t);
327 void *tests_reallocate (void *, size_t, size_t);
328 void tests_free (void *, size_t);
329 
330 #if defined (__cplusplus)
331 }
332 #endif
333 
334 /* With GCC, a macro "volatile" can be defined to test some special code
335    in mpfr-impl.h (code for compilers that define such a macro), but the
336    volatile keyword is necessary in some tests to avoid some GCC bugs.
337    Thus we need to undef this macro (if defined). We do that at the end,
338    so that mpfr-impl.h (included earlier) is not affected by this undef.
339  */
340 #if defined(__GNUC__) && defined(volatile)
341 # undef volatile
342 #endif
343 
344 #endif
345