less_retarded_wiki/sin.md
2022-11-19 22:33:58 +01:00

7.2 KiB

Sine

Sine, abbreviated sin, is a trigonometric function that simply said models a smooth oscillation, it is one of the most important and basic functions in geometry, mathematics and physics, and of course in programming. Along with cosine, tangent and cotangent 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 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 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 values on the x line??? Nubs often can't comprehend this. These pi values are values in radians, units of measuring angles where 2 pi is the full angle (360 degrees). In fact sine is sometimes shown with degrees 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, the codomain are real numbers in interval <-1,1> (including both bounds).
  • It is an odd function (-sin(x) = sin(-x)).
  • It is periodic, with a period of 2 pi.
  • Sine is just shifted cosine, i.e. sin(x) = cos(x - 1/2 pi)
  • Its inverse function is arcus sine, 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.
  • Derivative of sin(x) is cos(x), the integral 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.
  • Sine and cosine functions are used to draw circles. If you plot points with x coordinate equal to sin(t) and y coordinate equal to cos(t) for t going from 0 to 2 * pi, you'll get a unit circle.
  • 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 the function sin is in math.h. Spare yourself bugs, always check if your sin function expects radians or degrees!

There exists an ugly engineering approximation 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) that doesn't need extreme accuracy, consider using a look up table. 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 by further interpolating (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.

Very rough and fast approximations e.g. for primitive music synthesis can be done with the traditional very basic square or triangle 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(unsigned char 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, 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 fixed point 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 to approximate sine with a polynomial to whatever precision we need (this is used e.g. in calculators etc.).