#include "libm.h"

#if FLT_EVAL_METHOD == 0 || FLT_EVAL_METHOD == 1
#    define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD == 2
#    define EPS LDBL_EPSILON
#endif
static const double_t toint = 1 / EPS;

double floor(double x)
{
    union
    {
        double f;
        uint64_t i;
    } u = {x};
    int e = u.i >> 52 & 0x7ff;
    double_t y;

    if (e >= 0x3ff + 52 || x == 0)
        return x;
    /* y = int(x) - x, where int(x) is an integer neighbor of x */
    if (u.i >> 63)
        y = x - toint + toint - x;
    else
        y = x + toint - toint - x;
    /* special case because of non-nearest rounding modes */
    if (e <= 0x3ff - 1)
    {
        FORCE_EVAL(y);
        return u.i >> 63 ? -1 : 0;
    }
    if (y > 0)
        return x + y - 1;
    return x + y;
}
