fn simplex4d(
p: Array[Float],
perm_table: Array[Int],
grads: Array[Array[Float]],
scale: Float
) -> Float {
let f4 = (@math.sqrt(5.0) - 1.0) / 4.0
let g4 = (5.0 - @math.sqrt(5.0)) / 20.0
let nx = p[0] * scale
let ny = p[1] * scale
let nz = p[2] * scale
let nw = p[3] * scale
let s = (nx + ny + nz + nw) * f4.to_float()
let i = @math.floor(nx.to_double() + s.to_double()).to_int()
let j = @math.floor(ny.to_double() + s.to_double()).to_int()
let k = @math.floor(nz.to_double() + s.to_double()).to_int()
let l = @math.floor(nw.to_double() + s.to_double()).to_int()
let t = (i + j + k + l).to_float() * g4.to_float()
let x0 = nx - (i.to_float() - t)
let y0 = ny - (j.to_float() - t)
let z0 = nz - (k.to_float() - t)
let w0 = nw - (l.to_float() - t)
// 确定 4D 单纯形内部次序
let rank = [0, 0, 0, 0]
if x0 > y0 {
rank[0] += 1
} else {
rank[1] += 1
}
if x0 > z0 {
rank[0] += 1
} else {
rank[2] += 1
}
if x0 > w0 {
rank[0] += 1
} else {
rank[3] += 1
}
if y0 > z0 {
rank[1] += 1
} else {
rank[2] += 1
}
if y0 > w0 {
rank[1] += 1
} else {
rank[3] += 1
}
if z0 > w0 {
rank[2] += 1
} else {
rank[3] += 1
}
let i1 = if rank[0] >= 3 { 1 } else { 0 }
let j1 = if rank[1] >= 3 { 1 } else { 0 }
let k1 = if rank[2] >= 3 { 1 } else { 0 }
let l1 = if rank[3] >= 3 { 1 } else { 0 }
let i2 = if rank[0] >= 2 { 1 } else { 0 }
let j2 = if rank[1] >= 2 { 1 } else { 0 }
let k2 = if rank[2] >= 2 { 1 } else { 0 }
let l2 = if rank[3] >= 2 { 1 } else { 0 }
let i3 = if rank[0] >= 1 { 1 } else { 0 }
let j3 = if rank[1] >= 1 { 1 } else { 0 }
let k3 = if rank[2] >= 1 { 1 } else { 0 }
let l3 = if rank[3] >= 1 { 1 } else { 0 }
// 四个顶点偏移
let x1 = x0 - i1.to_float() + g4.to_float()
let y1 = y0 - j1.to_float() + g4.to_float()
let z1 = z0 - k1.to_float() + g4.to_float()
let w1 = w0 - l1.to_float() + g4.to_float()
let x2 = x0 - i2.to_float() + 2.0 * g4.to_float()
let y2 = y0 - j2.to_float() + 2.0 * g4.to_float()
let z2 = z0 - k2.to_float() + 2.0 * g4.to_float()
let w2 = w0 - l2.to_float() + 2.0 * g4.to_float()
let x3 = x0 - i3.to_float() + 3.0 * g4.to_float()
let y3 = y0 - j3.to_float() + 3.0 * g4.to_float()
let z3 = z0 - k3.to_float() + 3.0 * g4.to_float()
let w3 = w0 - l3.to_float() + 3.0 * g4.to_float()
let x4 = x0 - 1.0 + 4.0 * g4.to_float()
let y4 = y0 - 1.0 + 4.0 * g4.to_float()
let z4 = z0 - 1.0 + 4.0 * g4.to_float()
let w4 = w0 - 1.0 + 4.0 * g4.to_float()
// 计算四个角落的梯度索引
let gi0 = hash4d(i, j, k, l, perm_table, grads)
let gi1 = hash4d(i + i1, j + j1, k + k1, l + l1, perm_table, grads)
let gi2 = hash4d(i + i2, j + j2, k + k2, l + l2, perm_table, grads)
let gi3 = hash4d(i + i3, j + j3, k + k3, l + l3, perm_table, grads)
let gi4 = hash4d(i + 1, j + 1, k + 1, l + 1, perm_table, grads)
let mut n0 = 0.0
let mut n1 = 0.0
let mut n2 = 0.0
let mut n3 = 0.0
let mut n4 = 0.0
let t0 = 0.6 - (x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0).to_double()
if t0 >= 0.0 {
let t0_2 = t0 * t0
n0 = t0_2 * t0_2 * (gi0[0] * x0 + gi0[1] * y0 + gi0[2] * z0 + gi0[3] * w0).to_double()
}
let t1 = 0.6 - (x1 * x1 + y1 * y1 + z1 * z1 + w1 * w1).to_double()
if t1 >= 0.0 {
let t1_2 = t1 * t1
n1 = t1_2 * t1_2 * (gi1[0] * x1 + gi1[1] * y1 + gi1[2] * z1 + gi1[3] * w1).to_double()
}
let t2 = 0.6 - (x2 * x2 + y2 * y2 + z2 * z2 + w2 * w2).to_double()
if t2 >= 0.0 {
let t2_2 = t2 * t2
n2 = t2_2 * t2_2 * (gi2[0] * x2 + gi2[1] * y2 + gi2[2] * z2 + gi2[3] * w2).to_double()
}
let t3 = 0.6 - (x3 * x3 + y3 * y3 + z3 * z3 + w3 * w3).to_double()
if t3 >= 0.0 {
let t3_2 = t3 * t3
n3 = t3_2 * t3_2 * (gi3[0] * x3 + gi3[1] * y3 + gi3[2] * z3 + gi3[3] * w3).to_double()
}
let t4 = 0.6 - (x4 * x4 + y4 * y4 + z4 * z4 + w4 * w4).to_double()
if t4 >= 0.0 {
let t4_2 = t4 * t4
n4 = t4_2 * t4_2 * (gi4[0] * x4 + gi4[1] * y4 + gi4[2] * z4 + gi4[3] * w4).to_double()
}
27.0 * (n0 + n1 + n2 + n3 + n4).to_float() // 归一化
}