diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2009-04-03 17:39:24 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2009-04-03 17:39:24 +0000 |
commit | 8ca79ad630602e500e5e6a183089b120b52a014e (patch) | |
tree | 51c5e371de39c541949ba5c2ee9074a89c544ae3 /newlib/libm/common/s_llrint.c | |
parent | f5e097fa4ba9ca520ad488e6d33c9823c2455f26 (diff) | |
download | cygnal-8ca79ad630602e500e5e6a183089b120b52a014e.tar.gz cygnal-8ca79ad630602e500e5e6a183089b120b52a014e.tar.bz2 cygnal-8ca79ad630602e500e5e6a183089b120b52a014e.zip |
2009-04-03 Craig Howland <howland@LGSInnovations.com>
* libm/common/s_llrint.c: New file, implementing llrint().
* libm/common/sf_llrint.c: New file, implementing llrintf().
* libm/common/Makefile.am: Add s_llrint.c (src); sf_llrint.c (fsrc).
* libm/common/Makefile.in: Regenerate.
Diffstat (limited to 'newlib/libm/common/s_llrint.c')
-rw-r--r-- | newlib/libm/common/s_llrint.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/newlib/libm/common/s_llrint.c b/newlib/libm/common/s_llrint.c new file mode 100644 index 000000000..2239c4667 --- /dev/null +++ b/newlib/libm/common/s_llrint.c @@ -0,0 +1,108 @@ +/* lrint adapted to be llrint for Newlib, 2009 by Craig Howland. */ +/* @(#)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. + * ==================================================== + */ + +/* + * llrint(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 llrint(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 */ +}; + +long long int +#ifdef __STDC__ + llrint(double x) +#else + llrint(x) + double x; +#endif +{ + __int32_t i0,j0,sx; + __uint32_t i1; + double t; + volatile double w; + long long int result; + + EXTRACT_WORDS(i0,i1,x); + + /* Extract sign bit. */ + sx = (i0>>31)&1; + + /* Extract exponent field. */ + 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); + /* Detect the all-zeros representation of plus and + minus zero, which fails the calculation below. */ + if ((i0 & ~(1 << 31)) == 0) + return 0; + j0 = ((i0 & 0x7ff00000) >> 20) - 1023; + i0 &= 0x000fffff; + i0 |= 0x00100000; + result = i0 >> (20 - j0); + } + } + else if (j0 < (int)(8 * sizeof (long long int)) - 1) + { + if (j0 >= 52) + result = ((long long int) ((i0 & 0x000fffff) | 0x0010000) << (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 long int) i0 << (j0 - 20)) | (i1 >> (52 - j0)); + } + } + else + { + return (long long int) x; + } + + return sx ? -result : result; +} + +#endif /* _DOUBLE_IS_32BITS */ |