xref: /illumos-gate/usr/src/lib/libc/port/gen/_ftoull.c (revision 1da57d551424de5a9d469760be7c4b4d4f10a755)
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 # into a 64-bit unsigned int.
42  *
43  * For compatibility with Sun's other conversion routines, pretend result
44  * is signed if input is negative.
45  */
46 unsigned long long
__dtoull(double dval)47 __dtoull(double dval)
48 {
49 	int i0;			/* bitslam */
50 	unsigned i1;		/* bitslam */
51 	int exp;		/* exponent */
52 	unsigned int m0;	/* most significant word of mantissa */
53 	unsigned int m1;	/* least sig. word of mantissa */
54 	unsigned int _fp_current_exceptions = 0;
55 	union {
56 		int i[2];
57 		double d;
58 	} u;
59 
60 	/*
61 	 * Extract the exponent and check boundary conditions.
62 	 * Notice that the exponent is equal to the bit number where
63 	 * we want the most significant bit to live.
64 	 */
65 	u.d = dval;
66 	i0 = u.i[0];
67 	i1 = u.i[1];
68 
69 	exp = ((i0 >> 20) & 0x7ff) - 0x3ff;
70 	if (exp < 0) {
71 		/* abs(x) < 1.0, so round to 0 */
72 		return ((unsigned long long)0);
73 	} else if (exp > 63)  {
74 		/*
75 		 * abs(x) > MAXLLONG; return {MIN,MAX}ULLONG and as
76 		 * overflow, Inf, NaN set fp_invalid exception
77 		 */
78 		_fp_current_exceptions |= (1 << (int)fp_invalid);
79 		(void) _Q_set_exception(_fp_current_exceptions);
80 		if (i0 < 0)
81 			return ((unsigned long long)LLONG_MIN);
82 		else
83 			return (ULLONG_MAX); /* MAXLONG */
84 	}
85 
86 	/* Extract the mantissa. */
87 
88 	m0 = 0x80000000 | ((i0 << 11) & 0x7ffff800) | ((i1 >> 21) & 0x7ff);
89 	m1 = i1 << 11;
90 
91 	/*
92 	 * The most significant bit of the mantissa is now in bit 63 of m0:m1.
93 	 * Shift right by (63 - exp) bits.
94 	 */
95 	switch (exp) {
96 	case 63:
97 		break;
98 	case 31:
99 		m1 = m0;
100 		m0 = 0;
101 		break;
102 	default:
103 		if (exp > 31) {
104 			m1 = (m0 << (exp - 31)) | (m1 >> (63 - exp));
105 			m0 = (m0 >> (63 - exp));
106 		} else {
107 			m1 = (m0 >> (31 - exp));
108 			m0 = 0;
109 		}
110 		break;
111 	}
112 
113 	if (i0 < 0) {
114 		if ((int)m0 < 0) {	/* x < MINLLONG; return MINLLONG */
115 			m0 = 0x80000000;
116 			m1 = 0;
117 		} else {
118 			m0 = ~m0;
119 			m1 = ~m1;
120 			if (++m1 == 0)
121 				m0++;
122 		}
123 	}
124 
125 	(void) _Q_set_exception(_fp_current_exceptions);
126 	return (((unsigned long long)m0 << 32) | m1);
127 }
128 
129 /*
130  * Convert a floating point number into a 64-bit unsigned int.
131  *
132  * For compatibility with Sun's other conversion routines, pretend result
133  * is signed if input is negative.
134  */
135 unsigned long long
__ftoull(float fval)136 __ftoull(float fval)
137 {
138 	int i0;			/* bitslam */
139 	int exp;		/* exponent */
140 	unsigned int m0;	/* most significant word of mantissa */
141 	unsigned int m1;	/* least sig. word of mantissa */
142 	unsigned int _fp_current_exceptions = 0;
143 	union {
144 		int i;
145 		float f;
146 	} u;
147 
148 	/*
149 	 * Extract the exponent and check boundary conditions.
150 	 * Notice that the exponent is equal to the bit number where
151 	 * we want the most significant bit to live.
152 	 */
153 	u.f = fval;
154 	i0 = u.i;
155 
156 	exp = ((i0 >> 23) & 0xff) - 0x7f;
157 	if (exp < 0) {
158 		/* abs(x) < 1.0, so round to 0 */
159 		return ((unsigned long long)0);
160 	} else if (exp > 63)  {
161 		/*
162 		 * abs(x) > MAXLLONG; return {MIN,MAX}ULLONG and as
163 		 * overflow, Inf, NaN set fp_invalid exception
164 		 */
165 		_fp_current_exceptions |= (1 << (int)fp_invalid);
166 		(void) _Q_set_exception(_fp_current_exceptions);
167 		if (i0 < 0)
168 			return ((unsigned long long)LLONG_MIN);
169 		else
170 			return (ULLONG_MAX); /* MAXLONG */
171 	}
172 
173 	/* Extract the mantissa. */
174 
175 	m0 = 0x80000000 | (i0 << 8) & 0x7fffff00;
176 	m1 = 0;
177 
178 	/*
179 	 * The most significant bit of the mantissa is now in bit 63 of m0:m1.
180 	 * Shift right by (63 - exp) bits.
181 	 */
182 	switch (exp) {
183 	case 63:
184 		break;
185 	case 31:
186 		m1 = m0;
187 		m0 = 0;
188 		break;
189 	default:
190 		if (exp > 31) {
191 			m1 = m0 << (exp - 31);
192 			m0 = (m0 >> (63 - exp));
193 		} else {
194 			m1 = (m0 >> (31 - exp));
195 			m0 = 0;
196 		}
197 		break;
198 	}
199 
200 	if (i0 < 0) {
201 		if ((int)m0 < 0) {	/* x < MINLLONG; return MINLLONG */
202 			m0 = 0x80000000;
203 			m1 = 0;
204 		} else {
205 			m0 = ~m0;
206 			m1 = ~m1;
207 			if (++m1 == 0)
208 				m0++;
209 		}
210 	}
211 
212 	(void) _Q_set_exception(_fp_current_exceptions);
213 	return (((unsigned long long)m0 << 32) | m1);
214 }
215 
216 /*
217  * Convert an extended precision floating point # into a 64-bit unsigned int.
218  *
219  * For compatibility with Sun's other conversion routines, pretend result
220  * is signed if input is negative.
221  */
222 unsigned long long
_Q_qtoull(long double ld)223 _Q_qtoull(long double ld)
224 {
225 	int i0;
226 	unsigned int i1, i2;	/* a long double is 128-bit in length */
227 	int exp;		/* exponent */
228 	unsigned int m0;	/* most significant word of mantissa */
229 	unsigned int m1;	/* least sig. word of mantissa */
230 	unsigned int _fp_current_exceptions = 0;
231 	int	 *plngdbl = (int *)&ld;
232 
233 	/* Only 96-bits of precision used */
234 	i0 = plngdbl[0];
235 	i1 = plngdbl[1];
236 	i2 = plngdbl[2];
237 
238 	/*
239 	 * Extract the exponent and check boundary conditions.
240 	 * Notice that the exponent is equal to the bit number where
241 	 * we want the most significant bit to live.
242 	 */
243 	exp = ((i0 >> 16) & 0x7fff) - 0x3fff;
244 	if (exp < 0) {
245 		return ((long long)0); /* abs(x) < 1.0, so round to 0 */
246 	} else if (exp > 63) {
247 		/*
248 		 * abs(x) > MAXLLONG; return {MIN,MAX}ULLONG and as
249 		 * overflow, Inf, NaN set fp_invalid exception
250 		 */
251 		_fp_current_exceptions |= (1 << (int)fp_invalid);
252 		(void) _Q_set_exception(_fp_current_exceptions);
253 		if (i0 < 0)
254 			return ((unsigned long long)LLONG_MIN);
255 		else
256 			return (ULLONG_MAX); /* MAXLONG */
257 	}
258 
259 	/* Extract the mantissa. */
260 
261 	m0 = 0x80000000 | ((i0<<15) & 0x7fff8000) | ((i1>>17) & 0x7fff);
262 	m1 = (i1 << 15) | ((i2 >> 17) & 0x7fff);
263 
264 	/*
265 	 * The most significant bit of the mantissa is now in bit 63 of m0:m1.
266 	 * Shift right by (63 - exp) bits.
267 	 */
268 	switch (exp) {
269 	case 63:
270 		break;
271 	case 31:
272 		m1 = m0;
273 		m0 = 0;
274 		break;
275 	default:
276 		if (exp > 31) {
277 			m1 = (m0 << (exp - 31)) | (m1 >> (63 - exp));
278 			m0 = (m0 >> (63 - exp));
279 		} else {
280 			m1 = (m0 >> (31 - exp));
281 			m0 = 0;
282 		}
283 		break;
284 	}
285 
286 	if (i0 < 0) {
287 		if ((int)m0 < 0) {	/* x < MINLLONG; return MINLLONG */
288 			m0 = 0x80000000;
289 			m1 = 0;
290 		} else {
291 			m0 = ~m0;
292 			m1 = ~m1;
293 			if (++m1 == 0)
294 				m0++;
295 		}
296 	}
297 
298 	(void) _Q_set_exception(_fp_current_exceptions);
299 	return (((unsigned long long)m0 << 32) | m1);
300 }
301