// GS 双格 SIMD 快路径(自 fluid.mbt 拆分,与标量逐位等价,白盒测试守护):
// 红黑相位内同奇偶格互不依赖,相邻同奇偶两格(b = a+2)打包 f64x2 双车道,每车道独立更新。
// 字节序推导:f32 数组里相距 2 格的两个值不相邻(跨 8 字节),不能 load32x2 直取——
// lanes02(v) 用 i8x16_shuffle 把 v 的 lane0/1(字节 0..7)与 lane2/3(字节 8..15)前移拼成
// 低 16 字节,再 promote 成两个 f64 车道;横邻居对跨两个相邻 f32x4(p[a-1..a+2] 与 p[a+1..a+4]),
// hb 的 shuffle 从 v1 取字节 8..11、从 v2 取字节 24..27(即 v2 的 lane0)各组成一对。
// gs_pair:4 个 f64x2 邻居对求和 → 减 div_h2 车道对 → ×0.25 → demote 回 f32x4 → lane0/lane1 写回两格

///|
fn lanes02(v : V128) -> V128 {
  @v128.f64x2_promote_low_f32x4(
    @v128.i8x16_shuffle(
      v, v, 0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15,
    ),
  )
}

///|
fn gs_pair(a : Int) -> Unit {
  let nx = pm.nx
  let off = a * 4
  let v1 = v128_load4_f32(p, off - 4)
  let v2 = v128_load4_f32(p, off + 4)
  let ha = lanes02(v1)
  let hb = @v128.f64x2_promote_low_f32x4(
    @v128.i8x16_shuffle(
      v1, v2, 8, 9, 10, 11, 24, 25, 26, 27, 4, 5, 6, 7, 12, 13, 14, 15,
    ),
  )
  let h = @v128.f64x2_add(ha, hb)
  let vu = lanes02(v128_load4_f32(p, off - nx * 4))
  let vd = lanes02(v128_load4_f32(p, off + nx * 4))
  let t = @v128.f64x2_add(h, vu)
  let s = @v128.f64x2_add(t, vd)
  let d = v128_load1_f64_lane1(
    div_h2,
    (a + 2) * 8,
    v128_load1_f64(div_h2, a * 8),
  )
  let s = @v128.f64x2_mul(@v128.f64x2_sub(s, d), @v128.f64x2_splat(0.25))
  let f = @v128.f32x4_demote_f64x2_zero(s)
  v128_store1_f32_lane0(p, off, f)
  v128_store1_f32_lane1(p, off + 8, f)
}

///|
fn buoyancy2(k : Double, a_t : Double) -> Unit {
  let nx = pm.nx
  let ny = pm.ny
  let kv = @v128.f64x2_splat(k)
  let av = @v128.f64x2_splat(a_t)
  let last = nx - 2
  for j in 1..<(ny - 1) {
    let row = j * nx
    let mut i = 1
    while i + 1 <= last {
      let idx = i + row
      let vp = @v128.f64x2_promote_low_f32x4(v128_load4_f32(v, idx * 4))
      let tp = @v128.f64x2_promote_low_f32x4(v128_load4_f32(t, idx * 4))
      let s = @v128.f64x2_sub(vp, @v128.f64x2_mul(kv, @v128.f64x2_add(tp, av)))
      let f = @v128.f32x4_demote_f64x2_zero(s)
      v128_store1_f32_lane0(v, idx * 4, f)
      v128_store1_f32_lane1(v, (idx + 1) * 4, f)
      i = i + 2
    }
    if i <= last {
      let idx = i + row
      v[idx] = Float::from_double(
        v[idx].to_double() - k * (t[idx].to_double() + a_t),
      )
    }
  }
}