Skip to content

Commit

Permalink
Sin/Cos Opts
Browse files Browse the repository at this point in the history
  • Loading branch information
duplexsystem committed Sep 24, 2024
1 parent bd73427 commit 1d05f95
Showing 1 changed file with 34 additions and 24 deletions.
58 changes: 34 additions & 24 deletions common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,51 @@ public final class MathUtil {
* Epsilon for fuzzy floating point comparisons.
*/
public static final double EPSILON = 1.0E-5;
private static final int SIN_BITS, SIN_MASK, SIN_COUNT;
private static final double radFull, radToIndex;
private static final double degFull, degToIndex;
private static final double[] sin, cos;
static {
SIN_BITS = 12;
SIN_MASK = ~(-1 << SIN_BITS);
SIN_COUNT = SIN_MASK + 1;
private static final int lookupBits = 14;

radFull = Math.PI * 2.0;
degFull = 360.0;
radToIndex = SIN_COUNT / radFull;
degToIndex = SIN_COUNT / degFull;
static final int lookupTableSize = 1 << lookupBits;

sin = new double[SIN_COUNT];
cos = new double[SIN_COUNT];
private static final int lookupTableSizeWithMargin = lookupTableSize + 1;
private static final double tauOverLookupSize = TrigonometryConstants.TAU / lookupTableSize;
static final double radianToIndex = (~(-1 << lookupBits) + 1) / TrigonometryConstants.TAU;

Check failure on line 27 in common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java

View workflow job for this annotation

GitHub Actions / build

[Task :common:api:compileJava] cannot find symbol static final double radianToIndex = (~(-1 << lookupBits) + 1) / TrigonometryConstants.TAU; ^ symbol: variable TrigonometryConstants
private static final long[] sinTable;

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);
static {
sinTable = new long[lookupTableSizeWithMargin];
for (int i = 0; i < lookupTableSizeWithMargin; i++) {
double d = i * tauOverLookupSize;
sinTable[i] = Double.doubleToRawLongBits(StrictMath.sin(d));
}
}

// Four cardinal directions (credits: Nate)
for(int i = 0; i < 360; i += 90) {
sin[(int) (i * degToIndex) & SIN_MASK] = Math.sin(i * Math.PI / 180.0);
cos[(int) (i * degToIndex) & SIN_MASK] = Math.cos(i * Math.PI / 180.0);
}
static double sinLookup(long index) {
// Trigonometric identity: sin(-x) = -sin(x)
// Given a domain of 0 <= x <= 2*pi, just negate the value if x > pi.
// 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) {
return sin[(int) (rad * radToIndex) & SIN_MASK];
return sinLookup((long) (rad * radianToIndex) & 0xFFFFFFFFL);
}

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) {
Expand Down

0 comments on commit 1d05f95

Please sign in to comment.