A Flash Developer Resource Site

# Thread: semi-inaccurate sin & cos (250% increase in performance!)

1. ## semi-inaccurate sin & cos (250% increase in performance!)

ok just to mention I like making particles
but I dislike needing to use Math.sin, Math.cos for each particle,
Why do I need so much accuracy?
I came up with the idea of making a fast sine and cosine without worrying
dont use it for your shooting game this aint THAT accurate,
but it looks GREAT when used with stuff like particles (snow, dust, bricks, etc)

help improving performance.

it requires angles from an MC
ex.-
Cosine= fcos(alpha_mc.rotation)

Actionscript Code:
`var reminder:Number=1;function fcos(alf:Number):Number {    if (alf < 0) {        alf = -alf;    }    if (alf > 180) {        alf = 180-alf;    }    if (alf>45) {        alf=.7-((alf-45)*.0222)*.7;    } else {        alf=.7+((45-alf)*.0222)*.3;    }    return alf;}function fsin(alf:Number):Number {    reminder=1;    if (alf<0) {        reminder=-1;    }    if (alf > 90) {        alf = 180-alf;    } else if (alf < -90) {        alf = 180+alf;    }    if (alf < 0) {        alf = -alf;    }    if (alf>45) {        alf=.7+((alf-45)*.0222)*.3;    } else {        alf=(alf*.0222)*.7;    }    return alf * reminder;}`

(Flash player10)

Speed Tests
average 40 tests
Mat.sin()=1081 fsin()=419
+257% more performance
Mat.cos()=1129.54 fcos()=371.72
+303% more performance

Accuracy tests

System averaged 100000 tests with random angles
fcos() = -6.845% accuracy
fsin() = -9.937% accuracy
EDIT: updated cosine,updated accuracy tests
EDIT2: updated speed tests  Reply With Quote

2. Could you post up a simple test bed so we can all work with the same code, it's easier to see if any optimisations have actually helped that way.

Cheers,

Squize.  Reply With Quote

3. Regardless of testing, I don't see how 200% speed could make up for 17% and 22% inaccuracy. Now my game is just screwed up faster.  Reply With Quote

4. If you're just using it for spot effects, like particles, then it makes no difference, no one will notice.

Squize.  Reply With Quote

5. you mean a small example?
ok here ya go.

@ImprisonedPride it does make up if you don't need accuracy.  Reply With Quote

6. Thanks dude!  Reply With Quote

7. @Son of Bryce You're welcome fixed the Cosine it runs better than the sine this time,
still less accurate than the sine though

Actionscript Code:
`var reminder:Number=1;function fcos(alf:Number):Number {    if (alf < 0) {        alf = -alf;    }    if (alf > 180) {        alf = 180-alf;    }    if (alf>45) {        alf=.7-((alf-45)*.0222)*.7;    } else {        alf=.7+((45-alf)*.0222)*.3;    }    return alf;}function fsin(alf:Number):Number {    reminder=1;    if (alf<0) {        reminder=-1;    }    if (alf > 90) {        alf = 180-alf;    } else if (alf < -90) {        alf = 180+alf;    }    if (alf < 0) {        alf = -alf;    }    if (alf>45) {        alf=.7+((alf-45)*.0222)*.3;    } else {        alf=(alf*.0222)*.7;    }    return alf * reminder;}`

PS. the (*.0222) is the exact replacement to ( /45 ); (*.0222) is just faster

EDIT: forget previous edit

EDIT2:

Accuracy tests

System averaged 100000 tests with random angles
fsin() = -17% accuracy
fcos() = -22% accuracy

I kind of ruined the accuracy test they where all wrong this are the real Numbers
fcos() = -6.845% accuracy
fsin() = -9.937% accuracy

ok, there it is I promise this time the tests are right on spot  Reply With Quote

8. Untested, so I mighta made a mistake, but try:

var reminder:Number=1;
function fcos(alf:Number):Number {
if (alf < 0) alf = -alf;
if (alf > 180) alf = 180-alf;
alf = alf>45 ? .0007-.01554*alf : .9997-alf*0.00666;
return alf;
}
function fsin(alf:Number):Number {
reminder= alf<0 -1 : 1;
alf = alf > 90 ? 180-alf : 180+alf;
if (alf < 0) alf = -alf;
alf= alf>45 ? .4003+alf*.00666-0.2997 : alf*0.01554;
return alf * reminder;
}

Expanded the brackets (brackets are pretty slow), changed all your if/elses to conditional operations, pre-calculated some of the addition and subtraction.

There's probably a faster, bitwise way to do that reminded line.

