diff --git a/c2me-opts-natives-math/src/main/java/com/ishland/c2me/opts/natives_math/common/Bindings.java b/c2me-opts-natives-math/src/main/java/com/ishland/c2me/opts/natives_math/common/Bindings.java index 3ad803b7d..e94fbc2af 100644 --- a/c2me-opts-natives-math/src/main/java/com/ishland/c2me/opts/natives_math/common/Bindings.java +++ b/c2me-opts-natives-math/src/main/java/com/ishland/c2me/opts/natives_math/common/Bindings.java @@ -78,6 +78,9 @@ public static float c2me_natives_end_islands_sample(MemorySegment data, int x, i } public static float c2me_natives_end_islands_sample(long data_ptr, int x, int z) { + if ((int) (x * x + z * z) < 0) { // workaround some compiler bugs + return Float.NaN; + } try { return (float) MH_c2me_natives_end_islands_sample_ptr.invokeExact(data_ptr, x, z); } catch (Throwable e) { diff --git a/src/jmh/java/natives/accuracy/AbstractAccuracy.java b/src/jmh/java/natives/accuracy/AbstractAccuracy.java index f14f2b715..3307dd194 100644 --- a/src/jmh/java/natives/accuracy/AbstractAccuracy.java +++ b/src/jmh/java/natives/accuracy/AbstractAccuracy.java @@ -10,34 +10,58 @@ public abstract class AbstractAccuracy { protected final ISATarget[] targets; protected final MethodHandle[] MHs; - protected final int[] maxUlp; + protected final long[] maxUlp; protected AbstractAccuracy(ISATarget[] targets, MethodHandle template, String prefix) { this.targets = Arrays.stream(targets).filter(ISATarget::isNativelySupported).toArray(ISATarget[]::new); this.MHs = Arrays.stream(this.targets) .map(isaTarget -> template.bindTo(NativeLoader.lookup.find(prefix + isaTarget.getSuffix()).get())) .toArray(MethodHandle[]::new); - this.maxUlp = new int[this.targets.length]; + this.maxUlp = new long[this.targets.length]; } - protected static int ulpDistance(double original, double that) { - int dist = 0; + protected static long ulpDistance(double original, double that) { + long dist = 0; + if (original > that) { + double tmp = that; + that = original; + original = tmp; + } while (that > original) { that = Math.nextAfter(that, original); dist ++; } + if (dist == 0 && !equals(original, that)) { + return Long.MAX_VALUE; + } return dist; } - protected static int ulpDistance(float original, float that) { - int dist = 0; + private static boolean equals(double original, double that) { + return (Double.isNaN(original) && Double.isNaN(that)) || original == that; + } + + protected static long ulpDistance(float original, float that) { + long dist = 0; + if (original > that) { + float tmp = that; + that = original; + original = tmp; + } while (that > original) { that = Math.nextAfter(that, original); dist ++; } + if (dist == 0 && !equals(original, that)) { + return Long.MAX_VALUE; + } return dist; } + private static boolean equals(float original, float that) { + return (Float.isNaN(original) && Float.isNaN(that)) || original == that; + } + protected void printUlps() { for (int i = 0; i < this.maxUlp.length; i++) { System.out.println(String.format("%s: max error %d ulps", this.targets[i], this.maxUlp[i])); diff --git a/src/jmh/java/natives/accuracy/DoublePerlinNoiseAccuracy.java b/src/jmh/java/natives/accuracy/DoublePerlinNoiseAccuracy.java index bd342f5e2..61a41776e 100644 --- a/src/jmh/java/natives/accuracy/DoublePerlinNoiseAccuracy.java +++ b/src/jmh/java/natives/accuracy/DoublePerlinNoiseAccuracy.java @@ -49,7 +49,7 @@ private void loopBody() { double original = invokeVanilla(x, y, z); for (int i = 0; i < this.MHs.length; i ++) { double actual = invokeNative(this.MHs[i], x, y, z); - int ulpDiff = ulpDistance(original, actual); + long ulpDiff = ulpDistance(original, actual); if (ulpDiff > this.maxUlp[i]) { this.maxUlp[i] = ulpDiff; System.out.println(String.format("%s: new max error %d ulps at x=%.18g, y=%.18g, z=%.18g (expected %.18g but got %.18g)", this.targets[i], ulpDiff, x, y, z, original, actual)); diff --git a/src/jmh/java/natives/accuracy/EndIslandsAccuracy.java b/src/jmh/java/natives/accuracy/EndIslandsAccuracy.java index 610eb19e9..e28176590 100644 --- a/src/jmh/java/natives/accuracy/EndIslandsAccuracy.java +++ b/src/jmh/java/natives/accuracy/EndIslandsAccuracy.java @@ -30,6 +30,9 @@ protected EndIslandsAccuracy() { } private float invokeNative(MethodHandle handle, int x, int z) { + if ((int) (x * x + z * z) < 0) { + return Float.NaN; + } try { return (float) handle.invokeExact(nativeSamplerPtr, x, z); } catch (Throwable e) { @@ -48,7 +51,7 @@ private void loopBody() { float original = invokeVanilla(x, z); for (int i = 0; i < this.MHs.length; i ++) { float actual = invokeNative(this.MHs[i], x, z); - int ulpDiff = ulpDistance(original, actual); + long ulpDiff = ulpDistance(original, actual); if (ulpDiff > this.maxUlp[i]) { this.maxUlp[i] = ulpDiff; System.out.println(String.format("%s: new max error %d ulps at x=%d, z=%d (expected %.10g but got %.10g)", this.targets[i], ulpDiff, x, z, original, actual)); diff --git a/src/jmh/java/natives/accuracy/InterpolatedNoiseAccuracy.java b/src/jmh/java/natives/accuracy/InterpolatedNoiseAccuracy.java index 23a6c8237..7379536ee 100644 --- a/src/jmh/java/natives/accuracy/InterpolatedNoiseAccuracy.java +++ b/src/jmh/java/natives/accuracy/InterpolatedNoiseAccuracy.java @@ -43,7 +43,7 @@ private void loopBody() { double original = invokeVanilla(x, y, z); for (int i = 0; i < this.MHs.length; i ++) { double actual = invokeNative(this.MHs[i], x, y, z); - int ulpDiff = ulpDistance(original, actual); + long ulpDiff = ulpDistance(original, actual); if (ulpDiff > this.maxUlp[i]) { this.maxUlp[i] = ulpDiff; System.out.println(String.format("%s: new max error %d ulps at x=%.18g, y=%.18g, z=%.18g (expected %.18g but got %.18g)", this.targets[i], ulpDiff, x, y, z, original, actual));