|
Fast Trigonometry Functions Using Lookup Tables
Submitted by |
I'm actually working on generating 3d primitives like sphere, cylinders,
tores, for my 3d engine editor, and when searching on the web I'm surprised
to see that many 3d engines still use cos and sin functions of <math.h>
This code uses lookup tables, a well-known technique, it completely
replaces sin and cos functions, provided you don't use doubles and
you don't care about precision (but who cares for 3d display ?). The
input (in radians) is not limited to 0..PI or -PI..PI, it warps correctly
the input angle value.
Performance comparaison : on my PIV 1.3 GHz, release mode maximized for
speed :
math.h cossin : 3630 ticks
custom cossin : 770 ticks
Frank Rochet,
www.multimania.com/frochet
|
Download Associated File: CosSin.cpp (2,630 bytes)
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <conio.h>
#include <time.h>
#define MAX_CIRCLE_ANGLE 512
#define HALF_MAX_CIRCLE_ANGLE (MAX_CIRCLE_ANGLE/2)
#define QUARTER_MAX_CIRCLE_ANGLE (MAX_CIRCLE_ANGLE/4)
#define MASK_MAX_CIRCLE_ANGLE (MAX_CIRCLE_ANGLE - 1)
#define PI 3.14159265358979323846f
float fast_cossin_table[MAX_CIRCLE_ANGLE]; // Declare table of fast cosinus and sinus
// Copied from NVidia web site
inline void FloatToInt(int *int_pointer, float f)
{
__asm fld f
__asm mov edx,int_pointer
__asm FRNDINT
__asm fistp dword ptr [edx];
}
inline float fastcos(float n)
{
float f = n * HALF_MAX_CIRCLE_ANGLE / PI;
int i;
FloatToInt(&i, f);
if (i < 0)
{
return fast_cossin_table[((-i) + QUARTER_MAX_CIRCLE_ANGLE)&MASK_MAX_CIRCLE_ANGLE];
}
else
{
return fast_cossin_table[(i + QUARTER_MAX_CIRCLE_ANGLE)&MASK_MAX_CIRCLE_ANGLE];
}
assert(0);
}
inline float fastsin(float n)
{
float f = n * HALF_MAX_CIRCLE_ANGLE / PI;
int i;
FloatToInt(&i, f);
if (i < 0)
{
return fast_cossin_table[(-((-i)&MASK_MAX_CIRCLE_ANGLE)) + MAX_CIRCLE_ANGLE];
}
else
{
return fast_cossin_table[i&MASK_MAX_CIRCLE_ANGLE];
}
assert(0);
}
const long iMaxTests = 10000000;
void main()
{
long i;
float s, c;
float sc, scr = 0;
unsigned long dwTickStart, dwTickEnd, dwDuration;
// Build cossin table
for (i = 0 ; i < MAX_CIRCLE_ANGLE ; i++)
{
fast_cossin_table[i] = (float)sin((double)i * PI / HALF_MAX_CIRCLE_ANGLE);
}
double d;
dwTickStart = clock();
for (i = - (iMaxTests/2) ; i < iMaxTests/2 ; i++)
{
d = (double)i;
s = (float)sin(d);
c = (float)cos(d);
// This exist only to force optimiser to not delete code
sc = s * c;
if (sc > scr)
{
scr = sc;
}
}
dwTickEnd = clock();
dwDuration = dwTickEnd - dwTickStart;
printf("%d sin and cos computed in %d ticks with standard math funcs\n", iMaxTests, dwDuration);
float f;
dwTickStart = clock();
for (i = - (iMaxTests/2) ; i < iMaxTests/2 ; i++)
{
f = (float)i;
s = fastsin(f);
c = fastcos(f);
// This exist only to force optimiser to not delete code
sc = s * c;
if (sc > scr)
{
scr = sc;
}
}
dwTickEnd = clock();
dwDuration = dwTickEnd - dwTickStart;
printf("%d sin and cos computed in %d ticks with fast[cos/sin]\n", iMaxTests, dwDuration);
getch();
}
|
|
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
|