A Flash Developer Resource Site

Page 1 of 2 12 LastLast
Results 1 to 20 of 23

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

  1. #1
    talk to the hand! Never_land:('s Avatar
    Join Date
    Nov 2007
    Location
    your mother's bedroom
    Posts
    490

    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
    that much about accuracy
    but worrying about performance.
    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)

    please help with any ideas to improve accuracy without taking away performance;
    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
    Last edited by Never_land:(; 05-20-2010 at 04:07 PM.

  2. #2
    Hype over content... Squize's Avatar
    Join Date
    Apr 2001
    Location
    Lost forever in a happy crowd...
    Posts
    5,928
    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.

  3. #3
    Pumpkin Carving 2008 ImprisonedPride's Avatar
    Join Date
    Apr 2006
    Location
    Grand Rapids MI
    Posts
    2,379
    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.
    The 'Boose':
    ASUS Sabertooth P67 TUF
    Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
    8GB G.Skill Ripjaws 1600 DDR3
    ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
    New addition: OCZ Vertex 240GB SATA III SSD
    WEI Score: 7.6

  4. #4
    Hype over content... Squize's Avatar
    Join Date
    Apr 2001
    Location
    Lost forever in a happy crowd...
    Posts
    5,928
    If you're just using it for spot effects, like particles, then it makes no difference, no one will notice.

    Squize.

  5. #5
    talk to the hand! Never_land:('s Avatar
    Join Date
    Nov 2007
    Location
    your mother's bedroom
    Posts
    490
    you mean a small example?
    ok here ya go.

    @ImprisonedPride it does make up if you don't need accuracy.
    Attached Files Attached Files

  6. #6
    When you know are. Son of Bryce's Avatar
    Join Date
    Aug 2002
    Location
    Los Angeles
    Posts
    839
    Thanks dude!

  7. #7
    talk to the hand! Never_land:('s Avatar
    Join Date
    Nov 2007
    Location
    your mother's bedroom
    Posts
    490
    @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
    Last edited by Never_land:(; 05-20-2010 at 04:08 PM.

  8. #8
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    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).
    http://www.birchlabs.co.uk/
    You know you want to.

  9. #9
    talk to the hand! Never_land:('s Avatar
    Join Date
    Nov 2007
    Location
    your mother's bedroom
    Posts
    490
    @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.

  10. #10
    Pumpkin Carving 2008 ImprisonedPride's Avatar
    Join Date
    Apr 2006
    Location
    Grand Rapids MI
    Posts
    2,379
    Which reminder line are you talking about, Veng? There's 2.
    Last edited by ImprisonedPride; 05-21-2010 at 08:57 AM.
    The 'Boose':
    ASUS Sabertooth P67 TUF
    Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
    8GB G.Skill Ripjaws 1600 DDR3
    ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
    New addition: OCZ Vertex 240GB SATA III SSD
    WEI Score: 7.6

  11. #11
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    @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.
    http://www.birchlabs.co.uk/
    You know you want to.

  12. #12
    Hype over content... Squize's Avatar
    Join Date
    Apr 2001
    Location
    Lost forever in a happy crowd...
    Posts
    5,928
    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.

  13. #13
    Pumpkin Carving 2008 ImprisonedPride's Avatar
    Join Date
    Apr 2006
    Location
    Grand Rapids MI
    Posts
    2,379
    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;
    doesn't produce the same answer.
    The 'Boose':
    ASUS Sabertooth P67 TUF
    Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
    8GB G.Skill Ripjaws 1600 DDR3
    ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
    New addition: OCZ Vertex 240GB SATA III SSD
    WEI Score: 7.6

  14. #14
    Senior Member
    Join Date
    Apr 2002
    Posts
    226
    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)
    Last edited by erixon; 05-22-2010 at 04:42 AM.

  15. #15
    Senior Member
    Join Date
    Oct 2009
    Posts
    118
    Quote Originally Posted by erixon View Post
    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.

  16. #16
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    Quote Originally Posted by ImprisonedPride View Post
    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;
    doesn't produce the same answer.

    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.
    http://www.birchlabs.co.uk/
    You know you want to.

  17. #17
    ism BlinkOk's Avatar
    Join Date
    Aug 2001
    Location
    , location, location
    Posts
    5,002
    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?.
    Graphics Attract, Motion Engages, Gameplay Addicts
    XP Pro | P4 2.8Ghz | 2Gb | 80Gb,40Gb | 128Mb DDR ATI Radeon 9800 Pro

  18. #18
    Script kiddie VENGEANCE MX's Avatar
    Join Date
    Jun 2004
    Location
    England
    Posts
    2,590
    @BlinkOk:

    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.
    http://www.birchlabs.co.uk/
    You know you want to.

  19. #19
    ism BlinkOk's Avatar
    Join Date
    Aug 2001
    Location
    , location, location
    Posts
    5,002
    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?
    Graphics Attract, Motion Engages, Gameplay Addicts
    XP Pro | P4 2.8Ghz | 2Gb | 80Gb,40Gb | 128Mb DDR ATI Radeon 9800 Pro

  20. #20
    Senior Member
    Join Date
    May 2006
    Location
    Manhattan
    Posts
    246
    Quote Originally Posted by VENGEANCE MX View Post
    @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.

Posting Permissions

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




Click Here to Expand Forum to Full Width

HTML5 Development Center