/**
 * Approximate 3D insphere test.  Non-robust.
 *
 * Return a positive value if the point pe lies inside the
 * sphere passing through pa, pb, pc, and pd; a negative value
 * if it lies outside; and zero if the five points are
 * cospherical.  The points pa, pb, pc, and pd must be ordered
 * so that they have a positive orientation (as defined by
 * orient3d()), or the sign of the result will be reversed.
 *
 * @see "Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates." Technical Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon University, Pittsburgh, Pennsylvania, May 1996
 * @see http://www.cs.cmu.edu/~quake/robust.html
 * @see https://gitlab.onelab.info/gmsh/gmsh/-/blob/master/contrib/hxt/predicates/src/predicates.c
 * @param {number[]} points
 * @param {number} a tetrahedral point index
 * @param {number} b tetrahedral point index
 * @param {number} c tetrahedral point index
 * @param {number} d tetrahedral point index
 * @param {number} e reference point index that we are testing against the tetrahedron
 * @returns {number}
 */
export function in_sphere3d_fast(
    points,
    a, b, c, d, e
) {

    const a3 = a * 3;
    const b3 = b * 3;
    const c3 = c * 3;
    const d3 = d * 3;
    const e3 = e * 3;

    const ex = points[e3];
    const ey = points[e3 + 1];
    const ez = points[e3 + 2];

    const aex = points[a3] - ex;
    const aey = points[a3 + 1] - ey;
    const aez = points[a3 + 2] - ez;

    const bex = points[b3] - ex;
    const bey = points[b3 + 1] - ey;
    const bez = points[b3 + 2] - ez;

    const cex = points[c3] - ex;
    const cey = points[c3 + 1] - ey;
    const cez = points[c3 + 2] - ez;

    const dex = points[d3] - ex;
    const dey = points[d3 + 1] - ey;
    const dez = points[d3 + 2] - ez;

    const aexbey = aex * bey;
    const bexaey = bex * aey;
    const ab = aexbey - bexaey;

    const bexcey = bex * cey;
    const cexbey = cex * bey;
    const bc = bexcey - cexbey;

    const cexdey = cex * dey;
    const dexcey = dex * cey;
    const cd = cexdey - dexcey;

    const dexaey = dex * aey;
    const aexdey = aex * dey;
    const da = dexaey - aexdey;

    const aexcey = aex * cey;
    const cexaey = cex * aey;
    const ac = aexcey - cexaey;

    const bexdey = bex * dey;
    const dexbey = dex * bey;
    const bd = bexdey - dexbey;

    const abc = aez * bc - bez * ac + cez * ab;
    const bcd = bez * cd - cez * bd + dez * bc;
    const cda = cez * da + dez * ac + aez * cd;
    const dab = dez * ab + aez * bd + bez * da;

    const alift = aex * aex + aey * aey + aez * aez;
    const blift = bex * bex + bey * bey + bez * bez;
    const clift = cex * cex + cey * cey + cez * cez;
    const dlift = dex * dex + dey * dey + dez * dez;

    const det = (dlift * abc - clift * dab) + (blift * cda - alift * bcd);

    return det;
}
