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