Also, have you considered that for small angles of x, sin x = x? So, if the angle is below about 30º (lower if you want more accuracy), you can just convert to radians (multiply by 0.017 or π/180) and there's your sine. Plus, you can use this to get the cosine of angles 60º≤x≤90º (return 0.017(90-angle); basically just throwing it into sine instead).  Reply With Quote

9. @Vengeance
dude thanks but what you gave me has no difference in FP10 but it does in FP9

I'll try and see the separating it in more pieces, and I couldn't find anywhere to use bitwise stuff, why don't you try giving something up.  Reply With Quote

10. Which reminder line are you talking about, Veng? There's 2.  Reply With Quote

11. @Never_land:

Right. Thought there was a chance that Flash or Flash Player would be smart enough to simplify it like I did. It's the kind of thing that any good compiler would do for you.

@ImprisonedPride:

reminder= alf<0 -1 : 1;

This line. Just thinking that there's probably a faster way to check if a number is positive, using the bitwise operators (check if the first bit == 0). Also, the result (true or false, ie 1 or 0) can be immediately used as part of the calculation, so it'd be something like:

reminder = alf%0<<1-1;

where (alf%0) represents the hypothetical bitwise function I am referring to (I'm sure something like that must exist, but maybe I'm thinking of a function, in which case we wouldn't get a speed boost). But you can see that this method would not need a condition, and would use entirely bitwise operations, which are really fast. So it might just be faster.

Btw, the <<1-1 part doubles the result (using another bitwise operation) and subtracts one. Which turns the (alf%0)'s true and false (1 and 0) into 1 and -1, respectively.

However, reminder= alf<0 -1 : 1; is already a pretty damned fast way of doing it.  Reply With Quote

12. NeverLand I just d/loaded your example, sorry, I meant more of a test bed, ie the code you're running yourself to check the timing / accuracy, rather than an example of how to use it.

That way any changes can be compared straight away so we have no false starts.

Squize.  Reply With Quote

13. Venge, under the assumption that the line you gave me had a typo:
Code:
```reminder= alf<0 -1 : 1; // doesn't compile
//should be
reminder= alf<0 ? -1 : 1;```
Because of this, after testing (and I know your solution was hypothetical),
Code:
`reminder = alf%0<<1-1;`  Reply With Quote

14. Why not do a precalculated array/vector?

sinArray[0..0xFFF] = Math.sin(0..2*Math.PI);

sinArray[angle & 0xFFF] which means the circle is from 0 to 0xFFF

Just increase the array for better resolution (2^x)  Reply With Quote

15. Originally Posted by erixon Why not do a precalculated array/vector?
Yes, a lookup table is the way to go. Pre-calculate all the values when the game initialises, push them into an array, and just read the array values when you need them.  Reply With Quote

16. Originally Posted by ImprisonedPride Venge, under the assumption that the line you gave me had a typo:
Code:
```reminder= alf<0 -1 : 1; // doesn't compile
//should be
reminder= alf<0 ? -1 : 1;```
Because of this, after testing (and I know your solution was hypothetical),
Code:
`reminder = alf%0<<1-1;`

Ah yeah, that was a typo, but I don't believe that breaks my other line of code in any way.

If we (as I intended) take alf%0 to mean (alf<0 ? -1 : 1), then surely that line,

(alf<0 ? -1 : 1)<<1-1

is one that compiles fine? unless I've got my bitwise BODMAS wrong.

@erixon,
I believe that array lookups are slower than using the trig functions in AS3. Actually, I think this optimization happened sometime around Flash Player 5.  Reply With Quote

17. hey have you guys ever tried rotating the object and then using localToGLobal, with the x value being the speed, to determine the next position of the object?.  Reply With Quote

That sounds like it would be really, really slow, surely? Also, I'm not sure that their boundaries get updated as soon as you run the _rotation++; line - I think all coordinate changes happen with the render, at the end of the frame's code.

Sorry for my pessimism... ordinarily I used to just check these things, but Flash CS4 takes so long to load... am currently just working things out based on gut feelings.

Also, that idea only works if you're trying to move a movie clip. I'd want fast trig for blitting sprites around.  Reply With Quote

19. there are a lot of conditions in the posted code which i think would be pretty slow.
i think it would be pretty quick actually, only a couple lines of code and the local/global functions are very very quick
it doesn't need to render either.
why not give it a go?  Reply With Quote

20. Originally Posted by VENGEANCE MX @erixon,
I believe that array lookups are slower than using the trig functions in AS3. Actually, I think this optimization happened sometime around Flash Player 5.
Definitely not! Lookups will be ~400 TRILLION BILLION etc. times faster. Especially using a Vector of floats.  Reply With Quote

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

 » Home » Movies » Tutorials » Submissions » Board » Links » Reviews » Feedback » Gallery » Fonts » The Lounge » Sound Loops » Sound FX » About FK » Sitemap 