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 #if defined(ELFOBJ)
31 #pragma weak llroundl = __llroundl
32 #if defined(__sparcv9) || defined(__amd64)
33 #pragma weak lroundl = __llroundl
34 #pragma weak __lroundl = __llroundl
35 #endif
36 #endif
37
38 #include "libm.h"
39
40 #if defined(__sparc)
41 long long
42 llroundl(long double x) {
43 union {
44 unsigned i[4];
45 long double q;
46 } xx;
47 union {
48 unsigned i[2];
49 long long l;
50 } zz;
51 union {
52 unsigned i;
53 float f;
54 } tt;
55 unsigned hx, sx, frac;
56 int j;
57
58 xx.q = x;
59 sx = xx.i[0] & 0x80000000;
60 hx = xx.i[0] & ~0x80000000;
61
62 /* handle trivial cases */
63 if (hx > 0x403e0000) { /* |x| > 2^63 + ... or x is nan */
64 /* convert an out-of-range float */
65 tt.i = sx | 0x7f000000;
66 return ((long long) tt.f);
67 }
68
69 /* handle |x| < 1 */
70 if (hx < 0x3fff0000) {
71 if (hx >= 0x3ffe0000)
72 return (sx ? -1LL : 1LL);
73 return (0LL);
74 }
75
76 /* extract the integer and fractional parts of x */
77 j = 0x406f - (hx >> 16);
78 xx.i[0] = 0x10000 | (xx.i[0] & 0xffff);
79 if (j >= 96) {
80 zz.i[0] = 0;
81 zz.i[1] = xx.i[0] >> (j - 96);
82 frac = ((xx.i[0] << 1) << (127 - j)) | (xx.i[1] >> (j - 96));
83 if (((xx.i[1] << 1) << (127 - j)) | xx.i[2] | xx.i[3])
84 frac |= 1;
85 } else if (j >= 64) {
86 zz.i[0] = xx.i[0] >> (j - 64);
87 zz.i[1] = ((xx.i[0] << 1) << (95 - j)) | (xx.i[1] >> (j - 64));
88 frac = ((xx.i[1] << 1) << (95 - j)) | (xx.i[2] >> (j - 64));
89 if (((xx.i[2] << 1) << (95 - j)) | xx.i[3])
90 frac |= 1;
91 } else {
92 zz.i[0] = ((xx.i[0] << 1) << (63 - j)) | (xx.i[1] >> (j - 32));
93 zz.i[1] = ((xx.i[1] << 1) << (63 - j)) | (xx.i[2] >> (j - 32));
94 frac = ((xx.i[2] << 1) << (63 - j)) | (xx.i[3] >> (j - 32));
95 if ((xx.i[3] << 1) << (63 - j))
96 frac |= 1;
97 }
98
99 /* round */
100 if (frac >= 0x80000000u) {
101 if (++zz.i[1] == 0)
102 zz.i[0]++;
103 }
104
105 /* check for result out of range (note that z is |x| at this point) */
106 if (zz.i[0] > 0x80000000u || (zz.i[0] == 0x80000000 && (zz.i[1] ||
107 !sx))) {
108 tt.i = sx | 0x7f000000;
109 return ((long long) tt.f);
110 }
111
112 /* negate result if need be */
113 if (sx) {
114 zz.i[0] = ~zz.i[0];
115 zz.i[1] = -zz.i[1];
116 if (zz.i[1] == 0)
117 zz.i[0]++;
118 }
119
120 return (zz.l);
121 }
122 #elif defined(__x86)
123 long long
124 llroundl(long double x) {
125 union {
126 unsigned i[3];
127 long double e;
128 } xx;
129 int ex, sx, i;
130
131 xx.e = x;
132 ex = xx.i[2] & 0x7fff;
133 sx = xx.i[2] & 0x8000;
134
135 if (ex < 0x403e) { /* |x| < 2^63 */
136 /* handle |x| < 1 */
137 if (ex < 0x3fff) {
138 if (ex >= 0x3ffe)
139 return (sx ? -1LL : 1LL);
140 return (0LL);
141 }
142
143 /* round x at the integer bit */
144 if (ex < 0x401e) {
145 i = 1 << (0x401d - ex);
146 xx.i[1] = (xx.i[1] + i) & ~(i | (i - 1));
147 xx.i[0] = 0;
148 } else {
149 i = 1 << (0x403d - ex);
150 xx.i[0] += i;
151 if (xx.i[0] < i)
152 xx.i[1]++;
153 xx.i[0] &= ~(i | (i - 1));
154 }
155 if (xx.i[1] == 0) {
156 xx.i[2] = sx | ++ex;
157 xx.i[1] = 0x80000000U;
158 }
159 }
160
161 /* now x is nan, inf, or integral */
162 return ((long long) xx.e);
163 }
164 #else
165 #error Unknown architecture
166 #endif