Tuesday, June 14, 2011

Java Math Functions which are not available in J2ME

package com.huayu.gps;

public class Deg {

    public static final int SEC = 500;
    public static final int MIN = 60 * SEC;
    public static final int DEG = 60 * MIN;

    public static final int FORMAT_AUTO = -1;
    public static final int FORMAT_D = 0;
    public static final int FORMAT_DM = 1;
    public static final int FORMAT_DMS = 2;
    public static final int FORMAT_NMEA = 3;
    public static final int FORMAT_FIXED = 4;

    public static final int PRECISION_D = 6;
    public static final int PRECISION_M = 4;
    public static final int PRECISION_S = 2;

    // fixed decimal point = 1
    public static final int iFIXED = 1000; // Integer.MAX_VALUE;
    //public static final long FIXED = Long.MAX_VALUE;

    private static int format = FORMAT_D;

    protected int deg;

    public Deg() { this.deg = 0; }
    public Deg( int deg ) { this.deg = limitDeg( deg ); }
    public Deg( long deg ) { this.deg = limitDeg( deg ); }
    public Deg( Deg deg ) { this.deg = deg.deg; }

    public void set( int deg ) { this.deg = limitDeg( deg ); }
    public void set( long deg ) { this.deg = limitDeg( deg ); }
    public void set( Deg deg ) { this.deg = deg.deg; }

    public int get() { return deg; }
    public String toString() {
        return "";    // TODO
    }

    public static void setFormat( int f ) { format = f; }
    public static int getFormat() { return format; }

    public static int min( int a, int b ) {
        return ( a < b ) ? a : b;
    }

    public static int max( int a, int b ) {
        return ( a > b ) ? a : b;
    }

    public static int abs( int x ) {
        return ( x < 0 ) ? -x : x;
    }

    public static int limitDeg( int deg ) {
        while( deg >= 360 * DEG ) deg -= 360 * DEG;
        while( deg < 0 ) deg += 360 * DEG;
        return deg;
    }

    public static int limitDeg( long deg ) {
        while( deg >= 360 * DEG ) deg -= 360 * DEG;
        while( deg < 0 ) deg += 360 * DEG;
        return (int) deg;
    }

    public static int limitDeg( double deg ) {
        while( deg >= 360 * DEG ) deg -= 360 * DEG;
        while( deg < 0 ) deg += 360 * DEG;
        return (int) deg;
    }

    public static String degToStr( int value, int f, int n, int precision, String signPlus, String signMinus ) {
        StringBuffer tmpsb = new StringBuffer();
        if( ( ( f < 0 ) ? format : f ) != FORMAT_FIXED ) {
            tmpsb.append( ( value < 0 ) ? signMinus : signPlus );
            value = ( value < 0 ) ? -value : value;
        }
        switch( ( f < 0 ) ? format : f ) {
            case FORMAT_FIXED :
            case FORMAT_D :
                tmpsb.append( VlkText.fixToStr( value, DEG, n, ( precision < 0) ? PRECISION_D : precision ) );
                break;
            case FORMAT_DM :
                tmpsb.append( VlkText.intToStr( value / DEG, n ) );
                tmpsb.append( "°" );
                tmpsb.append( VlkText.fixToStr( value % DEG, MIN, 2, ( precision < 0) ? PRECISION_M : precision ) );
                break;
            case FORMAT_DMS :
                tmpsb.append( VlkText.intToStr( value / DEG, n ) );
                tmpsb.append( "°" );
                tmpsb.append( VlkText.intToStr( ( value % DEG ) / MIN, 2 ) );
                tmpsb.append( "'" );
                tmpsb.append( VlkText.fixToStr( value % MIN, SEC, 2, ( precision < 0) ? PRECISION_S : precision ) );
                break;
        }
        return tmpsb.toString();
    }

    public static int strToDeg( String value ) {
        int idp = value.indexOf( '.' );
        int idk = value.indexOf( ',' );              
        int igr = value.indexOf( "°" );
        int imn = value.indexOf( "'" );
        if( imn > igr ) {
            // FORMAT_DMS // DDD°MM'SS.ss // TODO rewrite to int
            int tmpi = Integer.parseInt( value.substring( 0, igr ) ) * DEG;
            tmpi += Integer.parseInt( value.substring( igr + 1, imn ) ) * MIN;
            tmpi += (int) ( Double.parseDouble( value.substring( imn + 1 ) ) * SEC );
            return tmpi;
        }
        if( igr > 0 ) {
            // FORMAT_DM // DDD°MM.mmmm // TODO rewrite to int
            int tmpi = Integer.parseInt( value.substring( 0, igr ) ) * DEG;
            tmpi += (int) ( Double.parseDouble( value.substring( igr + 1 ) ) * MIN );
            return tmpi;
        }
        if( ( idp == 4 ) || ( idp == 5 ) ) {
            // FORMAT_NMEA // DDDMM.mmmm
            int tmpi = Integer.parseInt( value.substring( 0, idp - 2 ) ) * DEG;
            tmpi += (int) ( Double.parseDouble( value.substring( idp - 2 ) ) * MIN );
//            tmpi += Integer.parseInt( value.substring( idp - 2, idp ) ) * MIN;
//            tmpi += Integer.parseInt( value.substring( idp + 1 ) ) * ( MIN / 10000 );
            return tmpi;
        }
        if( ( idp >= 0 ) && ( idp <= 3 ) ) {
            // FORMAT_D // DDD.dddddd
            double tmpd = Double.parseDouble( value );
            return degToInt( tmpd );
        }
        if( ( idk >= 0 ) && ( idk <= 3 ) ) {
            // FORMAT_D // DDD,dddddd
            double tmpd = Double.parseDouble( value.replace(',','.') );
            return degToInt( tmpd );
        }
        // FORMAT_ERROR
        return 0; // make exception!
    }

