Go to notes and algorithms index. ~ Go to home page.

Get a sine and/or a cosine for an angle.


Integer version.

This is a simple function that returns a sine or cosine (or both) for a given angle. It is called sine_12 because it has 12 bits accuracy... The angle you supply is 0 to 4095 where 4095 would be nearly 360 degrees (and 4096 would be the full 360 degrees). The results you get back are -4096 to 4096 (which represents -1.0 to 1.0).

It's unlikely that you'd need this function since you most probably have sin() and cos() functions in your opperating system / SDK... you'd only need it if you were using bare hardware for example, or knocking-up a home brew SDK for a platform... or if your SDK only has floating point versions and for some project you want integer ones.

You can get either or both sine or cosine from this function. You just have to set-up one or two long variables in your program and pass its address, or their addresses, to this routine, and after the routine has competed your variables will have been updated with the results. For example:-


long sine, cosine;

sine_12( 3072, &sine, &cosine );

... sine will then contain the result -4096 and cosine will contain the result 0. The angle 3072 represented 270 degrees and the sine value -4096 represents -1.0. If, for example, you do not want the cosine result then you could have just done the following:

long sine;

sine_12( 3072, &sine, 0 );

To convert degrees to 4096ths multiply by 11.3778.

See below the following array of numbers to see the actual sine_12() routine.



