Update
This commit is contained in:
parent
46523273c7
commit
64e42585cf
13 changed files with 93 additions and 23 deletions
21
sin.md
21
sin.md
|
@ -69,12 +69,29 @@ There exists an **ugly engineering [approximation](approximation.md)** of sine t
|
|||
|
||||
Indeed, sine looks similar to a mere line near 0, but you can see it quickly diverges.
|
||||
|
||||
|
||||
When implementing your own `sin` function, consider what you expect from it.
|
||||
|
||||
If you want a small, fast and perhaps integer only `sin` function (the one we'd prefer in [LRS](lrs.md)) that doesn't need extreme accuracy, consider using a **[look up table](lut.md)**. You simply precompute the values of the sine function into a static table in memory and the function just retrieves them when called -- this is super fast. Note that you can save a lot of space by **only storing sine values between 0 and 1/2 pi**, the remaining parts of the function are just different transformations of this part. You can further save space and/or make the function work with [floats](float.md) by further [interpolating](interpolation.md) (even just linearly) between the stored values, for example if `sin(3.45)` is called and you only have values stored for `sin(3.4)` and `sin(3.5)`, you simply average them.
|
||||
|
||||
If you don't need extreme speed there exist nice sine [approximation](approximation.md), e.g. the extremely accurate **Bhaskara I's approximation** (angle in radians): *sin(x) ~= (16 * x * (pi - x)) / (5 * pi^2 - 4 * x * (pi - x))*. (This formula is actually more elegant for cosine, so it may be even better to consider using that.) Here is a [C](c.md) [fixed point](fixed_point.md) implementation:
|
||||
Very rough and fast approximations e.g. for primitive music synthesis can be done with the traditional very basic [square](square_function.md) or [triangle](triangle_function.md) functions. The following is a simple 8bit linear approximation that's more accurate than square or triangle (approximates sine with a linear function in each quadrant):
|
||||
|
||||
```
|
||||
unsigned char sinA(uint8_t x)
|
||||
{
|
||||
unsigned char quadrant = x / 64;
|
||||
|
||||
x %= 64;
|
||||
|
||||
if (quadrant % 2 == 1)
|
||||
x = 63 - x;
|
||||
|
||||
x = x < 32 ? (2 * x + x) : (64 + x);
|
||||
|
||||
return quadrant <= 1 ? (128 + x) : (127 - x);
|
||||
}
|
||||
```
|
||||
|
||||
If you don't need extreme speed there exist very nice sine [approximations](approximation.md), e.g. the extremely accurate **Bhaskara I's approximation** (angle in radians): *sin(x) ~= (16 * x * (pi - x)) / (5 * pi^2 - 4 * x * (pi - x))*. (This formula is actually more elegant for cosine, so it may be even better to consider using that.) Here is a [C](c.md) [fixed point](fixed_point.md) implementation:
|
||||
|
||||
```
|
||||
#define UNIT 1024
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue