--- original_noise_math.h
+++ noise_math_optimized.h
@@ -1490,73 +1490,87 @@
return f;
}
+/* Unsigned arithmetic preserves the Java long wraparound. */
+static inline __attribute__((const, always_inline)) uint64_t
+noiseopt_biome_hash_step(uint64_t v, uint64_t salt) {
+ return v * (v * UINT64_C(6364136223846793005) +
+ UINT64_C(1442695040888963407)) + salt;
+}
+
+/* This comparison idiom maps to hardware MINPD for non-NaN inputs. */
+static inline __attribute__((const, always_inline)) double
+noiseopt_biome_min(double a, double b) {
+ return a > b ? b : a;
+}
+
__attribute__((const)) uint32_t
math_biome_access_sample(const int64_t theSeed, const int32_t x, const int32_t y, const int32_t z) {
- const int32_t var0 = x - 2;
- const int32_t var1 = y - 2;
- const int32_t var2 = z - 2;
- const int32_t var3 = var0 >> 2;
- const int32_t var4 = var1 >> 2;
- const int32_t var5 = var2 >> 2;
- const double var6 = (double) (var0 & 3) / 4.0;
- const double var7 = (double) (var1 & 3) / 4.0;
- const double var8 = (double) (var2 & 3) / 4.0;
- uint32_t var9 = 0;
- double var10 = DBL_MAX;
+ /* Java integer subtraction wraps modulo 2^32. */
+ const int32_t xx = (int32_t)((uint32_t)x - 2u);
+ const int32_t yy = (int32_t)((uint32_t)y - 2u);
+ const int32_t zz = (int32_t)((uint32_t)z - 2u);
+
+ const int32_t cx = xx >> 2;
+ const int32_t cy = yy >> 2;
+ const int32_t cz = zz >> 2;
+ const double fx = (double)(xx & 3) * 0.25;
+ const double fy = (double)(yy & 3) * 0.25;
+ const double fz = (double)(zz & 3) * 0.25;
+
+ const uint64_t seed = (uint64_t)theSeed;
+ const uint64_t x0 = (uint64_t)(int64_t)cx;
+ const uint64_t x1 = (uint64_t)(int64_t)(cx + 1);
+ const uint64_t y0 = (uint64_t)(int64_t)cy;
+ const uint64_t y1 = (uint64_t)(int64_t)(cy + 1);
+ const uint64_t z0 = (uint64_t)(int64_t)cz;
+ const uint64_t z1 = (uint64_t)(int64_t)(cz + 1);
- double var28s[8];
+
+ double distance[8];
#pragma clang loop vectorize_width(NOISEOPT_DOUBLE_LANES) interleave_count(NOISEOPT_BIOME_INTERLEAVE)
- for (uint32_t var11 = 0; var11 < 8; ++var11) {
- uint32_t var12 = var11 & 4;
- uint32_t var13 = var11 & 2;
- uint32_t var14 = var11 & 1;
- int64_t var15 = var12 ? var3 + 1 : var3;
- int64_t var16 = var13 ? var4 + 1 : var4;
- int64_t var17 = var14 ? var5 + 1 : var5;
- double var18 = var12 ? var6 - 1.0 : var6;
- double var19 = var13 ? var7 - 1.0 : var7;
- double var20 = var14 ? var8 - 1.0 : var8;
- int64_t var21 = theSeed * (theSeed * 6364136223846793005L + 1442695040888963407L) + var15;
- var21 = var21 * (var21 * 6364136223846793005L + 1442695040888963407L) + var16;
- var21 = var21 * (var21 * 6364136223846793005L + 1442695040888963407L) + var17;
- var21 = var21 * (var21 * 6364136223846793005L + 1442695040888963407L) + var15;
- var21 = var21 * (var21 * 6364136223846793005L + 1442695040888963407L) + var16;
- var21 = var21 * (var21 * 6364136223846793005L + 1442695040888963407L) + var17;
- double var22 = (double) ((var21 >> 24) & 1023) / 1024.0;
- double var23 = (var22 - 0.5) * 0.9;
- var21 = var21 * (var21 * 6364136223846793005L + 1442695040888963407L) + theSeed;
- double var24 = (double) ((var21 >> 24) & 1023) / 1024.0;
- double var25 = (var24 - 0.5) * 0.9;
- var21 = var21 * (var21 * 6364136223846793005L + 1442695040888963407L) + theSeed;
- double var26 = (double) ((var21 >> 24) & 1023) / 1024.0;
- double var27 = (var26 - 0.5) * 0.9;
- double var28 = math_square(var20 + var27) + math_square(var19 + var25) + math_square(var18 + var23);
- __builtin_assume(!__builtin_isnan(var28) && !__builtin_signbit(var28));
- var28s[var11] = var28;
+ for (uint32_t i = 0; i < 8; ++i) {
+ const uint64_t ix = (i & 4) ? x1 : x0;
+ const uint64_t iy = (i & 2) ? y1 : y0;
+ const uint64_t iz = (i & 1) ? z1 : z0;
+ const double dx = (i & 4) ? fx - 1.0 : fx;
+ const double dy = (i & 2) ? fy - 1.0 : fy;
+ const double dz = (i & 1) ? fz - 1.0 : fz;
+
+ uint64_t h = noiseopt_biome_hash_step(noiseopt_biome_hash_step(seed, ix), iy);
+ h = noiseopt_biome_hash_step(h, iz);
+ h = noiseopt_biome_hash_step(h, ix);
+ h = noiseopt_biome_hash_step(h, iy);
+ h = noiseopt_biome_hash_step(h, iz);
+
+ const double rx = ((double)((h >> 24) & 1023u) / 1024.0 - 0.5) * 0.9;
+ h = noiseopt_biome_hash_step(h, seed);
+ const double ry = ((double)((h >> 24) & 1023u) / 1024.0 - 0.5) * 0.9;
+ h = noiseopt_biome_hash_step(h, seed);
+ const double rz = ((double)((h >> 24) & 1023u) / 1024.0 - 0.5) * 0.9;
+
+ distance[i] = math_square(dz + rz) + math_square(dy + ry) + math_square(dx + rx);
}
- // use bmin or use >= produces different asm
- double m04 = __builtin_fmin(var28s[0], var28s[4]);
- double m15 = __builtin_fmin(var28s[1], var28s[5]);
- double m26 = __builtin_fmin(var28s[2], var28s[6]);
- double m37 = __builtin_fmin(var28s[3], var28s[7]);
- double m0426 = __builtin_fmin(m04, m26);
- double m1537 = __builtin_fmin(m15, m37);
- double minimum = __builtin_fmin(m0426, m1537);
-
- uint8_t bitmap = (uint8_t)(var28s[0] == minimum)
- | (uint8_t)((var28s[1] == minimum) << 1)
- | (uint8_t)((var28s[2] == minimum) << 2)
- | (uint8_t)((var28s[3] == minimum) << 3)
- | (uint8_t)((var28s[4] == minimum) << 4)
- | (uint8_t)((var28s[5] == minimum) << 5)
- | (uint8_t)((var28s[6] == minimum) << 6)
- | (uint8_t)((var28s[7] == minimum) << 7);
-
- return __builtin_ctz(bitmap);
+ const double m04 = noiseopt_biome_min(distance[0], distance[4]);
+ const double m15 = noiseopt_biome_min(distance[1], distance[5]);
+ const double m26 = noiseopt_biome_min(distance[2], distance[6]);
+ const double m37 = noiseopt_biome_min(distance[3], distance[7]);
+ const double m0426 = noiseopt_biome_min(m04, m26);
+ const double m1537 = noiseopt_biome_min(m15, m37);
+ const double minimum = noiseopt_biome_min(m0426, m1537);
+
+ /* Distances are finite and >= +0.0, so at least one lane matches. */
+ const unsigned mask = ((unsigned)(distance[0] == minimum) << 0)
+ | ((unsigned)(distance[1] == minimum) << 1)
+ | ((unsigned)(distance[2] == minimum) << 2)
+ | ((unsigned)(distance[3] == minimum) << 3)
+ | ((unsigned)(distance[4] == minimum) << 4)
+ | ((unsigned)(distance[5] == minimum) << 5)
+ | ((unsigned)(distance[6] == minimum) << 6)
+ | ((unsigned)(distance[7] == minimum) << 7);
+ return (uint32_t)__builtin_ctz(mask);
}
-
typedef const struct aquifer_data {
int32_t startX;
int32_t startY;