Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  FastMath class  (Read 4895 times)
0 Members and 1 Guest are viewing this topic.
Offline bert

Junior Duke




Miles of road and miles of code


« Posted 2007-03-12 23:09:48 »

Just a simple utility class I created for my current project. It keeps a lookup table of all the trig values and square root values, etc. so that it is only a simple lookup operation and it doesn't have to calculate anything. You can adjust the resolution of the trig and square root functions and the maximum argument the square root function can handle depending on your memory limitations. Feel free to extend it. Let me know what you think  Smiley

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
public final class FastMath{
   public static final float PI=3.1415926535897932384626433832795028841971f;
   public static final float DEGRAD=PI/180f, RADDEG=180f/PI;
   private static final float TRIG_RES=DEGRAD*0.1f, SQRT_RES=0.1f, SQRT_MAX=10000f;
   private static float[] sin, cos, tan, asin, acos, atan, sqrt;
   private static boolean initialized=false;
   public static final void initialize(){
      sin=new float[(int)(2f*PI/TRIG_RES)];
      cos=new float[(int)(2f*PI/TRIG_RES)];
      tan=new float[(int)(2f*PI/TRIG_RES)];
      asin=new float[(int)(2f*PI/TRIG_RES)];
      acos=new float[(int)(2f*PI/TRIG_RES)];
      atan=new float[(int)(2f*PI/TRIG_RES)];
      for(int i=0;i<sin.length;i++){
         sin[i]=(float)Math.sin(i*TRIG_RES);
         cos[i]=(float)Math.cos(i*TRIG_RES);
         tan[i]=(float)Math.tan(i*TRIG_RES);
         asin[i]=(float)Math.asin(i*TRIG_RES);
         acos[i]=(float)Math.acos(i*TRIG_RES);
         atan[i]=(float)Math.atan(i*TRIG_RES);
      }
      sqrt=new float[(int)(SQRT_MAX*(1f/SQRT_RES))];
      for(int i=0;i<sqrt.length;i++){
         sqrt[i]=(float)Math.sqrt(i*SQRT_RES);
      }
      initialized=true;
   }
   public static final float sin(float i){
      if(!initialized) initialize();
      return sin[(int)(i/TRIG_RES)%sin.length];
   }
   public static final double sin(double i){
      if(!initialized) initialize();
      return (double)sin[(int)(i/TRIG_RES)%sin.length];
   }
   public static final float cos(float i){
      if(!initialized) initialize();
      return cos[(int)(i/TRIG_RES)%sin.length];
   }
   public static final double cos(double i){
      if(!initialized) initialize();
      return (double)cos[(int)(i/TRIG_RES)%sin.length];
   }
   public static final float tan(float i){
      if(!initialized) initialize();
      return tan[(int)(i/TRIG_RES)%sin.length];
   }
   public static final double tan(double i){
      if(!initialized) initialize();
      return (double)tan[(int)(i/TRIG_RES)%sin.length];
   }
   public static final float asin(float i){
      if(!initialized) initialize();
      return asin[(int)(i/TRIG_RES)%sin.length];
   }
   public static final double asin(double i){
      if(!initialized) initialize();
      return (double)asin[(int)(i/TRIG_RES)%sin.length];
   }
   public static final float acos(float i){
      if(!initialized) initialize();
      return acos[(int)(i/TRIG_RES)%sin.length];
   }
   public static final double acos(double i){
      if(!initialized) initialize();
      return (double)acos[(int)(i/TRIG_RES)%sin.length];
   }
   public static final float atan(float i){
      if(!initialized) initialize();
      return atan[(int)(i/TRIG_RES)%sin.length];
   }
   public static final double atan(double i){
      if(!initialized) initialize();
      return (double)atan[(int)(i/TRIG_RES)%sin.length];
   }
   public static final float abs(float i){
      return (i<0?-i:i);
   }
   public static final double abs(double i){
      return (i<0?-i:i);
   }
   public static final int abs(int i){
      return (i<0?-i:i);
   }
   public static final float sqrt(float i){
      if(!initialized) initialize();
      return sqrt[(int)(i/SQRT_RES)%sqrt.length];
   }
   public static final double sqrt(double i){
      if(!initialized) initialize();
      return (double)sqrt[(int)(i/SQRT_RES)%sqrt.length];
   }
   public static final float toDegrees(float rad){
      return rad*180f/PI;
   }
   public static final double toDegrees(double rad){
      return rad*180f/PI;
   }
   public static final float toRadians(float deg){
      return deg*PI/180f;
   }
   public static final double toRadians(double deg){
      return deg*PI/180f;
   }
   
}

w00t, i'm winning
Offline Kova

Senior Duke





« Reply #1 - Posted 2007-03-12 23:18:36 »

Just a simple utility class I created for my current project. It keeps a lookup table of all the trig values and square root values, etc. so that it is only a simple lookup operation and it doesn't have to calculate anything. You can adjust the resolution of the trig and square root functions and the maximum argument the square root function can handle depending on your memory limitations. Feel free to extend it. Let me know what you think  Smiley

