home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Education
/
collectionofeducationcarat1997.iso
/
GAMES
/
CAROM10.ZIP
/
CAROMSRC.ZIP
/
TRIGO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-13
|
8KB
|
266 lines
/*
Copyright (c) 1994 Csaba Mßrkus. All rights reserved.
E-mail: ethcms@duna.ericsson.se
Addr.: H-9600 Sßrvßr, Szatmßr u. 4, Hungary
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without written agreement
is hereby granted, provided that the above copyright notice and the
following two paragraphs appear in all copies of this software.
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE AUTHOR HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE AUTHOR DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS
OR MODIFICATIONS.
*/
/* File: TRIGO.C
Purpose: Replaces the sin(), cos() and atan2() functions with
an implementation where angles are measured in unsigned int numbers:
PI equals 32768 units.
In this system, if we count with a twelwe foot long snooker table,
the maximum error is 0.34 millimetres, which can be considered
very accurate!
*/
#include <windows.h>
#include <math.h>
#include "trigo.h"
/* We use three big global tables:
- sine table for the range 0 .. PI/4 : 8193 float entries (32K)
- cosine table for 0 .. PI/4 : 8193 float entries (32K)
- arc tangent table for the range 0 .. 1 : 10432 int entries (21K)
So we use a total of 85K of memory.
*/
#define SINE_TABLE_ENTRIES 8193
#define ARCTAN_TABLE_ENTRIES 10432
/* Structure for computing the sine and cosine values
*/
typedef struct tag_sincos_struct {
int positive;
int sin;
unsigned constant;
int plus;
} sincos_struct;
/* Structure for computing the arctangent values
*/
typedef struct tag_arctan_struct {
unsigned constant;
int plus;
} arctan_struct;
sincos_struct sine_sincos_struct_table[8] = {
{ 1, 1, 0U, 1 }, /* Sector 0 */
{ 1, 0, 16384U, 0 }, /* Sector 1 */
{ 1, 0, 49152U, 1 }, /* Sector 2 */
{ 1, 1, 32768U, 0 }, /* Sector 3 */
{ 0, 1, 32768U, 1 }, /* Sector 4 */
{ 0, 0, 49152U, 0 }, /* Sector 5 */
{ 0, 0, 16384U, 1 }, /* Sector 6 */
{ 0, 1, 0U, 0 } /* Sector 7 */
};
sincos_struct cosine_sincos_struct_table[8] = {
{ 1, 0, 0U, 1 }, /* Sector 0 */
{ 1, 1, 16384U, 0 }, /* Sector 1 */
{ 0, 1, 49152U, 1 }, /* Sector 2 */
{ 0, 0, 32768U, 0 }, /* Sector 3 */
{ 0, 0, 32768U, 1 }, /* Sector 4 */
{ 0, 1, 49152U, 0 }, /* Sector 5 */
{ 1, 1, 16384U, 1 }, /* Sector 6 */
{ 1, 0, 0U, 0 } /* Sector 7 */
};
arctan_struct arctan_struct_table[8] = {
{ 0U, 1 }, /* Sector 0 */
{ 16384U, 0 }, /* Sector 1 */
{ 16384U, 1 }, /* Sector 2 */
{ 32768U, 0 }, /* Sector 3 */
{ 32768U, 1 }, /* Sector 4 */
{ 49152U, 0 }, /* Sector 5 */
{ 49152U, 1 }, /* Sector 6 */
{ 0U, 0 } /* Sector 7 */
};
/* Global variables containing handles of and pointers to tables.
Note that HGLOBAL is specific to Windows!
*/
HGLOBAL sine_table_handle, cosine_table_handle, arctan_table_handle;
float far *sine_table, *cosine_table;
unsigned far *arctan_table;
/* Memory management: allocation, lock, unlock and free.
These routines are specific to Windows, so you must change them
if you compile this program in a different environment.
*/
HGLOBAL trigo_alloc(DWORD bytes)
{
return GlobalAlloc(GMEM_MOVEABLE, bytes);
}
void far * trigo_lock(HGLOBAL handle)
{
return GlobalLock(handle);
}
void trigo_unlock(HGLOBAL handle)
{
GlobalUnlock(handle);
}
void trigo_free(HGLOBAL handle)
{
GlobalFree(handle);
}
/* Initialization of trigonometric functions.
Returns nonzero if successful.
*/
int init_trigo(void (*callback)(int))
{
float a;
unsigned i;
float s;
/* Allocate memory for tables:
*/
sine_table_handle = trigo_alloc(SINE_TABLE_ENTRIES * sizeof(float));
cosine_table_handle = trigo_alloc(SINE_TABLE_ENTRIES * sizeof(float));
arctan_table_handle = trigo_alloc(ARCTAN_TABLE_ENTRIES * sizeof(unsigned));
if (sine_table_handle == NULL ||
cosine_table_handle == NULL ||
arctan_table_handle == NULL) {
return 0; /* Could not allocate enough memory */
}
/* Lock these tables in memory:
*/
if (!lock_trigo()) {
return 0;
}
if (callback != NULL) {
callback(292);
}
/* Fill in the tables. This takes some seconds...
*/
for (i = 0; i < SINE_TABLE_ENTRIES; i++) {
a = M_PI * (i / 32768.0);
*sine_table++ = s = sin(a);
*cosine_table++ = sqrt(1.0 - s * s);
if ((callback != NULL) && !(i & 63)) {
callback(0);
}
}
for (i = 0; i < ARCTAN_TABLE_ENTRIES; i++) {
a = ((float) i) / ((float) (ARCTAN_TABLE_ENTRIES - 1));
*arctan_table++ = ((float) atan(a)) * ((float) (8192.0 / M_PI_4));
if ((callback != NULL) && !(i & 63)) {
callback(0);
}
}
if (callback != NULL) {
callback(-1);
}
/* Unlock the tables:
*/
unlock_trigo();
/* Initialization was successful:
*/
return 1;
}
/* Frees the global tables:
*/
void uninit_trigo(void)
{
GlobalFree(sine_table_handle);
GlobalFree(cosine_table_handle);
GlobalFree(arctan_table_handle);
}
/* Locks the tables so that an application can begin using these
special trigonometric functions.
Returns nonzero if siccessful.
*/
int lock_trigo(void)
{
sine_table = (float far *) trigo_lock(sine_table_handle);
cosine_table = (float far *) trigo_lock(cosine_table_handle);
arctan_table = (unsigned far *) trigo_lock(arctan_table_handle);
return sine_table == NULL ||
cosine_table == NULL ||
arctan_table == NULL ? 0 : 1;
}
/* Unlocks the global tables. An application should call this routine
when it has finished using the special trigonometric functions and
it won't use them for a while.
*/
void unlock_trigo(void)
{
trigo_unlock(sine_table_handle);
trigo_unlock(cosine_table_handle);
trigo_unlock(arctan_table_handle);
}
float tsin(unsigned angle)
{
sincos_struct *s;
s = sine_sincos_struct_table + (angle / 8192);
return s->positive ?
(s->sin ? sine_table : cosine_table)
[s->plus ? s->constant + angle : s->constant - angle] :
-(s->sin ? sine_table : cosine_table)
[s->plus ? s->constant + angle : s->constant - angle];
}
float tcos(unsigned angle)
{
sincos_struct *s;
s = cosine_sincos_struct_table + (angle / 8192);
return s->positive ?
(s->sin ? sine_table : cosine_table)
[s->plus ? s->constant + angle : s->constant - angle] :
-(s->sin ? sine_table : cosine_table)
[s->plus ? s->constant + angle : s->constant - angle];
}
unsigned tatan2(float y, float x)
{
int sx = (x < 0.0);
int sy = (y < 0.0);
float ax = sx ? -x : x;
float ay = sy ? -y : y;
unsigned index;
arctan_struct *t;
if (ax < ay) {
t = arctan_struct_table + (4 * sy) + (2 * (sx != sy)) + (sx == sy);
index = (ax / ay) * (ARCTAN_TABLE_ENTRIES - 1) + 0.5;
}
else {
t = arctan_struct_table + (4 * sy) + (3 * (sx != sy));
index = (ay / ax) * (ARCTAN_TABLE_ENTRIES - 1) + 0.5;
}
return t->plus ? t->constant + arctan_table[index] :
t->constant - arctan_table[index];
}