aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2016-06-14 14:56:42 +0000
committerJoseph Myers <joseph@codesourcery.com>2016-06-14 14:56:42 +0000
commit4fea2cda618de1c74959aaec79c020993c34c552 (patch)
tree539442064517695eadeeec91c18817045edb781d
parentc8376f3e07602aaef9cb843bb73cb5f2b860634a (diff)
downloadglibc-4fea2cda618de1c74959aaec79c020993c34c552.tar
glibc-4fea2cda618de1c74959aaec79c020993c34c552.tar.gz
glibc-4fea2cda618de1c74959aaec79c020993c34c552.tar.bz2
glibc-4fea2cda618de1c74959aaec79c020993c34c552.zip
Simplify generic fdim implementations.
The generic fdim implementations have unnecessarily complicated code, using fpclassify to determine whether the arguments are NaNs, subtracting NaNs if so and otherwise subtracting the non-NaN arguments if not (x <= y), then using fpclassify on the result to see if it is infinite. This patch simplifies the code. Instead of handling NaNs separately, it suffices to use an unordered comparison with islessequal (x, y) to determine whether to return zero, and otherwise NaNs can go through the same subtraction as non-NaN arguments; no explicit tests for NaN are needed at all. Then, isinf instead of fpclassify can be used to determine whether to set errno (in the normal non-overflow case, only one classification will need to occur, unlike the three in the previous code, of which two occurred even if returning zero, because the result will not be infinite in the normal case). The resulting logic is essentially the same as that in the powerpc version, except that the powerpc version is missing errno setting and uses <= not islessequal, so relying on <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58684>, the GCC bug that unordered comparison instructions are wrongly used on powerpc for ordered comparisons. The compiled code for fdim and fdimf on x86_64 is less than half the size of the previous code. Tested for x86_64. * math/s_fdim.c (__fdim): Use islessequal and isinf instead of fpclassify. * math/s_fdimf.c (__fdimf): Likewise. * math/s_fdiml.c (__fdiml): Likewise.
-rw-r--r--ChangeLog7
-rw-r--r--math/s_fdim.c12
-rw-r--r--math/s_fdimf.c12
-rw-r--r--math/s_fdiml.c12
4 files changed, 13 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index 495f088196..abd8fcbba4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2016-06-14 Joseph Myers <joseph@codesourcery.com>
+
+ * math/s_fdim.c (__fdim): Use islessequal and isinf instead of
+ fpclassify.
+ * math/s_fdimf.c (__fdimf): Likewise.
+ * math/s_fdiml.c (__fdiml): Likewise.
+
2016-06-14 Rajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com>
* sysdeps/powerpc/powerpc64/multiarch/Makefile:
diff --git a/math/s_fdim.c b/math/s_fdim.c
index b02ed27233..8789ca4c38 100644
--- a/math/s_fdim.c
+++ b/math/s_fdim.c
@@ -23,19 +23,11 @@
double
__fdim (double x, double y)
{
- int clsx = fpclassify (x);
- int clsy = fpclassify (y);
-
- if (clsx == FP_NAN || clsy == FP_NAN)
- /* Raise invalid flag for signaling but not quiet NaN. */
- return x - y;
-
- if (x <= y)
+ if (islessequal (x, y))
return 0.0;
double r = x - y;
- if (fpclassify (r) == FP_INFINITE
- && clsx != FP_INFINITE && clsy != FP_INFINITE)
+ if (isinf (r) && !isinf (x) && !isinf (y))
__set_errno (ERANGE);
return r;
diff --git a/math/s_fdimf.c b/math/s_fdimf.c
index b905380478..2e8eccfc4f 100644
--- a/math/s_fdimf.c
+++ b/math/s_fdimf.c
@@ -23,19 +23,11 @@
float
__fdimf (float x, float y)
{
- int clsx = fpclassify (x);
- int clsy = fpclassify (y);
-
- if (clsx == FP_NAN || clsy == FP_NAN)
- /* Raise invalid flag for signaling but not quiet NaN. */
- return x - y;
-
- if (x <= y)
+ if (islessequal (x, y))
return 0.0f;
float r = x - y;
- if (fpclassify (r) == FP_INFINITE
- && clsx != FP_INFINITE && clsy != FP_INFINITE)
+ if (isinf (r) && !isinf (x) && !isinf (y))
__set_errno (ERANGE);
return r;
diff --git a/math/s_fdiml.c b/math/s_fdiml.c
index df3f1e5ba4..4a1f6722c6 100644
--- a/math/s_fdiml.c
+++ b/math/s_fdiml.c
@@ -23,19 +23,11 @@
long double
__fdiml (long double x, long double y)
{
- int clsx = fpclassify (x);
- int clsy = fpclassify (y);
-
- if (clsx == FP_NAN || clsy == FP_NAN)
- /* Raise invalid flag for signaling but not quiet NaN. */
- return x - y;
-
- if (x <= y)
+ if (islessequal (x, y))
return 0.0f;
long double r = x - y;
- if (fpclassify (r) == FP_INFINITE
- && clsx != FP_INFINITE && clsy != FP_INFINITE)
+ if (isinf (r) && !isinf (x) && !isinf (y))
__set_errno (ERANGE);
return r;