Difference between revisions of "User:Rednaxela/FastTrig"

From Robowiki
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 = 2880;
+
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 double[] cosineTable = 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*Math.PI*2/DIVISIONS;
+
double value = i/K;
 
sineTable[i] = Math.sin(value);
 
sineTable[i] = Math.sin(value);
cosineTable[i] = Math.cos(value);
 
 
}
 
}
 
}
 
}
 
 
 
public static final double sin(double value) {
 
public static final double sin(double value) {
return sineTable[(int)(value/(Math.PI*2/DIVISIONS) + 40*DIVISIONS + 0.5) % DIVISIONS];
+
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 cosineTable[(int)(value/(Math.PI*2/DIVISIONS) + 40*DIVISIONS + 0.5) % DIVISIONS];
+
return sineTable[(int)(((value*K + 0.5) % DIVISIONS + 1.25*DIVISIONS)%DIVISIONS)];
 
}
 
}
 
 
/*
 
 
public static void main(String[] args) {
 
public static void main(String[] args) {
init();
+
double v=0;
 
double v=12.23;
 
 
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<100000; i++)
+
for ( int i = 0; i < A; ++i ) for ( int j = 0; j < B; ++j )
v += Math.sin(i*Math.PI*2/10000);
+
v += FastTrig.sin(i * j * Math.PI - Math.PI / 3);
 
ms += System.nanoTime();
 
ms += System.nanoTime();
System.out.println(String.format("Done in %4.4f seconds", ms/1E9));
+
System.out.printf("FastTrig time: %.3f seconds\n", ms / 1E9);
+
v = 0;
 
ms = -System.nanoTime();
 
ms = -System.nanoTime();
for (int i=0; i<100000; i++) {
+
for ( int i = 0; i < A; ++i ) for ( int j = 0; j < B; ++j )
//v += FastTrig.sin(i*Math.PI*2/10000);
+
v += Math.sin(i * j * Math.PI - Math.PI / 3);
double value = i*Math.PI/10000;
 
v += sineTable[(int)(value/(Math.PI*2/DIVISIONS) + 40*DIVISIONS + 0.5) % DIVISIONS];
 
}
 
 
ms += System.nanoTime();
 
ms += System.nanoTime();
System.out.println(String.format("Done in %4.4f seconds", ms/1E9));
+
System.out.printf("Math time: %.3f seconds\n", ms/1E9);
 
}
 
}
*/
 
 
}</pre>
 
}</pre>
  
--[[User:Rednaxela|Rednaxela]] 21:57, 3 March 2009 (UTC)
+
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 02: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)