mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-10-25 13:30:10 +00:00
Sin/Cos Opts
This commit is contained in:
1 parent
bd73427072
commit
1d05f95f74
1 file changed
+36
-26
@@ -18,41 +18,51 @@ public final class MathUtil {
|
|||||||
* Epsilon for fuzzy floating point comparisons.
|
* Epsilon for fuzzy floating point comparisons.
|
||||||
*/
|
*/
|
||||||
public static final double EPSILON = 1.0E-5;
|
public static final double EPSILON = 1.0E-5;
|
||||||
private static final int SIN_BITS, SIN_MASK, SIN_COUNT;
|
private static final int lookupBits = 14;
|
||||||
private static final double radFull, radToIndex;
|
|
||||||
private static final double degFull, degToIndex;
|
static final int lookupTableSize = 1 << lookupBits;
|
||||||
private static final double[] sin, cos;
|
|
||||||
|
private static final int lookupTableSizeWithMargin = lookupTableSize + 1;
|
||||||
|
private static final double tauOverLookupSize = TrigonometryConstants.TAU / lookupTableSize;
|
||||||
|
static final double radianToIndex = (~(-1 << lookupBits) + 1) / TrigonometryConstants.TAU;
|
||||||
|
private static final long[] sinTable;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
SIN_BITS = 12;
|
sinTable = new long[lookupTableSizeWithMargin];
|
||||||
SIN_MASK = ~(-1 << SIN_BITS);
|
for (int i = 0; i < lookupTableSizeWithMargin; i++) {
|
||||||
SIN_COUNT = SIN_MASK + 1;
|
double d = i * tauOverLookupSize;
|
||||||
|
sinTable[i] = Double.doubleToRawLongBits(StrictMath.sin(d));
|
||||||
radFull = Math.PI * 2.0;
|
|
||||||
degFull = 360.0;
|
|
||||||
radToIndex = SIN_COUNT / radFull;
|
|
||||||
degToIndex = SIN_COUNT / degFull;
|
|
||||||
|
|
||||||
sin = new double[SIN_COUNT];
|
|
||||||
cos = new double[SIN_COUNT];
|
|
||||||
|
|
||||||
for(int i = 0; i < SIN_COUNT; i++) {
|
|
||||||
sin[i] = Math.sin((i + 0.5f) / SIN_COUNT * radFull);
|
|
||||||
cos[i] = Math.cos((i + 0.5f) / SIN_COUNT * radFull);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Four cardinal directions (credits: Nate)
|
static double sinLookup(long index) {
|
||||||
for(int i = 0; i < 360; i += 90) {
|
// Trigonometric identity: sin(-x) = -sin(x)
|
||||||
sin[(int) (i * degToIndex) & SIN_MASK] = Math.sin(i * Math.PI / 180.0);
|
// Given a domain of 0 <= x <= 2*pi, just negate the value if x > pi.
|
||||||
cos[(int) (i * degToIndex) & SIN_MASK] = Math.cos(i * Math.PI / 180.0);
|
// This allows the sin table size to be halved.
|
||||||
}
|
long neg = (index & 0x8000000000000000L) << 32;
|
||||||
|
|
||||||
|
// All bits set if (pi/2 <= x), none set otherwise
|
||||||
|
// Extracts the 31st bit from 'half'
|
||||||
|
long mask = (index << 33) >> 63;
|
||||||
|
|
||||||
|
// Trigonometric identity: sin(x) = sin(pi/2 - x)
|
||||||
|
long pos = (0x8000000000000001L & mask) + (index ^ mask);
|
||||||
|
|
||||||
|
// Wrap the position in the table. Moving this down to immediately before the array access
|
||||||
|
// seems to help the Hotspot compiler optimize the bit math better.
|
||||||
|
pos &= 0x7fffffffffffffffL;
|
||||||
|
|
||||||
|
// Fetch the corresponding value from the LUT and invert the sign bit as needed
|
||||||
|
// This directly manipulate the sign bit on the double bits to simplify logic
|
||||||
|
return Double.longBitsToDouble(sinTable[(int) pos] ^ neg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double sin(double rad) {
|
public static double sin(double rad) {
|
||||||
return sin[(int) (rad * radToIndex) & SIN_MASK];
|
return sinLookup((long) (rad * radianToIndex) & 0xFFFFFFFFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double cos(double rad) {
|
public static double cos(double rad) {
|
||||||
return cos[(int) (rad * radToIndex) & SIN_MASK];
|
return sinLookup((long) (rad * radianToIndex + lookupTableSize) & 0xFFFFFFFFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double tan(double rad) {
|
public static double tan(double rad) {
|
||||||
|
|||||||
Reference in new issue
Block a user