package mikera.util.mathz;

import mikera.util.Maths;

/**
 * Static class for specialised maths functions that return floats
 * 
 * @author Mike
 *
 */
public final class FloatMaths {
	
	/** Float round to a specified number of decimal places */
	public static float round(float f, int dp) {
		float factor=(float)Math.pow(10, -dp);
		return Math.round(f/factor)*factor;
	}
	
	/**
	 * Computes a fast approximation to Math.pow(a, b). Adapted
	 * from http://www.dctsystems.co.uk/Software/power.html.
	 * 
	 * @param a a positive number
	 * @param b a number
	 * @return a^b
	 */
	public static final float fastPower(float a, float b) {
	    // adapted from: http://www.dctsystems.co.uk/Software/power.html
	    float x = Float.floatToRawIntBits(a);
	    x *= 1.0f / (1 << 23);
	    x = x - 127;
	    float y = x - (int) Math.floor(x);
	    b *= x + (y - y * y) * 0.346607f;
	    y = b - (int) Math.floor(b);
	    y = (y - y * y) * 0.33971f;
	    return Float.intBitsToFloat((int) ((b + 127 - y) * (1 << 23)));
	}
	

	/** Linear interpolation between a and b */
	public static final float lerp(float t,float a, float b) {
	    return (1-t) * a + t*b;		
	}
	
	/** Smooth factor function for linear interpolation, with dy/dx=0 at x=0 and x=1 */
	public static final float smoothFactor(float x) {
	    return x * x * (3 - (2 * x));		
	}
	
	
	/** Mod function implemented for float values */
	public static float mod(float n, float d) {
		float x=n/d;
		return n- (Maths.roundDown(x)*d);
	}


	public static final float smoothStep(float a, float b, float x) {
	    if (x <= a)
	        return 0;
	    if (x >= b)
	        return 1;
	    float t = bound((x - a) / (b - a), 0.0f, 1.0f);
	    return t * t * (3 - 2 * t);
	}
	

    /** Bound a value within a given range */
	public static final float bound(float v, float min, float max) {
		if (vmax) return max;
		return v;
	}
	
	/** float abs function */
	public static float abs(final float a) {
		if (a<0) return -a;
		return a;
	}

	/** Square function */
	public static float square(float x) {
		return x*x;
	}
	
	/** float square root */
	public static float sqrt(float a) {
		return (float) Math.sqrt(a);
	}
	
	/**
	 * Interesting way to approximate a square root.... however seems to be slower than standard Math.sqrt() approach
	 * @param x
	 * @return
	 */
	public static float alternateSqrt(float x) {
		if (x<0) return 0;
		float r=approxSqrt(x);
		r=r-(0.5f*((r*r)-x)/r); // Newton iteration
		r=r-(0.5f*((r*r)-x)/r); // Newton iteration
		return r;
	}
	
	/** Fast approximate square root */
	public static float approxSqrt(float x) {
	    int i = Float.floatToRawIntBits(x);
	    //int exponent=i&0x7F800000; // 8 bits below sign bit
	    //int value=(i&0x7FFFFFF)+((exponent!=0)?0:0x08000000); // 23 low bits, implicit 1 unless exponent=0
	    i=(i+0x3F800000)>>>1;
	    return Float.intBitsToFloat(i);
	}
	
	
	/** Fast inverse square root on floats - amusing hack used in Quake */
	public static float fastInverseSqrt(float x) {
	    float xhalf = 0.5f*x;
	    int i = Float.floatToRawIntBits(x);
	    i = 0x5F3759DF - (i>>1);
	    x = Float.intBitsToFloat(i);
	    x = x*(1.5f - xhalf*x*x);
	    return x;
	}
	
	/** Float-returning version of Math.sin */
	public static float sin(double a) {
		a = a % Maths.TWO_PI;
		return (float)Math.sin(a);
	}
	
	/** Float-returning version of Math.cos */
	public static float cos(double a) {
		a = a % Maths.TWO_PI;
		return (float)Math.cos(a);
	}

	/** Float-returning version of Math.sin */
	public static float sin(float a) {
		a =  a % ((float) Maths.TWO_PI);
		return (float)Math.sin(a);
	}
	
	/** float version of Math.tanh */
	public static float tanh (float x) {
		double ex=Math.exp(2*x);
		float df=(float)((ex-1)/(ex+1));
		if (Float.isNaN(df)) return (x>0)?1:-1;
		return df;
	}
	
	public static float tanhDerivative (float x) {
		double sa=Math.tanh(x);
		return 1.0f-(float)(sa*sa);
	}
	
	/** Float-returning version of Math.cos */
	public static float cos(float a) {
		a =  a % ((float) Maths.TWO_PI);
		return (float)Math.cos(a);
	}
}

 

Ads help maintain this website.