Difference between revisions of "User:Rednaxela/FastTrig"
Jump to navigation
Jump to search
(Fix for negative values) |
(Updated version, no atan (yet), it's a tricky one) |
||
| Line 9: | Line 9: | ||
public class FastTrig { | public class FastTrig { | ||
| − | public static final int DIVISIONS = | + | public static final int DIVISIONS = 7200; |
| + | public static final double K = DIVISIONS/(Math.PI*2); | ||
public static final double[] sineTable = new double[DIVISIONS]; | public static final double[] sineTable = new double[DIVISIONS]; | ||
| − | |||
public static final void init() { | public static final void init() { | ||
for (int i=0; i<DIVISIONS; i++) { | for (int i=0; i<DIVISIONS; i++) { | ||
| − | double value = i | + | double value = i/K; |
sineTable[i] = Math.sin(value); | sineTable[i] = Math.sin(value); | ||
| − | |||
} | } | ||
} | } | ||
public static final double sin(double value) { | public static final double sin(double value) { | ||
| − | return sineTable[(int)(value | + | return sineTable[(int)(((value*K + 0.5) % DIVISIONS + DIVISIONS)%DIVISIONS)]; |
} | } | ||
public static final double cos(double value) { | public static final double cos(double value) { | ||
| − | return | + | return sineTable[(int)(((value*K + 0.5) % DIVISIONS + 1.25*DIVISIONS)%DIVISIONS)]; |
} | } | ||
| − | |||
public static void main(String[] args) { | public static void main(String[] args) { | ||
| − | + | double v=0; | |
| − | |||
| − | double v= | ||
long ms; | long ms; | ||
| + | |||
| + | ms = -System.nanoTime(); | ||
| + | FastTrig.init(); | ||
| + | ms += System.nanoTime(); | ||
| + | System.out.printf("FastTrig init time: %.5f seconds\n", ms / 1E9); | ||
| + | |||
| + | int A = 10000; | ||
| + | int B = 1000; | ||
| + | double absolute = 0; | ||
| + | for ( int i = 0; i < A; ++i ) for ( int j = 0; j < B; ++j ) { | ||
| + | double angle = Math.random() * Math.PI * 200 - Math.PI * 100; | ||
| + | absolute = Math.max(absolute, Math.abs(Math.sin(angle) - FastTrig.sin(angle))); | ||
| + | absolute = Math.max(absolute, Math.abs(Math.cos(angle) - FastTrig.cos(angle))); | ||
| + | } | ||
| + | System.out.printf("Wrost error: %.12f\n", absolute); | ||
| + | v=0; | ||
ms = -System.nanoTime(); | ms = -System.nanoTime(); | ||
| − | for (int i=0; i< | + | for ( int i = 0; i < A; ++i ) for ( int j = 0; j < B; ++j ) |
| − | v += | + | v += FastTrig.sin(i * j * Math.PI - Math.PI / 3); |
ms += System.nanoTime(); | ms += System.nanoTime(); | ||
| − | System.out. | + | System.out.printf("FastTrig time: %.3f seconds\n", ms / 1E9); |
| − | + | v = 0; | |
ms = -System.nanoTime(); | ms = -System.nanoTime(); | ||
| − | for (int i=0; i< | + | for ( int i = 0; i < A; ++i ) for ( int j = 0; j < B; ++j ) |
| − | + | v += Math.sin(i * j * Math.PI - Math.PI / 3); | |
| − | |||
| − | |||
| − | |||
ms += System.nanoTime(); | ms += System.nanoTime(); | ||
| − | System.out. | + | System.out.printf("Math time: %.3f seconds\n", ms/1E9); |
} | } | ||
| − | |||
}</pre> | }</pre> | ||
| − | --[[User:Rednaxela|Rednaxela]] | + | Test output is as follows: |
| + | <pre>FastTrig init time: 0.00470 seconds | ||
| + | Wrost error: 0.000436329459 | ||
| + | FastTrig time: 0.506 seconds | ||
| + | Math time: 8.619 seconds</pre> | ||
| + | --[[User:Rednaxela|Rednaxela]] 00:34, 4 March 2009 (UTC) | ||
Revision as of 01:34, 4 March 2009
A little class for fast trig lookups. Tests show that:
- When used with the sin/cos static methods, it ranges from twice as slow, to three times as fast, depending on how much of a chance the JIT has to optimize
- When you inline the index-calculation code into your own code (see usage in the main method) instead of using static methods, it ranges from just slightly faster, up to three times as fast.
- Increasing the number of divisions has no impact on runtime performance, only initialization time and memory consumption.
This could provide some measurable speedup to intensive play-it-forward guns or precise prediction in surfers. Cheers!
package ags.util;
public class FastTrig {
public static final int DIVISIONS = 7200;
public static final double K = DIVISIONS/(Math.PI*2);
public static final double[] sineTable = new double[DIVISIONS];
public static final void init() {
for (int i=0; i<DIVISIONS; i++) {
double value = i/K;
sineTable[i] = Math.sin(value);
}
}
public static final double sin(double value) {
return sineTable[(int)(((value*K + 0.5) % DIVISIONS + DIVISIONS)%DIVISIONS)];
}
public static final double cos(double value) {
return sineTable[(int)(((value*K + 0.5) % DIVISIONS + 1.25*DIVISIONS)%DIVISIONS)];
}
public static void main(String[] args) {
double v=0;
long ms;
ms = -System.nanoTime();
FastTrig.init();
ms += System.nanoTime();
System.out.printf("FastTrig init time: %.5f seconds\n", ms / 1E9);
int A = 10000;
int B = 1000;
double absolute = 0;
for ( int i = 0; i < A; ++i ) for ( int j = 0; j < B; ++j ) {
double angle = Math.random() * Math.PI * 200 - Math.PI * 100;
absolute = Math.max(absolute, Math.abs(Math.sin(angle) - FastTrig.sin(angle)));
absolute = Math.max(absolute, Math.abs(Math.cos(angle) - FastTrig.cos(angle)));
}
System.out.printf("Wrost error: %.12f\n", absolute);
v=0;
ms = -System.nanoTime();
for ( int i = 0; i < A; ++i ) for ( int j = 0; j < B; ++j )
v += FastTrig.sin(i * j * Math.PI - Math.PI / 3);
ms += System.nanoTime();
System.out.printf("FastTrig time: %.3f seconds\n", ms / 1E9);
v = 0;
ms = -System.nanoTime();
for ( int i = 0; i < A; ++i ) for ( int j = 0; j < B; ++j )
v += Math.sin(i * j * Math.PI - Math.PI / 3);
ms += System.nanoTime();
System.out.printf("Math time: %.3f seconds\n", ms/1E9);
}
}
Test output is as follows:
FastTrig init time: 0.00470 seconds Wrost error: 0.000436329459 FastTrig time: 0.506 seconds Math time: 8.619 seconds
--Rednaxela 00:34, 4 March 2009 (UTC)