Last active
April 28, 2019 19:16
-
-
Save leptos-null/85a8259eeb43b5f60a4bbbfb4019bce4 to your computer and use it in GitHub Desktop.
A C sine routine implemented using a Taylor series
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// taylor_sin.c | |
// | |
// Created by Leptos on 4/25/19. | |
// Copyright © 2019 Leptos. All rights reserved. | |
// | |
#include <math.h> // not required- included only for the M_PI macros which are also included below | |
#include <errno.h> // needed to set errno in the even that the input of sin is an infinity | |
/* including these macros in case you're using this function becuase you don't have a math.h */ | |
#ifndef M_PI | |
#define M_PI 3.14159265358979323846264338327950288 /* pi */ | |
#endif | |
#ifndef M_PI_2 | |
#define M_PI_2 1.57079632679489661923132169163975144 /* pi/2 */ | |
#endif | |
// if you need a cosine routine, likely, the easiest implementation would be `return sin(M_PI_2 - x)` | |
/// A sine routine implemented using a Taylor series. | |
__attribute__((const, nothrow)) double taylor_sin(double x) { | |
if (isinf(x)) { | |
errno = EDOM; | |
return NAN; | |
} | |
/* clamp to [-pi, pi] */ | |
while (x < -M_PI) { | |
x += (M_PI * 2); | |
} | |
while (x > M_PI) { | |
x -= (M_PI * 2); | |
} | |
const double xSquared = x*x; | |
/* the current power value of the series. in order to not recalculate the power, maintain the last value. | |
* on the first interation, we want x**1; on the second, x**3; third, x**5; etc. just multiply by x**2 | |
*/ | |
double xPower = x; | |
/* the current factorial value of the series. similar to xPower, we can just maintain a value | |
*/ | |
uint64_t factorial = 1; | |
/* we need to keep track of the index of the factorial series. | |
* it's possible to use the loop control variable to calculate, but I decided a seperate variable is better */ | |
unsigned factorialIndex = 2; | |
/* this is boolean. it determines whether we're using a plus or minus. flipped on every loop | |
*/ | |
unsigned sign = 0; | |
/* the value to add each series component to, returned after the loop has completed | |
*/ | |
double ret = 0; | |
for (unsigned i = 0; i < 9; i++) { // this controls precision only- the loop control is not used within the body | |
double portion = xPower/factorial; | |
if (sign) { | |
portion = -portion; | |
} | |
ret += portion; | |
sign ^= 1; | |
xPower *= xSquared; | |
factorial *= factorialIndex++; | |
factorial *= factorialIndex++; | |
} | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment