MoreMath (FastMath)

Hey, I found this in a realtime raytracing software thingie which I downloaded a long time ago. Could be interesting. Unfortunately there was no README or something in the package so I cannot give credit to the person who wrote this.


/**
 * The MoreMath class provides functions not contained in the java.lang.Math or java.lang.StrictMath classes.
 */
public class MoreMath {
	
	//a sin table with 4096 entries
	private static final int SIN_TABLE_SIZE_BITS = 12;
	private static final int SIN_TABLE_SIZE = 1 << SIN_TABLE_SIZE_BITS;
	private static final int SIN_TABLE_SIZE_MASK = SIN_TABLE_SIZE - 1;
	private static final int SIN_HALF_PI = SIN_TABLE_SIZE / 4;
	private static final float SIN_CONVERSION_FACTOR = (float)(SIN_TABLE_SIZE / (2*Math.PI));
	
	private static float[] sinTable;
	
	//a asin table with 2000 entries
	private static final int ASIN_TABLE_SIZE = 2001;
	private static final float ASIN_CONVERSION_FACTOR = (float)((ASIN_TABLE_SIZE-1) / 2);
	
	private static float[] asinTable;
	
	//a sqrt table with 1024 entries (for 0 to 1)
	private static final int SQRT_TABLE_SIZE = 1025;
	private static final float SQRT_CONVERSION_FACTOR = (float)((SQRT_TABLE_SIZE-1));
	
	private static float[] sqrtTable;
	
	public static final float PI = (float)(Math.PI);
	public static final float HALF_PI = (float)(Math.PI / 2.0);
	public static final float TWO_PI = (float)(Math.PI * 2.0);
	public static final float PI_INV = (float)(1.0 / Math.PI);
	public static final float HALF_PI_INV = (float)(2.0 / Math.PI);
	public static final float TWO_PI_INV = (float)(1.0 / (Math.PI * 2.0));
	
	//some coefficients for conversion from the RGB-model to RGB components.
	//Using bitshifting instead of multiplication is faster.
	//private final int[] RGB_CONVERT_COEFF = {0x010000,0x000100,0x000001};
	//The blue channel occupies the first 8 bits of the color, the green channel the next 8 bits and the 
	//red channel the last 8 bits. I extract those bits by multiplying with a number that only has ones on those
	//bits. Finally I shift back and divide by 255.
	/*private static final int[] ARGB_DECONVERT_COEFF = {
	    ((1<<24) + (1<<25) + (1<<26) + (1<<27) + (1<<28) + (1<<29) + (1<<30) + (1<<31)),
		((1<<16) + (1<<17) + (1<<18) + (1<<19) + (1<<20) + (1<<21) + (1<<22) + (1<<23)),
		((1<<8) + (1<<9) + (1<<10) + (1<<11) + (1<<12) + (1<<13) + (1<<14) + (1<<15)),
		((1<<0) + (1<<1) + (1<<2) + (1<<3) + (1<<4) + (1<<5) + (1<<6) + (1<<7))
		};*/
	//I'm now shifting first and the just chop of what I need.
	private static final float ARGB_DECONVERT_SCALING = 1f / 255f;
	
	
	//init tables when this class is loaded
	static {
		init();
	}
	
	private static void init() {
		sinTable = new float[SIN_TABLE_SIZE];
		for(int i=0; i<SIN_TABLE_SIZE; i++) {
			sinTable[i] = (float)Math.sin(i / SIN_CONVERSION_FACTOR);
		}
		
		asinTable = new float[ASIN_TABLE_SIZE];
		for(int i=0; i<ASIN_TABLE_SIZE; i++) {
			asinTable[i] = (float)Math.asin((i / ASIN_CONVERSION_FACTOR) - 1);
		}
		
		sqrtTable = new float[SQRT_TABLE_SIZE];
		for(int i=0; i<SQRT_TABLE_SIZE; i++) {
			sqrtTable[i] = (float)Math.sqrt(i / SQRT_CONVERSION_FACTOR);
		}
	}
	
	/**
	 * Gives the square root faster if 0 <= x <= 1.
	 * @param x the value to get the root of.
	 * @return the root.
	 */
	public static float sqrt(float x) {
		if(x>1) {
			return (float)Math.sqrt(x);
		}
		return sqrtTable[(int)(x*SQRT_CONVERSION_FACTOR)];
	}
	