1  
2  
3  
4  
public final class FastMath{
   public static final float PI=3.1415926535897932384626433832795028841971f;
   public static final float DEGRAD=PI/180f, RADDEG=180f/PI;  
}


why not use Math.round(Math.PI) ? It would be most precise PI as float. Also there are toDegrees and toRadians as I remember in Math, probably more precise and faster then PI/180f and 180f/PI.
Offline bert

Junior Duke




Miles of road and miles of code


« Reply #2 - Posted 2007-03-12 23:28:09 »

I forgot that I typed in PI, I just did that because I memorized it to over 100 places and I wanted it to be as exact as possible. Unless Math.PI goes to more than 100 places...

Interesting sidenote: By only using PI to 47 places it would be possible to accurately draw a circle around the known universe, accurate to the width of an atom.

w00t, i'm winning
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2007-03-12 23:34:36 »

Compare your code:
1  
2  
3  
4  
   public static final float sin(float i){
      if(!initialized) initialize();
      return sin[(int)(i/TRIG_RES)%sin.length];
   }


To this:
1  
2  
3  
4  
   public static final float sin(float rad)
   {
      return sin[(int) (rad * radToIndex) & SIN_MASK];
   }


You can get rid of these:
1 if-statement (30 cycles)
1 division (8 cycles)
1 modulo (8 cycles)

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline oNyx

JGO Coder


Medals: 2


pixels! :x


« Reply #4 - Posted 2007-03-13 00:01:14 »

I would do the init stuff in a static block and be done with it.

Also checkout the abs thread of doom:
http://www.java-gaming.org/forums/index.php?topic=12543.0

弾幕 ☆ @mahonnaiseblog
Offline Kova

Senior Duke





« Reply #5 - Posted 2007-03-13 06:45:21 »

I forgot that I typed in PI, I just did that because I memorized it to over 100 places and I wanted it to be as exact as possible. Unless Math.PI goes to more than 100 places...

as javadoc says, Math.PI is most accurate PI estimate that you can put into double, with that logic Math.round(Math.PI) should be most accurate value of PI in float.

Interesting sidenote: By only using PI to 47 places it would be possible to accurately draw a circle around the known universe, accurate to the width of an atom.

you mean a sphere probably...


c'mon really, optimizing abs!? ... while it could be fun it's pointless
Online Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #6 - Posted 2007-03-13 08:55:12 »

as javadoc says, Math.PI is most accurate PI estimate that you can put into double, with that logic Math.round(Math.PI) should be most accurate value of PI in float.

Math.round(3.141596....) = 3

not exactly accurate Roll Eyes

Didn't you just mean:
(float)Math.PI;
?

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline DzzD
« Reply #7 - Posted 2007-03-13 12:14:21 »

you should replace i/TRIG_RES everywhere it appears by i*ITREG_RES with ITREG_RES initialised to 1/TRIG_RES maybe it will also be much faster by using integer as index rather than double and using power of two for the resolution

lets say that resolution is 65536 for 16bit

to index your array you can than do something like that:

1  
ITREG_RES=65536/TRIG_RES;


and

1  
2  
int ii=(int)i*65536; 
((ii*ITREG_RES)>>16)&0xFFFF;


example:

1  
sin[(int)(i/TRIG_RES)%sin.length]


replaced by

1  
sin[((ii*ITREG_RES)>>16)&0xFFFF]


i guess it will be much faster

nb: I did not try this solution, it may work unproperly, if you try it, let me know!

Offline Kova

Senior Duke





« Reply #8 - Posted 2007-03-13 14:33:17 »

Math.round(3.141596....) = 3

not exactly accurate Roll Eyes

Didn't you just mean:
(float)Math.PI;
?

eh... I though rounding a double gives you a float... don't know why Smiley ... it gives long, while rounding float gives int. So I guess
(float)Math.PI is closest PI as float
Offline DzzD
« Reply #9 - Posted 2007-03-13 14:57:45 »

another thing you can do is to replace :

1  
rad*180f/PI


by

1  
rad*idegPI;


with idegPI initialized only once :

1  
float idegPI=(float)(180.0/Math.PI)


and the same for deg*PI/180


EDIT: sorry, i just see that riven already mention this optimisation with radToIndex

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline emzic

Senior Duke





« Reply #10 - Posted 2007-03-20 09:17:28 »

good work bert!

it would be interesting if you would have any comparisons on how much faster it really is than regular Math.*

thanks!

www.embege.com - personal website
webstart blendinspect - OpenGL BlendingModes visualization.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (39 views)
2014-10-17 03:59:02

Norakomi (30 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (28 views)
2014-10-15 16:18:58

TehJavaDev (57 views)
2014-10-14 00:39:48

TehJavaDev (58 views)
2014-10-14 00:35:47

TehJavaDev (48 views)
2014-10-14 00:32:37

BurntPizza (64 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (78 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!