/* sf_rint.c -- float version of s_rint.c.
 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
 */

/*
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunPro, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

#include "fdlibm.h"

static const float TWO23[2] = {
    8.3886080000e+06,  /* 0x4b000000 */
    -8.3886080000e+06, /* 0xcb000000 */
};

float
rintf(float x)
{
    __int32_t      i0, j0, sx;
    __uint32_t     i, i1, ix;
    float          t;
    volatile float w;
    GET_FLOAT_WORD(i0, x);
    sx = (i0 >> 31) & 1;
    ix = (i0 & 0x7fffffff);
    j0 = (ix >> 23) - 0x7f;
    if (j0 < 23) {
        if (FLT_UWORD_IS_ZERO(ix))
            return x;
        if (j0 < 0) {
            i1 = (i0 & 0x07fffff);
            i0 &= 0xfff00000;
            i0 |= ((i1 | -i1) >> 9) & 0x400000;
            SET_FLOAT_WORD(x, i0);
            w = TWO23[sx] + x;
            t = w - TWO23[sx];
            GET_FLOAT_WORD(i0, t);
            SET_FLOAT_WORD(t, (i0 & 0x7fffffff) | lsl(sx, 31));
            return t;
        } else {
            i = (0x007fffff) >> j0;
            if ((i0 & i) == 0)
                return x; /* x is integral */
            i >>= 1;
            if ((i0 & i) != 0)
                i0 = (i0 & (~i)) | ((0x200000) >> j0);
        }
    } else {
        if (!FLT_UWORD_IS_FINITE(ix))
            return opt_barrier_float(x + x); /* inf or NaN */
        else
            return x; /* x is integral */
    }
    SET_FLOAT_WORD(x, i0);
    w = TWO23[sx] + x;
    return w - TWO23[sx];
}

_MATH_ALIAS_f_f(rint)