	/**
	 * Cosine function with the angle from 0 to 2*Pi.
	 * @param angle the angle (float).
	 * @return the cosine of the angle.
	 */
	public static float cos(float angle) {
		return sinTable[(SIN_HALF_PI-((int)(angle * SIN_CONVERSION_FACTOR))) & SIN_TABLE_SIZE_MASK];
	}
	
	/**
	 * Sine function with the angle from 0 to 2*Pi.
	 * @param angle the angle (float).
	 * @return the sine of the angle.
	 */
	public static float sin(float angle) {
		return sinTable[((int)(angle * SIN_CONVERSION_FACTOR)) & SIN_TABLE_SIZE_MASK];
	}
	
	/**
	 * Acosine function with the x from -1 to 1.
	 * @param x the x (float).
	 * @return the acosine of the x.
	 */
	public static float acos(float x) {
		if(x > 1) {
			x = 1; 
		}
		else if(x < -1) {
		    x = -1;
		}
		return (HALF_PI-asinTable[((int)((x+1) * ASIN_CONVERSION_FACTOR))]);
	}
	
	/**
	 * Asine function with the x from -1 to 1.
	 * @param x the x (float).
	 * @return the asine of the x.
	 */
	public static float asin(float x) {
		if(x > 1) {
			x = 1; 
		}
		else if(x < -1) {
		    x = -1;
		}
		return asinTable[((int)((x+1) * ASIN_CONVERSION_FACTOR))];
	}

    /**
     * Returns the sign of the number. Returns -1 for negative, 1 for positive, and 0 otherwise.
     */
	public static int sign(short v) {
        return (v>0)?1:(v<0)?-1:0;
    }

    /**
     * Returns the sign of the number. Returns -1 for negative, 1 for positive, and 0 otherwise.
     */
    public static int sign(int v) {
        return (v>0)?1:(v<0)?-1:0;
    }

    /**
     * Returns the sign of the number. Returns -1 for negative, 1 for positive, and 0 otherwise.
     */
    public static int sign(long v) {
        return (v>0)?1:(v<0)?-1:0;
    }

    /**
     * Returns the sign of the number. Returns -1 for negative, 1 for positive, and 0 otherwise.
     */
    public static int sign(float v) {
        return (v>0)?1:(v<0)?-1:0;
    }

    /**
     * Returns the sign of the number. Returns -1 for negative, 1 for positive, and 0 otherwise.
     */
    public static int sign(double v) {
        return (v>0)?1:(v<0)?-1:0;
    }

… continued…

…continued from post #1


    /**
     * Faster ceil function to convert a float to an int. Contrary to the java.lang.Math ceil function, this 
     * function takes a float as an argument, returns an int instead of a double, and does not consider special 
     * cases.
     */
    public static int ceil(float f) {
        if (f > 0) {
            return (int)f + 1;
        }
        else {
           return (int)f;
        }
    }

    /**
     * Faster floor function to convert a float to an int. Contrary to the java.lang.Math floor function, this 
     * function takes a float as an argument, returns an int instead of a double, and does not consider special 
     * cases.
     */
    public static int floor(float f) {
        if (f >= 0) {
            return (int)f;
        }
        else {
           return (int)f - 1;
        }
    }
    
    /**
     * Faster round function to convert a float to an int. Contrary to the java.lang.Math round function, this 
     * function takes a float as an argument, returns an int and does not consider special 
     * cases.
     */
    public static int round(float f) {
        return (int)MoreMath.floor(f+0.5f);
    }

    /**
     * Returns true if the specified number is a power of 2.
     */
    public static boolean isPowerOfTwo(int n) {
        return ((n & (n-1)) == 0);
    }
    
    /**
     * Gets the number of "on" bits in an integer.
     */
    public static int getBitCount(int n) {
        int count = 0;
        while (n > 0) {
            count+=(n & 1);
            n>>=1;
        }
        return count;
    }
    
    /**
     * A faster pow function tot calculate x^n. It is vital that n>0 or this function will have an infinite loop.
     * @param x a float number.
     * @param n an interger.
     * @return x^n is returned.
     */
    public static float pow(float x,int n) {
    	if(n == 0) {
    		return 1;
    	}
    	else {
			float y = x;
			for(int i=1; i!=n; i++) {
				y *= x;
			}
			return y;
    	}
    }
    
