My panorama viewers use a lot of the Math methods.
They are really slow and not all that precise.

http://pancyl.com/SittingRoom.htm

The trig functions are inaccurate near a multiple of
PI and zero.  So much so that I have to check against
an Epsilon value and if the absolute returned value is
less than Epsilon then I manually set the value I need.

I also had to develop -- with some help -- an approximation
calculation for atan2() and I use a lookup table for asin().

I've found that lookup tables are not all that great near
a multiple of PI especially if you are trying to use a look
up table for tan/atan.  They change very fast near their
asymptote.  I use lookup tables "in the middle" but revert
to the real method near the poles with an Epsilon check.

I've wanted to gripe about the slowness and inaccuracy of
the Math package but who do I talk to?

[EMAIL PROTECTED] wrote:
Is there an alternate, faster way to do the maths?

The problem here is Math.round and Math.atan2, the Math class is optimized for 
high precission but often sacrifices speed.

Your original version took 205ms on my C2D, replacing atan2 with this unprecise 
version and removing the round braught it down to 35ms.
Be sure to use the server-runtime if possible, it gave me a solid 40% speed 
boost :)

[code]
    private final double aTan2(double y, double x) {
        double coeff_1 = Math.PI / 4d;
        double coeff_2 = 3d * coeff_1;
        double abs_y = Math.abs(y);
        double angle;
        if (x >= 0d) {
                double r = (x - abs_y) / (x + abs_y);
                angle = coeff_1 - coeff_1 * r;
        } else {
                double r = (x + abs_y) / (abs_y - x);
                angle = coeff_2 - coeff_1 * r;
        }
        return y < 0d ? -angle : angle;
    }
[/code]
However that method seems to be very unprecise, a slightly better looking 
result can be archived using this lookup-table based implementation, however 
its slower (45ms):
[code]
package waterfall;

public class TableMath
{
        private static final int TABLE_SIZE = 10000;
        static double[] atanTable = initAtanTable();
        
        private static double[] initAtanTable()
        {
                double[] table = new double[TABLE_SIZE];
                
                for(int i=0; i < TABLE_SIZE; i++)
                {
                        table[i] = Math.atan(((double)i) / TABLE_SIZE);
                }
                
                return table;
        }
        
        private static double atan_1(int y,int x)
        {
            int index;
            int vorz;
            double erg = 0;
vorz = 1;
            if (((x < 0) && (y < 0)) || ((x > 0) && (y > 0)))  {vorz = 0;}
            else x = -x;
/*atan of y/x */
            index =(int) (((y*(TABLE_SIZE-1)*10)/x+5)/10); //+5 for rounding
erg = atanTable[index]; if (vorz == 0 ) return erg;
            else return -erg;
        }

        public static double atan2(int y, int x) {
            double result;
if(Math.abs(x) > Math.abs(y))
                result = atan_1(y,x);
            else
            {
                result = atan_1(x,y);
                if(result < 0)
                    result = -Math.PI/2 - result;
                else
                    result = Math.PI/2 - result;
            }
if (x < 0)
                if(y < 0)
                    result = result - Math.PI;
                else
                    result = result + Math.PI;
return result; } }
[/code]

I don't know if any of those two implementations fit your needs, but they are 
definitily faster ;)

Another possible optimization would be multi-threading, so each thread could do 
a part of the total work - should be perfectly paralizeable. I am not sure if 
unsynchronized write-access is valid (if no one is reading), but I guess it is. 
That would bring the fastest version down to 20ms on my machine :)

lg Clemens
[Message sent by forum member 'linuxhippy' (linuxhippy)]

http://forums.java.net/jive/thread.jspa?messageID=301636

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".


===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to