See what's going on with flipcode!




This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  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.

     

    Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
    Please read our Terms, Conditions, and Privacy information.