lib/msun: Fix tgammal(3) on IEEE 128-bit platforms

Undo the 80-bit "stub" implementation of the 128-bit long double
tgammal(3) function. The latest (as of Feb 2024) version of the
src/contrib/arm-optimised-routines library includes a standalone,
full 128-bit replacement. This needs a small bit of wrapping to
fit it in, but is otherwise a drop-in replacement.

Testing this is hard, as most maths packages blow up as soon as
their 80-bit floating-point capability is exceeded. With 128-bit
tgammal(), this is easy to do, and this is the range that needs to
be checked the most carefully. Using my copy of Maple, I was able
to check that the output was within a few ULP of the correct answer,
right up to the point of 128-bit over- and underflow. Additionally,
the results are no worse, and indeed better than the 80-bit version.

Steve Kargl sent me his libm testing code, which I used to verify
that the excpetions for certain key values were correct. Tested in
this case were +-Inf, +-NaN, +-1 and +-0.

Differential Revision:	https://reviews.freebsd.org/D44168
Reviewed by:	theraven, andrew, imp
This commit is contained in:
Mark Murray 2024-03-01 15:53:58 +00:00
parent c547f17816
commit e38f230827
3 changed files with 15 additions and 59 deletions

View File

@ -26,7 +26,7 @@ CFLAGS+= -I${.CURDIR}/x86
CFLAGS+= -I${.CURDIR}/ld80
.elif ${LDBL_PREC} == 113
.PATH: ${.CURDIR}/ld128
CFLAGS+= -I${.CURDIR}/ld128
CFLAGS+= -I${.CURDIR}/ld128 -I${SRCTOP}/contrib/arm-optimized-routines/math
.endif
CFLAGS+= -I${.CURDIR}/${ARCH_SUBDIR}

View File

@ -1,55 +1,12 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2013 David Chisnall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* Copyright (c) 2024 The FreeBSD Foundation
*/
#include <float.h>
#include <math.h>
/*
* If long double is not the same size as double, then these will lose
* precision and we should emit a warning whenever something links against
* them.
* This is a pure C function generously donated by ARM.
* See src/contrib/arm-optimized-routines/math/tgamma128.[ch].
*/
#if (LDBL_MANT_DIG > 53)
#define WARN_IMPRECISE(x) \
__warn_references(x, # x " has lower than advertised precision");
#else
#define WARN_IMPRECISE(x)
#endif
/*
* Declare the functions as weak variants so that other libraries providing
* real versions can override them.
*/
#define DECLARE_WEAK(x)\
__weak_reference(imprecise_## x, x);\
WARN_IMPRECISE(x)
#define DECLARE_IMPRECISE(f) \
long double imprecise_ ## f ## l(long double v) { return f(v); }\
DECLARE_WEAK(f ## l)
DECLARE_IMPRECISE(tgamma);
#define tgamma128 tgammal
#include "tgamma128.c"

View File

@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd December 8, 2017
.Dd March 1, 2024
.Dt LGAMMA 3
.Os
.Sh NAME
@ -167,15 +167,6 @@ non-positive integers.
For large non-integer negative values,
.Fn tgamma
will underflow.
.Sh BUGS
To conform with newer C/C++ standards, a stub implementation for
.Nm tgammal
was committed to the math library, where
.Nm tgammal
is mapped to
.Nm tgamma .
Thus, the numerical accuracy is at most that of the 53-bit double
precision implementation.
.Sh SEE ALSO
.Xr math 3
.Sh STANDARDS
@ -212,3 +203,11 @@ The
.Fn tgamma
function appeared in
.Fx 5.0 .
The 128-bit
.Ft long double
version of
.Fn tgammal
replaced the 80-bit stub version in
version in
.Fx 16 ,
thanks to an appropriate implementation from Arm.