Skip to content

Instantly share code, notes, and snippets.

@leptos-null
Last active April 28, 2019 19:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leptos-null/85a8259eeb43b5f60a4bbbfb4019bce4 to your computer and use it in GitHub Desktop.
Save leptos-null/85a8259eeb43b5f60a4bbbfb4019bce4 to your computer and use it in GitHub Desktop.
A C sine routine implemented using a Taylor series
//
// 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