summaryrefslogtreecommitdiff
path: root/libmath/fdlibm/s_rint.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /libmath/fdlibm/s_rint.c
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'libmath/fdlibm/s_rint.c')
-rw-r--r--libmath/fdlibm/s_rint.c88
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];
+}