// -*-C++-*- #ifndef MATHFUNCS_ASIN_H #define MATHFUNCS_ASIN_H #include "mathfuncs_base.h" #include namespace vecmathlib { template realvec_t mathfuncs::vml_atan(realvec_t x) { // Handle negative values realvec_t x0 = x; x = fabs(x); // Reduce range using 1/x identity VML_ASSERT(all(x >= RV(0.0))); boolvec_t gt_one = x > RV(1.0); x = ifthen(gt_one, rcp(x), x); // Reduce range again using half-angle formula; see // . // This is necessary for good convergence below. x = x / (RV(1.0) + sqrt(RV(1.0) + x*x)); #if 0 // Taylor expansion; see // . VML_ASSERT(all(x >= RV(0.0) && x <= RV(0.5))); int const nmax = 30; // ??? realvec_t y = x / (RV(1.0) + x*x); realvec_t x2 = x * y; realvec_t r = y; for (int n=3; n realvec_t mathfuncs::vml_acos(realvec_t x) { return RV(M_PI_2) - asin(x); } template realvec_t mathfuncs::vml_asin(realvec_t x) { return RV(2.0) * atan(x / (RV(1.0) + sqrt(RV(1.0) - x*x))); } // Note: the order of arguments is y, x, as is convention for atan2 template realvec_t mathfuncs::vml_atan2(realvec_t y, realvec_t x) { realvec_t r = atan(y/x); realvec_t offset = copysign(ifthen(signbit(x), RV(M_PI), RV(0.0)), y); r = r + offset; // Note: the case x=y=0 is implemented via the second if // condition; thus, the order of the two if conditions cannot be // exchanged r = ifthen(x==RV(0.0), copysign(RV(M_PI_2), y), r); r = ifthen(y==RV(0.0), offset, r); return r; } }; // namespace vecmathlib #endif // #ifndef MATHFUNCS_ASIN_H