less_retarded_wiki/sin.md

127 lines
6.9 KiB
Markdown
Raw Normal View History

# Sine
Sine, abbreviated *sin*, is a [trigonometric](trigonometry.md) [function](function.md) that simply said models a smooth oscillation, it is one of the most important and basic functions in geometry, [mathematics](math.md) and [physics](physics.md), and of course in [programming](programming.md). Along with [cosine](cos.md), [tangent](tan.md) and [cotangent](cot.md) it belongs to a group of functions that can be defined by ratios of sides of a right triangle depending on one of the angles in it (hence *trigonometric* -- "triangle measuring"). If some measurement looks like sine function, we say it is *harmonic*. This is very common in nature and technology, e.g. a weight on a spring goes up and down by this function, [alternating current](ac.md) voltage has the sine shape (because it is generated by a circular motion) etc.
The function is most commonly defined using a right triangle as follows. Consider the following triangle:
```
/|
/ |
/ |
c/ |
/ |a
/ |
/ _|
/A____|_|
b
```
*Sin(A)*, where *A* is the angle between side *b* and *c*, is the ratio *a* / *c*. The function can be defined in many other ways, for example it is the curve we get when tracking only one direction (e.g. horizontal) of a point moving alongside circle. It can also be defined as a solution to some [differential equations](differential_equation.md) etc.
The graph of the sine function is following:
```
^ sin(x)
|
1_|_
| .--'''--.
-1/2 pi | _.'' ''._ 3/2 pi
.________|________.'________|________'|________|________.' --> x
'._ | _.'|0 | |'._ | _.'|
''--___--'' _|_ 1/2 pi pi ''--___--'' 2 pi
-1 |
```
**Why the fuck are there these [pi](pi.md) values on the x line???** Nubs often can't comprehend this. These pi values are values in **[radians](radian.md)**, units of measuring angles where *2 pi* is the full angle (360 degrees). In fact sine is sometimes shown with [degrees](degree.md) instead of radians (so imagine 90 degrees on the line where there is 1/2 pi etc.), but mathematicians prefer radians. **But why are there angles in the first place???** Why doesn't it go e.g. from 0 to 1 like all other nice functions? Well, it's because of the relation to geometry, remember the fucking triangle above... also if you define sine with a circle it all repeats after *2 pi*. Just draw some picture if you don't get it.
Some additional facts and properties regarding the sine functions are:
- The domain are all [real numbers](real_number.md), the [codomain](codomain.md) are real numbers in interval <-1,1> (including both bounds).
- It is an [odd function](odd_function.md) (*-sin(x) = sin(-x)*).
- It is periodic, with a period of 2 [pi](pi.md).
- Sine is just shifted [cosine](cos.md), i.e. *sin(x) = cos(x - 1/2 pi)*
- Its inverse function is [arcus sine](asin.md), abbreviated *asin*, also written as *sin^-1* -- this function tells you what argument you need to give to sin to get a specific result number. It's actually an inverse of only part of the sine function because the whole sine function can't be inverted, it isn't [bijective](bijection.md).
- [Derivative](derivative.md) of *sin(x)* is *cos(x)*, the [integral](integral.md) of *sin(x) dx* is *-cos(x)*.
- By adding many differently shifted and scaled sine functions we can create basically any other function, see e.g. [cosine transform](cosine_transform.md).
- *sin(x)^2 + cos(x)^2 = 1*
Some values of the sine function are:
| x (rad) | x (deg) | sin(x) |
|----------|----------|--------------------|
| 0 | 0 | 0 |
| pi / 12 | 15 | ~0.259 |
| pi / 6 | 30 | 0.5 |
| pi / 4 | 45 | sqrt(2)/2 ~= 0.707 |
| pi / 3 | 60 | sqrt(3)/2 ~= 0.866 |
| pi / 2 | 90 | 1 |
| 2 pi | 360 | 0 |
## Programming
In programming languages sine is generally available in some math library, for example in [C](c.md) the function `sin` is in `math.h`. Spare yourself bugs, **always check if your sin function expects [radians](radian.md) or degrees!**
There exists an **ugly engineering [approximation](approximation.md)** of sine that can be useful sometimes, it says that
*sin(x) = x, for small x*
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.
2022-11-18 15:01:33 +01:00
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
#define PI ((int) (UNIT * 3.14159265))
/* Integer sine using Bhaskara's approx. Returns a number
in <-UNIT, UNIT> interval. Argument is in radians * UNIT. */
int sinInt(int x)
{
int sign = 1;
if (x < 0) // odd function
{
x *= -1;
sign = -1;
}
x %= 2 * PI;
if (x > PI)
{
x -= PI;
sign *= -1;
}
int tmp = PI - x;
return sign * (16 * x * tmp) / ((5 * PI * PI - 4 * x * tmp) / UNIT);
}
```
Another approach is to use [Taylor series](taylor_series.md) to approximate sine with a [polynomial](polynomial.md) to whatever precision we need (this is used e.g. in calculators etc.).