short sine_12_table[1025] = 
   {
    0,  6,  13,  19,  25,  31,  38,  44,  50,  57,  63,  69,  75,  82,  88,  94, 
    101,  107,  113,  119,  126,  132,  138,  144,  151,  157,  163,  170,  176,  182,  188,  195, 
    201,  207,  214,  220,  226,  232,  239,  245,  251,  257,  264,  270,  276,  283,  289,  295, 
    301,  308,  314,  320,  326,  333,  339,  345,  351,  358,  364,  370,  376,  383,  389,  395, 
    401,  408,  414,  420,  426,  433,  439,  445,  451,  458,  464,  470,  476,  483,  489,  495, 
    501,  508,  514,  520,  526,  533,  539,  545,  551,  557,  564,  570,  576,  582,  589,  595, 
    601,  607,  613,  620,  626,  632,  638,  644,  651,  657,  663,  669,  675,  682,  688,  694, 
    700,  706,  713,  719,  725,  731,  737,  744,  750,  756,  762,  768,  774,  781,  787,  793, 

    799,  805,  811,  818,  824,  830,  836,  842,  848,  854,  861,  867,  873,  879,  885,  891, 
    897,  904,  910,  916,  922,  928,  934,  940,  946,  953,  959,  965,  971,  977,  983,  989, 
    995,  1001,  1007,  1014,  1020,  1026,  1032,  1038,  1044,  1050,  1056,  1062,  1068,  1074,  1080,  1086, 
    1092,  1099,  1105,  1111,  1117,  1123,  1129,  1135,  1141,  1147,  1153,  1159,  1165,  1171,  1177,  1183, 
    1189,  1195,  1201,  1207,  1213,  1219,  1225,  1231,  1237,  1243,  1249,  1255,  1261,  1267,  1273,  1279, 
    1285,  1291,  1297,  1303,  1309,  1315,  1321,  1327,  1332,  1338,  1344,  1350,  1356,  1362,  1368,  1374, 
    1380,  1386,  1392,  1398,  1404,  1409,  1415,  1421,  1427,  1433,  1439,  1445,  1451,  1457,  1462,  1468, 
    1474,  1480,  1486,  1492,  1498,  1503,  1509,  1515,  1521,  1527,  1533,  1538,  1544,  1550,  1556,  1562, 

    1567,  1573,  1579,  1585,  1591,  1596,  1602,  1608,  1614,  1620,  1625,  1631,  1637,  1643,  1648,  1654, 
    1660,  1666,  1671,  1677,  1683,  1689,  1694,  1700,  1706,  1711,  1717,  1723,  1729,  1734,  1740,  1746, 
    1751,  1757,  1763,  1768,  1774,  1780,  1785,  1791,  1797,  1802,  1808,  1813,  1819,  1825,  1830,  1836, 
    1842,  1847,  1853,  1858,  1864,  1870,  1875,  1881,  1886,  1892,  1898,  1903,  1909,  1914,  1920,  1925, 
    1931,  1936,  1942,  1947,  1953,  1958,  1964,  1970,  1975,  1981,  1986,  1992,  1997,  2002,  2008,  2013, 
    2019,  2024,  2030,  2035,  2041,  2046,  2052,  2057,  2062,  2068,  2073,  2079,  2084,  2090,  2095,  2100, 
    2106,  2111,  2117,  2122,  2127,  2133,  2138,  2143,  2149,  2154,  2159,  2165,  2170,  2175,  2181,  2186, 
    2191,  2197,  2202,  2207,  2213,  2218,  2223,  2228,  2234,  2239,  2244,  2249,  2255,  2260,  2265,  2270, 

    2276,  2281,  2286,  2291,  2296,  2302,  2307,  2312,  2317,  2322,  2328,  2333,  2338,  2343,  2348,  2353, 
    2359,  2364,  2369,  2374,  2379,  2384,  2389,  2394,  2399,  2405,  2410,  2415,  2420,  2425,  2430,  2435, 
    2440,  2445,  2450,  2455,  2460,  2465,  2470,  2475,  2480,  2485,  2490,  2495,  2500,  2505,  2510,  2515, 
    2520,  2525,  2530,  2535,  2540,  2545,  2550,  2555,  2559,  2564,  2569,  2574,  2579,  2584,  2589,  2594, 
    2598,  2603,  2608,  2613,  2618,  2623,  2628,  2632,  2637,  2642,  2647,  2652,  2656,  2661,  2666,  2671, 
    2675,  2680,  2685,  2690,  2694,  2699,  2704,  2709,  2713,  2718,  2723,  2727,  2732,  2737,  2741,  2746, 
    2751,  2755,  2760,  2765,  2769,  2774,  2779,  2783,  2788,  2792,  2797,  2802,  2806,  2811,  2815,  2820, 
    2824,  2829,  2833,  2838,  2843,  2847,  2852,  2856,  2861,  2865,  2870,  2874,  2878,  2883,  2887,  2892, 

    2896,  2901,  2905,  2910,  2914,  2918,  2923,  2927,  2932,  2936,  2940,  2945,  2949,  2953,  2958,  2962, 
    2967,  2971,  2975,  2979,  2984,  2988,  2992,  2997,  3001,  3005,  3009,  3014,  3018,  3022,  3026,  3031, 
    3035,  3039,  3043,  3048,  3052,  3056,  3060,  3064,  3068,  3073,  3077,  3081,  3085,  3089,  3093,  3097, 
    3102,  3106,  3110,  3114,  3118,  3122,  3126,  3130,  3134,  3138,  3142,  3146,  3150,  3154,  3158,  3162, 
    3166,  3170,  3174,  3178,  3182,  3186,  3190,  3194,  3198,  3202,  3206,  3210,  3214,  3217,  3221,  3225, 
    3229,  3233,  3237,  3241,  3244,  3248,  3252,  3256,  3260,  3264,  3267,  3271,  3275,  3279,  3282,  3286, 
    3290,  3294,  3297,  3301,  3305,  3309,  3312,  3316,  3320,  3323,  3327,  3331,  3334,  3338,  3342,  3345, 
    3349,  3352,  3356,  3360,  3363,  3367,  3370,  3374,  3378,  3381,  3385,  3388,  3392,  3395,  3399,  3402, 

    3406,  3409,  3413,  3416,  3420,  3423,  3426,  3430,  3433,  3437,  3440,  3444,  3447,  3450,  3454,  3457, 
    3461,  3464,  3467,  3471,  3474,  3477,  3481,  3484,  3487,  3490,  3494,  3497,  3500,  3504,  3507,  3510, 
    3513,  3516,  3520,  3523,  3526,  3529,  3532,  3536,  3539,  3542,  3545,  3548,  3551,  3555,  3558,  3561, 
    3564,  3567,  3570,  3573,  3576,  3579,  3582,  3585,  3588,  3591,  3594,  3597,  3600,  3603,  3606,  3609, 
    3612,  3615,  3618,  3621,  3624,  3627,  3630,  3633,  3636,  3639,  3642,  3644,  3647,  3650,  3653,  3656, 
    3659,  3661,  3664,  3667,  3670,  3673,  3675,  3678,  3681,  3684,  3686,  3689,  3692,  3695,  3697,  3700, 
    3703,  3705,  3708,  3711,  3713,  3716,  3719,  3721,  3724,  3727,  3729,  3732,  3734,  3737,  3739,  3742, 
    3745,  3747,  3750,  3752,  3755,  3757,  3760,  3762,  3765,  3767,  3770,  3772,  3775,  3777,  3779,  3782, 

    3784,  3787,  3789,  3791,  3794,  3796,  3798,  3801,  3803,  3805,  3808,  3810,  3812,  3815,  3817,  3819, 
    3822,  3824,  3826,  3828,  3831,  3833,  3835,  3837,  3839,  3842,  3844,  3846,  3848,  3850,  3852,  3854, 
    3857,  3859,  3861,  3863,  3865,  3867,  3869,  3871,  3873,  3875,  3877,  3879,  3881,  3883,  3885,  3887, 
    3889,  3891,  3893,  3895,  3897,  3899,  3901,  3903,  3905,  3907,  3909,  3910,  3912,  3914,  3916,  3918, 
    3920,  3921,  3923,  3925,  3927,  3929,  3930,  3932,  3934,  3936,  3937,  3939,  3941,  3943,  3944,  3946, 
    3948,  3949,  3951,  3953,  3954,  3956,  3958,  3959,  3961,  3962,  3964,  3965,  3967,  3969,  3970,  3972, 
    3973,  3975,  3976,  3978,  3979,  3981,  3982,  3984,  3985,  3987,  3988,  3989,  3991,  3992,  3994,  3995, 
    3996,  3998,  3999,  4001,  4002,  4003,  4005,  4006,  4007,  4008,  4010,  4011,  4012,  4014,  4015,  4016, 

    4017,  4019,  4020,  4021,  4022,  4023,  4024,  4026,  4027,  4028,  4029,  4030,  4031,  4032,  4034,  4035, 
    4036,  4037,  4038,  4039,  4040,  4041,  4042,  4043,  4044,  4045,  4046,  4047,  4048,  4049,  4050,  4051, 
    4052,  4053,  4053,  4054,  4055,  4056,  4057,  4058,  4059,  4060,  4060,  4061,  4062,  4063,  4064,  4064, 
    4065,  4066,  4067,  4067,  4068,  4069,  4070,  4070,  4071,  4072,  4072,  4073,  4074,  4074,  4075,  4076, 
    4076,  4077,  4077,  4078,  4079,  4079,  4080,  4080,  4081,  4081,  4082,  4082,  4083,  4083,  4084,  4084, 
    4085,  4085,  4086,  4086,  4087,  4087,  4088,  4088,  4088,  4089,  4089,  4089,  4090,  4090,  4090,  4091, 
    4091,  4091,  4092,  4092,  4092,  4092,  4093,  4093,  4093,  4093,  4094,  4094,  4094,  4094,  4094,  4095, 
    4095,  4095,  4095,  4095,  4095,  4095,  4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096,  4096, 

    4096
   };



