Your problem is here:
for (; d < DEPTH; n += 2, d++, sign *= -1) { x += pow(i_x, n) / fact(n) * sign; }
You use d < DEPTH in error, when it should be n < DEPTH , d not related to your calculations in the loop. The following should work - although I am not compiled for testing.
for (; n < DEPTH; n += 2, sign *= -1) { x += pow(i_x, n) / fact(n) * sign; }
Note: a DEPTH of 12 (for example, expanding the Taylor series with members 1, 3, 5, ... 11 ) is enough for a 3e-10 error - 3 ten billion in 60-degrees . (although the error increases with increasing angle between 0-360 , a DEPTH 20 will contain an error less than 1.0e-8 in the entire range.)
Enabling compiler warnings might catch on an unused d in sine .
Here is a sample code with changes (note: Gnu provides the M_PI constant for PI):
#include <stdio.h> #include <stdint.h> #include <math.h> #define DEPTH 16 /* n factorial */ uint64_t nfact (int n) { if (n <= 0) return 1; uint64_t s = n; while (--n) s *= n; return s; } /* y ^ x */ double powerd (const double y, const int x) { if (!x) return 1; double r = y; for (int i = 1; i < x; i++) r *= y; return r; } double sine (double deg) { double rad = deg * M_PI / 180.0, x = rad; int sign = -1; for (int n = 3; n < DEPTH; n += 2, sign *= -1) x += sign * powerd (rad, n) / nfact (n); return x; } int main (void) { printf (" deg sin sine\n\n"); for (int i = 0; i < 180; i++) printf ("%3d %11.8f %11.8f\n", i, sin (i * M_PI / 180.0), sine (i)); return 0; }
Usage / Output Example
$ ./bin/sine deg sin sine 0 0.00000000 0.00000000 1 0.01745241 0.01745241 2 0.03489950 0.03489950 3 0.05233596 0.05233596 4 0.06975647 0.06975647 5 0.08715574 0.08715574 6 0.10452846 0.10452846 7 0.12186934 0.12186934 8 0.13917310 0.13917310 9 0.15643447 0.15643447 10 0.17364818 0.17364818 11 0.19080900 0.19080900 12 0.20791169 0.20791169 13 0.22495105 0.22495105 14 0.24192190 0.24192190 15 0.25881905 0.25881905 16 0.27563736 0.27563736 17 0.29237170 0.29237170 18 0.30901699 0.30901699 19 0.32556815 0.32556815 20 0.34202014 0.34202014 21 0.35836795 0.35836795 22 0.37460659 0.37460659 23 0.39073113 0.39073113 24 0.40673664 0.40673664 25 0.42261826 0.42261826 26 0.43837115 0.43837115 27 0.45399050 0.45399050 28 0.46947156 0.46947156 29 0.48480962 0.48480962 30 0.50000000 0.50000000 31 0.51503807 0.51503807 32 0.52991926 0.52991926 33 0.54463904 0.54463904 34 0.55919290 0.55919290 35 0.57357644 0.57357644 36 0.58778525 0.58778525 37 0.60181502 0.60181502 38 0.61566148 0.61566148 39 0.62932039 0.62932039 40 0.64278761 0.64278761 41 0.65605903 0.65605903 42 0.66913061 0.66913061 43 0.68199836 0.68199836 44 0.69465837 0.69465837 45 0.70710678 0.70710678 46 0.71933980 0.71933980 47 0.73135370 0.73135370 48 0.74314483 0.74314483 49 0.75470958 0.75470958 50 0.76604444 0.76604444 51 0.77714596 0.77714596 52 0.78801075 0.78801075 53 0.79863551 0.79863551 54 0.80901699 0.80901699 55 0.81915204 0.81915204 56 0.82903757 0.82903757 57 0.83867057 0.83867057 58 0.84804810 0.84804810 59 0.85716730 0.85716730 60 0.86602540 0.86602540 61 0.87461971 0.87461971 62 0.88294759 0.88294759 63 0.89100652 0.89100652 64 0.89879405 0.89879405 65 0.90630779 0.90630779 66 0.91354546 0.91354546 67 0.92050485 0.92050485 68 0.92718385 0.92718385 69 0.93358043 0.93358043 70 0.93969262 0.93969262 71 0.94551858 0.94551858 72 0.95105652 0.95105652 73 0.95630476 0.95630476 74 0.96126170 0.96126170 75 0.96592583 0.96592583 76 0.97029573 0.97029573 77 0.97437006 0.97437006 78 0.97814760 0.97814760 79 0.98162718 0.98162718 80 0.98480775 0.98480775 81 0.98768834 0.98768834 82 0.99026807 0.99026807 83 0.99254615 0.99254615 84 0.99452190 0.99452190 85 0.99619470 0.99619470 86 0.99756405 0.99756405 87 0.99862953 0.99862953 88 0.99939083 0.99939083 89 0.99984770 0.99984770 90 1.00000000 1.00000000 91 0.99984770 0.99984770 92 0.99939083 0.99939083 93 0.99862953 0.99862953 94 0.99756405 0.99756405 95 0.99619470 0.99619470 96 0.99452190 0.99452190 97 0.99254615 0.99254615 98 0.99026807 0.99026807 99 0.98768834 0.98768834 100 0.98480775 0.98480775 101 0.98162718 0.98162718 102 0.97814760 0.97814760 103 0.97437006 0.97437006 104 0.97029573 0.97029573 105 0.96592583 0.96592583 106 0.96126170 0.96126170 107 0.95630476 0.95630476 108 0.95105652 0.95105652 109 0.94551858 0.94551858 110 0.93969262 0.93969262 111 0.93358043 0.93358043 112 0.92718385 0.92718385 113 0.92050485 0.92050485 114 0.91354546 0.91354546 115 0.90630779 0.90630779 116 0.89879405 0.89879405 117 0.89100652 0.89100652 118 0.88294759 0.88294759 119 0.87461971 0.87461971 120 0.86602540 0.86602540 121 0.85716730 0.85716730 122 0.84804810 0.84804810 123 0.83867057 0.83867057 124 0.82903757 0.82903757 125 0.81915204 0.81915204 126 0.80901699 0.80901699 127 0.79863551 0.79863551 128 0.78801075 0.78801075 129 0.77714596 0.77714596 130 0.76604444 0.76604444 131 0.75470958 0.75470958 132 0.74314483 0.74314482 133 0.73135370 0.73135370 134 0.71933980 0.71933980 135 0.70710678 0.70710678 136 0.69465837 0.69465836 137 0.68199836 0.68199835 138 0.66913061 0.66913060 139 0.65605903 0.65605902 140 0.64278761 0.64278760 141 0.62932039 0.62932038 142 0.61566148 0.61566146 143 0.60181502 0.60181501 144 0.58778525 0.58778523 145 0.57357644 0.57357642 146 0.55919290 0.55919288 147 0.54463904 0.54463901 148 0.52991926 0.52991924 149 0.51503807 0.51503804 150 0.50000000 0.49999996 151 0.48480962 0.48480958 152 0.46947156 0.46947152 153 0.45399050 0.45399045 154 0.43837115 0.43837109 155 0.42261826 0.42261820 156 0.40673664 0.40673657 157 0.39073113 0.39073105 158 0.37460659 0.37460651 159 0.35836795 0.35836786 160 0.34202014 0.34202004 161 0.32556815 0.32556804 162 0.30901699 0.30901686 163 0.29237170 0.29237156 164 0.27563736 0.27563720 165 0.25881905 0.25881887 166 0.24192190 0.24192170 167 0.22495105 0.22495084 168 0.20791169 0.20791145 169 0.19080900 0.19080873 170 0.17364818 0.17364788 171 0.15643447 0.15643414 172 0.13917310 0.13917274 173 0.12186934 0.12186895 174 0.10452846 0.10452803 175 0.08715574 0.08715526 176 0.06975647 0.06975595 177 0.05233596 0.05233537 178 0.03489950 0.03489886 179 0.01745241 0.01745170
DEPTH-based error checking
In response to the comment regarding error calculation, you examine the error associated with the Taylor-Series extensions for sin and cos databases by the number of members, changing the DEPTH and setting the maximum error EMAX 1.0e-8 using something similar to the following for range 0-360 (or 0-2PI ),
#define DEPTH 20 #define EMAX 1.0e-8 ... /* sine as above */ ... /* cos with taylor series expansion to n = DEPTH */ long double cose (const long double deg) { long double rad = deg * M_PI / 180.0, x = 1.0; int sign = -1; for (int n = 2; n < DEPTH; n += 2, sign *= -1) x += sign * powerd (rad, n) / nfact (n); return x; } int main (void) { for (int i = 0; i < 180; i++) { long double sinlibc = sin (i * M_PI / 180.0), coslibc = cos (i * M_PI / 180.0), sints = sine (i), costs = cose (i), serr = fabs (sinlibc - sints), cerr = fabs (coslibc - costs); if (serr > EMAX) fprintf (stderr, "sine error exceeds limit of %e\n" "%3d %11.8Lf %11.8Lf %Le\n", EMAX, i, sinlibc, sints, serr); if (cerr > EMAX) fprintf (stderr, "cose error exceeds limit of %e\n" "%3d %11.8Lf %11.8Lf %Le\n", EMAX, i, coslibc, costs, cerr); } return 0; }
If you check, you will find that for anything less than DEPTH 20 (10 members in each extension) the error will exceed 1.0e-8 for higher angles. Surprisingly, the decompositions are very accurate in the first quadrant with DEPTH values ββbelow 12 (6 terms).
Addemdum - Improved Taylor Series Accuracy Using 0-90 and Quadrants
In the normal expansion of the Taylor series, the error increases with increasing angle. And ... because some just can't mess around, I would like to further compare the accuracy between libc sin/cos and the Taylor series if the calculations were limited to 0-90 degrees and the rest of the period from 90-360 processed by quadrant ( 2, 3 & 4 ), reflecting results from 0-90 . It works - amazingly.
For example, the results of transferring only angles 0-90 and brace angles between 90 - 180 , 180 - 270 and 270 - 360 with an initial angle % 360 give results comparable to the libc math lib functions. The maximum error between the libc and 8 and 10 Taylor-Series extensions was apparently:
Max. error from libc sin/cos
With TSLIM 16
sine_ts max err at : 90.00 deg -- 6.023182e-12 cose_ts max err at : 270.00 deg -- 6.513370e-11
With TSLIM 20
sine_ts max err at : 357.00 deg -- 5.342948e-16 cose_ts max err at : 270.00 deg -- 3.557149e-15
(with a lot of angles that don't differ at all)
The enhanced versions of sine and cose with the Taylor-Series were as follows:
double sine (const double deg) { double fp = deg - (int64_t)deg, qdeg = (int64_t)deg % 360, rad, sine_deg; int pos_quad = 1, sign = -1; qdeg += fp; if (90 < qdeg && qdeg <= 180) qdeg = 180 - qdeg; else if (180 < qdeg && qdeg <= 270) { qdeg = qdeg - 180; pos_quad = 0; } else if (270 < qdeg && qdeg <= 360) { qdeg = 360 - qdeg; pos_quad = 0; } rad = qdeg * M_PI / 180.0; sine_deg = rad; for (int n = 3; n < TSLIM; n += 2, sign *= -1) { double p = rad; uint64_t f = n; for (int i = 1; i < n; i++) p *= rad; for (int i = 1; i < n; i++) f *= i; sine_deg += sign * p / f; } return pos_quad ? sine_deg : -sine_deg; }
and for cos
double cose (const double deg) { double fp = deg - (int64_t)deg, qdeg = (int64_t)deg % 360, rad, cose_deg = 1.0; int pos_quad = 1, sign = -1; qdeg += fp; if (90 < qdeg && qdeg <= 180) { qdeg = 180 - qdeg; pos_quad = 0; } else if (180 < qdeg && qdeg <= 270) { qdeg = qdeg - 180; pos_quad = 0; } else if (270 < qdeg && qdeg <= 360) qdeg = 360 - qdeg; rad = qdeg * M_PI / 180.0; for (int n = 2; n < TSLIM; n += 2, sign *= -1) { double p = rad; uint64_t f = n; for (int i = 1; i < n; i++) p *= rad; for (int i = 1; i < n; i++) f *= i; cose_deg += sign * p / f; } return pos_quad ? cose_deg : -cose_deg; }
The tip of the rabbit trail was found ...