#include "libm.h"

float nextafterf(float x, float y)
{
    union
    {
        float f;
        uint32_t i;
    } ux = {x}, uy = {y};
    uint32_t ax, ay, e;

    if (isnan(x) || isnan(y))
        return x + y;
    if (ux.i == uy.i)
        return y;
    ax = ux.i & 0x7fffffff;
    ay = uy.i & 0x7fffffff;
    if (ax == 0)
    {
        if (ay == 0)
            return y;
        ux.i = (uy.i & 0x80000000) | 1;
    }
    else if (ax > ay || ((ux.i ^ uy.i) & 0x80000000))
        ux.i--;
    else
        ux.i++;
    e = ux.i & 0x7f800000;
    /* raise overflow if ux.f is infinite and x is finite */
    if (e == 0x7f800000)
        FORCE_EVAL(x + x);
    /* raise underflow if ux.f is subnormal or zero */
    if (e == 0)
        FORCE_EVAL(x * x + ux.f * ux.f);
    return ux.f;
}
