aboutsummaryrefslogtreecommitdiff
path: root/libquadmath/math
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-04-09 08:17:25 +0200
committerJakub Jelinek <jakub@redhat.com>2024-04-09 08:17:25 +0200
commit481ba4fb5fce8257f5dbeb994dac2748c0237fa2 (patch)
tree2735ff2a9bda99ffa89fdbc5f3e5e5c34b9e0d5d /libquadmath/math
parent18e94e04dae724c61cbc13ace85fa68f2deda900 (diff)
downloadgcc-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.c25
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
}
-