From dcddc0504e67677e6b6423d7cc548e47cae71f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zo=C3=AB=20Gidiere?= Date: Sat, 7 Oct 2023 22:44:19 -0600 Subject: [PATCH] detect fma --- buildSrc/src/main/kotlin/Versions.kt | 1 + .../samplers/noise/PseudoErosionSampler.java | 11 ++++--- common/api/build.gradle.kts | 4 +++ .../com/dfsek/terra/api/util/MathUtil.java | 33 +++++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index f977e5f01..a6c15c842 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -13,6 +13,7 @@ object Versions { const val apacheText = "1.9" const val apacheIO = "2.6" const val fastutil = "8.5.6" + const val cpuFeaturesJava = "1.0.1" } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/PseudoErosionSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/PseudoErosionSampler.java index c417d9aa7..dfcc8e63c 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/PseudoErosionSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/PseudoErosionSampler.java @@ -10,6 +10,8 @@ package com.dfsek.terra.addons.noise.samplers.noise; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.util.MathUtil; +import com.google.errorprone.annotations.InlineMe; + import static com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction.PRIME_X; import static com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction.PRIME_Y; import static com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction.hash; @@ -229,6 +231,7 @@ public class PseudoErosionSampler implements NoiseSampler { this.cellularJitter = 0.43701595 * jitterModifier; } + public double getNoiseRaw(long sl, double x, double y) { int seed = (int) sl; double finalDistance = Double.MAX_VALUE; @@ -248,8 +251,8 @@ public class PseudoErosionSampler implements NoiseSampler { int gridYi = gridY + yi; int jitterIdx = hash(seed, gridXiPrimed, gridYi * PRIME_Y) & (255 << 1); - double cellX = Math.fma(RAND_VECS_2D[jitterIdx], cellularJitter, gridXi); - double cellY = Math.fma(RAND_VECS_2D[jitterIdx | 1], cellularJitter, gridYi); + double cellX = MathUtil.fma(RAND_VECS_2D[jitterIdx], cellularJitter, gridXi); + double cellY = MathUtil.fma(RAND_VECS_2D[jitterIdx | 1], cellularJitter, gridYi); // Transform to actual coordinates for lookup double actualCellX = cellX * inverseFrequency; @@ -322,7 +325,7 @@ public class PseudoErosionSampler implements NoiseSampler { double x2dx = x - x2; double y2dx = y - y2; - double dotProduct = Math.fma(ldy, y1dx, (ldx * x1dx)); + double dotProduct = MathUtil.fma(ldy, y1dx, (ldx * x1dx)); double lt = dotProduct * invLineLengthSquared; // Position along the line if (lt > 0) { @@ -330,7 +333,7 @@ public class PseudoErosionSampler implements NoiseSampler { } else if (lt < -1) { return MathUtil.hypot(x2dx, y2dx); // Distance between point 2 and position } else { - double distance = Math.fma(ldy, x1dx, (-(ldx * y1dx))) * Math.sqrt(invLineLengthSquared); + double distance = MathUtil.fma(ldy, x1dx, (-(ldx * y1dx))) * Math.sqrt(invLineLengthSquared); return Math.abs(distance); // Distance from the line } } diff --git a/common/api/build.gradle.kts b/common/api/build.gradle.kts index bdcdd3901..370ae3206 100644 --- a/common/api/build.gradle.kts +++ b/common/api/build.gradle.kts @@ -8,4 +8,8 @@ dependencies { api("com.github.ben-manes.caffeine:caffeine:3.1.0") + api("io.github.aecsocket", "cpu-features-jni", Versions.Libraries.Internal.cpuFeaturesJava) + api("io.github.aecsocket", "cpu-features-jni-natives-linux", Versions.Libraries.Internal.cpuFeaturesJava) + api("io.github.aecsocket", "cpu-features-jni-natives-windows", Versions.Libraries.Internal.cpuFeaturesJava) + api("io.github.aecsocket", "cpu-features-jni-natives-macos", Versions.Libraries.Internal.cpuFeaturesJava) } \ No newline at end of file diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java index 4e77a4d17..b310b0661 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java @@ -7,6 +7,11 @@ package com.dfsek.terra.api.util; +import cpufeatures.CpuFeatures; +import cpufeatures.aarch64.Aarch64Feature; +import cpufeatures.arm.ArmFeature; +import cpufeatures.x86.X86Feature; + import java.util.List; @@ -19,6 +24,26 @@ public final class MathUtil { private static final double degFull, degToIndex; private static final double[] sin, cos; + public static final boolean hasFMA; + + static { + boolean configHasFMA = false; + try { + CpuFeatures.load(); + configHasFMA = switch (CpuFeatures.getArchitecture()) { + case UNSUPPORTED -> false; + case AARCH64 -> CpuFeatures.getAarch64Info().has(Aarch64Feature.ASIMD); + case ARM -> CpuFeatures.getArmInfo().has(ArmFeature.NEON); + case RISCV -> true; + case X86 -> CpuFeatures.getX86Info().has(X86Feature.FMA3); + }; + } catch (Throwable t) { + System.err.println("Failed to determine FMA support, assuming no FMA support"); + } + hasFMA = configHasFMA; + System.out.println("FMA: " + configHasFMA); + } + static { SIN_BITS = 12; SIN_MASK = ~(-1 << SIN_BITS); @@ -259,4 +284,12 @@ public final class MathUtil { public static double hypot(double x, double y) { return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); } + + public static double fma(double a, double b, double c) { + if (hasFMA) { + return Math.fma(a, b, c); + } else { + return a * b + c; + } + } }