[ home ] [ math / cs / ai / phy / as / chem / bio / geo ] [ civ / aero / mech / ee / hdl / os / dev / web / app / sys / net / sec ] [ med / fin / psy / soc / his / lit / lin / phi / arch ] [ off / vg / jp / 2hu / tc / ts / adv / hr / meta / tex ] [ chat ] [ wiki ]

Viewing source code

The following is the source code for post >>>/math/198

\textbf{Computation of trigonometric functions}

Maclaurin series lend an easy way to numerically compute.
We need a helper function  \`ifac(n)\` that computes \[n!,\; n\in\mathbb{N}\] and a helper function \`fpow(x, n)\` that computes \[x^n,\;x\in\mathbb{R}, n\in\mathbb{N}\]:

```
int ifac(int n) {
    return (n > 0) ? (n * ifac(n - 1)) : 1;
}
float fpow(float x, int n) {
    return (n < 0) ? fpow(1/x, -n)
        : (n == 0) ? 1
        : (n == 1) ? x
        : (n > 1)  ? x * fpow(x, n - 1)
        : 1;
}
```
Now \[\sin(x)\] can be computed with \`fsin(x, prec)\`:
```float fsin(float x, int termCount) {
    int n, sign = 1;
    float numer  = x,
          denom  = 1,
          result = sign * (numer / denom);

    for (n = 1; n < termCount; n++)  {
        sign *= -1;
        numer = fpow(x, 2*n+1);
        denom = ifac(2*n+1);
        result += sign * (numer / denom);
    }

    return result;
}```
While \[\cos(x)\] can be computed with \`fcos(x, prec)\`:

```
float fcos(float x, int termCount) {
    int n, sign = 1;
    float numer = 1,
          denom = 1,
          result = sign * (numer / denom);
    for (n = 1; n < termCount; n++)  {
        sign *= -1;
        numer = fpow(x, 2*n);
        denom = ifac(2*n);
        result += sign * (numer / denom);
    }
    return result;
}```

While Maclaurin series for \[\sin(x)\] and \[\cos(x)\] converge on entire \[\mathbb{R}\], they converge the fastest when \[x\in(-\pi,\pi]\] so its good to bound \[x\] to that interval considering trigonometric functions are periodic. In fact, only 5-15 are iterations are usually good enough in double-precision floating point precision.