    public static int degToInt( double deg ) {
        return( (int) ( deg * DEG ) );
    }

    public static double sqr( double x ) {
        return ( x * x );
    }

    public static int asin( double x ) {
        return (int)( (double)DEG * Math.toDegrees( Float11.asin( x ) ) );
    }

//    public static int asin( long x ) {
//        return (int)( (double)DEG * Math.toDegrees( Float11.asin( ( (double)x ) / FIXED ) ) );
//    }

    public static int acos( double x ) {
        return (int)( (double)DEG * Math.toDegrees( Float11.acos( x ) ) );
    }

//    public static int acos( long x ) {
//        return (int)( (double)DEG * Math.toDegrees( Float11.acos( ( (double)x ) / FIXED ) ) );
//    }

    public static int atan( double x ) {
        return (int)( (double)DEG * Math.toDegrees( Float11.atan( x ) ) );
    }

    public static int atan2( double y, double x ) {
        return (int)( (double)DEG * Math.toDegrees( Float11.atan2( y, x ) ) );
    }

    public static double sin( int x ) {
        return Math.sin( Math.toRadians( ( (double) x ) / DEG ) );
    }

    public static double cos( int x ) {
        return Math.cos( Math.toRadians( ( (double) x ) / DEG ) );
    }

    private static int[] tabSin = new int[ 720 ];
    private static boolean mathTablesCreated = false;

    public static int fastSin( int x ) {
        return( tabSin[ limitDeg( x ) / ( DEG / 2 ) ] );
    }

    public static int fastCos( int x ) {
        x += 90 * DEG;
        return( tabSin[ limitDeg( x ) / ( DEG / 2 ) ] );
    }

    public static void initFastMath() {
        if( ! mathTablesCreated ) {
            //Debug.debug( "Generating fast math tables" );
            for( int i = 0; i < 720; i++ ) {
                tabSin[ i ] = ( int ) ( iFIXED * Math.sin( Math.toRadians( i / 2 ) ) );
            }
            mathTablesCreated = true;
        }
    }

    public static void mathBench() {
        //Debug.debug( "Math speed test:" );
        int j = 0;
        long drawTime = System.currentTimeMillis();
        for( int i = 0; i < 1000; i++, j += MIN ) {
            sin( j );
        }
        //Debug.debug( "sin(): " + (int)( System.currentTimeMillis() - drawTime ) + "us" );
        j = 0;
        drawTime = System.currentTimeMillis();
        for( int i = 0; i < 1000; i++, j += MIN ) {
            cos( j );
        }
        //Debug.debug( "cos(): " + (int)( System.currentTimeMillis() - drawTime ) + "us" );
        j = 0;
        drawTime = System.currentTimeMillis();
        for( int i = 0; i < 1000; i++, j += MIN ) {
            asin( j );
        }
        //Debug.debug( "asin(): " + (int)( System.currentTimeMillis() - drawTime ) + "us" );
        j = 0;
        drawTime = System.currentTimeMillis();
        for( int i = 0; i < 1000; i++, j += MIN ) {
            acos( j );
        }
        //Debug.debug( "acos(): " + (int)( System.currentTimeMillis() - drawTime ) + "us" );
        j = 0;
        drawTime = System.currentTimeMillis();
        for( int i = 0; i < 1000; i++, j += MIN ) {
            fastSin( j );
        }
        //Debug.debug( "fastSin(): " + (int)( System.currentTimeMillis() - drawTime ) + "us" );
        j = 0;
        drawTime = System.currentTimeMillis();
        for( int i = 0; i < 1000; i++, j += MIN ) {
            fastCos( j );
        }
        //Debug.debug( "fastCos(): " + (int)( System.currentTimeMillis() - drawTime ) + "us" );
        Coords wpt1 = new Coords( 10 * DEG, 30 * DEG, 0 );
        Coords wpt2 = new Coords( 20 * DEG, 70 * DEG, 0 );
        drawTime = System.currentTimeMillis();
        for( int i = 0; i < 1000; i++ ) {
            j = wpt1.zenith( wpt2 );
        }
        //Debug.debug( "zenith(): " + (int)( System.currentTimeMillis() - drawTime ) + "us" );
        drawTime = System.currentTimeMillis();
        int k = j;
        for( int i = 0; i < 1000; i++ ) {
            j = wpt1.azimuth( wpt2, k );
        }
        //Debug.debug( "azimuth(): " + (int)( System.currentTimeMillis() - drawTime ) + "us" );
    }

}

No comments:

Post a Comment