Sorry. 32-bit floats only.
public final class FloatMath
{
private FloatMath() {}
// 3rd order: 14 good bits
/**
private static final float EXP2_0 = 0xf.ff8fcp-4f;
private static final float EXP2_1 = 0xb.24b09p-4f;
private static final float EXP2_2 = 0x3.96e3dp-4f;
private static final float EXP2_3 = 0x1.446bap-4f;
*/
// 4th order: 17 good bits
/**
private static final float EXP2_0 = 0x1.00002cp0f;
private static final float EXP2_1 = 0x1.62d166p-1f;
private static final float EXP2_2 = 0x1.ee798ap-3f;
private static final float EXP2_3 = 0x1.aa13fp-5f;
private static final float EXP2_4 = 0x1.bb7cd4p-7f;
*/
// 5th order: 21 good bits
private static final float EXP2_0 = 0xf.ffffep-4f;
private static final float EXP2_1 = 0xb.1729ap-4f;
private static final float EXP2_2 = 0x3.d79c1p-4f;
private static final float EXP2_3 = 0xe.4d4cp-8f;
private static final float EXP2_4 = 0x2.4a14p-8f;
private static final float EXP2_5 = 0x7.c45p-12f;
/**
* Calculates: 2<sup>x</sup>
*/
public static final float exp2(float x)
{
int a = (int)x;
float b = x-a;
float r = 0;
//r = b*(r + EXP2_6);
r = b*(r + EXP2_5);
r = b*(r + EXP2_4);
r = b*(r + EXP2_3);
r = b*(r + EXP2_2);
r = b*(r + EXP2_1);
r = (r + EXP2_0);
return exp2(a)*r;
}
// Result accurate to 22 bits (on primary range).
private static final float LOG2_1 = 0x1.71547ap1f;
private static final float LOG2_2 = 0x1.ec554ep-1f;
private static final float LOG2_3 = 0x1.310a2cp-1f;
/**
* Calculates: Log<sub>2</sub> x
* <p>
* Accuracy: 22 bits (in normal range)
*/
public static final float log2(float x)
{
int i = Float.floatToRawIntBits(x);
int e = ((i >>> 23) & 0xff)-127;
float y = Float.intBitsToFloat(i - (e<<23));
float r = (y-sqrtOf2f)/(y+sqrtOf2f);
float b = r * r;
float a;
// Approximate via ArcTanh:
a = r*(LOG2_1 + b*(LOG2_2 + b*LOG2_3));
return 0.5f + e + a;
}
// change to pre-calculated correctly round hex constant
private static final float oneOverLog2 = (float)(1.0/Math.log(2));
/**
* Calculates: e<sup>x</sup>
* <p>
*/
public static final float exp(float x)
{
return exp2(x * oneOverLog2);
}
/**
* Calculates: x<sup>y</sup>
*/
public static final float powf(float x, float y)
{
return exp2(y * log2(x));
}
/**
* Calculates: x<sup>n</sup>
*/
public static final float pow(float x, int n)
{
float r = 1.f;
int e = n;
if (n < 0)
e = -n;
do {
if ((e & 1) != 0) r *= x;
e >>>= 1;
if (e != 0) {
x *= x;
continue;
}
if (n >= 0)
return r;
return 1/r;
} while(true);
}
// hastings style
private static final float sqrtOf2f = (float)Math.sqrt(2);
// TODO: change to precalculated exact constant
private static final float logOf2 = (float)Math.log(2);
/**
* Calculates: Log x
*/
public static final float log(float x)
{
return log2(x) * logOf2;
}
// Log[2]/Log[10]
private static final float log10Convert = 0x1.344136p-2f;
/**
* Calculates: Log<sub>10</sub> x
*/
public static final float log10(float x)
{
return log2(x) * log10Convert;
}
/**
* Calculates: 2<sup>x</sup> for inputs on [-127, 128].
* <p>
* The result is exact for valid input values,
* otherwise the result is undefined.
*/
public static final float exp2(int x)
{
return Float.intBitsToFloat((x+127)<<23);
}
}