summaryrefslogtreecommitdiffstats
path: root/mathfuncs_sin.h
diff options
context:
space:
mode:
Diffstat (limited to 'mathfuncs_sin.h')
-rw-r--r--mathfuncs_sin.h96
1 files changed, 96 insertions, 0 deletions
diff --git a/mathfuncs_sin.h b/mathfuncs_sin.h
new file mode 100644
index 0000000..3e1a6d6
--- /dev/null
+++ b/mathfuncs_sin.h
@@ -0,0 +1,96 @@
+// -*-C++-*-
+
+#ifndef MATHFUNCS_SIN_H
+#define MATHFUNCS_SIN_H
+
+#include "mathfuncs_base.h"
+
+#include <cassert>
+#include <cmath>
+
+
+
+namespace vecmathlib {
+
+ template<typename realvec_t>
+ realvec_t mathfuncs<realvec_t>::vml_sin(realvec_t x)
+ {
+ // Reduce range: sin(x) = sin(x + 2pi)
+ x = remainder(x, RV(2.0*M_PI));
+ assert(all(x >= RV(-M_PI) && x <= RV(M_PI)));
+
+ // Reduce range: sin(x) = -sin(-x)
+ realvec_t sign = x;
+ x = fabs(x);
+ assert(all(x >= RV(0.0) && x <= RV(M_PI)));
+
+ // Reduce range: sin(x) = sin(pi-x)
+ x = ifthen(x > RV(M_PI_2), RV(M_PI) - x, x);
+ assert(all(x >= RV(0.0) && x <= RV(M_PI_2)));
+
+ // Reduce range: cos(x) = sin(pi/2 - x)
+ boolvec_t use_cos = x > RV(0.5*M_PI_2);
+ x = ifthen(use_cos, RV(M_PI_2) - x, x);
+
+ // Taylor expansion
+ // sin(x) = Sum[n=0,nmax,n%2!=0] (-1)^((n-1)/2) x^n / n!
+ // cos(x) = Sum[n=0,nmax,n%2==0] (-1)^((n-1)/2) x^n / n!
+ realvec_t noffset = ifthen(use_cos, RV(-1.0), RV(0.0));
+ int const nmax = 15;
+ realvec_t x2 = x*x;
+ realvec_t y = ifthen(use_cos, RV(1.0), x);
+ realvec_t r = y;
+ for (int n=3; n<nmax; n+=2) {
+ // sin: (n-1)*n
+ // cos: n*(n+1)
+ realvec_t rn = RV(FP::convert_float(n)) + noffset;
+ y *= - x2 * rcp((rn-RV(1.0))*rn);
+ r += y;
+ }
+
+ // Undo range reduction
+ r = copysign(r, sign);
+
+ return r;
+ }
+
+
+
+ template<typename realvec_t>
+ realvec_t mathfuncs<realvec_t>::vml_cos(realvec_t x)
+ {
+ return sin(x + RV(M_PI_2));
+ }
+
+ template<typename realvec_t>
+ realvec_t mathfuncs<realvec_t>::vml_tan(realvec_t x)
+ {
+ // Reduce range: tan(x) = tan(x + pi)
+ x = remainder(x, RV(M_PI));
+ assert(all(x >= RV(-M_PI_2) && x <= RV(M_PI_2)));
+
+ // Reduce range: tan(x) = -tan(-x)
+ realvec_t sign = x;
+ x = fabs(x);
+ assert(all(x >= RV(0.0) && x <= RV(M_PI_2)));
+
+ // Reduce range: cot(x) = -tan(x + pi/2)
+ boolvec_t use_cot = x > RV(0.5 * M_PI_2);
+ x = ifthen(use_cot, RV(M_PI_2) -x, x);
+ assert(all(x >= RV(0.0) && x <= RV(0.5 * M_PI_2)));
+
+ // Calculate tan
+ realvec_t r = sin(x) / cos(x);
+
+ // Undo range reduction
+ r = ifthen(use_cot, -rcp(r), r);
+
+ // Undo range reducion
+ r = copysign(r, sign);
+
+ return r;
+ }
+
+}; // namespace vecmathlib
+
+#endif // #ifndef MATHFUNCS_SIN_H
OpenPOWER on IntegriCloud