diff options
Diffstat (limited to 'newlib/libm/common/sf_lrint.c')
-rw-r--r-- | newlib/libm/common/sf_lrint.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/newlib/libm/common/sf_lrint.c b/newlib/libm/common/sf_lrint.c new file mode 100644 index 000000000..a58508f02 --- /dev/null +++ b/newlib/libm/common/sf_lrint.c @@ -0,0 +1,93 @@ + +/* @(#)sf_lrint.c 5.1 93/09/24 */ +/* + * ==================================================== + * 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. + * ==================================================== + */ + +/* + * lrintf(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to lrintf(x). + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +TWO23[2]={ + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ +}; + +#ifdef __STDC__ + long int lrintf(float x) +#else + long int lrintf(x) + float x; +#endif +{ + __int32_t j0,sx; + __uint32_t i0; + float t; + volatile float w; + long int result; + + GET_FLOAT_WORD(i0,x); + + /* Extract sign bit. */ + sx = (i0 >> 31); + + /* Extract exponent field. */ + j0 = ((i0 & 0x7f800000) >> 23) - 127; + + if (j0 < (sizeof (long int) * 8) - 1) + { + if (j0 < -1) + return 0; + else if (j0 >= 23) + result = (long int) i0 << (j0 - 23); + else + { + w = TWO23[sx] + x; + t = w - TWO23[sx]; + GET_FLOAT_WORD (i0, t); + j0 = ((i0 >> 23) & 0xff) - 0x7f; + i0 &= 0x7fffff; + i0 |= 0x800000; + result = i0 >> (23 - j0); + } + } + else + { + return (long int) x; + } + return sx ? -result : result; +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + long int lrint(double x) +#else + long int lrint(x) + double x; +#endif +{ + return (double) lrintf((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ |