/* @(#)z_sine.c 1.0 98/08/13 */ /****************************************************************** * The following routines are coded directly from the algorithms * and coefficients given in "Software Manual for the Elementary * Functions" by William J. Cody, Jr. and William Waite, Prentice * Hall, 1980. ******************************************************************/ /* FUNCTION <>, <>, <>, <>, <>, <>---sine or cosine INDEX sin INDEX sinf INDEX cos INDEX cosf ANSI_SYNOPSIS #include double sin(double <[x]>); float sinf(float <[x]>); double cos(double <[x]>); float cosf(float <[x]>); TRAD_SYNOPSIS #include double sin(<[x]>) double <[x]>; float sinf(<[x]>) float <[x]>; double cos(<[x]>) double <[x]>; float cosf(<[x]>) float <[x]>; DESCRIPTION <> and <> compute (respectively) the sine and cosine of the argument <[x]>. Angles are specified in radians. RETURNS The sine or cosine of <[x]> is returned. PORTABILITY <> and <> are ANSI C. <> and <> are extensions. QUICKREF sin ansi pure sinf - pure */ /****************************************************************** * sine * * Input: * x - floating point value * cosine - indicates cosine value * * Output: * Sine of x. * * Description: * This routine calculates sines and cosines. * *****************************************************************/ #include "fdlibm.h" #include "zmath.h" #ifndef _DOUBLE_IS_32BITS static const double HALF_PI = 1.57079632679489661923; static const double ONE_OVER_PI = 0.31830988618379067154; static const double r[] = { -0.16666666666666665052, 0.83333333333331650314e-02, -0.19841269841201840457e-03, 0.27557319210152756119e-05, -0.25052106798274584544e-07, 0.16058936490371589114e-09, -0.76429178068910467734e-12, 0.27204790957888846175e-14 }; double _DEFUN (sine, (double, int), double x _AND int cosine) { int sgn, N; double y, XN, g, R, res; double YMAX = 210828714.0; switch (numtest (x)) { case NAN: errno = EDOM; return (x); case INF: errno = EDOM; return (z_notanum.d); } /* Use sin and cos properties to ease computations. */ if (cosine) { sgn = 1; y = fabs (x) + HALF_PI; } else { if (x < 0.0) { sgn = -1; y = -x; } else { sgn = 1; y = x; } } /* Check for values of y that will overflow here. */ if (y > YMAX) { errno = ERANGE; return (x); } /* Calculate the exponent. */ if (y < 0.0) N = (int) (y * ONE_OVER_PI - 0.5); else N = (int) (y * ONE_OVER_PI + 0.5); XN = (double) N; if (N & 1) sgn = -sgn; if (cosine) XN -= 0.5; y = fabs (x) - XN * __PI; if (-z_rooteps < y && y < z_rooteps) res = y; else { g = y * y; /* Calculate the Taylor series. */ R = (((((((r[6] * g + r[5]) * g + r[4]) * g + r[3]) * g + r[2]) * g + r[1]) * g + r[0]) * g); /* Finally, compute the result. */ res = y + y * R; } res *= sgn; return (res); } #endif /* _DOUBLE_IS_32BITS */