diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-04-09 08:17:25 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-04-09 08:17:25 +0200 |
commit | 481ba4fb5fce8257f5dbeb994dac2748c0237fa2 (patch) | |
tree | 2735ff2a9bda99ffa89fdbc5f3e5e5c34b9e0d5d /libquadmath/math | |
parent | 18e94e04dae724c61cbc13ace85fa68f2deda900 (diff) | |
download | gcc-481ba4fb5fce8257f5dbeb994dac2748c0237fa2.zip gcc-481ba4fb5fce8257f5dbeb994dac2748c0237fa2.tar.gz gcc-481ba4fb5fce8257f5dbeb994dac2748c0237fa2.tar.bz2 |
libquadmath: Use soft-fp for sqrtq finite positive arguments [PR114623]
sqrt should be 0.5ulp precise, but the current implementation is less
precise than that.
The following patch uses the soft-fp code (like e.g. glibc for x86) for it
if possible. I didn't want to replicate the libgcc infrastructure for
choosing the right sfp-machine.h, so the patch just uses a single generic
implementation. As the code is used solely for the finite positive arguments,
it shouldn't generate NaNs (so the exact form of canonical QNaN/SNaN is
irrelevant), and sqrt for these shouldn't produce underflows/overflows either,
for < 1.0 arguments it always returns larger values than the argument and for
> 1.0 smaller values than the argument.
2024-04-09 Jakub Jelinek <jakub@redhat.com>
PR libquadmath/114623
* sfp-machine.h: New file.
* math/sqrtq.c: Include from libgcc/soft-fp also soft-fp.h and quad.h
if possible.
(USE_SOFT_FP): Define in that case.
(sqrtq): Use soft-fp based implementation for the finite positive
arguments if possible.
Diffstat (limited to 'libquadmath/math')
-rw-r--r-- | libquadmath/math/sqrtq.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/libquadmath/math/sqrtq.c b/libquadmath/math/sqrtq.c index 56ea5d3..8ca2828 100644 --- a/libquadmath/math/sqrtq.c +++ b/libquadmath/math/sqrtq.c @@ -1,6 +1,17 @@ #include "quadmath-imp.h" #include <math.h> #include <float.h> +#if __has_include("../../libgcc/soft-fp/soft-fp.h") \ + && __has_include("../../libgcc/soft-fp/quad.h") \ + && defined(FE_TONEAREST) \ + && defined(FE_UPWARD) \ + && defined(FE_DOWNWARD) \ + && defined(FE_TOWARDZERO) \ + && defined(FE_INEXACT) +#define USE_SOFT_FP 1 +#include "../../libgcc/soft-fp/soft-fp.h" +#include "../../libgcc/soft-fp/quad.h" +#endif __float128 sqrtq (const __float128 x) @@ -20,6 +31,18 @@ sqrtq (const __float128 x) return (x - x) / (x - x); } +#if USE_SOFT_FP + FP_DECL_EX; + FP_DECL_Q (X); + FP_DECL_Q (Y); + + FP_INIT_ROUNDMODE; + FP_UNPACK_Q (X, x); + FP_SQRT_Q (Y, X); + FP_PACK_Q (y, Y); + FP_HANDLE_EXCEPTIONS; + return y; +#else if (x <= DBL_MAX && x >= DBL_MIN) { /* Use double result as starting point. */ @@ -59,5 +82,5 @@ sqrtq (const __float128 x) y -= 0.5q * (y - x / y); y -= 0.5q * (y - x / y); return y; +#endif } - |