2 dnl Copyright (C) 2011-2020 Free Software Foundation, Inc.
3 dnl This file is free software; the Free Software Foundation
4 dnl gives unlimited permission to copy and/or distribute it,
5 dnl with or without modifications, as long as this notice is preserved.
7 AC_DEFUN([gl_FUNC_FMAL],
9 AC_REQUIRE([gl_MATH_H_DEFAULTS])
10 AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE])
12 dnl Persuade glibc <math.h> to declare fmal().
13 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
15 dnl Determine FMAL_LIBM.
16 gl_MATHFUNC([fmal], [long double], [(long double, long double, long double)],
21 long double fmal (long double, long double, long double);
23 if test $gl_cv_func_fmal_no_libm = yes \
24 || test $gl_cv_func_fmal_in_libm = yes; then
25 dnl Also check whether it's declared.
26 dnl IRIX 6.5 has fmal() in libm but doesn't declare it in <math.h>,
27 dnl and the function is buggy.
28 AC_CHECK_DECL([fmal], , [REPLACE_FMAL=1], [[#include <math.h>]])
29 if test $REPLACE_FMAL = 0; then
31 case "$gl_cv_func_fmal_works" in
32 *no) REPLACE_FMAL=1 ;;
38 if test $HAVE_FMAL = 0 || test $REPLACE_FMAL = 1; then
39 dnl Find libraries needed to link lib/fmal.c.
40 if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then
41 AC_REQUIRE([gl_FUNC_FMA])
44 AC_REQUIRE([gl_FUNC_FREXPL])
45 AC_REQUIRE([gl_FUNC_LDEXPL])
46 AC_REQUIRE([gl_FUNC_FEGETROUND])
48 dnl Append $FREXPL_LIBM to FMAL_LIBM, avoiding gratuitous duplicates.
49 case " $FMAL_LIBM " in
50 *" $FREXPL_LIBM "*) ;;
51 *) FMAL_LIBM="$FMAL_LIBM $FREXPL_LIBM" ;;
53 dnl Append $LDEXPL_LIBM to FMAL_LIBM, avoiding gratuitous duplicates.
54 case " $FMAL_LIBM " in
55 *" $LDEXPL_LIBM "*) ;;
56 *) FMAL_LIBM="$FMAL_LIBM $LDEXPL_LIBM" ;;
58 dnl Append $FEGETROUND_LIBM to FMAL_LIBM, avoiding gratuitous duplicates.
59 case " $FMAL_LIBM " in
60 *" $FEGETROUND_LIBM "*) ;;
61 *) FMAL_LIBM="$FMAL_LIBM $FEGETROUND_LIBM" ;;
68 dnl Test whether fmal() has any of the 15 known bugs of glibc 2.11.3 on x86_64.
69 AC_DEFUN([gl_FUNC_FMAL_WORKS],
71 AC_REQUIRE([AC_PROG_CC])
72 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
73 AC_REQUIRE([gl_FUNC_LDEXPL])
75 LIBS="$LIBS $FMAL_LIBM $LDEXPL_LIBM"
76 AC_CACHE_CHECK([whether fmal works], [gl_cv_func_fmal_works],
82 /* Override the values of <float.h>, like done in float.in.h. */
83 #if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
85 # define LDBL_MANT_DIG 64
87 # define LDBL_MIN_EXP (-16381)
89 # define LDBL_MAX_EXP 16384
91 #if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
93 # define LDBL_MANT_DIG 64
95 # define LDBL_MIN_EXP (-16381)
97 # define LDBL_MAX_EXP 16384
99 #if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__
101 # define LDBL_MIN_EXP DBL_MIN_EXP
103 #if defined __sgi && (LDBL_MANT_DIG >= 106)
104 # undef LDBL_MANT_DIG
105 # define LDBL_MANT_DIG 106
106 # if defined __GNUC__
108 # define LDBL_MIN_EXP DBL_MIN_EXP
111 long double p0 = 0.0L;
114 int failed_tests = 0;
115 /* This test fails on glibc 2.11 powerpc. */
117 volatile long double x = 1.5L; /* 3 * 2^-1 */
118 volatile long double y = x;
119 volatile long double z = ldexpl (1.0L, LDBL_MANT_DIG + 1); /* 2^65 */
120 /* x * y + z with infinite precision: 2^65 + 9 * 2^-2.
121 Lies between (2^63 + 0) * 2^2 and (2^63 + 1) * 2^2
122 and is closer to (2^63 + 1) * 2^2, therefore the rounding
123 must round up and produce (2^63 + 1) * 2^2. */
124 volatile long double expected = z + 4.0L;
125 volatile long double result = fmal (x, y, z);
126 if (result != expected)
129 /* This test fails on glibc 2.11 powerpc. */
131 volatile long double x = 1.25L; /* 2^0 + 2^-2 */
132 volatile long double y = - x;
133 volatile long double z = ldexpl (1.0L, LDBL_MANT_DIG + 1); /* 2^65 */
134 /* x * y + z with infinite precision: 2^65 - 2^0 - 2^-1 - 2^-4.
135 Lies between (2^64 - 1) * 2^1 and 2^64 * 2^1
136 and is closer to (2^64 - 1) * 2^1, therefore the rounding
137 must round down and produce (2^64 - 1) * 2^1. */
138 volatile long double expected = (ldexpl (1.0L, LDBL_MANT_DIG) - 1.0L) * 2.0L;
139 volatile long double result = fmal (x, y, z);
140 if (result != expected)
143 /* This test fails on glibc 2.11 x86,x86_64,powerpc, glibc 2.7 hppa,sparc,
146 volatile long double x = 1.0L + ldexpl (1.0L, 1 - LDBL_MANT_DIG); /* 2^0 + 2^-63 */
147 volatile long double y = x;
148 volatile long double z = 4.0L; /* 2^2 */
149 /* x * y + z with infinite precision: 2^2 + 2^0 + 2^-62 + 2^-126.
150 Lies between (2^63 + 2^61) * 2^-61 and (2^63 + 2^61 + 1) * 2^-61
151 and is closer to (2^63 + 2^61 + 1) * 2^-61, therefore the rounding
152 must round up and produce (2^63 + 2^61 + 1) * 2^-61. */
153 volatile long double expected = 4.0L + 1.0L + ldexpl (1.0L, 3 - LDBL_MANT_DIG);
154 volatile long double result = fmal (x, y, z);
155 if (result != expected)
158 /* This test fails on glibc 2.11 x86,x86_64,powerpc glibc 2.7 hppa,sparc,
161 volatile long double x = 1.0L + ldexpl (1.0L, 1 - LDBL_MANT_DIG); /* 2^0 + 2^-63 */
162 volatile long double y = - x;
163 volatile long double z = 8.0L; /* 2^3 */
164 /* x * y + z with infinite precision: 2^2 + 2^1 + 2^0 - 2^-62 - 2^-126.
165 Lies between (2^63 + 2^62 + 2^61 - 1) * 2^-61 and
166 (2^63 + 2^62 + 2^61) * 2^-61 and is closer to
167 (2^63 + 2^62 + 2^61 - 1) * 2^-61, therefore the rounding
168 must round down and produce (2^63 + 2^62 + 2^61 - 1) * 2^-61. */
169 volatile long double expected = 7.0L - ldexpl (1.0L, 3 - LDBL_MANT_DIG);
170 volatile long double result = fmal (x, y, z);
171 if (result != expected)
174 /* This test fails on glibc 2.11 powerpc. */
176 volatile long double x = 1.25L; /* 2^0 + 2^-2 */
177 volatile long double y = - 0.75L; /* - 2^0 + 2^-2 */
178 volatile long double z = ldexpl (1.0L, LDBL_MANT_DIG); /* 2^64 */
179 /* x * y + z with infinite precision: 2^64 - 2^0 + 2^-4.
180 Lies between (2^64 - 2^0) and 2^64 and is closer to (2^64 - 2^0),
181 therefore the rounding must round down and produce (2^64 - 2^0). */
182 volatile long double expected = ldexpl (1.0L, LDBL_MANT_DIG) - 1.0L;
183 volatile long double result = fmal (x, y, z);
184 if (result != expected)
187 if ((LDBL_MANT_DIG % 2) == 1)
189 /* These tests fail on glibc 2.7 hppa,sparc, OSF/1 5.1. */
191 volatile long double x = 1.0L + ldexpl (1.0L, - (LDBL_MANT_DIG + 1) / 2); /* 2^0 + 2^-27 */
192 volatile long double y = 1.0L - ldexpl (1.0L, - (LDBL_MANT_DIG + 1) / 2); /* 2^0 - 2^-27 */
193 volatile long double z = - ldexpl (1.0L, LDBL_MIN_EXP - LDBL_MANT_DIG); /* - 2^-1074 */
194 /* x * y + z with infinite precision: 2^0 - 2^-54 - 2^-1074.
195 Lies between (2^53 - 1) * 2^-53 and 2^53 * 2^-53 and is closer to
196 (2^53 - 1) * 2^-53, therefore the rounding must round down and
197 produce (2^53 - 1) * 2^-53. */
198 volatile long double expected = 1.0L - ldexpl (1.0L, - LDBL_MANT_DIG);
199 volatile long double result = fmal (x, y, z);
200 if (result != expected)
204 volatile long double x = 1.0L + ldexpl (1.0L, - (LDBL_MANT_DIG + 1) / 2); /* 2^0 + 2^-57 */
205 volatile long double y = x;
206 volatile long double z = ldexpl (1.0L, - LDBL_MANT_DIG); /* 2^-113 */
207 /* x * y + z with infinite precision: 2^0 + 2^-56 + 2^-113 + 2^-114.
208 Lies between (2^112 + 2^56) * 2^-112 and (2^112 + 2^56 + 1) * 2^-112
209 and is closer to (2^112 + 2^56 + 1) * 2^-112, therefore the rounding
210 must round up and produce (2^112 + 2^56 + 1) * 2^-112. */
211 volatile long double expected =
212 1.0L + ldexpl (1.0L, - (LDBL_MANT_DIG - 1) / 2) + ldexpl (1.0L, 1 - LDBL_MANT_DIG);
213 volatile long double result = fmal (x, y, z);
214 if (result != expected)
220 /* These tests fail on glibc 2.11 x86,x86_64,powerpc, mingw. */
222 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2); /* 2^0 + 2^-32 */
223 volatile long double y = x;
224 volatile long double z = ldexpl (1.0L, LDBL_MIN_EXP - LDBL_MANT_DIG); /* 2^-16445 */
225 /* x * y + z with infinite precision: 2^0 + 2^-31 + 2^-64 + 2^-16445.
226 Lies between (2^63 + 2^32 + 0) * 2^-63 and (2^63 + 2^32 + 1) * 2^-63
227 and is closer to (2^63 + 2^32 + 1) * 2^-63, therefore the rounding
228 must round up and produce (2^63 + 2^32 + 1) * 2^-63. */
229 volatile long double expected =
230 1.0L + ldexpl (1.0L, 1 - LDBL_MANT_DIG / 2) + ldexpl (1.0L, 1 - LDBL_MANT_DIG);
231 volatile long double result = fmal (x, y, z);
232 if (result != expected)
236 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2); /* 2^0 + 2^-32 */
237 volatile long double y = x;
238 volatile long double z = ldexpl (1.0L, - LDBL_MANT_DIG); /* 2^-64 */
239 /* x * y + z with infinite precision: 2^0 + 2^-31 + 2^-63.
240 Rounding must return this value unchanged. */
241 volatile long double expected = 1.0L + ldexpl (1.0L, 1 - LDBL_MANT_DIG / 2) + ldexpl (1.0L, 1 - LDBL_MANT_DIG);
242 volatile long double result = fmal (x, y, z);
243 if (result != expected)
247 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2); /* 2^0 + 2^-32 */
248 volatile long double y = x;
249 volatile long double z = ldexpl (1.0L, 1 - LDBL_MANT_DIG); /* 2^-63 */
250 /* x * y + z with infinite precision: 2^0 + 2^-31 + 2^-63 + 2^-64.
251 Lies between (2^63 + 2^32 + 1) * 2^-63 and (2^63 + 2^32 + 2) * 2^-63
252 and is at the same distance from each. According to the round-to-even
253 rule, the rounding must round up and produce (2^63 + 2^32 + 2) * 2^-63. */
254 volatile long double expected = 1.0L + ldexpl (1.0L, -31) + ldexpl (1.0L, -62);
255 volatile long double result = fmal (x, y, z);
256 if (result != expected)
260 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2); /* 2^0 + 2^-32 */
261 volatile long double y = x;
262 volatile long double z = ldexpl (1.0L, LDBL_MANT_DIG / 2 + 1); /* 2^33 */
263 /* x * y + z with infinite precision: 2^33 + 2^0 + 2^-31 + 2^-64.
264 Lies between (2^63 + 2^30) * 2^-30 and (2^63 + 2^30 + 1) * 2^-30
265 and is closer to (2^63 + 2^30 + 1) * 2^-30, therefore the rounding
266 must round up and produce (2^63 + 2^30 + 1) * 2^-30. */
267 volatile long double expected = z + 1.0L + ldexp (1.0L, 2 - LDBL_MANT_DIG / 2);
268 volatile long double result = fmal (x, y, z);
269 if (result != expected)
273 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2); /* 2^0 + 2^-32 */
274 volatile long double y = x;
275 volatile long double z = - ldexpl (1.0, 1 - LDBL_MANT_DIG); /* - 2^-63 */
276 /* x * y + z with infinite precision: 2^0 + 2^-31 - 2^-64.
277 Lies between (2^63 + 2^32 - 1) * 2^-63 and (2^63 + 2^32) * 2^-63
278 and is at the same distance from each. According to the round-to-even
279 rule, the rounding must round up and produce (2^63 + 2^32) * 2^-63. */
280 volatile long double expected = 1.0L + ldexpl (1.0L, 1 - LDBL_MANT_DIG / 2);
281 volatile long double result = fmal (x, y, z);
282 if (result != expected)
286 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2); /* 2^0 + 2^-32 */
287 volatile long double y = x;
288 volatile long double z = - 1.0L; /* - 2^0 */
289 /* x * y + z with infinite precision: 2^-31 + 2^-64.
290 Rounding must return this value unchanged. */
291 volatile long double expected = ldexpl (1.0L, 1 - LDBL_MANT_DIG / 2) + ldexpl (1.0L, - LDBL_MANT_DIG);
292 volatile long double result = fmal (x, y, z);
293 if (result != expected)
297 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2); /* 2^0 + 2^-32 */
298 volatile long double y = - x;
299 volatile long double z = 2.0L; /* 2^1 */
300 /* x * y + z with infinite precision: 2^0 - 2^31 - 2^-64.
301 Rounding must return this value unchanged. */
302 volatile long double expected = 1.0L - ldexpl (1.0L, 1 - LDBL_MANT_DIG / 2) - ldexpl (1.0L, - LDBL_MANT_DIG);
303 volatile long double result = fmal (x, y, z);
304 if (result != expected)
308 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2); /* 2^0 + 2^-32 */
309 volatile long double y = - x;
310 volatile long double z = ldexpl (1.0L, LDBL_MANT_DIG / 2 + 2); /* 2^34 */
311 /* x * y + z with infinite precision: 2^34 - (2^0 + 2^-31 + 2^-64).
312 Lies between (2^64 - 2^30 - 1) * 2^-30 and (2^64 - 2^30) * 2^-30
313 and is closer to (2^64 - 2^30 - 1) * 2^-30, therefore the rounding
314 must round down and produce (2^64 - 2^30 - 1) * 2^-30. */
315 volatile long double expected = z - 1.0L - ldexpl (1.0L, 2 - LDBL_MANT_DIG / 2);
316 volatile long double result = fmal (x, y, z);
317 if (result != expected)
321 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2 - 1); /* 2^0 + 2^-33 */
322 volatile long double y = 1.0L - ldexpl (1.0L, - LDBL_MANT_DIG / 2 - 1); /* 2^0 - 2^-33 */
323 volatile long double z = - ldexpl (1.0L, - LDBL_MANT_DIG - 1); /* 2^-65 */
324 /* x * y + z with infinite precision: 2^0 - 2^-65 - 2^-66.
325 Lies between (2^64 - 1) * 2^-64 and 2^64 * 2^-64 and is closer to
326 (2^64 - 1) * 2^-64, therefore the rounding must round down and
327 produce (2^64 - 1) * 2^-64. */
328 volatile long double expected = 1.0L - ldexpl (1.0L, - LDBL_MANT_DIG);
329 volatile long double result = fmal (x, y, z);
330 if (result != expected)
334 volatile long double x = 1.0L + ldexpl (1.0L, - LDBL_MANT_DIG / 2 - 1); /* 2^0 + 2^-33 */
335 volatile long double y = 1.0L - ldexpl (1.0L, - LDBL_MANT_DIG / 2 - 1); /* 2^0 - 2^-33 */
336 volatile long double z = - 1.0L; /* 2^0 */
337 /* x * y + z with infinite precision: - 2^-66.
338 Rounding must return this value unchanged. */
339 volatile long double expected = - ldexpl (1.0L, - LDBL_MANT_DIG - 2);
340 volatile long double result = fmal (x, y, z);
341 if (result != expected)
345 /* This test fails on glibc 2.11 x86,x86_64,powerpc, glibc 2.7 hppa,sparc,
346 FreeBSD 6.4 x86, mingw. */
348 long double minus_inf = -1.0L / p0;
349 volatile long double x = ldexpl (1.0L, LDBL_MAX_EXP - 1);
350 volatile long double y = ldexpl (1.0L, LDBL_MAX_EXP - 1);
351 volatile long double z = minus_inf;
352 volatile long double result = fmal (x, y, z);
353 if (!(result == minus_inf))
356 /* This test fails on glibc 2.11 x86,x86_64,powerpc glibc 2.7 hppa,sparc,
357 Mac OS X 10.5, FreeBSD 6.4 x86, OSF/1 5.1, mingw. */
359 volatile long double x = ldexpl (1.0L, LDBL_MAX_EXP - 1);
360 volatile long double y = 2.0L;
361 volatile long double z =
362 - ldexpl (ldexpl (1.0L, LDBL_MAX_EXP - 1) - ldexpl (1.0L, LDBL_MAX_EXP - LDBL_MANT_DIG - 1), 1);
363 volatile long double expected = ldexpl (1.0L, LDBL_MAX_EXP - LDBL_MANT_DIG);
364 volatile long double result = fmal (x, y, z);
365 if (result != expected)
370 [gl_cv_func_fmal_works=yes],
371 [gl_cv_func_fmal_works=no],
372 [dnl Guess yes on native Windows with MSVC.
373 dnl Otherwise guess no, even on glibc systems.
374 gl_cv_func_fmal_works="$gl_cross_guess_normal"
377 AC_EGREP_CPP([Known], [
381 ], [gl_cv_func_fmal_works="guessing yes"])
389 # Prerequisites of lib/fmal.c.
390 AC_DEFUN([gl_PREREQ_FMAL], [:])