diff options
Diffstat (limited to 'newlib/libm/common/s_lrint.c')
-rw-r--r-- | newlib/libm/common/s_lrint.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/newlib/libm/common/s_lrint.c b/newlib/libm/common/s_lrint.c new file mode 100644 index 000000000..541bf2c7e --- /dev/null +++ b/newlib/libm/common/s_lrint.c @@ -0,0 +1,98 @@ + +/* @(#)s_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. + * ==================================================== + */ + +/* + * lrint(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 lrint(x). + */ + +#include "fdlibm.h" + +#ifndef _DOUBLE_IS_32BITS + +#ifdef __STDC__ +static const double +#else +static double +#endif + +/* Adding a double, x, to 2^52 will cause the result to be rounded based on + the fractional part of x, according to the implementation's current rounding + mode. 2^52 is the smallest double that can be represented using all 52 significant + digits. */ +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +#ifdef __STDC__ + long int lrint(double x) +#else + long int lrint(x) + double x; +#endif +{ + __int32_t i0,j0,sx; + __uint32_t i1; + double t; + volatile double w; + long int result; + + EXTRACT_WORDS(i0,i1,x); + sx = (i0>>31)&1; + j0 = ((i0 & 0x7ff00000) >> 20) - 1023; + + if(j0 < 20) + { + if(j0 < -1) + return 0; + else + { + w = TWO52[sx] + x; + t = w - TWO52[sx]; + GET_HIGH_WORD(i0, t); + j0 = ((i0 & 0x7ff00000) >> 20) - 1023; + i0 &= 0x000fffff; + i0 |= 0x00100000; + result = i0 >> (20 - j0); + } + } + else if (j0 < (8 * sizeof (long int)) - 1) + { + if (j0 >= 52) + result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); + else + { + w = TWO52[sx] + x; + t = w - TWO52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 & 0x7ff00000) >> 20) - 1023; + i0 &= 0x000fffff; + i0 |= 0x00100000; + result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0)); + } + } + else + { + return (long int) x; + } + + return sx ? -result : result; +} + +#endif /* _DOUBLE_IS_32BITS */ |