xref: /illumos-gate/usr/src/lib/libc/port/gen/_ftoll.c (revision a92282e44f968185a6bba094d1e5fece2da819cf)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include "lint.h"
28 #include <sys/isa_defs.h>
29 #include <floatingpoint.h>
30 #include <limits.h>
31 #include "libc.h"
32 
33 /*
34  * Ensure that this "portable" code is only used on big-endian ISAs
35  */
36 #if !defined(_BIG_ENDIAN) || defined(_LITTLE_ENDIAN)
37 #error	"big-endian only!"
38 #endif
39 
40 /*
41  * Convert a double precision floating point number into a 64-bit int.
42  */
43 long long
44 __dtoll(double dval)
45 {
46 	int i0, i1;		/* bitslam */
47 	int exp;		/* exponent */
48 	int m0;			/* most significant word of mantissa */
49 	unsigned int m1;	/* least sig. word of mantissa */
50 	unsigned int _fp_current_exceptions = 0;
51 	union {
52 		int i[2];
53 		double d;
54 	} u;
55 
56 	/*
57 	 * Extract the exponent and check boundary conditions.
58 	 * Notice that the exponent is equal to the bit number where
59 	 * we want the most significant bit to live.
60 	 */
61 	u.d = dval;
62 	i0 = u.i[0];
63 	i1 = u.i[1];
64 
65 	exp = ((i0 >> 20) & 0x7ff) - 0x3ff;
66 	if (exp < 0) {
67 		return ((long long)0); /* abs(x) < 1.0, so round to 0 */
68 	} else if (exp > 62) {
69 		/*
70 		 * fp_invalid NOT raised if <i0,i1> == LLONG_MIN
71 		 */
72 		if (i0 >= 0 || exp != 63 || (i0 & 0xfffff) != 0 || i1 != 0) {
73 			/*
74 			 * abs(x) > MAXLLONG; return {MIN,MAX}LLONG and as
75 			 * overflow, Inf, NaN set fp_invalid exception
76 			 */
77 			_fp_current_exceptions |= (1 << (int)fp_invalid);
78 			(void) _Q_set_exception(_fp_current_exceptions);
79 		}
80 		if (i0 < 0)
81 			return (LLONG_MIN);
82 		else
83 			return (LLONG_MAX); /* MAXLONG */
84 	}
85 
86 	/* Extract the mantissa. */
87 
88 	m0 = 0x40000000 | ((i0 << 10) & 0x3ffffc00) | ((i1 >> 22) & 0x3ff);
89 	m1 = i1 << 10;
90 
91 	/*
92 	 * The most significant bit of the mantissa is now in bit 62 of m0:m1.
93 	 * Shift right by (62 - exp) bits.
94 	 */
95 	switch (exp) {
96 	case 62:
97 		break;
98 	case 30:
99 		m1 = m0;
100 		m0 = 0;
101 		break;
102 	default:
103 		if (exp > 30) {
104 			m1 = (m0 << (exp - 30)) |
105 			    (m1 >> (62 - exp)) & ~(UINT_MAX << (exp - 30));
106 			m0 >>= 62 - exp;
107 		} else {
108 			m1 = m0 >> (30 - exp);
109 			m0 = 0;
110 		}
111 		break;
112 	}
113 
114 	if (i0 < 0) {
115 		m0 = ~m0;
116 		m1 = ~m1;
117 		if (++m1 == 0)
118 			m0++;
119 	}
120 
121 	(void) _Q_set_exception(_fp_current_exceptions);
122 	return ((long long)(((unsigned long long)m0 << 32) | m1));
123 }
124 
125 /*
126  * Convert a floating point number into a 64-bit int.
127  */
128 long long
129 __ftoll(float fval)
130 {
131 	int i0;
132 	int exp;		/* exponent */
133 	int m0;			/* most significant word of mantissa */
134 	unsigned int m1;	/* least sig. word of mantissa */
135 	unsigned int _fp_current_exceptions = 0;
136 	union {
137 		int i;
138 		float f;
139 	} u;
140 
141 	/*
142 	 * Extract the exponent and check boundary conditions.
143 	 * Notice that the exponent is equal to the bit number where
144 	 * we want the most significant bit to live.
145 	 */
146 	u.f = fval;
147 	i0 = u.i;
148 
149 	exp = ((i0 >> 23) & 0xff) - 0x7f;
150 	if (exp < 0) {
151 		return ((long long) 0); /* abs(x) < 1.0, so round to 0 */
152 	} else if (exp > 62)  {
153 		/*
154 		 * fp_invalid NOT raised if <i0> == LLONG_MIN
155 		 */
156 		if (i0 >= 0 || exp != 63 || (i0 & 0x7fffff) != 0) {
157 			/*
158 			 * abs(x) > MAXLLONG; return {MIN,MAX}LLONG and as
159 			 * overflow, Inf, NaN set fp_invalid exception
160 			 */
161 			_fp_current_exceptions |= (1 << (int)fp_invalid);
162 			(void) _Q_set_exception(_fp_current_exceptions);
163 		}
164 		if (i0 < 0)
165 			return (LLONG_MIN);
166 		else
167 			return (LLONG_MAX); /* MAXLONG */
168 	}
169 
170 	/* Extract the mantissa. */
171 
172 	m0 = 0x40000000 | (i0 << 7) & 0x3fffff80;
173 	m1 = 0;
174 
175 	/*
176 	 * The most significant bit of the mantissa is now in bit 62 of m0:m1.
177 	 * Shift right by (62 - exp) bits.
178 	 */
179 	switch (exp) {
180 	case 62:
181 		break;
182 	case 30:
183 		m1 = m0;
184 		m0 = 0;
185 		break;
186 	default:
187 		if (exp > 30) {
188 			m1 = m0 << (exp - 30);
189 			m0 >>= 62 - exp;
190 		} else {
191 			m1 = m0 >> (30 - exp);
192 			m0 = 0;
193 		}
194 		break;
195 	}
196 
197 	if (i0 < 0) {
198 		m0 = ~m0;
199 		m1 = ~m1;
200 		if (++m1 == 0)
201 			m0++;
202 	}
203 
204 	(void) _Q_set_exception(_fp_current_exceptions);
205 	return ((long long)(((unsigned long long)m0 << 32) | m1));
206 }
207 
208 /*
209  * Convert an extended precision floating point number into a 64-bit int.
210  */
211 long long
212 _Q_qtoll(long double longdbl)
213 {
214 	int i0;
215 	unsigned int i1, i2;	/* a long double is 128-bit in length */
216 	int *plngdbl = (int *)&longdbl;
217 	int exp;		/* exponent */
218 	int m0;			/* most significant word of mantissa */
219 	unsigned int m1;	/* least sig. word of mantissa */
220 	unsigned int _fp_current_exceptions = 0;
221 
222 	/*
223 	 * Only 96-bits of precision used
224 	 */
225 	i0 = plngdbl[0];
226 	i1 = plngdbl[1];
227 	i2 = plngdbl[2];
228 
229 	/*
230 	 * Extract the exponent and check boundary conditions.
231 	 * Notice that the exponent is equal to the bit number where
232 	 * we want the most significant bit to live.
233 	 */
234 	exp = ((i0 >> 16) & 0x7fff) - 0x3fff;
235 	if (exp < 0) {
236 		return ((long long)0); /* abs(x) < 1.0, so round to 0 */
237 	} else if (exp > 62)	{
238 		/*
239 		 * fp_invalid NOT raised if <i0,i1,i2,i3> when chopped to
240 		 * 64 bits == LLONG_MIN
241 		 */
242 		if (i0 >= 0 || exp != 63 || (i0 & 0xffff) != 0 || i1 != 0 ||
243 		    (i2 & 0xfffe0000) != 0) {
244 			/*
245 			 * abs(x) > MAXLLONG; return {MIN,MAX}LLONG and as
246 			 * overflow, Inf, NaN set fp_invalid exception
247 			 */
248 			_fp_current_exceptions |= (1 << (int)fp_invalid);
249 			(void) _Q_set_exception(_fp_current_exceptions);
250 		}
251 		if (i0 < 0)
252 			return (LLONG_MIN);
253 		else
254 			return (LLONG_MAX); /* MAXLONG */
255 	}
256 
257 	/* Extract the mantissa. */
258 
259 	m0 = 0x40000000 | ((i0 << 14) & 0x3fffc000) | ((i1 >> 18) & 0x3fff);
260 	m1 = (i1 << 14) | ((i2 >> 18) & 0x3fff);
261 
262 	/*
263 	 * The most significant bit of the mantissa is now in bit 62 of m0:m1.
264 	 * Shift right by (62 - exp) bits.
265 	 */
266 	switch (exp) {
267 	case 62:
268 		break;
269 	case 30:
270 		m1 = m0;
271 		m0 = 0;
272 		break;
273 	default:
274 		if (exp > 30) {
275 			m1 = (m0 << (exp - 30)) |
276 			    (m1 >> (62 - exp)) & ~(UINT_MAX << (exp - 30));
277 			m0 >>= 62 - exp;
278 		} else {
279 			m1 = m0 >> (30 - exp);
280 			m0 = 0;
281 		}
282 		break;
283 	}
284 
285 	if (i0 < 0) {
286 		m0 = ~m0;
287 		m1 = ~m1;
288 		if (++m1 == 0)
289 			m0++;
290 	}
291 
292 	(void) _Q_set_exception(_fp_current_exceptions);
293 	return ((long long)(((unsigned long long)m0 << 32) | m1));
294 }
295