home *** CD-ROM | disk | FTP | other *** search
/ Collection of Education / collectionofeducationcarat1997.iso / GAMES / CAROM10.ZIP / CAROMSRC.ZIP / TRIGO.C < prev    next >
C/C++ Source or Header  |  1994-08-13  |  8KB  |  266 lines

  1. /*
  2.    Copyright (c) 1994 Csaba Mßrkus. All rights reserved.
  3.    E-mail: ethcms@duna.ericsson.se
  4.    Addr.:  H-9600 Sßrvßr, Szatmßr u. 4, Hungary
  5.  
  6.    Permission to use, copy, modify, and distribute this software and its
  7.    documentation for any purpose, without fee, and without written agreement
  8.    is hereby granted, provided that the above copyright notice and the
  9.    following two paragraphs appear in all copies of this software.
  10.  
  11.    IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR
  12.    DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  13.    OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS
  14.    BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  15.  
  16.    THE AUTHOR DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17.    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.    THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS
  19.    NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS
  20.    OR MODIFICATIONS.
  21. */
  22.  
  23. /* File: TRIGO.C
  24.  
  25.    Purpose: Replaces the sin(), cos() and atan2() functions with
  26.    an implementation where angles are measured in unsigned int numbers:
  27.    PI equals 32768 units.
  28.    In this system, if we count with a twelwe foot long snooker table,
  29.    the maximum error is 0.34 millimetres, which can be considered
  30.    very accurate!
  31. */
  32.  
  33. #include <windows.h>
  34. #include <math.h>
  35. #include "trigo.h"
  36.  
  37. /* We use three big global tables:
  38.      - sine table for the range 0 .. PI/4 : 8193 float entries (32K)
  39.      - cosine table for 0 .. PI/4 :         8193 float entries (32K)
  40.      - arc tangent table for the range 0 .. 1 : 10432 int entries (21K)
  41.    So we use a total of 85K of memory.
  42. */
  43.  
  44. #define SINE_TABLE_ENTRIES    8193
  45. #define ARCTAN_TABLE_ENTRIES   10432
  46.  
  47. /* Structure for computing the sine and cosine values
  48. */
  49. typedef struct tag_sincos_struct {
  50.     int positive;
  51.     int sin;
  52.     unsigned constant;
  53.     int plus;
  54. } sincos_struct; 
  55.  
  56. /* Structure for computing the arctangent values
  57. */
  58. typedef struct tag_arctan_struct {
  59.     unsigned constant;
  60.     int plus;
  61. } arctan_struct; 
  62.  
  63. sincos_struct sine_sincos_struct_table[8] = {
  64.     { 1, 1,     0U, 1 },    /* Sector 0 */
  65.     { 1, 0, 16384U, 0 },    /* Sector 1 */
  66.     { 1, 0, 49152U, 1 },    /* Sector 2 */
  67.     { 1, 1, 32768U, 0 },    /* Sector 3 */
  68.     { 0, 1, 32768U, 1 },    /* Sector 4 */
  69.     { 0, 0, 49152U, 0 },    /* Sector 5 */
  70.     { 0, 0, 16384U, 1 },    /* Sector 6 */
  71.     { 0, 1,     0U, 0 }        /* Sector 7 */
  72. };
  73.  
  74. sincos_struct cosine_sincos_struct_table[8] = {
  75.     { 1, 0,     0U, 1 },    /* Sector 0 */
  76.     { 1, 1, 16384U, 0 },    /* Sector 1 */
  77.     { 0, 1, 49152U, 1 },    /* Sector 2 */
  78.     { 0, 0, 32768U, 0 },    /* Sector 3 */
  79.     { 0, 0, 32768U, 1 },    /* Sector 4 */
  80.     { 0, 1, 49152U, 0 },    /* Sector 5 */
  81.     { 1, 1, 16384U, 1 },    /* Sector 6 */
  82.     { 1, 0,     0U, 0 }        /* Sector 7 */
  83. };
  84.  
  85. arctan_struct arctan_struct_table[8] = {
  86.     {     0U, 1 },    /* Sector 0 */
  87.     { 16384U, 0 },      /* Sector 1 */
  88.     { 16384U, 1 },      /* Sector 2 */
  89.     { 32768U, 0 },      /* Sector 3 */
  90.     { 32768U, 1 },      /* Sector 4 */
  91.     { 49152U, 0 },      /* Sector 5 */
  92.     { 49152U, 1 },      /* Sector 6 */
  93.     {     0U, 0 }       /* Sector 7 */
  94. };
  95.  
  96. /* Global variables containing handles of and pointers to tables.
  97.    Note that HGLOBAL is specific to Windows!
  98. */
  99. HGLOBAL sine_table_handle, cosine_table_handle, arctan_table_handle;
  100. float far *sine_table, *cosine_table;
  101. unsigned far *arctan_table;
  102.  
  103. /* Memory management: allocation, lock, unlock and free. 
  104.    These routines are specific to Windows, so you must change them
  105.    if you compile this program in a different environment.
  106. */
  107. HGLOBAL trigo_alloc(DWORD bytes)
  108. {
  109.     return GlobalAlloc(GMEM_MOVEABLE, bytes);
  110. }
  111.  
  112. void far * trigo_lock(HGLOBAL handle)
  113. {
  114.     return GlobalLock(handle);
  115. }
  116.  
  117. void trigo_unlock(HGLOBAL handle)
  118. {
  119.     GlobalUnlock(handle);
  120. }
  121.  
  122. void trigo_free(HGLOBAL handle)
  123. {
  124.     GlobalFree(handle);
  125. }
  126.  
  127.  
  128. /* Initialization of trigonometric functions.
  129.    Returns nonzero if successful.
  130. */
  131. int init_trigo(void (*callback)(int))
  132. {
  133.     float a;
  134.     unsigned i;
  135.     float s;
  136.  
  137.     /* Allocate memory for tables:
  138.     */
  139.     sine_table_handle = trigo_alloc(SINE_TABLE_ENTRIES * sizeof(float));
  140.     cosine_table_handle = trigo_alloc(SINE_TABLE_ENTRIES * sizeof(float));
  141.     arctan_table_handle = trigo_alloc(ARCTAN_TABLE_ENTRIES * sizeof(unsigned));
  142.     if (sine_table_handle == NULL ||
  143.     cosine_table_handle == NULL ||
  144.     arctan_table_handle == NULL) {
  145.     return 0;        /* Could not allocate enough memory */
  146.     }
  147.  
  148.     /* Lock these tables in memory:
  149.     */
  150.     if (!lock_trigo()) {
  151.     return 0;
  152.     }
  153.  
  154.     if (callback != NULL) {
  155.     callback(292);
  156.     }
  157.  
  158.     /* Fill in the tables. This takes some seconds...
  159.     */
  160.     for (i = 0; i < SINE_TABLE_ENTRIES; i++) {
  161.     a = M_PI * (i / 32768.0);
  162.     *sine_table++ = s = sin(a);
  163.     *cosine_table++ = sqrt(1.0 - s * s);
  164.     if ((callback != NULL) && !(i & 63)) {
  165.         callback(0);
  166.         }
  167.     }
  168.     for (i = 0; i < ARCTAN_TABLE_ENTRIES; i++) {
  169.     a = ((float) i) / ((float) (ARCTAN_TABLE_ENTRIES - 1));
  170.     *arctan_table++ = ((float) atan(a)) * ((float) (8192.0 / M_PI_4));
  171.     if ((callback != NULL) && !(i & 63)) {
  172.         callback(0);
  173.         }
  174.     }
  175.  
  176.     if (callback != NULL) {
  177.     callback(-1);
  178.     }
  179.  
  180.     /* Unlock the tables:
  181.     */
  182.     unlock_trigo();
  183.  
  184.     /* Initialization was successful:
  185.     */
  186.     return 1;
  187. }
  188.  
  189. /* Frees the global tables:
  190. */
  191. void uninit_trigo(void)
  192. {
  193.     GlobalFree(sine_table_handle);
  194.     GlobalFree(cosine_table_handle);
  195.     GlobalFree(arctan_table_handle);
  196. }
  197.  
  198. /* Locks the tables so that an application can begin using these
  199.    special trigonometric functions.
  200.    Returns nonzero if siccessful.
  201. */
  202. int lock_trigo(void)
  203. {
  204.     sine_table = (float far *) trigo_lock(sine_table_handle);
  205.     cosine_table = (float far *) trigo_lock(cosine_table_handle);
  206.     arctan_table = (unsigned far *) trigo_lock(arctan_table_handle);
  207.     return sine_table == NULL ||
  208.        cosine_table == NULL ||
  209.        arctan_table == NULL ? 0 : 1;
  210. }
  211.  
  212. /* Unlocks the global tables. An application should call this routine
  213.    when it has finished using the special trigonometric functions and
  214.    it won't use them for a while.
  215. */
  216. void unlock_trigo(void)
  217. {
  218.     trigo_unlock(sine_table_handle);
  219.     trigo_unlock(cosine_table_handle);
  220.     trigo_unlock(arctan_table_handle);
  221. }
  222.  
  223. float tsin(unsigned angle)
  224. {
  225.     sincos_struct *s;
  226.  
  227.     s = sine_sincos_struct_table + (angle / 8192);
  228.     return s->positive ?
  229.         (s->sin ? sine_table : cosine_table)
  230.             [s->plus ? s->constant + angle : s->constant - angle] :
  231.     -(s->sin ? sine_table : cosine_table)
  232.         [s->plus ? s->constant + angle : s->constant - angle];
  233. }
  234.  
  235. float tcos(unsigned angle)
  236. {
  237.     sincos_struct *s;
  238.  
  239.     s = cosine_sincos_struct_table + (angle / 8192);
  240.     return s->positive ?
  241.     (s->sin ? sine_table : cosine_table)
  242.             [s->plus ? s->constant + angle : s->constant - angle] :
  243.     -(s->sin ? sine_table : cosine_table)
  244.         [s->plus ? s->constant + angle : s->constant - angle];
  245. }
  246.  
  247. unsigned tatan2(float y, float x)
  248. {
  249.     int sx = (x < 0.0);
  250.     int sy = (y < 0.0);
  251.     float ax = sx ? -x : x;
  252.     float ay = sy ? -y : y;
  253.     unsigned index;
  254.     arctan_struct *t;
  255.  
  256.     if (ax < ay) {
  257.         t = arctan_struct_table + (4 * sy) + (2 * (sx != sy)) + (sx == sy);
  258.     index = (ax / ay) * (ARCTAN_TABLE_ENTRIES - 1) + 0.5;
  259.     }
  260.     else {
  261.         t = arctan_struct_table + (4 * sy) + (3 * (sx != sy));
  262.         index = (ay / ax) * (ARCTAN_TABLE_ENTRIES - 1) + 0.5;
  263.     }
  264.     return t->plus ? t->constant + arctan_table[index] :
  265.                  t->constant - arctan_table[index];    
  266. }