    public static int abs(int x) {
    	if(x < 0) {
    		return (-x);
    	}
    	return x;
    }
	
	public static float abs(float x) {
		if(x < 0) {
			return (-x);
		}
		return x;
	}
	
	/**
	 * This converts a color (3 int values representing red, green and blue components ranging from 0 to 255) to an 
	 * 8-bit ARGB color (0xAARRGGBB, where A for alpha, R for red, G for green and B for blue).
	 * @param c1 the red component of the color to convert.
	 * @param c2 the green component of the color to convert.
	 * @param c3 the blue component of the color to convert.
	 * @param alpha the alpha value.
	 * @return the converted color.
	 */
	public static int convertToARGB(int alpha,int c1,int c2,int c3) {
		return ((alpha << 24) | (c1 << 16) | (c2 << 8) | c3);
	}
	
	/**
	 * This converts a color (3 float values representing red, green and blue components ranging from 0 to 1) to an 
	 * 8-bit ARGB color (0xAARRGGBB, where A for alpha, R for red, G for green and B for blue).
	 * @param x the color to convert.
	 * @param alpha the alpha value.
	 * @return the converted color.
	 */
	public static int convertToARGB(float alpha,float[] x) {
		return convertToARGB((int)(alpha*255),(int)(x[0]*255),(int)(x[1]*255),(int)(x[2]*255));
	}
	
	/**
	 * This converts a color (3 int values representing red, green and blue components ranging from 0 to 255) to an 
	 * 8-bit RGB color (0xRRGGBB, where R for red, G for green and B for blue).
	 * @param c1 the red component of the color to convert.
	 * @param c2 the green component of the color to convert.
	 * @param c3 the blue component of the color to convert.
	 * @return the converted color.
	 */
	public static int convertToRGB(int c1,int c2,int c3) {
		return ((c1 << 16) | (c2 << 8) | c3);
	}
	
	/**
	 * This converts a color (3 float values representing red, green and blue components ranging from 0 to 1) to an 
	 * 8-bit RGB color (0xRRGGBB, where R for red, G for green and B for blue).
	 * @param x the color to convert.
	 * @return the converted color.
	 */
	public static int convertToRGB(float[] x) {
		return convertToRGB((int)(x[0]*255),(int)(x[1]*255),(int)(x[2]*255));
	}
	
	/**
	 * This converts a color (an integer value in the 8-bit RGB color model) to its components (3 float values 
	 * representing red, green and blue components ranging from 0 to 1).
	 * @param color the color to convert.
	 * @param dest the array to store the colors in (length must be >=3)
	 */
	public static void convertFromRGB(int color,float[] dest) {
		dest[0] = (float)((color >> 16) & 0xFF) * ARGB_DECONVERT_SCALING;
		dest[1] = (float)((color >> 8) & 0xFF) * ARGB_DECONVERT_SCALING;
		dest[2] = (float)(color & 0xFF) * ARGB_DECONVERT_SCALING;
	}
	
	/**
	 * This converts a color (an integer value in the 8-bit RGB color model) to its components (3 float values 
	 * representing red, green and blue components ranging from 0 to 1).
	 * @param color the color to convert.
	 * @return the converted color.
	 */
	public static float[] convertFromRGB(int color) {
		float[] x = new float[3];
		convertFromRGB(color,x);
		return x;
	}
	
	public static float getAlphaf(int color) {
		return (float)((color >> 24) & 0xFF) * ARGB_DECONVERT_SCALING;
	}
	public static float getRedf(int color) {
		return (float)((color >> 16) & 0xFF) * ARGB_DECONVERT_SCALING;
	}
	public static float getGreenf(int color) {
		return (float)((color >> 8) & 0xFF) * ARGB_DECONVERT_SCALING;
	}
	public static float getBluef(int color) {
		return (float)(color & 0xFF) * ARGB_DECONVERT_SCALING;
	}
	public static int getAlphai(int color) {
		return (int)((color >> 24) & 0xFF);
	}
	public static int getRedi(int color) {
		return ((color >> 16) & 0xFF);
	}
	public static int getGreeni(int color) {
		return ((color >> 8) & 0xFF);
	}
	public static int getBluei(int color) {
		return (color & 0xFF);
	}
}

hmmm

convertToRGB() should probably have the higher order bits all on anyway (ie. alpha 255, or 1.0) as does AlphaComposite.getAlpha() when no alpha is set.