xref: /onnv-gate/usr/src/lib/libc/port/fp/aconvert.c (revision 8378:27908cc5841e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56812Sraf  * Common Development and Distribution License (the "License").
66812Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
216812Sraf 
220Sstevel@tonic-gate /*
236812Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
276812Sraf #include "lint.h"
280Sstevel@tonic-gate #include "base_conversion.h"
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /* translation table from hex values to hex chars */
310Sstevel@tonic-gate static const char *hexchar = "0123456789abcdef";
320Sstevel@tonic-gate 
330Sstevel@tonic-gate /*
340Sstevel@tonic-gate  * Convert arg to a hexadecimal string.
350Sstevel@tonic-gate  *
360Sstevel@tonic-gate  * If arg is finite and nonzero, buf is filled with ndigits hexadecimal
370Sstevel@tonic-gate  * digits, representing the significand of arg, followed by a null byte
380Sstevel@tonic-gate  * (so ndigits must be at least 1 and buf must be large enough to hold
390Sstevel@tonic-gate  * ndigits + 1 characters).  If ndigits is large enough, the representa-
400Sstevel@tonic-gate  * tion is exact; otherwise, the value is rounded according to the pre-
410Sstevel@tonic-gate  * vailing rounding mode to fit the requested number of digits.  Either
420Sstevel@tonic-gate  * way, the result is normalized so that the first digit is '1'.  The
430Sstevel@tonic-gate  * corresponding base two exponent is passed back in *exp.
440Sstevel@tonic-gate  *
450Sstevel@tonic-gate  * If arg is zero, buf is filled with ndigits zeros followed by a null,
460Sstevel@tonic-gate  * and *exp is set to zero.  If arg is infinite or NaN, __infnanstring
470Sstevel@tonic-gate  * is called to place an appropriate string in buf, and *exp is set to
480Sstevel@tonic-gate  * zero.
490Sstevel@tonic-gate  *
500Sstevel@tonic-gate  * Regardless of the value of arg, its sign bit is stored in *sign.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #if defined(__sparc)
540Sstevel@tonic-gate 
550Sstevel@tonic-gate void
__aconvert(double arg,int ndigits,int * exp,int * sign,char * buf)560Sstevel@tonic-gate __aconvert(double arg, int ndigits, int *exp, int *sign, char *buf)
570Sstevel@tonic-gate {
580Sstevel@tonic-gate 	union {
590Sstevel@tonic-gate 		unsigned int	i[2];
600Sstevel@tonic-gate 		long long	l;
610Sstevel@tonic-gate 		double		d;
620Sstevel@tonic-gate 	} a, c;
630Sstevel@tonic-gate 	int		ha, i, s;
640Sstevel@tonic-gate 	unsigned int	d;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	a.d = arg;
670Sstevel@tonic-gate 	*sign = s = a.i[0] >> 31;
680Sstevel@tonic-gate 	ha = a.i[0] & ~0x80000000;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	/* check for infinity or nan */
710Sstevel@tonic-gate 	if (ha >= 0x7ff00000) {
720Sstevel@tonic-gate 		*exp = 0;
730Sstevel@tonic-gate 		__infnanstring((ha == 0x7ff00000 && a.i[1] == 0)?
740Sstevel@tonic-gate 		    fp_infinity : fp_quiet, ndigits, buf);
750Sstevel@tonic-gate 		return;
760Sstevel@tonic-gate 	}
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	/* check for subnormal or zero */
790Sstevel@tonic-gate 	if (ha < 0x00100000) {
800Sstevel@tonic-gate 		if ((ha | a.i[1]) == 0) {
810Sstevel@tonic-gate 			*exp = 0;
820Sstevel@tonic-gate 			for (i = 0; i < ndigits; i++)
830Sstevel@tonic-gate 				buf[i] = '0';
840Sstevel@tonic-gate 			buf[ndigits] = '\0';
850Sstevel@tonic-gate 			return;
860Sstevel@tonic-gate 		}
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 		/*
890Sstevel@tonic-gate 		 * Normalize.  It would be much simpler if we could just
900Sstevel@tonic-gate 		 * multiply by a power of two here, but some SPARC imple-
910Sstevel@tonic-gate 		 * mentations would flush the subnormal operand to zero
920Sstevel@tonic-gate 		 * when nonstandard mode is enabled.
930Sstevel@tonic-gate 		 */
940Sstevel@tonic-gate 		a.i[0] = ha;
950Sstevel@tonic-gate 		a.d = (double)a.l;
960Sstevel@tonic-gate 		if (s)
970Sstevel@tonic-gate 			a.d = -a.d;
980Sstevel@tonic-gate 		ha = a.i[0] & ~0x80000000;
990Sstevel@tonic-gate 		*exp = (ha >> 20) - 0x3ff - 1074;
1000Sstevel@tonic-gate 	} else {
1010Sstevel@tonic-gate 		*exp = (ha >> 20) - 0x3ff;
1020Sstevel@tonic-gate 	}
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	if (ndigits < 14) {
1050Sstevel@tonic-gate 		/*
1060Sstevel@tonic-gate 		 * Round the significand at the appropriate bit by adding
1070Sstevel@tonic-gate 		 * and subtracting a power of two.  This will also raise
1080Sstevel@tonic-gate 		 * the inexact exception if anything is rounded off.
1090Sstevel@tonic-gate 		 */
1100Sstevel@tonic-gate 		c.i[0] = (0x43700000 | (s << 31)) - (ndigits << 22);
1110Sstevel@tonic-gate 		c.i[1] = 0;
1120Sstevel@tonic-gate 		a.i[0] = (a.i[0] & 0x800fffff) | 0x3ff00000;
1130Sstevel@tonic-gate 		a.d = (a.d + c.d) - c.d;
1140Sstevel@tonic-gate 		ha = a.i[0] & ~0x80000000;
1150Sstevel@tonic-gate 		if (ha >= 0x40000000)
1160Sstevel@tonic-gate 			(*exp)++;
1170Sstevel@tonic-gate 	}
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	/* convert to hex digits */
1200Sstevel@tonic-gate 	buf[0] = '1';
1210Sstevel@tonic-gate 	d = ha << 12;
1220Sstevel@tonic-gate 	for (i = 1; i < ndigits && i < 6; i++) {
1230Sstevel@tonic-gate 		buf[i] = hexchar[d >> 28];
1240Sstevel@tonic-gate 		d <<= 4;
1250Sstevel@tonic-gate 	}
1260Sstevel@tonic-gate 	d = a.i[1];
1270Sstevel@tonic-gate 	for (; i < ndigits && i < 14; i++) {
1280Sstevel@tonic-gate 		buf[i] = hexchar[d >> 28];
1290Sstevel@tonic-gate 		d <<= 4;
1300Sstevel@tonic-gate 	}
1310Sstevel@tonic-gate 	for (; i < ndigits; i++)
1320Sstevel@tonic-gate 		buf[i] = '0';
1330Sstevel@tonic-gate 	buf[ndigits] = '\0';
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate void
__qaconvert(long double * arg,int ndigits,int * exp,int * sign,char * buf)1370Sstevel@tonic-gate __qaconvert(long double *arg, int ndigits, int *exp, int *sign, char *buf)
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	union {
1400Sstevel@tonic-gate 		unsigned int	i[4];
1410Sstevel@tonic-gate 		long double	q;
1420Sstevel@tonic-gate 	} a;
1430Sstevel@tonic-gate 	enum fp_direction_type	rd;
1440Sstevel@tonic-gate 	int			ha, i, s;
1450Sstevel@tonic-gate 	unsigned int		b, r, d;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	a.q = *arg;
1480Sstevel@tonic-gate 	*sign = a.i[0] >> 31;
149*8378SDouglas.Priest@Sun.COM 	ha = a.i[0] &= ~0x80000000;
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	/* check for infinity or nan */
1520Sstevel@tonic-gate 	if (ha >= 0x7fff0000) {
1530Sstevel@tonic-gate 		*exp = 0;
1540Sstevel@tonic-gate 		__infnanstring((ha == 0x7fff0000 && (a.i[1] | a.i[2] | a.i[3])
1550Sstevel@tonic-gate 		    == 0)? fp_infinity : fp_quiet, ndigits, buf);
1560Sstevel@tonic-gate 		return;
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	/* check for subnormal or zero */
1600Sstevel@tonic-gate 	if (ha < 0x00010000) {
1610Sstevel@tonic-gate 		if ((ha | a.i[1] | a.i[2] | a.i[3]) == 0) {
1620Sstevel@tonic-gate 			*exp = 0;
1630Sstevel@tonic-gate 			for (i = 0; i < ndigits; i++)
1640Sstevel@tonic-gate 				buf[i] = '0';
1650Sstevel@tonic-gate 			buf[ndigits] = '\0';
1660Sstevel@tonic-gate 			return;
1670Sstevel@tonic-gate 		}
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 		/* normalize */
1700Sstevel@tonic-gate 		i = 0;
1710Sstevel@tonic-gate 		while ((a.i[0] | (a.i[1] & 0xffff0000)) == 0) {
1720Sstevel@tonic-gate 			a.i[0] = a.i[1];
1730Sstevel@tonic-gate 			a.i[1] = a.i[2];
1740Sstevel@tonic-gate 			a.i[2] = a.i[3];
1750Sstevel@tonic-gate 			a.i[3] = 0;
1760Sstevel@tonic-gate 			i += 32;
1770Sstevel@tonic-gate 		}
1780Sstevel@tonic-gate 		while ((a.i[0] & 0x7fff0000) == 0) {
1790Sstevel@tonic-gate 			a.i[0] = (a.i[0] << 1) | (a.i[1] >> 31);
1800Sstevel@tonic-gate 			a.i[1] = (a.i[1] << 1) | (a.i[2] >> 31);
1810Sstevel@tonic-gate 			a.i[2] = (a.i[2] << 1) | (a.i[3] >> 31);
1820Sstevel@tonic-gate 			a.i[3] <<= 1;
1830Sstevel@tonic-gate 			i++;
1840Sstevel@tonic-gate 		}
1850Sstevel@tonic-gate 		*exp = -0x3ffe - i;
1860Sstevel@tonic-gate 	} else {
1870Sstevel@tonic-gate 		*exp = (ha >> 16) - 0x3fff;
1880Sstevel@tonic-gate 	}
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	if (ndigits < 29) {
1910Sstevel@tonic-gate 		/*
1920Sstevel@tonic-gate 		 * Round the significand at the appropriate bit using
1930Sstevel@tonic-gate 		 * integer arithmetic.  Explicitly raise the inexact
1940Sstevel@tonic-gate 		 * exception if anything is rounded off.
1950Sstevel@tonic-gate 		 */
196*8378SDouglas.Priest@Sun.COM 		a.i[0] = (a.i[0] & 0xffff) | 0x10000;
1970Sstevel@tonic-gate 		if (ndigits <= 5) {
1980Sstevel@tonic-gate 			/*
1990Sstevel@tonic-gate 			 * i and b are the index and bit position in a.i[]
2000Sstevel@tonic-gate 			 * of the last bit to be retained.  r holds the bits
2010Sstevel@tonic-gate 			 * to be rounded off, left-adjusted and sticky.
2020Sstevel@tonic-gate 			 */
2030Sstevel@tonic-gate 			i = 0;
2040Sstevel@tonic-gate 			s = (5 - ndigits) << 2;
2050Sstevel@tonic-gate 			b = 1 << s;
2060Sstevel@tonic-gate 			r = ((a.i[0] << 1) << (31 - s)) | (a.i[1] >> s);
2070Sstevel@tonic-gate 			if ((a.i[1] & (b - 1)) | a.i[2] | a.i[3])
2080Sstevel@tonic-gate 				r |= 1;
2090Sstevel@tonic-gate 			a.i[0] &= ~(b - 1);
2100Sstevel@tonic-gate 			a.i[1] = a.i[2] = a.i[3] = 0;
2110Sstevel@tonic-gate 		} else if (ndigits <= 13) {
2120Sstevel@tonic-gate 			i = 1;
2130Sstevel@tonic-gate 			s = (13 - ndigits) << 2;
2140Sstevel@tonic-gate 			b = 1 << s;
2150Sstevel@tonic-gate 			r = ((a.i[1] << 1) << (31 - s)) | (a.i[2] >> s);
2160Sstevel@tonic-gate 			if ((a.i[2] & (b - 1)) | a.i[3])
2170Sstevel@tonic-gate 				r |= 1;
2180Sstevel@tonic-gate 			a.i[1] &= ~(b - 1);
2190Sstevel@tonic-gate 			a.i[2] = a.i[3] = 0;
2200Sstevel@tonic-gate 		} else if (ndigits <= 21) {
2210Sstevel@tonic-gate 			i = 2;
2220Sstevel@tonic-gate 			s = (21 - ndigits) << 2;
2230Sstevel@tonic-gate 			b = 1 << s;
2240Sstevel@tonic-gate 			r = ((a.i[2] << 1) << (31 - s)) | (a.i[3] >> s);
2250Sstevel@tonic-gate 			if (a.i[3] & (b - 1))
2260Sstevel@tonic-gate 				r |= 1;
2270Sstevel@tonic-gate 			a.i[2] &= ~(b - 1);
2280Sstevel@tonic-gate 			a.i[3] = 0;
2290Sstevel@tonic-gate 		} else {
2300Sstevel@tonic-gate 			i = 3;
2310Sstevel@tonic-gate 			s = (29 - ndigits) << 2;
2320Sstevel@tonic-gate 			b = 1 << s;
2330Sstevel@tonic-gate 			r = (a.i[3] << 1) << (31 - s);
2340Sstevel@tonic-gate 			a.i[3] &= ~(b - 1);
2350Sstevel@tonic-gate 		}
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 		/* conversion is inexact if r is not zero */
2380Sstevel@tonic-gate 		if (r) {
2390Sstevel@tonic-gate 			__base_conversion_set_exception(
2400Sstevel@tonic-gate 			    (fp_exception_field_type)(1 << fp_inexact));
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 			/* massage the rounding direction based on the sign */
2430Sstevel@tonic-gate 			rd = _QgetRD();
2440Sstevel@tonic-gate 			if (*sign && (rd == fp_positive || rd == fp_negative))
2450Sstevel@tonic-gate 				rd = fp_positive + fp_negative - rd;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 			/* decide whether to round up */
2480Sstevel@tonic-gate 			if (rd == fp_positive || (rd == fp_nearest &&
2490Sstevel@tonic-gate 			    (r > 0x80000000u || (r == 0x80000000u &&
2500Sstevel@tonic-gate 			    (a.i[i] & b))))) {
2510Sstevel@tonic-gate 				a.i[i] += b;
2520Sstevel@tonic-gate 				while (a.i[i] == 0)
2530Sstevel@tonic-gate 					a.i[--i]++;
254*8378SDouglas.Priest@Sun.COM 				if (a.i[0] >= 0x20000)
2550Sstevel@tonic-gate 					(*exp)++;
2560Sstevel@tonic-gate 			}
2570Sstevel@tonic-gate 		}
2580Sstevel@tonic-gate 	}
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	/* convert to hex digits */
2610Sstevel@tonic-gate 	buf[0] = '1';
2620Sstevel@tonic-gate 	d = a.i[0] << 16;
2630Sstevel@tonic-gate 	for (i = 1; i < ndigits && i < 5; i++) {
2640Sstevel@tonic-gate 		buf[i] = hexchar[d >> 28];
2650Sstevel@tonic-gate 		d <<= 4;
2660Sstevel@tonic-gate 	}
2670Sstevel@tonic-gate 	d = a.i[1];
2680Sstevel@tonic-gate 	for (; i < ndigits && i < 13; i++) {
2690Sstevel@tonic-gate 		buf[i] = hexchar[d >> 28];
2700Sstevel@tonic-gate 		d <<= 4;
2710Sstevel@tonic-gate 	}
2720Sstevel@tonic-gate 	d = a.i[2];
2730Sstevel@tonic-gate 	for (; i < ndigits && i < 21; i++) {
2740Sstevel@tonic-gate 		buf[i] = hexchar[d >> 28];
2750Sstevel@tonic-gate 		d <<= 4;
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 	d = a.i[3];
2780Sstevel@tonic-gate 	for (; i < ndigits && i < 29; i++) {
2790Sstevel@tonic-gate 		buf[i] = hexchar[d >> 28];
2800Sstevel@tonic-gate 		d <<= 4;
2810Sstevel@tonic-gate 	}
2820Sstevel@tonic-gate 	for (; i < ndigits; i++)
2830Sstevel@tonic-gate 		buf[i] = '0';
2840Sstevel@tonic-gate 	buf[ndigits] = '\0';
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate #elif defined(__i386) || defined(__amd64)
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate /*
2900Sstevel@tonic-gate  * The following code assumes the rounding precision mode is set
2910Sstevel@tonic-gate  * to the default (round to 64 bits).
2920Sstevel@tonic-gate  */
2930Sstevel@tonic-gate void
__qaconvert(long double * arg,int ndigits,int * exp,int * sign,char * buf)2940Sstevel@tonic-gate __qaconvert(long double *arg, int ndigits, int *exp, int *sign, char *buf)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate 	union {
2970Sstevel@tonic-gate 		unsigned int	i[3];
2980Sstevel@tonic-gate 		long double	x;
2990Sstevel@tonic-gate 	} a, c;
3000Sstevel@tonic-gate 	int		ea, i, s;
3010Sstevel@tonic-gate 	unsigned int	d;
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	a.x = *arg;
3040Sstevel@tonic-gate 	*sign = s = (a.i[2] >> 15) & 1;
3050Sstevel@tonic-gate 	ea = a.i[2] & 0x7fff;
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	/* check for infinity or nan */
3080Sstevel@tonic-gate 	if (ea == 0x7fff) {
3090Sstevel@tonic-gate 		*exp = 0;
3100Sstevel@tonic-gate 		__infnanstring((((a.i[1] << 1) | a.i[0]) == 0)?
3110Sstevel@tonic-gate 		    fp_infinity : fp_quiet, ndigits, buf);
3120Sstevel@tonic-gate 		return;
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	/* check for subnormal or zero */
3160Sstevel@tonic-gate 	if (ea == 0) {
3170Sstevel@tonic-gate 		if ((a.i[1] | a.i[0]) == 0) {
3180Sstevel@tonic-gate 			*exp = 0;
3190Sstevel@tonic-gate 			for (i = 0; i < ndigits; i++)
3200Sstevel@tonic-gate 				buf[i] = '0';
3210Sstevel@tonic-gate 			buf[ndigits] = '\0';
3220Sstevel@tonic-gate 			return;
3230Sstevel@tonic-gate 		}
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 		/* normalize */
3260Sstevel@tonic-gate 		a.x *= 18446744073709551616.0; /* 2^64 */
3270Sstevel@tonic-gate 		ea = a.i[2] & 0x7fff;
3280Sstevel@tonic-gate 		*exp = ea - 0x403f;
3290Sstevel@tonic-gate 	} else {
3300Sstevel@tonic-gate 		*exp = ea - 0x3fff;
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	if (ndigits < 17) {
3340Sstevel@tonic-gate 		/*
3350Sstevel@tonic-gate 		 * Round the significand at the appropriate bit by adding
3360Sstevel@tonic-gate 		 * and subtracting a power of two.  This will also raise
3370Sstevel@tonic-gate 		 * the inexact exception if anything is rounded off.
3380Sstevel@tonic-gate 		 */
3390Sstevel@tonic-gate 		c.i[2] = (0x4042 | (s << 15)) - (ndigits << 2);
3400Sstevel@tonic-gate 		c.i[1] = 0x80000000;
3410Sstevel@tonic-gate 		c.i[0] = 0;
3420Sstevel@tonic-gate 		a.i[2] = 0x3fff | (s << 15);
3430Sstevel@tonic-gate 		a.x = (a.x + c.x) - c.x;
3440Sstevel@tonic-gate 		ea = a.i[2] & 0x7fff;
3450Sstevel@tonic-gate 		if (ea >= 0x4000)
3460Sstevel@tonic-gate 			(*exp)++;
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	/* convert to hex digits */
3500Sstevel@tonic-gate 	buf[0] = '1';
3510Sstevel@tonic-gate 	d = (a.i[1] << 1) | (a.i[0] >> 31);
3520Sstevel@tonic-gate 	for (i = 1; i < ndigits && i < 9; i++) {
3530Sstevel@tonic-gate 		buf[i] = hexchar[d >> 28];
3540Sstevel@tonic-gate 		d <<= 4;
3550Sstevel@tonic-gate 	}
3560Sstevel@tonic-gate 	d = a.i[0] << 1;
3570Sstevel@tonic-gate 	for (; i < ndigits && i < 17; i++) {
3580Sstevel@tonic-gate 		buf[i] = hexchar[d >> 28];
3590Sstevel@tonic-gate 		d <<= 4;
3600Sstevel@tonic-gate 	}
3610Sstevel@tonic-gate 	for (; i < ndigits; i++)
3620Sstevel@tonic-gate 		buf[i] = '0';
3630Sstevel@tonic-gate 	buf[ndigits] = '\0';
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate void
__aconvert(double arg,int ndigits,int * exp,int * sign,char * buf)3670Sstevel@tonic-gate __aconvert(double arg, int ndigits, int *exp, int *sign, char *buf)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate 	union {
3700Sstevel@tonic-gate 		int	i[2];
3710Sstevel@tonic-gate 		double	d;
3720Sstevel@tonic-gate 	} a;
3730Sstevel@tonic-gate 	long double	ldarg;
3740Sstevel@tonic-gate 	int		ha;
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	/* avoid raising invalid operation exception for signaling nan */
3770Sstevel@tonic-gate 	a.i[0] = *(int *)&arg;
3780Sstevel@tonic-gate 	a.i[1] = *(1+(int *)&arg);
3790Sstevel@tonic-gate 	ha = a.i[1] & ~0x80000000;
3800Sstevel@tonic-gate 	if (ha > 0x7ff00000 || (ha == 0x7ff00000 && a.i[0] != 0))
3810Sstevel@tonic-gate 		a.i[1] |= 0x80000; /* make nan quiet */
3820Sstevel@tonic-gate 	ldarg = a.d;
3830Sstevel@tonic-gate 	__qaconvert(&ldarg, ndigits, exp, sign, buf);
3840Sstevel@tonic-gate }
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate #else
3870Sstevel@tonic-gate #error Unknown architecture
3880Sstevel@tonic-gate #endif
389