void sine_12( long p_angle, long *p_sine_ptr, long *p_cosine_ptr )
   {
   // Jon P 2006.  Find the Sine and or Cosine for the specified
   // angle.
   //
   // Where a p_angle of 4096 is 360 degrees, 1024 is 90 degrees etc.
   // (Integer 12 bit accuracy).  Larger and negative angles can be
   // specified and will be wrapped to the range 0 to 4095 internally.
   //
   // A valid address must be supplied as for at least one of the
   // parameters: sine_ptr and cosine_ptr. This is where the result(s)
   // will be returned.  If you do not want one of the results specify
   // sine_ptr or cosine_ptr as zero.  If you specify both paramters
   // as zero this routine will have not produce any result.
   // 
   // This uses an abridged sine look-up table which stores only the
   // first quarter (90 degrees) of a complete sine wave. The correct
   // result is obtained for greater angles by changing the sign of the
   // value in the table and or doing an appropriate subrtaction
   // with the specified angle.
   //
   long angle = p_angle;
   while( angle > 4095 )
      { // wrap angle
      angle -= 4096;
      }
   while( angle < 0 )
      { // wrap angle
      angle += 4096;
      }
   if ( angle <= 1024 )
      {
      if ( p_sine_ptr ) *p_sine_ptr = sine_12_table[ angle ];
      if ( p_cosine_ptr ) *p_cosine_ptr = sine_12_table[ 1024 - angle ];
      }
   else if ( angle <= 2048 )
      {
      if ( p_sine_ptr ) *p_sine_ptr = sine_12_table[ 1024 - ( angle - 1024 ) ];
      if ( p_cosine_ptr ) *p_cosine_ptr = 0 - sine_12_table[ angle - 1024 ];
      }
   else if ( angle < 3072 )
      {
      if ( p_sine_ptr ) *p_sine_ptr =  0 - sine_12_table[ angle - 2048 ];
      if ( p_cosine_ptr ) *p_cosine_ptr = 0 - sine_12_table[ 1024 - ( angle - 2048 ) ];
      }
   else
      {
      if ( p_sine_ptr ) *p_sine_ptr =  0 - sine_12_table[ 1024 - ( angle - 3072 ) ];
      if ( p_cosine_ptr ) *p_cosine_ptr = sine_12_table[ angle - 3072 ];
      }
   }