xref: /illumos-gate/usr/src/lib/libm/common/R/rintf.c (revision 862246c1)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
24  */
25 /*
26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
27  * Use is subject to license terms.
28  */
29 
30 #pragma weak __rintf = rintf
31 
32 /* INDENT OFF */
33 /*
34  * aintf(x)	return x chopped to integral value
35  * anintf(x)	return sign(x)*(|x|+0.5) chopped to integral value
36  * irintf(x)	return rint(x) in integer format
37  * nintf(x)	return anint(x) in integer format
38  * rintf(x)	return x rounded to integral according to the rounding direction
39  *
40  * NOTE: rintf(x), aintf(x) and anintf(x) return results with the same sign as
41  * x's,  including 0.0.
42  */
43 
44 #include "libm.h"
45 
46 static const float xf[] = {
47 /* ZEROF */	0.0f,
48 /* TWO_23F */	8.3886080000e6f,
49 /* MTWO_23F */	-8.3886080000e6f,
50 /* ONEF */	1.0f,
51 /* MONEF */	-1.0f,
52 /* HALFF */	0.5f,
53 /* MHALFF */	-0.5f,
54 /* HUGEF */	1.0e30f,
55 };
56 
57 #define	ZEROF		xf[0]
58 #define	TWO_23F		xf[1]
59 #define	MTWO_23F	xf[2]
60 #define	ONEF		xf[3]
61 #define	MONEF		xf[4]
62 #define	HALFF		xf[5]
63 #define	MHALFF		xf[6]
64 #define	HUGEF		xf[7]
65 /* INDENT ON */
66 
67 float
aintf(float x)68 aintf(float x) {
69 	int hx, k;
70 	float y;
71 
72 	hx = *(int *) &x;
73 	k = (hx & ~0x80000000) >> 23;
74 	if (k < 150) {
75 		y = (float) ((int) x);
76 		/*
77 		 * make sure y has the same sign of x when |x|<0.5
78 		 * (i.e., y=0.0)
79 		 */
80 		return (((k - 127) & hx) < 0 ? -y : y);
81 	} else
82 		/* signal invalid if x is a SNaN */
83 		return (x * ONEF);		/* +0 -> *1 for Cheetah */
84 }
85 
86 float
anintf(float x)87 anintf(float x) {
88 	volatile float dummy __unused;
89 	int hx, k, j, ix;
90 
91 	hx = *(int *) &x;
92 	ix = hx & ~0x80000000;
93 	k = ix >> 23;
94 	if (((k - 127) ^ (k - 150)) < 0) {
95 		j = 1 << (149 - k);
96 		k = j + j - 1;
97 		if ((k & hx) != 0)
98 			dummy = HUGEF + x;	/* raise inexact */
99 		*(int *) &x = (hx + j) & ~k;
100 		return (x);
101 	} else if (k <= 126) {
102 		dummy = HUGEF + x;
103 		*(int *) &x = (0x3f800000 & ((125 - k) >> 31)) |
104 			(0x80000000 & hx);
105 		return (x);
106 	} else
107 		/* signal invalid if x is a SNaN */
108 		return (x * ONEF);		/* +0 -> *1 for Cheetah */
109 }
110 
111 int
irintf(float x)112 irintf(float x) {
113 	float v;
114 	int hx, k;
115 
116 	hx = *(int *) &x;
117 	k = (hx & ~0x80000000) >> 23;
118 	v = xf[((k - 150) >> 31) & (1 - (hx >> 31))];
119 	return ((int) ((float) (x + v) - v));
120 }
121 
122 int
nintf(float x)123 nintf(float x) {
124 	int hx, ix, k, j, m;
125 	volatile float dummy __unused;
126 
127 	hx = *(int *) &x;
128 	k = (hx & ~0x80000000) >> 23;
129 	if (((k - 126) ^ (k - 150)) < 0) {
130 		ix = (hx & 0x00ffffff) | 0x800000;
131 		m = 149 - k;
132 		j = 1 << m;
133 		if ((ix & (j + j - 1)) != 0)
134 			dummy = HUGEF + x;
135 		hx = hx >> 31;
136 		return ((((ix + j) >> (m + 1)) ^ hx) - hx);
137 	} else
138 		return ((int) x);
139 }
140 
141 float
rintf(float x)142 rintf(float x) {
143 	float w, v;
144 	int hx, k;
145 
146 	hx = *(int *) &x;
147 	k = (hx & ~0x80000000) >> 23;
148 #if defined(FPADD_TRAPS_INCOMPLETE_ON_NAN)
149 	if (k >= 150)
150 		return (x * ONEF);
151 	v = xf[1 - (hx >> 31)];
152 #else
153 	v = xf[((k - 150) >> 31) & (1 - (hx >> 31))];
154 #endif
155 	w = (float) (x + v);
156 	if (k < 127 && w == v)
157 		return (ZEROF * x);
158 	else
159 		return (w - v);
160 }
161