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

#include "core_math_private.h"

#include <string.h>

void MakeNormalVectors(const vec3_t forward, vec3_t right, vec3_t up)
{
    float dot;
    uint32_t bits;

    memcpy(&bits, &forward[0], sizeof(bits));
    bits ^= CODUO_FLOAT_SIGN_BIT;
    memcpy(&right[1], &bits, sizeof(right[1]));
    memcpy(&right[2], &forward[1], sizeof(right[2]));
    memcpy(&right[0], &forward[2], sizeof(right[0]));

#if EMULATE_X87
    /* x87-faithful transcription (stock coduo_lnxded 0x0806eef7): the dot is an
     * 80-bit three-term sum rounded to float; each Gram-Schmidt update
     * right[i] + (-dot*forward[i]) is an 80-bit product/add rounded to float. The
     * initial right stores are single-op copies/negate. */
    dot = x87f_store_f32(x87f_add(
        x87f_add(x87f_mul(x87f_load_f32(right[0]), x87f_load_f32(forward[0])),
                 x87f_mul(x87f_load_f32(right[1]), x87f_load_f32(forward[1]))),
        x87f_mul(x87f_load_f32(right[2]), x87f_load_f32(forward[2]))));

    for (int axis = 0; axis < 3; ++axis) {
        right[axis] = x87f_store_f32(
            x87f_add(x87f_load_f32(right[axis]),
                     x87f_mul(x87f_neg(x87f_load_f32(dot)),
                              x87f_load_f32(forward[axis]))));
    }
#else
    dot = ((right[0] * forward[0]) + (right[1] * forward[1])) +
          (right[2] * forward[2]);

    right[0] = right[0] + (-dot * forward[0]);
    right[1] = right[1] + (-dot * forward[1]);
    right[2] = right[2] + (-dot * forward[2]);
#endif

    VectorNormalize(right);
    CrossProduct(right, forward, up);
}
