167 lines
3.5 KiB
C
167 lines
3.5 KiB
C
|
|
||
|
/* @(#)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
|
||
|
<<sin>>, <<cos>>, <<sine>>, <<sinf>>, <<cosf>>, <<sinef>>---sine or cosine
|
||
|
INDEX
|
||
|
sin
|
||
|
INDEX
|
||
|
sinf
|
||
|
INDEX
|
||
|
cos
|
||
|
INDEX
|
||
|
cosf
|
||
|
ANSI_SYNOPSIS
|
||
|
#include <math.h>
|
||
|
double sin(double <[x]>);
|
||
|
float sinf(float <[x]>);
|
||
|
double cos(double <[x]>);
|
||
|
float cosf(float <[x]>);
|
||
|
|
||
|
TRAD_SYNOPSIS
|
||
|
#include <math.h>
|
||
|
double sin(<[x]>)
|
||
|
double <[x]>;
|
||
|
float sinf(<[x]>)
|
||
|
float <[x]>;
|
||
|
|
||
|
double cos(<[x]>)
|
||
|
double <[x]>;
|
||
|
float cosf(<[x]>)
|
||
|
float <[x]>;
|
||
|
|
||
|
DESCRIPTION
|
||
|
<<sin>> and <<cos>> 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
|
||
|
<<sin>> and <<cos>> are ANSI C.
|
||
|
<<sinf>> and <<cosf>> 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 */
|