lib/msun: avoid referring to broken LDBL_MAX

LDBL_MAX is broken on i386:
https://lists.freebsd.org/pipermail/freebsd-numerics/2012-September/000288.html

Gcc has produced +Infinity for LDBL_MAX on i386 and amd64 with -m32
for some time, and newer versions of gcc are now warning that the
"floating constant exceeds range of 'long double'".  Avoid this by
referring to proxy values instead.

Reviewed by:	bde
Approved by:	markj (mentor)
Sponsored by:	Dell EMC Isilon
This commit is contained in:
Ryan Libby 2017-08-29 22:32:29 +00:00
parent 3c3d2ba6fe
commit cf551d94ef
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=323003
3 changed files with 23 additions and 5 deletions

View File

@ -469,8 +469,13 @@ clog_for_large_values(double complex z)
/* /*
* Avoid overflow in hypot() when x and y are both very large. * Avoid overflow in hypot() when x and y are both very large.
* Divide x and y by E, and then add 1 to the logarithm. This depends * Divide x and y by E, and then add 1 to the logarithm. This
* on E being larger than sqrt(2). * depends on E being larger than sqrt(2), since the return value of
* hypot cannot overflow if neither argument is greater in magnitude
* than 1/sqrt(2) of the maximum value of the return type. Likewise
* this determines the necessary threshold for using this method
* (however, actually use 1/2 instead as it is simpler).
*
* Dividing by E causes an insignificant loss of accuracy; however * Dividing by E causes an insignificant loss of accuracy; however
* this method is still poor since it is uneccessarily slow. * this method is still poor since it is uneccessarily slow.
*/ */

View File

@ -57,10 +57,15 @@ __FBSDID("$FreeBSD$");
#undef signbit #undef signbit
#define signbit(x) (__builtin_signbitl(x)) #define signbit(x) (__builtin_signbitl(x))
#if LDBL_MAX_EXP != 0x4000
#error "Unsupported long double format"
#endif
static const long double static const long double
A_crossover = 10, A_crossover = 10,
B_crossover = 0.6417, B_crossover = 0.6417,
FOUR_SQRT_MIN = 0x1p-8189L, FOUR_SQRT_MIN = 0x1p-8189L,
HALF_MAX = 0x1p16383L,
QUARTER_SQRT_MAX = 0x1p8189L, QUARTER_SQRT_MAX = 0x1p8189L,
RECIP_EPSILON = 1 / LDBL_EPSILON, RECIP_EPSILON = 1 / LDBL_EPSILON,
SQRT_MIN = 0x1p-8191L; SQRT_MIN = 0x1p-8191L;
@ -307,7 +312,7 @@ clog_for_large_values(long double complex z)
ay = t; ay = t;
} }
if (ax > LDBL_MAX / 2) if (ax > HALF_MAX)
return (CMPLXL(logl(hypotl(x / m_e, y / m_e)) + 1, return (CMPLXL(logl(hypotl(x / m_e, y / m_e)) + 1,
atan2l(y, x))); atan2l(y, x)));

View File

@ -42,8 +42,16 @@ __FBSDID("$FreeBSD$");
*/ */
#pragma STDC CX_LIMITED_RANGE ON #pragma STDC CX_LIMITED_RANGE ON
/* We risk spurious overflow for components >= LDBL_MAX / (1 + sqrt(2)). */ /*
#define THRESH (LDBL_MAX / 2.414213562373095048801688724209698L) * We risk spurious overflow for components >= LDBL_MAX / (1 + sqrt(2)).
* Rather than determining the fully precise value at which we might
* overflow, just use a threshold of approximately LDBL_MAX / 4.
*/
#if LDBL_MAX_EXP != 0x4000
#error "Unsupported long double format"
#else
#define THRESH 0x1p16382L
#endif
long double complex long double complex
csqrtl(long double complex z) csqrtl(long double complex z)