/**
 * Pressure Poisson solver: Modified Incomplete Cholesky preconditioned Conjugate
 * Gradient — MIC(0)-PCG.
 *
 * Solves `A * p = -div(v)` where A is the 7-point discrete Laplacian over fluid
 * cells (same sign convention as {@link v3_grid_solve_pressure} — that
 * function's SOR update is exactly the splitting `A * p = -div`). Per cell:
 *
 *     A[c, c]  = number of fluid neighbours (= popcount(neighbour_mask[c]))
 *     A[c, c'] = -1 if c' is a fluid neighbour of c, else 0
 *
 * PCG converges in roughly `O(√κ)` iterations where κ is the spectral condition
 * number of `M⁻¹A`. The MIC(0) preconditioner reduces κ from `O(N²)` (raw
 * Laplacian) to `O(N)`, so a single PCG iter does a lot more useful work than
 * a single SOR sweep.
 *
 * **Empirical finding (V8 / Node, single-thread, this implementation).** Each
 * PCG iter involves ~8 separate per-cell passes (As compute, axpy×2,
 * mean-subtract, fwd+bwd triangular solves, dot, s update) vs SOR's 2. In
 * native code each pass is bandwidth-bound and per-iter ratio approaches the
 * textbook 2× — yielding the canonical 1.5–2× wall-time win for PCG. In V8,
 * per-pass loop overhead dominates; the actual per-iter ratio is closer to
 * 4-6× and PCG ends up SLOWER than SOR at iso-quality on production grids:
 *
 *     res=64:  SOR  16 iter  /  75 ms,  max|div| 3.09e-1
 *              PCG   8 iter  / 181 ms,  max|div| 3.72e-3   (PCG 2.4× slower)
 *
 *     res=128: SOR  32 iter  / 862 ms,  max|div| 8.74e-1
 *              PCG   8 iter  /1452 ms,  max|div| 5.65e-3   (PCG 1.7× slower)
 *
 * (Reproduce via `bench: MIC-PCG vs SOR` in bench.spec.js.)
 *
 * Where PCG still wins: **convergence depth**. At the SAME iter count it
 * produces dramatically lower residual divergence (84× better max|div| at
 * 64³, 247× at 128³). If you need quality below the cell-centered operator
 * floor SOR plateaus at — e.g. quantitative pressure inspection, or
 * extreme-impulse scenes where the SOR floor is visible — PCG is the answer.
 * For visual-fluids steady state, **leave the default at SOR**.
 *
 * If this code is ever ported to WASM SIMD or WebGPU the perf comparison
 * flips: per-iter overhead becomes negligible in those environments and the
 * theoretical 1.5–2× PCG win re-emerges. Worth re-running the bench then.
 *
 * Algorithm (Bridson "Fluid Simulation for Computer Graphics" §5.6, Saad
 * §10.2):
 *
 *     1.  build_preconditioner: walk fluid cells in lex order, computing
 *         precon[c] = 1 / sqrt(e[c]) where e[c] is the modified Cholesky
 *         diagonal. Backward neighbours (-x, -y, -z) contribute to the
 *         subtraction.
 *
 *     2.  r₀ = -div - A * p₀     (initial residual; p₀ is the warm-start)
 *         z₀ = M⁻¹ * r₀          (apply preconditioner — two triangular solves)
 *         s₀ = z₀
 *         σ₀ = r₀ · z₀
 *
 *     3.  For k = 0, 1, …, max_iter-1:
 *             A·sₖ
 *             α = σₖ / (sₖ · A·sₖ)
 *             p ← p + α·sₖ
 *             r ← r - α·A·sₖ
 *             z ← M⁻¹ · r
 *             σₖ₊₁ = r · z
 *             β = σₖ₊₁ / σₖ
 *             s ← z + β·s
 *
 * Preconditioner apply is a forward sweep (L·y = r) followed by a backward
 * sweep (Lᵀ·z = y). Both sweeps are O(N) and inherently sequential — they're
 * the hot path that prevents MIC-PCG from parallelizing onto a GPU without
 * substantial reformulation. On single-thread JS that's not a concern.
 *
 * Cells with no fluid neighbours — solid cells (mask bit 7 set) and isolated
 * fluid (mask = 0), both identified by `(mask & 63) === 0` — are excluded from
 * the system: their pressure stays at whatever it was (typically 0), their
 * entries in r, z, s, As stay 0, and they contribute nothing to dot products.
 *
 * @param {Float32Array|Float16Array} pressure  Mutated in place. Pre-fill with 0
 *     or with the previous step's solution to warm-start.
 * @param {Float32Array|Float16Array} divergence  From `v3_grid_compute_divergence`.
 * @param {number} res_x
 * @param {number} res_y
 * @param {number} res_z
 * @param {number} max_iterations  Cap. Converged early-exits via implicit-zero
 *     dot product (sigma reaches 0 or numerical noise).
 * @param {Uint8Array} neighbour_mask  From `v3_grid_compute_solid_neighbour_mask`.
 * @param {Float32Array} scratch_r  Length ≥ rx*ry*rz. Residual.
 * @param {Float32Array} scratch_z  Length ≥ rx*ry*rz. Preconditioned residual.
 * @param {Float32Array} scratch_s  Length ≥ rx*ry*rz. Search direction.
 * @param {Float32Array} scratch_As  Length ≥ rx*ry*rz. A applied to s.
 * @param {Float32Array} scratch_precon  Length ≥ rx*ry*rz. Preconditioner
 *     diagonal (1/sqrt(e_c) per fluid cell, 0 for solid).
 */
export function v3_grid_solve_pressure_pcg(pressure: Float32Array | Float16Array, divergence: Float32Array | Float16Array, res_x: number, res_y: number, res_z: number, max_iterations: number, neighbour_mask: Uint8Array, scratch_r: Float32Array, scratch_z: Float32Array, scratch_s: Float32Array, scratch_As: Float32Array, scratch_precon: Float32Array): void;
//# sourceMappingURL=v3_grid_solve_pressure_pcg.d.ts.map