aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiddhesh Poyarekar <siddhesh.poyarekar@linaro.org>2015-12-21 10:40:32 +0530
committerSiddhesh Poyarekar <siddhesh.poyarekar@linaro.org>2015-12-21 10:40:32 +0530
commita045832debe4191bcffed6e539a5470152e9c9e8 (patch)
tree024e6228fb366370a19096a689698c9dbe102932
parent760c2eb7da879e05252468a512a582a0e5c180af (diff)
downloadglibc-a045832debe4191bcffed6e539a5470152e9c9e8.zip
glibc-a045832debe4191bcffed6e539a5470152e9c9e8.tar.gz
glibc-a045832debe4191bcffed6e539a5470152e9c9e8.tar.bz2
Consolidate range reduction in sincos for x > 281474976710656
Range reduction needs to be done only once for sin and cos, so copy over all of the relevant functions (__sin, __cos, reduce_and_compute) and consolidate common code.
-rw-r--r--ChangeLog9
-rw-r--r--sysdeps/ieee754/dbl-64/s_sin.c4
-rw-r--r--sysdeps/ieee754/dbl-64/s_sincos.c55
3 files changed, 66 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 0024c1e..c8281dd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2015-12-21 Siddhesh Poyarekar <siddhesh.poyarekar@linaro.org>
+
+ * sysdeps/ieee754/dbl-64/s_sin.c (__sin) [!IN_SINCOS]: Skip
+ common code for sincos.
+ (__cos) [!IN_SINCOS]: Likewise.
+ * sysdeps/ieee754/dbl-64/s_sincos.c (reduce_and_compute_sincos):
+ New function.
+ (__sincos): Use it.
+
2015-12-20 Aurelien Jarno <aurelien@aurel32.net>
* sysdeps/i386/fpu/libm-test-ulps: Move to ....
diff --git a/sysdeps/ieee754/dbl-64/s_sin.c b/sysdeps/ieee754/dbl-64/s_sin.c
index a635a86..b619905 100644
--- a/sysdeps/ieee754/dbl-64/s_sin.c
+++ b/sysdeps/ieee754/dbl-64/s_sin.c
@@ -497,6 +497,7 @@ __sin (double x)
}
} /* else if (k < 0x42F00000 ) */
+#ifndef IN_SINCOS
/* -----------------281474976710656 <|x| <2^1024----------------------------*/
else if (k < 0x7ff00000)
retval = reduce_and_compute (x, 0);
@@ -508,6 +509,7 @@ __sin (double x)
__set_errno (EDOM);
retval = x / x;
}
+#endif
return retval;
}
@@ -729,6 +731,7 @@ __cos (double x)
}
} /* else if (k < 0x42F00000 ) */
+#ifndef IN_SINCOS
/* 281474976710656 <|x| <2^1024 */
else if (k < 0x7ff00000)
retval = reduce_and_compute (x, 1);
@@ -739,6 +742,7 @@ __cos (double x)
__set_errno (EDOM);
retval = x / x; /* |x| > 2^1024 */
}
+#endif
return retval;
}
diff --git a/sysdeps/ieee754/dbl-64/s_sincos.c b/sysdeps/ieee754/dbl-64/s_sincos.c
index 2a3fc06..f50ffa6 100644
--- a/sysdeps/ieee754/dbl-64/s_sincos.c
+++ b/sysdeps/ieee754/dbl-64/s_sincos.c
@@ -27,13 +27,64 @@
#define IN_SINCOS 1
#include "s_sin.c"
+/* Consolidated version of reduce_and_compute in s_sin.c that does range
+ reduction only once and computes sin and cos together. */
+static inline void
+__always_inline
+reduce_and_compute_sincos (double x, double *sinx, double *cosx)
+{
+ double a, da;
+ unsigned int n = __branred (x, &a, &da);
+
+ n = n & 3;
+
+ if (n == 1 || n == 2)
+ {
+ a = -a;
+ da = -da;
+ }
+
+ if (n & 1)
+ {
+ double *temp = cosx;
+ cosx = sinx;
+ sinx = temp;
+ }
+
+ if (a * a < 0.01588)
+ *sinx = bsloww (a, da, x, n);
+ else
+ *sinx = bsloww1 (a, da, x, n);
+ *cosx = bsloww2 (a, da, x, n);
+}
+
void
__sincos (double x, double *sinx, double *cosx)
{
+ mynumber u;
+ int k;
+
SET_RESTORE_ROUND_53BIT (FE_TONEAREST);
- *sinx = __sin (x);
- *cosx = __cos (x);
+ u.x = x;
+ k = 0x7fffffff & u.i[HIGH_HALF];
+
+ if (k < 0x42F00000)
+ {
+ *sinx = __sin_local (x);
+ *cosx = __cos_local (x);
+ return;
+ }
+ if (k < 0x7ff00000)
+ {
+ reduce_and_compute_sincos (x, sinx, cosx);
+ return;
+ }
+
+ if (isinf (x))
+ __set_errno (EDOM);
+
+ *sinx = *cosx = x / x;
}
weak_alias (__sincos, sincos)
#ifdef NO_LONG_DOUBLE