size : 3830
uploaded_on : Sat Jun 20 00:00:00 1998
modified_on : Wed Dec 8 14:03:38 1999
title : Super fast trigonometric functions
org_filename : fasttrig.pas
author : Klaus Hartnegg
authoremail : hartnegg@einstein.freinet.de
description : Super fast trigonometric functions
keywords :
tested : Borland Pascal 7.0
submitted_by : The CKB Crew
submitted_by_email : ckb@netalive.org
uploaded_by : nobody
modified_by : nobody
owner : nobody
lang : pas
file-type : text/plain
category : pascal-alg-maths
__END_OF_HEADER__
UNIT FastTrig;
(*******************************************************************
Turbo-Pascal Unit for super fast trigonometric functions.
(c) copyright 1990,91 by Klaus Hartnegg,
H.v.Kleist-Str. 7, D-79331 Teningen, Germany.
hartnegg@einstein.freinet.de
Free for non-commercial use.
SuperFastSin determines function value by lookup in tables (arrays)
that get initialized on the first call to the function or by a
explicit call to the initialization procedure.
Accuracy is a function of memory that you allow to be used
for the table.
FastSin is 5 times faster than Turbo's sin.
SuperFastSin is even 9.5 times faster but less accurate.
(times measured with FTRIGDEM on a 25 MHz 80386)
SuperFastSin simply looks up the nearest value in a table.
FastSin uses taylor series of first order around 0.
***********************************************************************)
INTERFACE
type
FPtr_1r_1r = function (x:real) : real;
var
FastSin, SuperFastSin : FPtr_1r_1r;
{ the variable FastSin behaves like
Function FastSin (x : real) : real; }
Function FastCos (x : real) : real;
Function SuperFastCos (x : real) : real;
Function FastTan (x : real) : real;
Function FastCot (x : real) : real;
Procedure Init;
{ this initialization will be called automatically upon the first
use of one of the functions but can be called explicitely to prevent
unexpected delay in the middle of your program. }
IMPLEMENTATION
const
Resolution = 256;
pi = 3.1415926535897932385;
Step = pi / resolution;
var
Sinus : array[0..Resolution] of real;
EndOfTaylor : integer;
const
initialized : boolean = false;
{$F+}
Function FastSin1 (x : real) : real;
var i : integer;
s : real;
negativ : boolean;
begin
negativ := (x < 0);
s := abs (x * (Resolution / pi));
i := trunc (s);
if odd(i div Resolution) then negativ := not negativ;
i := i mod Resolution;
if ((i <= EndOfTaylor) or (i >= Resolution - EndOfTaylor))
{ and (abs (frac(s) - 0.5) > 0.25) } then begin
x := abs (pi * frac (x / pi));
if x > pi/2 then x := abs(pi - x);
if negativ then FastSin1 := -X else FastSin1 := X;
end
else if negativ then FastSin1 := - Sinus[i]
else Fastsin1 := Sinus[i];
end;
Function SuperFastSin1 (x : real) : real;
var i : integer;
s : real;
negativ : boolean;
begin
i := trunc (x * ( Resolution / pi) );
negativ := false;
if i < 0 then begin
negativ := true;
i := -i;
end;
i := i mod (2 * Resolution);
if i > Resolution then begin
negativ := not negativ;
i := i - Resolution;
end;
if negativ then SuperFastSin1 := - Sinus[i]
else SuperFastSin1 := Sinus[i];
end;
Function FastCos (x:real) : real;
begin
Fastcos := Fastsin (x + pi/2);
end;
Function SuperFastCos (x:real) : real;
begin
SuperFastcos := SuperFastsin (x + pi/2);
end;
Function FastTan (x:real) : real;
begin
FastTan := FastSin(x) / FastCos(x);
end;
Function FastCot (x:real) : real;
begin
FastCot := FastCos(x) / FastSin(x);
end;
Procedure Init;
var x : real;
i : integer;
begin
if @FastSin = @FastSin1 then exit; { is already installed }
x := Step / 2;
for i := 0 to Resolution do begin
Sinus[i] := sin (x);
x := x + Step;
end;
EndOfTaylor := 0;
x := Step / 2;
while abs( x - sin(x)) < Step / 2 do begin
inc (EndOfTaylor);
x := x + Step;
end;
dec (EndOfTaylor,2);
FastSin := FastSin1;
SuperFastSin := SuperFastSin1;
end;
Function FastSin_Init (x:real) : real;
begin
Init;
FastSin_Init := FastSin(x);
end;
Function SuperFastSin_Init (x:real) : real;
begin
Init;
SuperFastSin_Init := SuperFastSin(x);
end;
BEGIN
FastSin := FastSin_Init;
SuperFastSin := SuperFastSin_init;
END.