Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/lib5/pml/dsin.c
There are 5 other files named dsin.c in the archive. Click here to see a list.
/*
* +++ NAME +++
*
* DSIN Double precision sine
*
* +++ INDEX +++
*
* DSIN
* machine independent routines
* trigonometric functions
* math libraries
*
* +++ DESCRIPTION +++
*
* Returns double precision sine of double precision
* floating point argument.
*
* +++ USAGE +++
*
* double dsin(x)
* double x;
*
* +++ REFERENCES +++
*
* Computer Approximations, J.F. Hart et al, John Wiley & Sons,
* 1968, pp. 112-120.
*
* +++ RESTRICTIONS +++
*
* The DSIN and DCOS routines are interactive in the sense that
* in the process of reducing the argument to the range -PI/4
* to PI/4, each may call the other. Ultimately one or the
* other uses a polynomial approximation on the reduced
* argument. The DSIN approximation has a maximum relative error
* of 10**(-17.59) and the DCOS approximation has a maximum
* relative error of 10**(-16.18).
*
* These error bounds assume exact arithmetic
* in the polynomial evaluation. Additional rounding and
* truncation errors may occur as the argument is reduced
* to the range over which the polynomial approximation
* is valid, and as the polynomial is evaluated using
* finite-precision arithmetic.
*
* +++ PROGRAMMER +++
*
* Fred Fish
* Goodyear Aerospace Corp, Arizona Div.
* (602) 932-7000 work
* (602) 894-6881 home
*
* +++ INTERNALS +++
*
* Computes DSIN(X) from:
*
* (1) Reduce argument X to range -PI to PI.
*
* (2) If X > PI/2 then call DSIN recursively
* using relation DSIN(X) = -DSIN(X - PI).
*
* (3) If X < -PI/2 then call DSIN recursively
* using relation DSIN(X) = -DSIN(X + PI).
*
* (4) If X > PI/4 then call DCOS using
* relation DSIN(X) = DCOS(PI/2 - X).
*
* (5) If X < -PI/4 then call DCOS using
* relation DSIN(X) = -DCOS(PI/2 + X).
*
* (6) If X is small enough that polynomial
* evaluation would cause underflow
* then return X, since SIN(X)
* approaches X as X approaches zero.
*
* (7) By now X has been reduced to range
* -PI/4 to PI/4 and the approximation
* from HART pg. 118 can be used:
*
* DSIN(X) = Y * ( P(Y) / Q(Y) )
* Where:
*
* Y = X * (4/PI)
*
* P(Y) = SUM [ Pj * (Y**(2*j)) ]
* over j = {0,1,2,3}
*
* Q(Y) = SUM [ Qj * (Y**(2*j)) ]
* over j = {0,1,2,3}
*
* P0 = 0.206643433369958582409167054e+7
* P1 = -0.18160398797407332550219213e+6
* P2 = 0.359993069496361883172836e+4
* P3 = -0.2010748329458861571949e+2
* Q0 = 0.263106591026476989637710307e+7
* Q1 = 0.3927024277464900030883986e+5
* Q2 = 0.27811919481083844087953e+3
* Q3 = 1.0000...
* (coefficients from HART table #3063 pg 234)
*
*
* **** NOTE **** The range reduction relations used in
* this routine depend on the final approximation being valid
* over the negative argument range in addition to the positive
* argument range. The particular approximation chosen from
* HART satisfies this requirement, although not explicitly
* stated in the text. This may not be true of other
* approximations given in the reference.
*
* ---
*/
/*)LIBRARY
*/
#include <stdio.h>
#include "c:pmluse.h"
#include "pml.h"
static double dsin_pcoeffs[] = {
0.20664343336995858240e7,
-0.18160398797407332550e6,
0.35999306949636188317e4,
-0.20107483294588615719e2
};
static double dsin_qcoeffs[] = {
0.26310659102647698963e7,
0.39270242774649000308e5,
0.27811919481083844087e3,
1.0
};
double dsin(x)
double x;
{
double y, yt2, fmod(), dcos(), dpoly();
if (x < -PI || x > PI) {
x = fmod(x,TWOPI);
if (x > PI) {
x = x - TWOPI;
} else if (x < -PI) {
x = x + TWOPI;
}
}
if (x > HALFPI) {
return (-(dsin(x - PI)));
} else if (x < -HALFPI) {
return (-(dsin(x + PI)));
} else if (x > FOURTHPI) {
return (dcos(HALFPI - x));
} else if (x < -FOURTHPI) {
return (-(dcos(HALFPI + x)));
} else if (x < X6_UNDERFLOWS && x > -X6_UNDERFLOWS) {
return (x);
} else {
y = x / FOURTHPI;
yt2 = y * y;
return ( y * (dpoly(3,dsin_pcoeffs,yt2) / dpoly(3,dsin_qcoeffs,yt2)));
}
}