Who remembers the Trig Functions? Sine Sine Tangent Tangent Cosine Cosine.
Faster Sin and Cosine Through Lookup Tables
Transcript of Faster Sin and Cosine Through Lookup Tables
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
1/15
JACKSONDUNSTAN.COM Mastering AS3Search G
Home About
XML Speed Even Faster Trig Through Inlining
Faster Math.sin and Math.cosThrough Lookup Tables
byjacksoninAS3
Tags: cos, cosine, look up table, LUT, performance, sin, sine, trig, triglut, trigonometry
Trigonometry functions like Math.sin and Math.cos are widely used in AS3
games and other apps that make intensive use of graphics, sound, or physics.
Todays article shows you a way to trade a little bit of memory for much faster
trigonometry computations, which can seriously speed up any app that makes
heavy use ofMath.sin, Math.cos, and the like. Keep reading for the class
thatll help you do this, a demo app, performance testing, analysis, and more.
(UPDATE: optimized thanks to(UPDATE: optimized thanks to(UPDATE: optimized thanks to(UPDATE: optimized thanks to skyboyskyboyskyboyskyboy))))
Lookup tables are a common technique in programming. They involve doing
expensive computations once, storing them in a table, and accessing them
later. In AS3, the idea is that accessing the values stored in a Vector table is
faster than computing the value and therefore you get a speed boost.
For such a widely-used technique, it doesnt seem to be getting much usage in
the AS3 world. I found a test on actionscript.org that uses lookup tables for
Math.sin and shows a performance boost, but the lookup table can only be
used with radians that happen to be whole numbers (integers) and is therefore
not very useful and an unfair comparison to the robust Math.sin function.
There is also an article on polygonal.de discussing the subject, but it doesnt
provide full source, uses the relatively-slow Array because it was written
before Vector debuted in Flash Player 10, and doesnt say specifically if
lookup tables are used to achieve the alleged 14x performance boost. It does,
however, have a cool demo app that inspired my demo app below.
Due to this lack of existing lookup table work, I decided to make my own
lookup table for trig functions: any function like Math.sin and Math.cos that
takes parameters in the range [0,2pi). Here is the basic usage:
// Make a lookup table for Math.sin with 2 decimal places of
precision
var sineLUT:TrigLUT = new TrigLUT(2,Math.sin);
// Query with arbitrary radians, just like the original Math.sin
result = sineLUT.val(-45.123);
If you dont need to pass an arbitrary radians value, there are even faster
functions that work as long as you can guarantee limits:
MAY 16
2011
TIP OF THE WEEK E-MAIL
EEEE----Mail AddressMail AddressMail AddressMail Address ::::
Subscribe
ARCHIVES
ULY 2012
UNE 2012
MAY 2012
APRIL 2012
MARCH 2012
FEBRUARY 2012
ANUARY 2012
DECEMBER 2011
NOVEMBER 2011
OCTOBER 2011
SEPTEMBER 2011
AUGUST 2011
ULY 2011
UNE 2011
MAY 2011
APRIL 2011
MARCH 2011
FEBRUARY 2011
ANUARY 2011
DECEMBER 2010
NOVEMBER 2010
OCTOBER 2010
SEPTEMBER 2010
AUGUST 2010
ULY 2010
UNE 2010
MAY 2010
APRIL 2010
MARCH 2010
FEBRUARY 2010
ANUARY 2010
DECEMBER 2009
NOVEMBER 2009
OCTOBER 2009
SEPTEMBER 2009
AUGUST 2009
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
2/15
// Radians >= 0
result = sineLUT.valPositive(45.123);
// Radians on (-2pi,2pi)
result = sineLUT.valNormalized(-4.123);
// Radians on [0,2pi)
result = sineLUT.valNormalizedPositive(4.123);
The lookup table and precision variable are public, so you can avoid the slow
function call by inlining them. The functions are small, so it wont bloat up
your code or be too messy:
// Inline version of TrigLUT.valNormalizedPositive
result = sineLUT.table[int(4.123*sineLUT.pow)];
For the ultimate speed boost when youre doing lots of lookups in one
function, cache the lookup table and precision variable as local variables:
var sineTable:Vector. = sineLUT.table;
var sinePow:Number = sineLUT.pow;
result = sineTable[int(4.123*sinePow)];
You can even make a lookup table for arbitrary functions. Heres one for the
square ofMath.sin with 2 decimal places of precision:
var sineSquaredLUT:TrigLUT = new TrigLUT(2,function(r:Number):Number{r = Math.sin(r);return r*r;}
);
Use this lookup table the same exact way you used the Math.sin lookup table:
sineSquaredLUT.val(-45.123);
Now that you know how to use it, here is the source code for TrigLUT(TrigTrigTrigTrigonometry LLLLookUUUUp TTTTable):
/*
The MIT License
Copyright (c) 2011 Jackson Dunstan
Permission is hereby granted, free of charge, to any person
obtaining a copy
of this software and associated documentation files (the
"Software"), to deal
in the Software without restriction, including without limitation
the rights
to use, copy, modify, merge, publish, distribute, sublicense,and/or sell
copies of the Software, and to permit persons to whom the Software
is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
ULY 2009
UNE 2009
CATEGORIES
AS2
AS3
AVASCRIPT
UNCATEGORIZED
ACCOUNT
REGISTER
LOG IN
ON-TOPIC SITES
OA EBERT
PAUCLAIR.NET
BIT-101
DESTROY TODAY
ALECMCE.COM
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
3/15
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
THE SOFTWARE.
*/
package
{
/**
* A lookup table for trig values (e.g. sine, cosine) to
improve on the
* performance of the static functions found in the Math class* @author Jackson Dunstan
*/
publicclass TrigLUT
{
/** 2 * PI, the number of radians in a circle*/
public static const TWO_PI:Number = 2.0*Math.PI;
/** The static TWO_PI cached as a non-static field*/
private const TWO_PI:Number = TrigLUT.TWO_PI;
/** Table of trig function values*/
publicvar table:Vector.;
/** 10^decimals of precision*/
publicvarpow:Number;
/**
* Make the look up table
* @param numDigits Number of digits places of precision
* @param mathFunc Math function to call to generate
stored values.
* Must be valid on [0,2pi).
* @throws Error If mathFunc is null or invalid on [0,2pi)
*/
publicfunction TrigLUT(numDigits:uint, mathFunc:Function)
{
varpow:Number = this.pow = Math.pow(10, numDigits);
varround:Number = 1.0/pow;
var len:uint = 1+this.TWO_PI*pow;
var table:Vector. = this.table = newVector.(len);
var theta:Number = 0;
for (var i:uint = 0; i < len;++i)
{
table[i] = mathFunc(theta);theta += round;
}
}
/**
* Look up the value of the given number of radians
* @param radians Radians to look up the value of
* @return The value of the given number of radians
*/publicfunction val(radians:Number):Number
{
return radians >= 0?this.table[int((radians%this.TWO_PI)*this.pow)]
:this.table[int((TWO_PI+radians%this.TWO_PI)
*this.pow)];
}
/**
* Look up the value of the given number of radians
* @param radians Radians to look up the value of. Must
be positive.
* @return The sine of the given number of radians
* @throws RangeError If radians is not positive
*/
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
4/15
publicfunction valPositive(radians:Number):Number
{
returnthis.table[int((radians%this.TWO_PI)*this.pow)];
}
/**
* Look up the value of the given number of radians
* @param radians Radians to look up the value of. Must
be on (-2pi,2pi).
* @return The value of the given number of radians
* @throws RangeError If radians is not on (-2pi,2pi)
*/
publicfunction valNormalized(radians:Number):Number
{return radians >= 0
?this.table[int(radians*this.pow)]
:this.table[int((this.TWO_PI+radians)*this.pow)];
}
/**
* Look up the value of the given number of radians
* @param radians Radians to look up the value of. Must
be on [0,2pi).
* @return The value of the given number of radians
* @throws RangeError If radians is not on [0,2pi)
*/
publicfunction valNormalizedPositive(radians:Number):
Number
{returnthis.table[int(radians*this.pow)];
}
}
}
Since the whole point of this exercise is to get a performance boost, lets do
some performance testing! Here is an app that compares the performance of
Math.sin and Math.cos to TrigLUT:
/*
The MIT License
Copyright (c) 2011 Jackson Dunstan
Permission is hereby granted, free of charge, to any person
obtaining a copy
of this software and associated documentation files (the
"Software"), to deal
in the Software without restriction, including without limitation
the rights
to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell
copies of the Software, and to permit persons to whom the Software
is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included inall copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
THE SOFTWARE.
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
5/15
*/
package
{
importflash.display.*;
importflash.utils.*;
importflash.text.*;
/**
* Performance test app for TrigLUT, the trig function lookup
table
* @author Jackson Dunstan
*/
publicclass TrigLUTTest extendsSprite
{privatevar __logger:TextField = newTextField();privatefunctionlog(msg:*):void { __logger.appendText
(msg +"\n"); }
publicfunction TrigLUTTest()
{
__logger.autoSize = TextFieldAutoSize.LEFT;
addChild(__logger);
const DIGITS:uint = 2;
const STEP:Number = 0.05;var beforeTime:int;var afterTime:int;var lut:TrigLUT = new TrigLUT(DIGITS,Math.sin);
var lutTable:Vector. = lut.table;var lutPow:Number = lut.pow;
const REPS:int = 100000;
const NUM:int = int(TrigLUT.TWO_PI / STEP);var theta:Number;var i:int;
var j:int;
var result:Number;
const TWO_PI:Number = TrigLUT.TWO_PI;
log("Function,Time");
beforeTime = getTimer();
for (i = 0; i < REPS;++i)
{
theta = 0;for (j = 0; j < NUM;++j)
{
result = Math.sin(theta);
theta += STEP;
}
}
afterTime = getTimer();
log("Math.sin,"+ (afterTime-beforeTime));
beforeTime = getTimer();for (i = 0; i < REPS;++i)
{
theta = 0;
for (j = 0; j < NUM;++j)
{
result = Math.cos(theta);
theta += STEP;
}
}
afterTime = getTimer();
log("Math.cos,"+ (afterTime-beforeTime));
beforeTime = getTimer();for (i = 0; i < REPS;++i)
{
theta = 0;
for (j = 0; j < NUM;++j)
{
result = lut.val(theta);
theta += STEP;
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
6/15
}
}
afterTime = getTimer();
log("TrigLUT.val,"+ (afterTime-beforeTime));
beforeTime = getTimer();
for (i = 0; i < REPS;++i)
{
theta = 0;for (j = 0; j < NUM;++j)
{
result = lut.valPositive(theta);
theta += STEP;
}}
afterTime = getTimer();
log("TrigLUT.valPositive,"+ (afterTime-beforeTime));
beforeTime = getTimer();
for (i = 0; i < REPS;++i)
{
theta = 0;
for (j = 0; j < NUM;++j)
{
result = lut.valNormalized(theta);
theta += STEP;
}
}
afterTime = getTimer();log("TrigLUT.valNormalized,"+ (afterTime-beforeTime));
beforeTime = getTimer();for (i = 0; i < REPS;++i)
{
theta = 0;
for (j = 0; j < NUM;++j)
{
result = lut.valNormalizedPositive(theta);
theta += STEP;
}
}
afterTime = getTimer();
log("TrigLUT.valNormalizedPositive,"+ (afterTime-
beforeTime));
beforeTime = getTimer();
for (i = 0; i < REPS;++i)
{
theta = 0;for (j = 0; j < NUM;++j){
result = theta >= 0
? lutTable[int((theta%TWO_PI)*lutPow)]
: lutTable[int((TWO_PI+theta%TWO_PI)*lutPow)];
theta += STEP;
}
}
afterTime = getTimer();log("inline val,"+ (afterTime-beforeTime));
beforeTime = getTimer();for (i = 0; i < REPS;++i)
{
theta = 0;
for (j = 0; j < NUM;++j)
{
result = lutTable[int((theta%TWO_PI)*lutPow)];
theta += STEP;
}
}
afterTime = getTimer();
log("inline valPositive,"+ (afterTime-beforeTime));
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
7/15
beforeTime = getTimer();
for (i = 0; i < REPS;++i)
{
theta = 0;
for (j = 0; j < NUM;++j)
{
result = theta >= 0
? lutTable[int(theta*lutPow)]: lutTable[int((TWO_PI+theta)*lutPow)];
theta += STEP;
}
}
afterTime = getTimer();
log("inline valNormalized,"+ (afterTime-beforeTime));
beforeTime = getTimer();
for (i = 0; i < REPS;++i)
{
theta = 0;
for (j = 0; j < NUM;++j)
{
result = lutTable[int(theta*lutPow)];
theta += STEP;
}
}
afterTime = getTimer();
log("inline valNormalizedPositive,"+ (afterTime-
beforeTime));
}}
}
Here is the test environment I ran this app on:
Flex SDK (MXMLC) 4.1.0.16076, compiling in release mode (no debugging
or verbose stack traces)
Release version of Flash Player 10.3.181.14
2.4 Ghz Intel Core i5
Mac OS X 10.6.7
And here are the results I got:
FUNCTION TIME
Math.sin 509
Math.cos 509
TrigLUT.val 464
TrigLUT.valPositive 447
TrigLUT.valNormalized 253
TrigLUT.valNormalizedPositive 214
inline val 336
inline valPositive 329
inline valNormalized 145
inline valNormalizedPositive 133
Here are the same results in graph form:
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
8/15
These results clearly show the performance benefits ofTrigLUT:
TrigLUT is always faster than Math.sin and Math.cos
Reducing the acceptable radian values helps performance a lot, especially
guaranteeing positive values
Inlining lookups results in maximum performance
In the best case, TrigLUT beats the Math class functions by almost 5x!5x!5x!5x!
With such compelling results, we should make sure that they are still accurate.
and not wildly different than the results we would normally get from the Math
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
9/15
class functions. TrigLUT allows you to set the number of digits of precision
youd like. The more digits you want, the bigger and more accurate the lookup
table gets. Its important to remember though that increasing precision does
notnotnotnot slow downTrigLUT. Usually, I find that two digits of precision (a lookup
table with 628 Numbers = 4.9KB of memory) is enough for most uses, but I
leave the precision up to each user ofTrigLUT to determine their own needs.
Here is the source code for a small demo app that simply draws a sine or
cosine curve using the Math class functions and the approximation via
TrigLUT over the top. A live demo follows.
/*
The MIT License
Copyright (c) 2011 Jackson Dunstan
Permission is hereby granted, free of charge, to any person
obtaining a copy
of this software and associated documentation files (the
"Software"), to deal
in the Software without restriction, including without limitation
the rights
to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell
copies of the Software, and to permit persons to whom the Software
is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
THE SOFTWARE.
*/
package
{
importflash.display.*;
importflash.events.*;
importflash.text.*;
importflash.geom.*;
/**
* Demonstration app for TrigLUT, the trig function lookuptable
* @author Jackson Dunstan
*/
[SWF(width=640,height=480,backgroundColor=0xEEEAD9)]publicclass TrigLUTDemo extendsSprite
{
private static const TEXT_FORMAT:TextFormat = new
TextFormat("_sans",11);
privatevar bmd:BitmapData;privatevar bmdRect:Rectangle;
privatevar mathFuncName:String;
privatevar digits:uint;
privatevar mathFuncFrame:Sprite;
privatevar digitsFrame:Sprite;
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
10/15
publicfunction TrigLUTDemo()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
this.bmd = newBitmapData(stage.stageWidth,
stage.stageHeight,false, 0xffffffff);
addChild(newBitmap(bmd));this.bmdRect = newRectangle(0,0,this.bmd.width,
this.bmd.height);
this.mathFuncFrame = addChoices(
"Math function: ",onMathFuncButton,0,
["sin","cos"]
);
this.digitsFrame = addChoices(
"Digits of precision: ",
onPrecisionButton,
this.mathFuncFrame.height,
["0","1","2","3","4","5"]
);
this.digits = 2;this.mathFuncName = "sin";
redraw();
var about:TextField = newTextField();
about.defaultTextFormat = TEXT_FORMAT;
about.y = this.digitsFrame.y+this.digitsFrame.height;
about.htmlText = "TrigLUT Demo by JacksonDunstan.com\n"+"Black line: trig function\n"+"Red line: lookup table";
about.autoSize = TextFieldAutoSize.LEFT;
about.selectable = false;
addChild(about);
}
privatefunction addChoices(
promptStr:String,
callback:Function,
y:Number,
choices:Array
):Sprite{
var prompt:TextField = newTextField();
prompt.defaultTextFormat = TEXT_FORMAT;
prompt.text = promptStr;
prompt.autoSize = TextFieldAutoSize.LEFT;
prompt.selectable = false;
addChild(prompt);
varx:Number = prompt.width;const PAD:Number = 3;foreach (var choiceName:Stringin choices)
{
var tf:TextField = newTextField();
tf.defaultTextFormat = TEXT_FORMAT;
tf.name = "label";
tf.text = choiceName;
tf.autoSize = TextFieldAutoSize.LEFT;
tf.selectable = false;
tf.x = tf.y = PAD;
var button:Sprite = newSprite();
button.name = choiceName;
button.graphics.beginFill(0xE6E2D1);
button.graphics.drawRect(0,0, tf.width+PAD*2,
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
11/15
tf.height+PAD*2);
button.graphics.endFill();
button.addChild(tf);
button.addEventListener(
MouseEvent.CLICK,
function(ev:MouseEvent):void
{
var button:Sprite = ev.currentTargetas
Sprite;var label:TextField = button.getChildByName
("label") asTextField;
callback(label.text);
}
);button.x = x;
button.y = y;
addChild(button);
x+= button.width+PAD;
}
prompt.y = y+ (button.height- prompt.height) /2;
varframe:Sprite = newSprite();
frame.graphics.lineStyle(1);
frame.graphics.drawRect(0,0, tf.width+PAD*2,
tf.height+PAD*2);
addChild(frame);
returnframe;
}
privatefunction onMathFuncButton(label:String):void
{
this.mathFuncName = label;
redraw();
}
privatefunction onPrecisionButton(label:String):void
{
this.digits = int(label);
redraw();
}
privatefunction redraw():void
{
var mathFuncButton:Sprite = getChildByName
(this.mathFuncName) asSprite;
this.mathFuncFrame.x = mathFuncButton.x;this.mathFuncFrame.y = mathFuncButton.y;
var digitsButton:Sprite = getChildByName(String
(this.digits)) asSprite;
this.digitsFrame.x = digitsButton.x;this.digitsFrame.y = digitsButton.y;
var mathFunc:Function = Math[this.mathFuncName];
var lut:TrigLUT = new TrigLUT(this.digits, mathFunc);
var bmd:BitmapData = this.bmd;
bmd.lock();var w:int = bmd.width;
var h:int = bmd.height;
bmd.fillRect(this.bmdRect, 0xEEEAD9);
var halfH:int = h /2;var stepTheta:Number = TrigLUT.TWO_PI / w;var theta:Number = 0;for (varx:int = 0;x< w;++x)
{
for (vary:int = 0;y< h;++y)
{
bmd.setPixel(
x,
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
12/15
0
halfH + mathFunc(theta)*halfH,
0xff000000
);
bmd.setPixel(
x,
halfH + lut.valNormalizedPositive(theta)
*halfH,
0xffff0000
);
}
theta += stepTheta;
}
bmd.unlock();
}}
}
Here is a live version of the demo. Make sure you have JavaScript turned on and
click Show Demo.
Show Demo
In short, TrigLUT offers improved performance for trig functions like
Math.sin and Math.cos by using lookup tables. If anyone has any suggestions
for improving TrigLUT or alternatives to lookup tables entirely, feel free to join
in the discussion below in the comments. To get the performance test, demo
app, and TrigLUT class all in one convenient ZIP, you can download TrigLUT
here.
Tweet
Comments (11)
Nice, a comparison with Joa Eberts FastMath sine and cosine functionwould also be interesting.
http://code.google.com/p/apparat/source/browse/as3/Apparat.Library.AS3/
r=c8b764b3a535184a604e9d2309655de99be1d8b8
#1 byKarlon May 16th, 2011 Reply|Quote
I considered FastMath while writing the article, but decided to leave it
out since it doesnt use lookup tables. Still, it achieves the same goal
by producing faster sine and cosine results and is therefore a
possibility for a future article.
#2byjacksonon May 16th, 2011 Reply|Quote
PROTIP: cos is sin with an offset, so you can use the same table for both if
you apply the offset for the lookups.
#3by Henke37Henke37Henke37Henke37 on May 16th, 2011 Reply|Quote
Indeed it is, but it makes the lookup slower. Id rather spend another
4.9KB of memory and have unique tables. Even on mobile, its not
much RAM.
#4byjacksonon May 16th, 2011 Reply|Quote
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
13/15
Interesting article (again)! I ones used a dictionary for this, which started
empty, and gets filled by lazy instantiation. However after a while it was
using a lot of memory, so thats slows the thing down too. I think it is
clever to use rounded values to save ram.
Maybe if you want more precision (dimension) you could calculate the
average between the prev/next angle-items in the lookup array around the
current returned item. I dont know if that helps anyway or if you loose toomuch speed on that.
public const sinusList:Dictionary = newDictionary();
publicfunction getSin(angleRadians:Number):Number
{
return sinusList[angleRadians] ||= Math.sin(angleRadians);
}
Thanks for this helpful article!
#5byMarkon May 16th, 2011 Reply|Quote
Glad to hear you enjoyed the article and that there are still more
people looking for a way to improve their trig computation
performance in AS3. :)
I considered using some interpolation like in polygonal.de article I
linked, but the lookup becomes much slower due to the extra Vector
access and math. To get better precision, I think its worth trading a
little more RAM. 3 decimal places is pretty extreme and its only 6283
Numbers = 49KB. Pretty cheap (if you ask me) and with zero
slowdown.
I also considered storing the values in a Dictionary, but since
Dictionary access is 3x slower than Vector access, I figured the
overhead would more than outweigh the Number multiply (* pow) and
int()explicit type conversion.
#6byjacksonon May 16th, 2011 Reply|Quote
I did a small rewrite to increase performance by removing the static lookup
(instance instead) and the conditional branch: the result was 15% faster
execution of val:
Windows XP x86 10.3.181.14(VM: 1.4 cyclone) Release PlugIn
5000000 loops; 1 test per loop
val (new): 490ms
val (old): 576ms
Test value: [-160] -0.21667508038735275 -0.21667508038735275
Test value: [+160] 0.2197836122251347 0.2197836122251347
Using this:
#7byskyboyon May 16th, 2011 Reply|Quote
-
7/31/2019 Faster Sin and Cosine Through Lookup Tables
14/15
NameNameNameName (required)(required)(required)(required)
EEEE----Mail (required,Mail (required,Mail (required,Mail (required, will not be published)will not be published)will not be published)will not be published)
publicfunction val(radians:Number):Number {
returnthis.table[int(((this.TWO_PI *int(radians