#include "coduo_x87emu.h" /* defines EMULATE_X87; x87 shim when it is 1 */

#include "core_math_private.h"

void ProjectPointOntoVector(const vec3_t point, const vec3_t lineStart,
                  const vec3_t lineEnd, vec3_t out)
{
    vec3_t delta;
    vec3_t lineDir;

    delta[0] = point[0] - lineStart[0];
    delta[1] = point[1] - lineStart[1];
    delta[2] = point[2] - lineStart[2];

    lineDir[0] = lineEnd[0] - lineStart[0];
    lineDir[1] = lineEnd[1] - lineStart[1];
    lineDir[2] = lineEnd[2] - lineStart[2];

    VectorNormalize(lineDir);

#if EMULATE_X87
    /* x87-faithful transcription (stock coduo_lnxded 0x08067806): the delta /
     * lineDir subtracts are single-op (native-identical); each output is
     * lineStart[i] + (80-bit projection dot) * lineDir[i], the dot recomputed per
     * component as stock does, rounded to float at the store. */
    for (int i = 0; i < 3; ++i) {
        x87f dot = x87f_add(
            x87f_add(x87f_mul(x87f_load_f32(delta[0]), x87f_load_f32(lineDir[0])),
                     x87f_mul(x87f_load_f32(delta[1]),
                              x87f_load_f32(lineDir[1]))),
            x87f_mul(x87f_load_f32(delta[2]), x87f_load_f32(lineDir[2])));
        out[i] = x87f_store_f32(x87f_add(
            x87f_load_f32(lineStart[i]),
            x87f_mul(dot, x87f_load_f32(lineDir[i]))));
    }
#else
    out[0] =
        lineStart[0] +
        (((delta[0] * lineDir[0]) + (delta[1] * lineDir[1])) +
         (delta[2] * lineDir[2])) *
            lineDir[0];
    out[1] =
        lineStart[1] +
        (((delta[0] * lineDir[0]) + (delta[1] * lineDir[1])) +
         (delta[2] * lineDir[2])) *
            lineDir[1];
    out[2] =
        lineStart[2] +
        (((delta[0] * lineDir[0]) + (delta[1] * lineDir[1])) +
         (delta[2] * lineDir[2])) *
            lineDir[2];
#endif
}
