diff options
Diffstat (limited to 'libmath/fdlibm/s_rint.c')
| -rw-r--r-- | libmath/fdlibm/s_rint.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/libmath/fdlibm/s_rint.c b/libmath/fdlibm/s_rint.c new file mode 100644 index 00000000..508ade7a --- /dev/null +++ b/libmath/fdlibm/s_rint.c @@ -0,0 +1,88 @@ +/* derived from /netlib/fdlibm */ + +/* @(#)s_rint.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* dummy routine to get around over-eager arm compiler optimization. + * Calling this causes a store and reload of floating point numbers + */ + +void +dummy(void) +{ +} + + +/* + * rint(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 rint(x). + */ + +#include "fdlibm.h" + +static const double +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + + double rint(double x) +{ + int i0,j0,sx; + unsigned i,i1; + double w,t; + i0 = __HI(x); + sx = (i0>>31)&1; + i1 = __LO(x); + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { + if(((i0&0x7fffffff)|i1)==0) return x; + i1 |= (i0&0x0fffff); + i0 &= 0xfffe0000; + i0 |= ((i1|-i1)>>12)&0x80000; + __HI(x)=i0; + w = TWO52[sx]+x; + dummy(); /* fix optimiser */ + t = w-TWO52[sx]; + i0 = __HI(t); + __HI(t) = (i0&0x7fffffff)|(sx<<31); + return t; + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + i>>=1; + if(((i0&i)|i1)!=0) { + if(j0==19) i1 = 0x40000000; else + i0 = (i0&(~i))|((0x20000)>>j0); + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((unsigned)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + i>>=1; + if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); + } + __HI(x) = i0; + __LO(x) = i1; + w = TWO52[sx]+x; + dummy(); /* fix optimiser */ + return w-TWO52[sx]; +} |
