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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 #include "base_conversion.h"
30 /* translation table from hex values to hex chars */
31 static const char *hexchar
= "0123456789abcdef";
34 * Convert arg to a hexadecimal string.
36 * If arg is finite and nonzero, buf is filled with ndigits hexadecimal
37 * digits, representing the significand of arg, followed by a null byte
38 * (so ndigits must be at least 1 and buf must be large enough to hold
39 * ndigits + 1 characters). If ndigits is large enough, the representa-
40 * tion is exact; otherwise, the value is rounded according to the pre-
41 * vailing rounding mode to fit the requested number of digits. Either
42 * way, the result is normalized so that the first digit is '1'. The
43 * corresponding base two exponent is passed back in *exp.
45 * If arg is zero, buf is filled with ndigits zeros followed by a null,
46 * and *exp is set to zero. If arg is infinite or NaN, __infnanstring
47 * is called to place an appropriate string in buf, and *exp is set to
50 * Regardless of the value of arg, its sign bit is stored in *sign.
56 __aconvert(double arg
, int ndigits
, int *exp
, int *sign
, char *buf
)
67 *sign
= s
= a
.i
[0] >> 31;
68 ha
= a
.i
[0] & ~0x80000000;
70 /* check for infinity or nan */
71 if (ha
>= 0x7ff00000) {
73 __infnanstring((ha
== 0x7ff00000 && a
.i
[1] == 0)?
74 fp_infinity
: fp_quiet
, ndigits
, buf
);
78 /* check for subnormal or zero */
79 if (ha
< 0x00100000) {
80 if ((ha
| a
.i
[1]) == 0) {
82 for (i
= 0; i
< ndigits
; i
++)
89 * Normalize. It would be much simpler if we could just
90 * multiply by a power of two here, but some SPARC imple-
91 * mentations would flush the subnormal operand to zero
92 * when nonstandard mode is enabled.
98 ha
= a
.i
[0] & ~0x80000000;
99 *exp
= (ha
>> 20) - 0x3ff - 1074;
101 *exp
= (ha
>> 20) - 0x3ff;
106 * Round the significand at the appropriate bit by adding
107 * and subtracting a power of two. This will also raise
108 * the inexact exception if anything is rounded off.
110 c
.i
[0] = (0x43700000 | (s
<< 31)) - (ndigits
<< 22);
112 a
.i
[0] = (a
.i
[0] & 0x800fffff) | 0x3ff00000;
113 a
.d
= (a
.d
+ c
.d
) - c
.d
;
114 ha
= a
.i
[0] & ~0x80000000;
115 if (ha
>= 0x40000000)
119 /* convert to hex digits */
122 for (i
= 1; i
< ndigits
&& i
< 6; i
++) {
123 buf
[i
] = hexchar
[d
>> 28];
127 for (; i
< ndigits
&& i
< 14; i
++) {
128 buf
[i
] = hexchar
[d
>> 28];
131 for (; i
< ndigits
; i
++)
137 __qaconvert(long double *arg
, int ndigits
, int *exp
, int *sign
, char *buf
)
143 enum fp_direction_type rd
;
145 unsigned int b
, r
, d
;
148 *sign
= a
.i
[0] >> 31;
149 ha
= a
.i
[0] &= ~0x80000000;
151 /* check for infinity or nan */
152 if (ha
>= 0x7fff0000) {
154 __infnanstring((ha
== 0x7fff0000 && (a
.i
[1] | a
.i
[2] | a
.i
[3])
155 == 0)? fp_infinity
: fp_quiet
, ndigits
, buf
);
159 /* check for subnormal or zero */
160 if (ha
< 0x00010000) {
161 if ((ha
| a
.i
[1] | a
.i
[2] | a
.i
[3]) == 0) {
163 for (i
= 0; i
< ndigits
; i
++)
171 while ((a
.i
[0] | (a
.i
[1] & 0xffff0000)) == 0) {
178 while ((a
.i
[0] & 0x7fff0000) == 0) {
179 a
.i
[0] = (a
.i
[0] << 1) | (a
.i
[1] >> 31);
180 a
.i
[1] = (a
.i
[1] << 1) | (a
.i
[2] >> 31);
181 a
.i
[2] = (a
.i
[2] << 1) | (a
.i
[3] >> 31);
187 *exp
= (ha
>> 16) - 0x3fff;
192 * Round the significand at the appropriate bit using
193 * integer arithmetic. Explicitly raise the inexact
194 * exception if anything is rounded off.
196 a
.i
[0] = (a
.i
[0] & 0xffff) | 0x10000;
199 * i and b are the index and bit position in a.i[]
200 * of the last bit to be retained. r holds the bits
201 * to be rounded off, left-adjusted and sticky.
204 s
= (5 - ndigits
) << 2;
206 r
= ((a
.i
[0] << 1) << (31 - s
)) | (a
.i
[1] >> s
);
207 if ((a
.i
[1] & (b
- 1)) | a
.i
[2] | a
.i
[3])
210 a
.i
[1] = a
.i
[2] = a
.i
[3] = 0;
211 } else if (ndigits
<= 13) {
213 s
= (13 - ndigits
) << 2;
215 r
= ((a
.i
[1] << 1) << (31 - s
)) | (a
.i
[2] >> s
);
216 if ((a
.i
[2] & (b
- 1)) | a
.i
[3])
220 } else if (ndigits
<= 21) {
222 s
= (21 - ndigits
) << 2;
224 r
= ((a
.i
[2] << 1) << (31 - s
)) | (a
.i
[3] >> s
);
225 if (a
.i
[3] & (b
- 1))
231 s
= (29 - ndigits
) << 2;
233 r
= (a
.i
[3] << 1) << (31 - s
);
237 /* conversion is inexact if r is not zero */
239 __base_conversion_set_exception(
240 (fp_exception_field_type
)(1 << fp_inexact
));
242 /* massage the rounding direction based on the sign */
244 if (*sign
&& (rd
== fp_positive
|| rd
== fp_negative
))
245 rd
= fp_positive
+ fp_negative
- rd
;
247 /* decide whether to round up */
248 if (rd
== fp_positive
|| (rd
== fp_nearest
&&
249 (r
> 0x80000000u
|| (r
== 0x80000000u
&&
254 if (a
.i
[0] >= 0x20000)
260 /* convert to hex digits */
263 for (i
= 1; i
< ndigits
&& i
< 5; i
++) {
264 buf
[i
] = hexchar
[d
>> 28];
268 for (; i
< ndigits
&& i
< 13; i
++) {
269 buf
[i
] = hexchar
[d
>> 28];
273 for (; i
< ndigits
&& i
< 21; i
++) {
274 buf
[i
] = hexchar
[d
>> 28];
278 for (; i
< ndigits
&& i
< 29; i
++) {
279 buf
[i
] = hexchar
[d
>> 28];
282 for (; i
< ndigits
; i
++)
287 #elif defined(__i386) || defined(__amd64)
290 * The following code assumes the rounding precision mode is set
291 * to the default (round to 64 bits).
294 __qaconvert(long double *arg
, int ndigits
, int *exp
, int *sign
, char *buf
)
304 *sign
= s
= (a
.i
[2] >> 15) & 1;
305 ea
= a
.i
[2] & 0x7fff;
307 /* check for infinity or nan */
310 __infnanstring((((a
.i
[1] << 1) | a
.i
[0]) == 0)?
311 fp_infinity
: fp_quiet
, ndigits
, buf
);
315 /* check for subnormal or zero */
317 if ((a
.i
[1] | a
.i
[0]) == 0) {
319 for (i
= 0; i
< ndigits
; i
++)
326 a
.x
*= 18446744073709551616.0; /* 2^64 */
327 ea
= a
.i
[2] & 0x7fff;
335 * Round the significand at the appropriate bit by adding
336 * and subtracting a power of two. This will also raise
337 * the inexact exception if anything is rounded off.
339 c
.i
[2] = (0x4042 | (s
<< 15)) - (ndigits
<< 2);
342 a
.i
[2] = 0x3fff | (s
<< 15);
343 a
.x
= (a
.x
+ c
.x
) - c
.x
;
344 ea
= a
.i
[2] & 0x7fff;
349 /* convert to hex digits */
351 d
= (a
.i
[1] << 1) | (a
.i
[0] >> 31);
352 for (i
= 1; i
< ndigits
&& i
< 9; i
++) {
353 buf
[i
] = hexchar
[d
>> 28];
357 for (; i
< ndigits
&& i
< 17; i
++) {
358 buf
[i
] = hexchar
[d
>> 28];
361 for (; i
< ndigits
; i
++)
367 __aconvert(double arg
, int ndigits
, int *exp
, int *sign
, char *buf
)
376 /* avoid raising invalid operation exception for signaling nan */
377 a
.i
[0] = *(int *)&arg
;
378 a
.i
[1] = *(1+(int *)&arg
);
379 ha
= a
.i
[1] & ~0x80000000;
380 if (ha
> 0x7ff00000 || (ha
== 0x7ff00000 && a
.i
[0] != 0))
381 a
.i
[1] |= 0x80000; /* make nan quiet */
383 __qaconvert(&ldarg
, ndigits
, exp
, sign
, buf
);
387 #error Unknown architecture