Skip to main content

Math is too slow

7 replies [Last post]
jcmeira
Offline
Joined: 2003-08-02

Math.sin(),Math.cos() are too slow

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
azeemjiva
Offline
Joined: 2005-03-31

It's already been integrated into the latest Mustang builds.

mthornton
Offline
Joined: 2003-06-10

It seems to me that the hardware cos/sin instructions are used. However in the case of x86, the processor native instruction does not do argument reduction accurately enough to meet even the relaxed Math.sin/cos specification for arguments larger than about PI/4. Therefore for these arguments the JVM uses a relatively expensive (but accurate) reduction before using the processors trig instruction.
This frustrates many people for whom the native instruction is accurate enough, but nevertheless have to pay the cost of Java getting those last few bits correct. Perhaps there should be a new package "SloppyMath" which provides few accuracy guarantees --- just standard accuracy for the hardware concerned.

bloid
Offline
Joined: 2003-06-11

There's already an RFE for this:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5005861

Vote for it!!

aces
Offline
Joined: 2003-07-17

while it does not happens, and you "need for speed" use something like this:
[i]
Disclaimer : not accurate, not precise, not faster than C,
no warranties of any order it will works for you.
Of course, feel free to improve it ;)
[/i]
[code]
/**
* A fast but low precison (error ~ 1x10^-6) floating sinTable.
* feel free to do anything with this class.
* Alessandro Borges 2004
*/
import java.text.DecimalFormat;
public class FloatSinTable
{
static float[] table=null;
static float step;
static float invStep;
static int size=0;

public FloatSinTable()
{
this(720);
}

public FloatSinTable(int n)
{
if (size==0)
{
build(n);
}
}

/**
* build sin table with size elements
* @param size
*/
final private void build(int pSize)
{
size=pSize;
table = new float[size];
step = (float) (2d * Math.PI / size);
invStep = 1.0f / step;
for (int i=0; i {
table[i] = (float)Math.sin(step*((float)i));
}
}

/**
* calculates fast sin, but with low precision.
* @param a angle in radians
* @return sin of angle a
*/
final public float sinFast(float a)
{
/* we need speed !

if (a == Double.NaN) return Double.NaN;
if (a == 0.0d) return 0.0d;
*/

int index = (int)(a/step);
return table[index];
}

/**
* interpolated values of sin.
* Not so fast, but much more precise than
* @param ang angle in radians
* @return sin of angle a
*/
final public float sin(float ang)
{
int indexA = (int)(ang / step);
int indexB = indexA + 1 ;
if (indexB >= size) return table[indexA];

float a = table[indexA];
/*
float b = table[indexB];
double real = Math.sin(ang);
float w = (b-a);
float x = ang - (indexA * step);//* invStep;
w = w * x / step;
a = a + w;
return a ;
*/
return a + (table[indexB] - a)*(ang - (indexA*step))*invStep;

}

/**
* Testing...
* @param args
*/
public static void main(String[] args)
{
FloatSinTable sinTable = new FloatSinTable(4*360);
DecimalFormat df = new DecimalFormat("0.########");
int max = 10000000;

float pi = (float)Math.PI;

for (int i=0; i< 20; i++)
{
float angle = (float)( Math.random() * Math.PI* 2f);
float sinT = sinTable.sin(angle);
float sin = (float)Math.sin(angle);
float delta = sin - sinT;
System.out.println("sin " + df.format(angle) + " :\t" + sinT + " : " + sin + " DELTA " + (delta));
}

long t1 = System.currentTimeMillis();
for (int i=0; i {
float x = sinTable.sin(pi);
}
long t2 = System.currentTimeMillis();
System.out.println("tempo SinTable: " + (t2-t1));

long t3 = System.currentTimeMillis();
for (int i=0; i {
float x = (float)Math.sin(pi);
}
long t4 = System.currentTimeMillis();
System.out.println("tempo Math.sin: " + (t4-t3));

/***** **********/
long t5 = System.currentTimeMillis();
for (int i=0; i {
float x = sinTable.sinFast(pi);
}
long t6 = System.currentTimeMillis();

System.out.println("tempo Sintable fast: " + (t6-t5));
}
}
[/code]

aces
Offline
Joined: 2003-07-17

also make sure angles are 0 <= angle < 2*pi

peterkessler
Offline
Joined: 2004-10-27

What platform (Java release, instruction set, and operating system) are you running on? Are you using strict math or "platform" math? What are you comparing the performance to? How are you measuring the performance?

Remember that the Sun HotSpot virtual machine starts out interpreting things, and only compiles to native code if a method is used enough to warrant compilation. Measuring performance is somewhat tricky, but if you post your timing harness, I'll critique it.

Also, we offer two runtime compilers, which you access with -client or -server on the command line. The -client runtime compiler generates code quickly, but the generated code itself is only so-so. The -server compiler is a full-up optimizing compiler, and I'd be surprised if we weren't turning Math.sin() and Math.cos() into the hardware instructions on platforms where that was available (maybe after appropriate scaling to get the argument into the range that the instruction can handle).

aces
Offline
Joined: 2003-07-17

Of course HW sin/cos calculation should be very nice.
But if sin/cos performance is really boring you, consider a sinTable cosTable for really fast calcs.