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/sf_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/sf_llrint.c')
-rw-r--r-- | newlib/libm/common/sf_llrint.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/newlib/libm/common/sf_llrint.c b/newlib/libm/common/sf_llrint.c new file mode 100644 index 000000000..5cc73c664 --- /dev/null +++ b/newlib/libm/common/sf_llrint.c @@ -0,0 +1,101 @@ +/* lrintf adapted to be llrintf for Newlib, 2009 by Craig Howland. */ +/* @(#)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. + * ==================================================== + */ + +/* + * llrintf(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 llrintf(x). + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +/* Adding a float, x, to 2^23 will cause the result to be rounded based on + the fractional part of x, according to the implementation's current rounding + mode. 2^23 is the smallest float that can be represented using all 23 significant + digits. */ +TWO23[2]={ + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ +}; + +#ifdef __STDC__ + long long int llrintf(float x) +#else + long long int llrintf(x) + float x; +#endif +{ + __int32_t j0,sx; + __uint32_t i0; + float t; + volatile float w; + long long int result; + + GET_FLOAT_WORD(i0,x); + + /* Extract sign bit. */ + sx = (i0 >> 31); + + /* Extract exponent field. */ + j0 = ((i0 & 0x7f800000) >> 23) - 127; + + if (j0 < (int)(sizeof (long long int) * 8) - 1) + { + if (j0 < -1) + return 0; + else if (j0 >= 23) + result = (long long int) ((i0 & 0x7fffff) | 0x800000) << (j0 - 23); + else + { + w = TWO23[sx] + x; + t = w - TWO23[sx]; + GET_FLOAT_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 >> 23) & 0xff) - 0x7f; + i0 &= 0x7fffff; + i0 |= 0x800000; + result = i0 >> (23 - j0); + } + } + else + { + return (long long int) x; + } + return sx ? -result : result; +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + long long int llrint(double x) +#else + long long int llrint(x) + double x; +#endif +{ + return llrintf((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ |