/**
 * Inverse-rotate a 3-D vector by a unit quaternion: `result = q* · v · q`,
 * where `q* = (-qx, -qy, -qz, qw)` is the conjugate.
 *
 * Geometrically: if {@link v3_quat3_apply} rotates a body-local vector
 * into world space (`v_world = q · v_local · q*`), this is the inverse —
 * it takes a world-space vector and writes it in body-local coordinates.
 * For unit quaternions the conjugate IS the inverse, so the two
 * functions are exact inverses of each other.
 *
 * Implementation: the conjugate's `xyz` are negated relative to `q`.
 * Expanding `c · v · c*` with `(cx, cy, cz, cw) = (-qx, -qy, -qz, qw)`
 * and simplifying produces the closed form below — different sign
 * pattern than {@link v3_quat3_apply}, NOT just a call with negated
 * components (the optimisation matters for hot-path callers such as
 * `PosedShape.support` and the per-triangle concave dispatch in
 * `narrowphase_step`).
 *
 * @param {number[]|Float32Array|Float64Array} out
 * @param {number} out_offset offset into `out`; receives 3 floats
 * @param {number} vx
 * @param {number} vy
 * @param {number} vz
 * @param {number} qx unit quaternion x
 * @param {number} qy
 * @param {number} qz
 * @param {number} qw unit quaternion w (last)
 */
export function v3_quat3_apply_inverse(out, out_offset, vx, vy, vz, qx, qy, qz, qw) {
    // t = q* · v   (conjugate · v, v as pure quaternion w=0)
    // Conjugate xyz negated; expanded:
    const tx = qw * vx - qy * vz + qz * vy;
    const ty = qw * vy - qz * vx + qx * vz;
    const tz = qw * vz - qx * vy + qy * vx;
    const tw = qx * vx + qy * vy + qz * vz; // note: +, conjugate-w stays qw

    // result = t · q   (q is the conjugate-of-conjugate)
    out[out_offset]     = tx * qw + tw * qx + ty * qz - tz * qy;
    out[out_offset + 1] = ty * qw + tw * qy + tz * qx - tx * qz;
    out[out_offset + 2] = tz * qw + tw * qz + tx * qy - ty * qx;
}
