1*25c28e83SPiotr Jasiukajtis /*
2*25c28e83SPiotr Jasiukajtis * CDDL HEADER START
3*25c28e83SPiotr Jasiukajtis *
4*25c28e83SPiotr Jasiukajtis * The contents of this file are subject to the terms of the
5*25c28e83SPiotr Jasiukajtis * Common Development and Distribution License (the "License").
6*25c28e83SPiotr Jasiukajtis * You may not use this file except in compliance with the License.
7*25c28e83SPiotr Jasiukajtis *
8*25c28e83SPiotr Jasiukajtis * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*25c28e83SPiotr Jasiukajtis * or http://www.opensolaris.org/os/licensing.
10*25c28e83SPiotr Jasiukajtis * See the License for the specific language governing permissions
11*25c28e83SPiotr Jasiukajtis * and limitations under the License.
12*25c28e83SPiotr Jasiukajtis *
13*25c28e83SPiotr Jasiukajtis * When distributing Covered Code, include this CDDL HEADER in each
14*25c28e83SPiotr Jasiukajtis * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*25c28e83SPiotr Jasiukajtis * If applicable, add the following below this CDDL HEADER, with the
16*25c28e83SPiotr Jasiukajtis * fields enclosed by brackets "[]" replaced with your own identifying
17*25c28e83SPiotr Jasiukajtis * information: Portions Copyright [yyyy] [name of copyright owner]
18*25c28e83SPiotr Jasiukajtis *
19*25c28e83SPiotr Jasiukajtis * CDDL HEADER END
20*25c28e83SPiotr Jasiukajtis */
21*25c28e83SPiotr Jasiukajtis
22*25c28e83SPiotr Jasiukajtis /*
23*25c28e83SPiotr Jasiukajtis * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24*25c28e83SPiotr Jasiukajtis */
25*25c28e83SPiotr Jasiukajtis /*
26*25c28e83SPiotr Jasiukajtis * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27*25c28e83SPiotr Jasiukajtis * Use is subject to license terms.
28*25c28e83SPiotr Jasiukajtis */
29*25c28e83SPiotr Jasiukajtis
30*25c28e83SPiotr Jasiukajtis #pragma weak nearbyintl = __nearbyintl
31*25c28e83SPiotr Jasiukajtis
32*25c28e83SPiotr Jasiukajtis #include "libm.h"
33*25c28e83SPiotr Jasiukajtis #include "fma.h"
34*25c28e83SPiotr Jasiukajtis #include "fenv_inlines.h"
35*25c28e83SPiotr Jasiukajtis
36*25c28e83SPiotr Jasiukajtis #if defined(__sparc)
37*25c28e83SPiotr Jasiukajtis
38*25c28e83SPiotr Jasiukajtis static union {
39*25c28e83SPiotr Jasiukajtis unsigned i;
40*25c28e83SPiotr Jasiukajtis float f;
41*25c28e83SPiotr Jasiukajtis } snan = { 0x7f800001 };
42*25c28e83SPiotr Jasiukajtis
43*25c28e83SPiotr Jasiukajtis long double
__nearbyintl(long double x)44*25c28e83SPiotr Jasiukajtis __nearbyintl(long double x) {
45*25c28e83SPiotr Jasiukajtis union {
46*25c28e83SPiotr Jasiukajtis unsigned i[4];
47*25c28e83SPiotr Jasiukajtis long double q;
48*25c28e83SPiotr Jasiukajtis } xx;
49*25c28e83SPiotr Jasiukajtis unsigned hx, sx, i, frac;
50*25c28e83SPiotr Jasiukajtis unsigned int fsr;
51*25c28e83SPiotr Jasiukajtis int rm, j;
52*25c28e83SPiotr Jasiukajtis volatile float dummy;
53*25c28e83SPiotr Jasiukajtis
54*25c28e83SPiotr Jasiukajtis xx.q = x;
55*25c28e83SPiotr Jasiukajtis sx = xx.i[0] & 0x80000000;
56*25c28e83SPiotr Jasiukajtis hx = xx.i[0] & ~0x80000000;
57*25c28e83SPiotr Jasiukajtis
58*25c28e83SPiotr Jasiukajtis /* handle trivial cases */
59*25c28e83SPiotr Jasiukajtis if (hx >= 0x406f0000) { /* x is nan, inf, or already integral */
60*25c28e83SPiotr Jasiukajtis /* check for signaling nan */
61*25c28e83SPiotr Jasiukajtis if ((hx > 0x7fff0000 || (hx == 0x7fff0000 &&
62*25c28e83SPiotr Jasiukajtis (xx.i[1] | xx.i[2] | xx.i[3]))) && !(hx & 0x8000)) {
63*25c28e83SPiotr Jasiukajtis dummy = snan.f;
64*25c28e83SPiotr Jasiukajtis dummy += snan.f;
65*25c28e83SPiotr Jasiukajtis xx.i[0] = sx | hx | 0x8000;
66*25c28e83SPiotr Jasiukajtis }
67*25c28e83SPiotr Jasiukajtis return (xx.q);
68*25c28e83SPiotr Jasiukajtis } else if ((hx | xx.i[1] | xx.i[2] | xx.i[3]) == 0) /* x is zero */
69*25c28e83SPiotr Jasiukajtis return (x);
70*25c28e83SPiotr Jasiukajtis
71*25c28e83SPiotr Jasiukajtis /* get the rounding mode */
72*25c28e83SPiotr Jasiukajtis __fenv_getfsr32(&fsr);
73*25c28e83SPiotr Jasiukajtis rm = fsr >> 30;
74*25c28e83SPiotr Jasiukajtis
75*25c28e83SPiotr Jasiukajtis /* flip the sense of directed roundings if x is negative */
76*25c28e83SPiotr Jasiukajtis if (sx)
77*25c28e83SPiotr Jasiukajtis rm ^= rm >> 1;
78*25c28e83SPiotr Jasiukajtis
79*25c28e83SPiotr Jasiukajtis /* handle |x| < 1 */
80*25c28e83SPiotr Jasiukajtis if (hx < 0x3fff0000) {
81*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (hx >= 0x3ffe0000 &&
82*25c28e83SPiotr Jasiukajtis ((hx & 0xffff) | xx.i[1] | xx.i[2] | xx.i[3]))))
83*25c28e83SPiotr Jasiukajtis xx.i[0] = sx | 0x3fff0000;
84*25c28e83SPiotr Jasiukajtis else
85*25c28e83SPiotr Jasiukajtis xx.i[0] = sx;
86*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[2] = xx.i[3] = 0;
87*25c28e83SPiotr Jasiukajtis return (xx.q);
88*25c28e83SPiotr Jasiukajtis }
89*25c28e83SPiotr Jasiukajtis
90*25c28e83SPiotr Jasiukajtis /* round x at the integer bit */
91*25c28e83SPiotr Jasiukajtis j = 0x406f - (hx >> 16);
92*25c28e83SPiotr Jasiukajtis if (j >= 96) {
93*25c28e83SPiotr Jasiukajtis i = 1 << (j - 96);
94*25c28e83SPiotr Jasiukajtis frac = ((xx.i[0] << 1) << (127 - j)) | (xx.i[1] >> (j - 96));
95*25c28e83SPiotr Jasiukajtis if ((xx.i[1] & (i - 1)) | xx.i[2] | xx.i[3])
96*25c28e83SPiotr Jasiukajtis frac |= 1;
97*25c28e83SPiotr Jasiukajtis if (!frac)
98*25c28e83SPiotr Jasiukajtis return (x);
99*25c28e83SPiotr Jasiukajtis xx.i[1] = xx.i[2] = xx.i[3] = 0;
100*25c28e83SPiotr Jasiukajtis xx.i[0] &= ~(i - 1);
101*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (frac > 0x80000000u ||
102*25c28e83SPiotr Jasiukajtis (frac == 0x80000000 && (xx.i[0] & i)))))
103*25c28e83SPiotr Jasiukajtis xx.i[0] += i;
104*25c28e83SPiotr Jasiukajtis } else if (j >= 64) {
105*25c28e83SPiotr Jasiukajtis i = 1 << (j - 64);
106*25c28e83SPiotr Jasiukajtis frac = ((xx.i[1] << 1) << (95 - j)) | (xx.i[2] >> (j - 64));
107*25c28e83SPiotr Jasiukajtis if ((xx.i[2] & (i - 1)) | xx.i[3])
108*25c28e83SPiotr Jasiukajtis frac |= 1;
109*25c28e83SPiotr Jasiukajtis if (!frac)
110*25c28e83SPiotr Jasiukajtis return (x);
111*25c28e83SPiotr Jasiukajtis xx.i[2] = xx.i[3] = 0;
112*25c28e83SPiotr Jasiukajtis xx.i[1] &= ~(i - 1);
113*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (frac > 0x80000000u ||
114*25c28e83SPiotr Jasiukajtis (frac == 0x80000000 && (xx.i[1] & i))))) {
115*25c28e83SPiotr Jasiukajtis xx.i[1] += i;
116*25c28e83SPiotr Jasiukajtis if (xx.i[1] == 0)
117*25c28e83SPiotr Jasiukajtis xx.i[0]++;
118*25c28e83SPiotr Jasiukajtis }
119*25c28e83SPiotr Jasiukajtis } else if (j >= 32) {
120*25c28e83SPiotr Jasiukajtis i = 1 << (j - 32);
121*25c28e83SPiotr Jasiukajtis frac = ((xx.i[2] << 1) << (63 - j)) | (xx.i[3] >> (j - 32));
122*25c28e83SPiotr Jasiukajtis if (xx.i[3] & (i - 1))
123*25c28e83SPiotr Jasiukajtis frac |= 1;
124*25c28e83SPiotr Jasiukajtis if (!frac)
125*25c28e83SPiotr Jasiukajtis return (x);
126*25c28e83SPiotr Jasiukajtis xx.i[3] = 0;
127*25c28e83SPiotr Jasiukajtis xx.i[2] &= ~(i - 1);
128*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (frac > 0x80000000u ||
129*25c28e83SPiotr Jasiukajtis (frac == 0x80000000 && (xx.i[2] & i))))) {
130*25c28e83SPiotr Jasiukajtis xx.i[2] += i;
131*25c28e83SPiotr Jasiukajtis if (xx.i[2] == 0)
132*25c28e83SPiotr Jasiukajtis if (++xx.i[1] == 0)
133*25c28e83SPiotr Jasiukajtis xx.i[0]++;
134*25c28e83SPiotr Jasiukajtis }
135*25c28e83SPiotr Jasiukajtis } else {
136*25c28e83SPiotr Jasiukajtis i = 1 << j;
137*25c28e83SPiotr Jasiukajtis frac = (xx.i[3] << 1) << (31 - j);
138*25c28e83SPiotr Jasiukajtis if (!frac)
139*25c28e83SPiotr Jasiukajtis return (x);
140*25c28e83SPiotr Jasiukajtis xx.i[3] &= ~(i - 1);
141*25c28e83SPiotr Jasiukajtis if (rm == FSR_RP || (rm == FSR_RN && (frac > 0x80000000u ||
142*25c28e83SPiotr Jasiukajtis (frac == 0x80000000 && (xx.i[3] & i))))) {
143*25c28e83SPiotr Jasiukajtis xx.i[3] += i;
144*25c28e83SPiotr Jasiukajtis if (xx.i[3] == 0)
145*25c28e83SPiotr Jasiukajtis if (++xx.i[2] == 0)
146*25c28e83SPiotr Jasiukajtis if (++xx.i[1] == 0)
147*25c28e83SPiotr Jasiukajtis xx.i[0]++;
148*25c28e83SPiotr Jasiukajtis }
149*25c28e83SPiotr Jasiukajtis }
150*25c28e83SPiotr Jasiukajtis
151*25c28e83SPiotr Jasiukajtis return (xx.q);
152*25c28e83SPiotr Jasiukajtis }
153*25c28e83SPiotr Jasiukajtis
154*25c28e83SPiotr Jasiukajtis #elif defined(__x86)
155*25c28e83SPiotr Jasiukajtis
156*25c28e83SPiotr Jasiukajtis /* inline template */
157*25c28e83SPiotr Jasiukajtis extern long double frndint(long double);
158*25c28e83SPiotr Jasiukajtis
159*25c28e83SPiotr Jasiukajtis long double
__nearbyintl(long double x)160*25c28e83SPiotr Jasiukajtis __nearbyintl(long double x) {
161*25c28e83SPiotr Jasiukajtis long double z;
162*25c28e83SPiotr Jasiukajtis unsigned oldcwsw, cwsw;
163*25c28e83SPiotr Jasiukajtis
164*25c28e83SPiotr Jasiukajtis /* save the control and status words, mask the inexact exception */
165*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&oldcwsw);
166*25c28e83SPiotr Jasiukajtis cwsw = oldcwsw | 0x00200000;
167*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&cwsw);
168*25c28e83SPiotr Jasiukajtis
169*25c28e83SPiotr Jasiukajtis z = frndint(x);
170*25c28e83SPiotr Jasiukajtis
171*25c28e83SPiotr Jasiukajtis /*
172*25c28e83SPiotr Jasiukajtis * restore the control and status words, preserving all but the
173*25c28e83SPiotr Jasiukajtis * inexact flag
174*25c28e83SPiotr Jasiukajtis */
175*25c28e83SPiotr Jasiukajtis __fenv_getcwsw(&cwsw);
176*25c28e83SPiotr Jasiukajtis oldcwsw |= (cwsw & 0x1f);
177*25c28e83SPiotr Jasiukajtis __fenv_setcwsw(&oldcwsw);
178*25c28e83SPiotr Jasiukajtis
179*25c28e83SPiotr Jasiukajtis return (z);
180*25c28e83SPiotr Jasiukajtis }
181*25c28e83SPiotr Jasiukajtis
182*25c28e83SPiotr Jasiukajtis #else
183*25c28e83SPiotr Jasiukajtis #error Unknown architecture
184*25c28e83SPiotr Jasiukajtis #endif
185