home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char sccsid[] = "@(#) trig.c 5.1 89/02/20";
- #endif
-
- /*
- * Copyright (c) David T. Lewis 1988
- * All rights reserved.
- *
- * Permission is granted to use this for any personal noncommercial use.
- * You may not distribute source or executable code for profit, nor
- * may you distribute it with a commercial product without the written
- * consent of the author. Please send modifications to the author for
- * inclusion in updates to the program. Thanks.
- */
-
- /* Integer approximations to simple trig functions. Results are scaled */
- /* by a factor of TRIG_SCALE. */
-
- /* The macro TRIG_SCALE is defined in graphics.h so that other routines */
- /* can use it. F_TRIG_SCALE is the same value, but in floating point */
- /* format. The defines should look like this: */
- /* */
- /* #define TRIG_SCALE 32768 */
- /* #define F_TRIG_SCALE 32768.0 */
- /* */
- /* The macro PTS_PER_QUADRANT defines the size of the sin_table and */
- /* cos_table arrays. It is defined in graphics.h and should look */
- /* like this: */
- /* */
- /* #define PTS_PER_QUADRANT 64 */
- /* */
-
- #include "config.h"
- #if MIX_C
- #else
- #include <math.h>
- #endif /* MIX_C */
- #include "bitmaps.h"
- #include "graphics.h"
-
- #define L_PI 102944L /* Value of pi times TRIG_SCALE. */
- #define L_PI_2 51472L /* Value of pi/2 times TRIG_SCALE. */
- #define L_PI_4 25736L /* Value of pi/4 times TRIG_SCALE. */
-
- #define CIRCLE_SIZE 205887L /* Value of pi * 2 * TRIG_SCALE. */
-
- #define TABLESLICE 804L /* (L_PI_2 / PTS_PER_QUADRANT) */
-
- #define XINDEX 0 /* For specifying array indices. */
- #define YINDEX 1
-
- /* The following two arrays are tables of values for cos and sin */
- /* for one quadrant of a circle, divided into PTS_PER_QUADRANT slices. */
-
- long cos_table[PTS_PER_QUADRANT] = {
- 32758L, 32729L, 32679L, 32610L, 32522L, 32413L, 32286L, 32138L,
- 31972L, 31786L, 31581L, 31357L, 31114L, 30853L, 30572L, 30274L,
- 29957L, 29622L, 29269L, 28899L, 28511L, 28106L, 27684L, 27246L,
- 26791L, 26320L, 25833L, 25330L, 24812L, 24279L, 23732L, 23170L,
- 22595L, 22006L, 21403L, 20788L, 20160L, 19520L, 18868L, 18205L,
- 17531L, 16846L, 16151L, 15447L, 14733L, 14010L, 13279L, 12540L,
- 11793L, 11039L, 10279L, 9512L, 8740L, 7962L, 7180L, 6393L,
- 5602L, 4808L, 4011L, 3212L, 2411L, 1608L, 804L, 0L
- };
-
- long sin_table[PTS_PER_QUADRANT] = {
- 804L, 1608L, 2411L, 3212L, 4011L, 4808L, 5602L, 6393L,
- 7180L, 7962L, 8740L, 9512L, 10279L, 11039L, 11793L, 12540L,
- 13279L, 14010L, 14733L, 15447L, 16151L, 16846L, 17531L, 18205L,
- 18868L, 19520L, 20160L, 20788L, 21403L, 22006L, 22595L, 23170L,
- 23732L, 24279L, 24812L, 25330L, 25833L, 26320L, 26791L, 27246L,
- 27684L, 28106L, 28511L, 28899L, 29269L, 29622L, 29957L, 30274L,
- 30572L, 30853L, 31114L, 31357L, 31581L, 31786L, 31972L, 32138L,
- 32286L, 32413L, 32522L, 32610L, 32679L, 32729L, 32758L, 32768L
- };
-
- /* Estimate sin by interpolation. Return long integer value. */
-
- long longsin(theta)
- float theta;
- {
- long longtheta;
- int quadrant;
- long value1, value2;
- long value;
- long intpart;
- long fractionpart;
-
- /* We have a floating point value for theta. Put theta */
- /* into a long integer for the rest of the processing. */
- /* Keep everything scaled by a factor of TRIG_SCALE. */
-
- longtheta = (long)(theta * F_TRIG_SCALE);
-
- /* Make angle positive. */
-
- while (longtheta < 0) longtheta += CIRCLE_SIZE;
-
- /* Figure quadrant while making it less than PI/2. */
-
- quadrant = 1;
-
- while (longtheta > L_PI_2) {
- longtheta -= L_PI_2;
- quadrant++;
- if (quadrant > 4) quadrant = 1;
- }
-
- /* If Quadrant 2 or 4 we need to use the reverse of the */
- /* interpolation table. */
-
- if (quadrant == 2 || quadrant == 4) longtheta = L_PI_2 - longtheta;
-
- /* Express angle in terms of number of table increments. */
-
- intpart = longtheta / TABLESLICE;
-
- fractionpart = longtheta % TABLESLICE;
-
- /* This looks like a kludge, but it isn't. When TABLESLICE is */
- /* set to TABLESLICE, we have the smallest error in the result. */
- /* This just rounds back down when we overshoot the table. */
-
- if (intpart >= PTS_PER_QUADRANT) {
- intpart = PTS_PER_QUADRANT - 1;
- fractionpart = TABLESLICE;
- }
-
- /* Interpolate. */
-
- if (intpart <= 0) {
- value1 = 0;
- value2 = sin_table[0];
- }
- else {
- value2 = sin_table[(int)(intpart--)];
- value1 = sin_table[(int)intpart];
- }
-
- value = value1 + (fractionpart * (value2 - value1)) / TABLESLICE;
-
- /* If Quadrant 3 or 4 the result should be negative. */
-
- if (quadrant == 3 || quadrant == 4) return(-value);
- else return(value);
- }
-
-
- /* Estimate cos by interpolation. Return long integer value. */
-
- long longcos(theta)
- float theta;
- {
- long longtheta;
- int quadrant;
- long value1, value2;
- long value;
- long intpart;
- long fractionpart;
-
- /* We have a floating point value for theta. Put theta */
- /* into a long integer for the rest of the processing. */
- /* Keep everything scaled by a factor of TRIG_SCALE. */
-
- longtheta = (long)(theta * F_TRIG_SCALE);
-
- /* Make angle positive. */
-
- while (longtheta < 0) longtheta += CIRCLE_SIZE;
-
- /* Figure quadrant while making it less than PI/2. */
-
- quadrant = 1;
-
- while (longtheta > L_PI_2) {
- longtheta -= L_PI_2;
- quadrant++;
- if (quadrant > 4) quadrant = 1;
- }
-
- /* If Quadrant 2 or 4 we need to use the reverse of the */
- /* interpolation table. */
-
- if (quadrant == 2 || quadrant == 4) longtheta = L_PI_2 - longtheta;
-
- /* Express angle in terms of number of table increments. */
-
- intpart = longtheta / TABLESLICE;
-
- fractionpart = longtheta % TABLESLICE;
-
- /* This looks like a kludge, but it isn't. When TABLESLICE is */
- /* set to TABLESLICE, we have the smallest error in the result. */
- /* This just rounds back down when we overshoot the table. */
-
- if (intpart >= PTS_PER_QUADRANT) {
- intpart = PTS_PER_QUADRANT - 1;
- fractionpart = TABLESLICE;
- }
-
- /* Interpolate. */
-
- if (intpart <= 0) {
- value1 = 32768L;
- value2 = cos_table[0];
- }
- else {
- value2 = cos_table[(int)(intpart--)];
- value1 = cos_table[(int)intpart];
- }
-
- value = value1 + (fractionpart * (value2 - value1)) / TABLESLICE;
-
- /* If Quadrant 2 or 3 the result should be negative. */
-
- if (quadrant == 2 || quadrant == 3) return(-value);
- else return(value);
- }
-
- /* Test program:
- main() {
- float theta;
-
- float sinval;
- float lsinval;
- float cosval;
- float lcosval;
-
- for (theta = -8.3; theta < 100.0; theta += 0.1) {
-
- sinval = sin((double)theta);
- lsinval = longsin(theta) / F_TRIG_SCALE;
- cosval = cos((double)theta);
- lcosval = longcos(theta) / F_TRIG_SCALE;
-
- printf("SIN: angle %g %lg %g err %g\n",theta,sinval,
- lsinval,sinval-lsinval);
- printf("COS: angle %g %lg %g err %g\n",theta,cosval,
- lcosval,cosval-lcosval);
- }
- }
- */
-
-