summaryrefslogtreecommitdiff
path: root/usr/src/lib/libm/common/R/rintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libm/common/R/rintf.c')
-rw-r--r--usr/src/lib/libm/common/R/rintf.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/usr/src/lib/libm/common/R/rintf.c b/usr/src/lib/libm/common/R/rintf.c
new file mode 100644
index 0000000000..c958dfd942
--- /dev/null
+++ b/usr/src/lib/libm/common/R/rintf.c
@@ -0,0 +1,166 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#if defined(ELFOBJ)
+#pragma weak aintf = __aintf
+#pragma weak anintf = __anintf
+#pragma weak irintf = __irintf
+#pragma weak nintf = __nintf
+#pragma weak rintf = __rintf
+#endif
+
+/* INDENT OFF */
+/*
+ * aintf(x) return x chopped to integral value
+ * anintf(x) return sign(x)*(|x|+0.5) chopped to integral value
+ * irintf(x) return rint(x) in integer format
+ * nintf(x) return anint(x) in integer format
+ * rintf(x) return x rounded to integral according to the rounding direction
+ *
+ * NOTE: rintf(x), aintf(x) and anintf(x) return results with the same sign as
+ * x's, including 0.0.
+ */
+
+#include "libm.h"
+
+static const float xf[] = {
+/* ZEROF */ 0.0f,
+/* TWO_23F */ 8.3886080000e6f,
+/* MTWO_23F */ -8.3886080000e6f,
+/* ONEF */ 1.0f,
+/* MONEF */ -1.0f,
+/* HALFF */ 0.5f,
+/* MHALFF */ -0.5f,
+/* HUGEF */ 1.0e30f,
+};
+
+#define ZEROF xf[0]
+#define TWO_23F xf[1]
+#define MTWO_23F xf[2]
+#define ONEF xf[3]
+#define MONEF xf[4]
+#define HALFF xf[5]
+#define MHALFF xf[6]
+#define HUGEF xf[7]
+/* INDENT ON */
+
+float
+aintf(float x) {
+ int hx, k;
+ float y;
+
+ hx = *(int *) &x;
+ k = (hx & ~0x80000000) >> 23;
+ if (k < 150) {
+ y = (float) ((int) x);
+ /*
+ * make sure y has the same sign of x when |x|<0.5
+ * (i.e., y=0.0)
+ */
+ return (((k - 127) & hx) < 0 ? -y : y);
+ } else
+ /* signal invalid if x is a SNaN */
+ return (x * ONEF); /* +0 -> *1 for Cheetah */
+}
+
+float
+anintf(float x) {
+ volatile float dummy;
+ int hx, k, j, ix;
+
+ hx = *(int *) &x;
+ ix = hx & ~0x80000000;
+ k = ix >> 23;
+ if (((k - 127) ^ (k - 150)) < 0) {
+ j = 1 << (149 - k);
+ k = j + j - 1;
+ if ((k & hx) != 0)
+ dummy = HUGEF + x; /* raise inexact */
+ *(int *) &x = (hx + j) & ~k;
+ return (x);
+ } else if (k <= 126) {
+ dummy = HUGEF + x;
+ *(int *) &x = (0x3f800000 & ((125 - k) >> 31)) |
+ (0x80000000 & hx);
+ return (x);
+ } else
+ /* signal invalid if x is a SNaN */
+ return (x * ONEF); /* +0 -> *1 for Cheetah */
+}
+
+int
+irintf(float x) {
+ float v;
+ int hx, k;
+
+ hx = *(int *) &x;
+ k = (hx & ~0x80000000) >> 23;
+ v = xf[((k - 150) >> 31) & (1 - (hx >> 31))];
+ return ((int) ((float) (x + v) - v));
+}
+
+int
+nintf(float x) {
+ int hx, ix, k, j, m;
+ volatile float dummy;
+
+ hx = *(int *) &x;
+ k = (hx & ~0x80000000) >> 23;
+ if (((k - 126) ^ (k - 150)) < 0) {
+ ix = (hx & 0x00ffffff) | 0x800000;
+ m = 149 - k;
+ j = 1 << m;
+ if ((ix & (j + j - 1)) != 0)
+ dummy = HUGEF + x;
+ hx = hx >> 31;
+ return ((((ix + j) >> (m + 1)) ^ hx) - hx);
+ } else
+ return ((int) x);
+}
+
+float
+rintf(float x) {
+ float w, v;
+ int hx, k;
+
+ hx = *(int *) &x;
+ k = (hx & ~0x80000000) >> 23;
+#if defined(FPADD_TRAPS_INCOMPLETE_ON_NAN)
+ if (k >= 150)
+ return (x * ONEF);
+ v = xf[1 - (hx >> 31)];
+#else
+ v = xf[((k - 150) >> 31) & (1 - (hx >> 31))];
+#endif
+ w = (float) (x + v);
+ if (k < 127 && w == v)
+ return (ZEROF * x);
+ else
+ return (w - v);
+}