1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero */
9*10465441SEvalZero #include <math.h>
10*10465441SEvalZero
11*10465441SEvalZero /*
12*10465441SEvalZero * COPYRIGHT: See COPYING in the top level directory
13*10465441SEvalZero * PROJECT: ReactOS CRT
14*10465441SEvalZero * FILE: lib/crt/math/cos.c
15*10465441SEvalZero * PURPOSE: Generic C Implementation of cos
16*10465441SEvalZero * PROGRAMMER: Timo Kreuzer ([email protected])
17*10465441SEvalZero */
18*10465441SEvalZero
19*10465441SEvalZero #define PRECISION 9
20*10465441SEvalZero
21*10465441SEvalZero static double cos_off_tbl[] = {0.0, -M_PI/2., 0, -M_PI/2.};
22*10465441SEvalZero static double cos_sign_tbl[] = {1,-1,-1,1};
23*10465441SEvalZero
24*10465441SEvalZero static double sin_off_tbl[] = {0.0, -M_PI/2., 0, -M_PI/2.};
25*10465441SEvalZero static double sin_sign_tbl[] = {1,-1,-1,1};
26*10465441SEvalZero
sin(double x)27*10465441SEvalZero double sin(double x)
28*10465441SEvalZero {
29*10465441SEvalZero int quadrant;
30*10465441SEvalZero double x2, result;
31*10465441SEvalZero
32*10465441SEvalZero /* Calculate the quadrant */
33*10465441SEvalZero quadrant = x * (2./M_PI);
34*10465441SEvalZero
35*10465441SEvalZero /* Get offset inside quadrant */
36*10465441SEvalZero x = x - quadrant * (M_PI/2.);
37*10465441SEvalZero
38*10465441SEvalZero /* Normalize quadrant to [0..3] */
39*10465441SEvalZero quadrant = (quadrant - 1) & 0x3;
40*10465441SEvalZero
41*10465441SEvalZero /* Fixup value for the generic function */
42*10465441SEvalZero x += sin_off_tbl[quadrant];
43*10465441SEvalZero
44*10465441SEvalZero /* Calculate the negative of the square of x */
45*10465441SEvalZero x2 = - (x * x);
46*10465441SEvalZero
47*10465441SEvalZero /* This is an unrolled taylor series using <PRECISION> iterations
48*10465441SEvalZero * Example with 4 iterations:
49*10465441SEvalZero * result = 1 - x^2/2! + x^4/4! - x^6/6! + x^8/8!
50*10465441SEvalZero * To save multiplications and to keep the precision high, it's performed
51*10465441SEvalZero * like this:
52*10465441SEvalZero * result = 1 - x^2 * (1/2! - x^2 * (1/4! - x^2 * (1/6! - x^2 * (1/8!))))
53*10465441SEvalZero */
54*10465441SEvalZero
55*10465441SEvalZero /* Start with 0, compiler will optimize this away */
56*10465441SEvalZero result = 0;
57*10465441SEvalZero
58*10465441SEvalZero #if (PRECISION >= 10)
59*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20);
60*10465441SEvalZero result *= x2;
61*10465441SEvalZero #endif
62*10465441SEvalZero #if (PRECISION >= 9)
63*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18);
64*10465441SEvalZero result *= x2;
65*10465441SEvalZero #endif
66*10465441SEvalZero #if (PRECISION >= 8)
67*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16);
68*10465441SEvalZero result *= x2;
69*10465441SEvalZero #endif
70*10465441SEvalZero #if (PRECISION >= 7)
71*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14);
72*10465441SEvalZero result *= x2;
73*10465441SEvalZero #endif
74*10465441SEvalZero #if (PRECISION >= 6)
75*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12);
76*10465441SEvalZero result *= x2;
77*10465441SEvalZero #endif
78*10465441SEvalZero #if (PRECISION >= 5)
79*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10);
80*10465441SEvalZero result *= x2;
81*10465441SEvalZero #endif
82*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8);
83*10465441SEvalZero result *= x2;
84*10465441SEvalZero
85*10465441SEvalZero result += 1./(1.*2*3*4*5*6);
86*10465441SEvalZero result *= x2;
87*10465441SEvalZero
88*10465441SEvalZero result += 1./(1.*2*3*4);
89*10465441SEvalZero result *= x2;
90*10465441SEvalZero
91*10465441SEvalZero result += 1./(1.*2);
92*10465441SEvalZero result *= x2;
93*10465441SEvalZero
94*10465441SEvalZero result += 1;
95*10465441SEvalZero
96*10465441SEvalZero /* Apply correct sign */
97*10465441SEvalZero result *= sin_sign_tbl[quadrant];
98*10465441SEvalZero
99*10465441SEvalZero return result;
100*10465441SEvalZero }
101*10465441SEvalZero
cos(double x)102*10465441SEvalZero double cos(double x)
103*10465441SEvalZero {
104*10465441SEvalZero int quadrant;
105*10465441SEvalZero double x2, result;
106*10465441SEvalZero
107*10465441SEvalZero /* Calculate the quadrant */
108*10465441SEvalZero quadrant = x * (2./M_PI);
109*10465441SEvalZero
110*10465441SEvalZero /* Get offset inside quadrant */
111*10465441SEvalZero x = x - quadrant * (M_PI/2.);
112*10465441SEvalZero
113*10465441SEvalZero /* Normalize quadrant to [0..3] */
114*10465441SEvalZero quadrant = quadrant & 0x3;
115*10465441SEvalZero
116*10465441SEvalZero /* Fixup value for the generic function */
117*10465441SEvalZero x += cos_off_tbl[quadrant];
118*10465441SEvalZero
119*10465441SEvalZero /* Calculate the negative of the square of x */
120*10465441SEvalZero x2 = - (x * x);
121*10465441SEvalZero
122*10465441SEvalZero /* This is an unrolled taylor series using <PRECISION> iterations
123*10465441SEvalZero * Example with 4 iterations:
124*10465441SEvalZero * result = 1 - x^2/2! + x^4/4! - x^6/6! + x^8/8!
125*10465441SEvalZero * To save multiplications and to keep the precision high, it's performed
126*10465441SEvalZero * like this:
127*10465441SEvalZero * result = 1 - x^2 * (1/2! - x^2 * (1/4! - x^2 * (1/6! - x^2 * (1/8!))))
128*10465441SEvalZero */
129*10465441SEvalZero
130*10465441SEvalZero /* Start with 0, compiler will optimize this away */
131*10465441SEvalZero result = 0;
132*10465441SEvalZero
133*10465441SEvalZero #if (PRECISION >= 10)
134*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20);
135*10465441SEvalZero result *= x2;
136*10465441SEvalZero #endif
137*10465441SEvalZero #if (PRECISION >= 9)
138*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18);
139*10465441SEvalZero result *= x2;
140*10465441SEvalZero #endif
141*10465441SEvalZero #if (PRECISION >= 8)
142*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16);
143*10465441SEvalZero result *= x2;
144*10465441SEvalZero #endif
145*10465441SEvalZero #if (PRECISION >= 7)
146*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12*13*14);
147*10465441SEvalZero result *= x2;
148*10465441SEvalZero #endif
149*10465441SEvalZero #if (PRECISION >= 6)
150*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10*11*12);
151*10465441SEvalZero result *= x2;
152*10465441SEvalZero #endif
153*10465441SEvalZero #if (PRECISION >= 5)
154*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8*9*10);
155*10465441SEvalZero result *= x2;
156*10465441SEvalZero #endif
157*10465441SEvalZero result += 1./(1.*2*3*4*5*6*7*8);
158*10465441SEvalZero result *= x2;
159*10465441SEvalZero
160*10465441SEvalZero result += 1./(1.*2*3*4*5*6);
161*10465441SEvalZero result *= x2;
162*10465441SEvalZero
163*10465441SEvalZero result += 1./(1.*2*3*4);
164*10465441SEvalZero result *= x2;
165*10465441SEvalZero
166*10465441SEvalZero result += 1./(1.*2);
167*10465441SEvalZero result *= x2;
168*10465441SEvalZero
169*10465441SEvalZero result += 1;
170*10465441SEvalZero
171*10465441SEvalZero /* Apply correct sign */
172*10465441SEvalZero result *= cos_sign_tbl[quadrant];
173*10465441SEvalZero
174*10465441SEvalZero return result;
175*10465441SEvalZero }
176*10465441SEvalZero
177