#include <Core/Common/CoreTypes.h>
#include <Core/Math/Math_Private.h>

#include <cfloat>

namespace Juliet
{
    // From MUSL lib https://github.com/rofl0r/musl
    namespace
    {
        consteval float GetEps()
        {
#if defined(__FLT_EVAL_METHOD__)
            if constexpr (__FLT_EVAL_METHOD__ == 1)
            {
                return static_cast<float>(DBL_EPSILON);
            }
            if constexpr (__FLT_EVAL_METHOD__ == 2)
            {
                return static_cast<float>(LDBL_EPSILON);
            }
#endif
            return FLT_EPSILON;
        }

        constexpr float EPS   = GetEps();
        constexpr float toint = 1.0f / EPS;
    } // namespace

    float RoundF(float value)
    {
        union
        {
            float  f;
            uint32 i;
        } u     = { value };
        auto  e = u.i >> 23 & 0xff;
        float y = 0.0f;

        if (e >= 0x7f + 23)
        {
            return value;
        }
        if (u.i >> 31)
        {
            value = -value;
        }
        if (e < 0x7f - 1)
        {
            ForceEval(value + toint);
            return 0 * u.f;
        }
        y = value + toint - toint - value;
        if (y > 0.5f)
        {
            y = y + value - 1;
        }
        else if (y <= -0.5f)
        {
            y = y + value + 1;
        }
        else
        {
            y = y + value;
        }
        if (u.i >> 31)
        {
            y = -y;
        }
        return y;
    }
} // namespace Juliet
