xref: /illumos-gate/usr/src/lib/libc/port/fp/__flt_decim.c (revision 1da57d55)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7257d1b4Sraf  * Common Development and Distribution License (the "License").
6*7257d1b4Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*7257d1b4Sraf 
227c478bd9Sstevel@tonic-gate /*
23*7257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * Short cut for conversion from double precision to decimal
297c478bd9Sstevel@tonic-gate  * floating point
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
32*7257d1b4Sraf #include "lint.h"
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
357c478bd9Sstevel@tonic-gate #include "base_conversion.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * Powers of ten rounded up.  If i is the largest index such that
397c478bd9Sstevel@tonic-gate  * tbl_decade[i] <= x, then:
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  *  if i == 0 then x < 10^-49
427c478bd9Sstevel@tonic-gate  *  else if i == TBL_DECADE_MAX then x >= 10^67
437c478bd9Sstevel@tonic-gate  *  else 10^(i-TBL_DECADE_OFFSET) <= x < 10^(i-TBL_DECADE_OFFSET+1)
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #define	TBL_DECADE_OFFSET	50
477c478bd9Sstevel@tonic-gate #define	TBL_DECADE_MAX		117
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate static const double tbl_decade[TBL_DECADE_MAX + 1] = {
507c478bd9Sstevel@tonic-gate 	0.0,
517c478bd9Sstevel@tonic-gate 	1.00000000000000012631e-49, 1.00000000000000012631e-48,
527c478bd9Sstevel@tonic-gate 	1.00000000000000009593e-47, 1.00000000000000002300e-46,
537c478bd9Sstevel@tonic-gate 	1.00000000000000013968e-45, 1.00000000000000007745e-44,
547c478bd9Sstevel@tonic-gate 	1.00000000000000007745e-43, 1.00000000000000003762e-42,
557c478bd9Sstevel@tonic-gate 	1.00000000000000000576e-41, 1.00000000000000013321e-40,
567c478bd9Sstevel@tonic-gate 	1.00000000000000009243e-39, 1.00000000000000009243e-38,
577c478bd9Sstevel@tonic-gate 	1.00000000000000006632e-37, 1.00000000000000010809e-36,
587c478bd9Sstevel@tonic-gate 	1.00000000000000000786e-35, 1.00000000000000014150e-34,
597c478bd9Sstevel@tonic-gate 	1.00000000000000005597e-33, 1.00000000000000005597e-32,
607c478bd9Sstevel@tonic-gate 	1.00000000000000008334e-31, 1.00000000000000008334e-30,
617c478bd9Sstevel@tonic-gate 	1.00000000000000008334e-29, 1.00000000000000008334e-28,
627c478bd9Sstevel@tonic-gate 	1.00000000000000003849e-27, 1.00000000000000003849e-26,
637c478bd9Sstevel@tonic-gate 	1.00000000000000003849e-25, 1.00000000000000010737e-24,
647c478bd9Sstevel@tonic-gate 	1.00000000000000010737e-23, 1.00000000000000004860e-22,
657c478bd9Sstevel@tonic-gate 	1.00000000000000009562e-21, 1.00000000000000009562e-20,
667c478bd9Sstevel@tonic-gate 	1.00000000000000009562e-19, 1.00000000000000007154e-18,
677c478bd9Sstevel@tonic-gate 	1.00000000000000007154e-17, 1.00000000000000010236e-16,
687c478bd9Sstevel@tonic-gate 	1.00000000000000007771e-15, 1.00000000000000015659e-14,
697c478bd9Sstevel@tonic-gate 	1.00000000000000003037e-13, 1.00000000000000018184e-12,
707c478bd9Sstevel@tonic-gate 	1.00000000000000010106e-11, 1.00000000000000003643e-10,
717c478bd9Sstevel@tonic-gate 	1.00000000000000006228e-09, 1.00000000000000002092e-08,
727c478bd9Sstevel@tonic-gate 	1.00000000000000008710e-07, 1.00000000000000016651e-06,
737c478bd9Sstevel@tonic-gate 	1.00000000000000008180e-05, 1.00000000000000004792e-04,
747c478bd9Sstevel@tonic-gate 	1.00000000000000002082e-03, 1.00000000000000002082e-02,
757c478bd9Sstevel@tonic-gate 	1.00000000000000005551e-01, 1.00000000000000000000e+00,
767c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+01, 1.00000000000000000000e+02,
777c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+03, 1.00000000000000000000e+04,
787c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+05, 1.00000000000000000000e+06,
797c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+07, 1.00000000000000000000e+08,
807c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+09, 1.00000000000000000000e+10,
817c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+11, 1.00000000000000000000e+12,
827c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+13, 1.00000000000000000000e+14,
837c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+15, 1.00000000000000000000e+16,
847c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+17, 1.00000000000000000000e+18,
857c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+19, 1.00000000000000000000e+20,
867c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+21, 1.00000000000000000000e+22,
877c478bd9Sstevel@tonic-gate 	1.00000000000000008389e+23, 1.00000000000000011744e+24,
887c478bd9Sstevel@tonic-gate 	1.00000000000000009060e+25, 1.00000000000000004765e+26,
897c478bd9Sstevel@tonic-gate 	1.00000000000000001329e+27, 1.00000000000000017821e+28,
907c478bd9Sstevel@tonic-gate 	1.00000000000000009025e+29, 1.00000000000000001988e+30,
917c478bd9Sstevel@tonic-gate 	1.00000000000000007618e+31, 1.00000000000000005366e+32,
927c478bd9Sstevel@tonic-gate 	1.00000000000000008969e+33, 1.00000000000000006087e+34,
937c478bd9Sstevel@tonic-gate 	1.00000000000000015310e+35, 1.00000000000000004242e+36,
947c478bd9Sstevel@tonic-gate 	1.00000000000000007194e+37, 1.00000000000000016638e+38,
957c478bd9Sstevel@tonic-gate 	1.00000000000000009082e+39, 1.00000000000000003038e+40,
967c478bd9Sstevel@tonic-gate 	1.00000000000000000620e+41, 1.00000000000000004489e+42,
977c478bd9Sstevel@tonic-gate 	1.00000000000000001394e+43, 1.00000000000000008821e+44,
987c478bd9Sstevel@tonic-gate 	1.00000000000000008821e+45, 1.00000000000000011990e+46,
997c478bd9Sstevel@tonic-gate 	1.00000000000000004385e+47, 1.00000000000000004385e+48,
1007c478bd9Sstevel@tonic-gate 	1.00000000000000007630e+49, 1.00000000000000007630e+50,
1017c478bd9Sstevel@tonic-gate 	1.00000000000000015937e+51, 1.00000000000000012614e+52,
1027c478bd9Sstevel@tonic-gate 	1.00000000000000020590e+53, 1.00000000000000007829e+54,
1037c478bd9Sstevel@tonic-gate 	1.00000000000000001024e+55, 1.00000000000000009190e+56,
1047c478bd9Sstevel@tonic-gate 	1.00000000000000004835e+57, 1.00000000000000008319e+58,
1057c478bd9Sstevel@tonic-gate 	1.00000000000000008319e+59, 1.00000000000000012779e+60,
1067c478bd9Sstevel@tonic-gate 	1.00000000000000009211e+61, 1.00000000000000003502e+62,
1077c478bd9Sstevel@tonic-gate 	1.00000000000000005786e+63, 1.00000000000000002132e+64,
1087c478bd9Sstevel@tonic-gate 	1.00000000000000010901e+65, 1.00000000000000013239e+66,
1097c478bd9Sstevel@tonic-gate 	1.00000000000000013239e+67
1107c478bd9Sstevel@tonic-gate };
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * Convert a positive double precision integer x <= 2147483647999999744
1147c478bd9Sstevel@tonic-gate  * (the largest double less than 2^31 * 10^9; this implementation works
1157c478bd9Sstevel@tonic-gate  * up to the largest double less than 2^25 * 10^12) to a string of ASCII
1167c478bd9Sstevel@tonic-gate  * decimal digits, adding leading zeroes so that the result has at least
1177c478bd9Sstevel@tonic-gate  * n digits.  The string is terminated by a null byte, and its length
1187c478bd9Sstevel@tonic-gate  * is returned.
1197c478bd9Sstevel@tonic-gate  *
1207c478bd9Sstevel@tonic-gate  * This routine assumes round-to-nearest mode is in effect and any
1217c478bd9Sstevel@tonic-gate  * exceptions raised will be ignored.
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate #define	tenm4	tbl_decade[TBL_DECADE_OFFSET - 4]
1257c478bd9Sstevel@tonic-gate #define	ten4	tbl_decade[TBL_DECADE_OFFSET + 4]
1267c478bd9Sstevel@tonic-gate #define	tenm12	tbl_decade[TBL_DECADE_OFFSET - 12]
1277c478bd9Sstevel@tonic-gate #define	ten12	tbl_decade[TBL_DECADE_OFFSET + 12]
1287c478bd9Sstevel@tonic-gate #define	one	tbl_decade[TBL_DECADE_OFFSET]
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate static int
__double_to_digits(double x,char * s,int n)1317c478bd9Sstevel@tonic-gate __double_to_digits(double x, char *s, int n)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	double		y;
1347c478bd9Sstevel@tonic-gate 	int		d[5], i, j;
1357c478bd9Sstevel@tonic-gate 	char		*ss, tmp[4];
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/* decompose x into four-digit chunks */
1387c478bd9Sstevel@tonic-gate 	y = (int)(x * tenm12);
1397c478bd9Sstevel@tonic-gate 	x -= y * ten12;
1407c478bd9Sstevel@tonic-gate 	if (x < 0.0) {
1417c478bd9Sstevel@tonic-gate 		y -= one;
1427c478bd9Sstevel@tonic-gate 		x += ten12;
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate 	d[0] = (int)(y * tenm4);
1457c478bd9Sstevel@tonic-gate 	d[1] = (int)(y - d[0] * ten4);
1467c478bd9Sstevel@tonic-gate 	y = (int)(x * tenm4);
1477c478bd9Sstevel@tonic-gate 	d[4] = (int)(x - y * ten4);
1487c478bd9Sstevel@tonic-gate 	d[2] = (int)(y * tenm4);
1497c478bd9Sstevel@tonic-gate 	d[3] = (int)(y - d[2] * ten4);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	/*
1527c478bd9Sstevel@tonic-gate 	 * Find the first nonzero chunk or the point at which to start
1537c478bd9Sstevel@tonic-gate 	 * converting so we have n digits, whichever comes first.
1547c478bd9Sstevel@tonic-gate 	 */
1557c478bd9Sstevel@tonic-gate 	ss = s;
1567c478bd9Sstevel@tonic-gate 	if (n > 20) {
1577c478bd9Sstevel@tonic-gate 		for (j = 0; j < n - 20; j++)
1587c478bd9Sstevel@tonic-gate 			*ss++ = '0';
1597c478bd9Sstevel@tonic-gate 		i = 0;
1607c478bd9Sstevel@tonic-gate 	} else {
1617c478bd9Sstevel@tonic-gate 		for (i = 0; d[i] == 0 && n <= ((4 - i) << 2); i++)
1627c478bd9Sstevel@tonic-gate 			;
1637c478bd9Sstevel@tonic-gate 		__four_digits_quick(d[i], tmp);
1647c478bd9Sstevel@tonic-gate 		for (j = 0; tmp[j] == '0' && n <= ((4 - i) << 2) + 3 - j; j++)
1657c478bd9Sstevel@tonic-gate 			;
1667c478bd9Sstevel@tonic-gate 		while (j < 4)
1677c478bd9Sstevel@tonic-gate 			*ss++ = tmp[j++];
1687c478bd9Sstevel@tonic-gate 		i++;
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	/* continue converting four-digit chunks */
1727c478bd9Sstevel@tonic-gate 	while (i < 5) {
1737c478bd9Sstevel@tonic-gate 		__four_digits_quick(d[i], ss);
1747c478bd9Sstevel@tonic-gate 		ss += 4;
1757c478bd9Sstevel@tonic-gate 		i++;
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	*ss = '\0';
1797c478bd9Sstevel@tonic-gate 	return (ss - s);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate  * Round a positive double precision number *x to the nearest integer,
1847c478bd9Sstevel@tonic-gate  * returning the result and passing back an indication of accuracy in
1857c478bd9Sstevel@tonic-gate  * *pe.  On entry, nrx is the number of rounding errors already com-
1867c478bd9Sstevel@tonic-gate  * mitted in forming *x.  On exit, *pe is 0 if *x was already integral
1877c478bd9Sstevel@tonic-gate  * and exact, 1 if the result is the correctly rounded integer value
1887c478bd9Sstevel@tonic-gate  * but not exact, and 2 if error in *x precludes determining the cor-
1897c478bd9Sstevel@tonic-gate  * rectly rounded integer value (i.e., the error might be larger than
1907c478bd9Sstevel@tonic-gate  * 1/2 - |*x - rx|, where rx is the nearest integer to *x).
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate static union {
1947c478bd9Sstevel@tonic-gate 	unsigned int	i[2];
1957c478bd9Sstevel@tonic-gate 	double		d;
1967c478bd9Sstevel@tonic-gate } C[] = {
1977c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
1987c478bd9Sstevel@tonic-gate 	{ 0x00000000, 0x43300000 },
1997c478bd9Sstevel@tonic-gate 	{ 0x00000000, 0x3ca00000 },
2007c478bd9Sstevel@tonic-gate 	{ 0x00000000, 0x3fe00000 },
2017c478bd9Sstevel@tonic-gate 	{ 0xffffffff, 0x3fdfffff },
2027c478bd9Sstevel@tonic-gate #else
2037c478bd9Sstevel@tonic-gate 	{ 0x43300000, 0x00000000 },
2047c478bd9Sstevel@tonic-gate 	{ 0x3ca00000, 0x00000000 },
2057c478bd9Sstevel@tonic-gate 	{ 0x3fe00000, 0x00000000 },
2067c478bd9Sstevel@tonic-gate 	{ 0x3fdfffff, 0xffffffff },	/* nextafter(1/2, 0) */
2077c478bd9Sstevel@tonic-gate #endif
2087c478bd9Sstevel@tonic-gate };
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate #define	two52	C[0].d
2117c478bd9Sstevel@tonic-gate #define	twom53	C[1].d
2127c478bd9Sstevel@tonic-gate #define	half	C[2].d
2137c478bd9Sstevel@tonic-gate #define	halfdec	C[3].d
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate static double
__arint_set_n(double * x,int nrx,int * pe)2167c478bd9Sstevel@tonic-gate __arint_set_n(double *x, int nrx, int *pe)
2177c478bd9Sstevel@tonic-gate {
2187c478bd9Sstevel@tonic-gate 	int	hx;
2197c478bd9Sstevel@tonic-gate 	double	rx, rmx;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
2227c478bd9Sstevel@tonic-gate 	hx = *(1+(int *)x);
2237c478bd9Sstevel@tonic-gate #else
2247c478bd9Sstevel@tonic-gate 	hx = *(int *)x;
2257c478bd9Sstevel@tonic-gate #endif
2267c478bd9Sstevel@tonic-gate 	if (hx >= 0x43300000) {
2277c478bd9Sstevel@tonic-gate 		/* x >= 2^52, so it's already integral */
2287c478bd9Sstevel@tonic-gate 		if (nrx == 0)
2297c478bd9Sstevel@tonic-gate 			*pe = 0;
2307c478bd9Sstevel@tonic-gate 		else if (nrx == 1 && hx < 0x43400000)
2317c478bd9Sstevel@tonic-gate 			*pe = 1;
2327c478bd9Sstevel@tonic-gate 		else
2337c478bd9Sstevel@tonic-gate 			*pe = 2;
2347c478bd9Sstevel@tonic-gate 		return (*x);
2357c478bd9Sstevel@tonic-gate 	} else if (hx < 0x3fe00000) {
2367c478bd9Sstevel@tonic-gate 		/* x < 1/2 */
2377c478bd9Sstevel@tonic-gate 		if (nrx > 1 && hx == 0x3fdfffff)
2387c478bd9Sstevel@tonic-gate 			*pe = (*x == halfdec)? 2 : 1;
2397c478bd9Sstevel@tonic-gate 		else
2407c478bd9Sstevel@tonic-gate 			*pe = 1;
2417c478bd9Sstevel@tonic-gate 		return (0.0);
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	rx = (*x + two52) - two52;
2457c478bd9Sstevel@tonic-gate 	if (nrx == 0) {
2467c478bd9Sstevel@tonic-gate 		*pe = (rx == *x)? 0 : 1;
2477c478bd9Sstevel@tonic-gate 	} else {
2487c478bd9Sstevel@tonic-gate 		rmx = rx - *x;
2497c478bd9Sstevel@tonic-gate 		if (rmx < 0.0)
2507c478bd9Sstevel@tonic-gate 			rmx = -rmx;
2517c478bd9Sstevel@tonic-gate 		*pe = (nrx * twom53 * *x < half - rmx)? 1 : 2;
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 	return (rx);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate /*
2577c478bd9Sstevel@tonic-gate  * Attempt to convert dd to a decimal record *pd according to the
2587c478bd9Sstevel@tonic-gate  * modes in *pm using double precision floating point.  Return zero
2597c478bd9Sstevel@tonic-gate  * and sets *ps to reflect any exceptions incurred if successful.
2607c478bd9Sstevel@tonic-gate  * Return a nonzero value if unsuccessful.
2617c478bd9Sstevel@tonic-gate  */
2627c478bd9Sstevel@tonic-gate int
__fast_double_to_decimal(double * dd,decimal_mode * pm,decimal_record * pd,fp_exception_field_type * ps)2637c478bd9Sstevel@tonic-gate __fast_double_to_decimal(double *dd, decimal_mode *pm, decimal_record *pd,
2647c478bd9Sstevel@tonic-gate     fp_exception_field_type *ps)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate 	int			i, is, esum, eround, hd;
2677c478bd9Sstevel@tonic-gate 	double			dds;
2687c478bd9Sstevel@tonic-gate 	__ieee_flags_type	fb;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	if (pm->rd != fp_nearest)
2717c478bd9Sstevel@tonic-gate 		return (1);
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	if (pm->df == fixed_form) {
2747c478bd9Sstevel@tonic-gate 		/* F format */
2757c478bd9Sstevel@tonic-gate 		if (pm->ndigits < 0 || pm->ndigits > __TBL_TENS_MAX)
2767c478bd9Sstevel@tonic-gate 			return (1);
2777c478bd9Sstevel@tonic-gate 		__get_ieee_flags(&fb);
2787c478bd9Sstevel@tonic-gate 		dds = __dabs(dd);
2797c478bd9Sstevel@tonic-gate 		esum = 0;
2807c478bd9Sstevel@tonic-gate 		if (pm->ndigits) {
2817c478bd9Sstevel@tonic-gate 			/* scale by a positive power of ten */
2827c478bd9Sstevel@tonic-gate 			if (pm->ndigits > __TBL_TENS_EXACT) {
2837c478bd9Sstevel@tonic-gate 				dds *= __tbl_tens[pm->ndigits];
2847c478bd9Sstevel@tonic-gate 				esum = 2;
2857c478bd9Sstevel@tonic-gate 			} else {
2867c478bd9Sstevel@tonic-gate 				dds = __mul_set(dds, __tbl_tens[pm->ndigits],
2877c478bd9Sstevel@tonic-gate 				    &eround);
2887c478bd9Sstevel@tonic-gate 				esum = eround;
2897c478bd9Sstevel@tonic-gate 			}
2907c478bd9Sstevel@tonic-gate 		}
2917c478bd9Sstevel@tonic-gate 		if (dds > 2147483647999999744.0) {
2927c478bd9Sstevel@tonic-gate 			__set_ieee_flags(&fb);
2937c478bd9Sstevel@tonic-gate 			return (1);
2947c478bd9Sstevel@tonic-gate 		}
2957c478bd9Sstevel@tonic-gate 		dds = __arint_set_n(&dds, esum, &eround);
2967c478bd9Sstevel@tonic-gate 		if (eround == 2) {
2977c478bd9Sstevel@tonic-gate 			/* error is too large to round reliably; punt */
2987c478bd9Sstevel@tonic-gate 			__set_ieee_flags(&fb);
2997c478bd9Sstevel@tonic-gate 			return (1);
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 		if (dds == 0.0) {
3027c478bd9Sstevel@tonic-gate 			is = (pm->ndigits > 0)? pm->ndigits : 1;
3037c478bd9Sstevel@tonic-gate 			for (i = 0; i < is; i++)
3047c478bd9Sstevel@tonic-gate 				pd->ds[i] = '0';
3057c478bd9Sstevel@tonic-gate 			pd->ds[is] = '\0';
3067c478bd9Sstevel@tonic-gate 			eround++;
3077c478bd9Sstevel@tonic-gate 		} else {
3087c478bd9Sstevel@tonic-gate 			is = __double_to_digits(dds, pd->ds, pm->ndigits);
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 		pd->ndigits = is;
3117c478bd9Sstevel@tonic-gate 		pd->exponent = -pm->ndigits;
3127c478bd9Sstevel@tonic-gate 	} else {
3137c478bd9Sstevel@tonic-gate 		/* E format */
3147c478bd9Sstevel@tonic-gate 		if (pm->ndigits < 1 || pm->ndigits > 18)
3157c478bd9Sstevel@tonic-gate 			return (1);
3167c478bd9Sstevel@tonic-gate 		__get_ieee_flags(&fb);
3177c478bd9Sstevel@tonic-gate 		dds = __dabs(dd);
3187c478bd9Sstevel@tonic-gate 		/* find the decade containing dds */
3197c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
3207c478bd9Sstevel@tonic-gate 		hd = *(1+(int *)dd);
3217c478bd9Sstevel@tonic-gate #else
3227c478bd9Sstevel@tonic-gate 		hd = *(int *)dd;
3237c478bd9Sstevel@tonic-gate #endif
3247c478bd9Sstevel@tonic-gate 		hd = (hd >> 20) & 0x7ff;
3257c478bd9Sstevel@tonic-gate 		if (hd >= 0x400) {
3267c478bd9Sstevel@tonic-gate 			if (hd > 0x4e0)
3277c478bd9Sstevel@tonic-gate 				i = TBL_DECADE_MAX;
3287c478bd9Sstevel@tonic-gate 			else
3297c478bd9Sstevel@tonic-gate 				i = TBL_DECADE_MAX - ((0x4e0 - hd) >> 2);
3307c478bd9Sstevel@tonic-gate 		} else {
3317c478bd9Sstevel@tonic-gate 			if (hd < 0x358)
3327c478bd9Sstevel@tonic-gate 				i = 0;
3337c478bd9Sstevel@tonic-gate 			else
3347c478bd9Sstevel@tonic-gate 				i = TBL_DECADE_OFFSET - ((0x3ff - hd) >> 2);
3357c478bd9Sstevel@tonic-gate 		}
3367c478bd9Sstevel@tonic-gate 		while (dds < tbl_decade[i])
3377c478bd9Sstevel@tonic-gate 			i--;
3387c478bd9Sstevel@tonic-gate 		/* determine the power of ten by which to scale */
3397c478bd9Sstevel@tonic-gate 		i = pm->ndigits - 1 - (i - TBL_DECADE_OFFSET);
3407c478bd9Sstevel@tonic-gate 		esum = 0;
3417c478bd9Sstevel@tonic-gate 		if (i > 0) {
3427c478bd9Sstevel@tonic-gate 			/* scale by a positive power of ten */
3437c478bd9Sstevel@tonic-gate 			if (i > __TBL_TENS_EXACT) {
3447c478bd9Sstevel@tonic-gate 				if (i > __TBL_TENS_MAX) {
3457c478bd9Sstevel@tonic-gate 					__set_ieee_flags(&fb);
3467c478bd9Sstevel@tonic-gate 					return (1);
3477c478bd9Sstevel@tonic-gate 				}
3487c478bd9Sstevel@tonic-gate 				dds *= __tbl_tens[i];
3497c478bd9Sstevel@tonic-gate 				esum = 2;
3507c478bd9Sstevel@tonic-gate 			} else {
3517c478bd9Sstevel@tonic-gate 				dds = __mul_set(dds, __tbl_tens[i], &eround);
3527c478bd9Sstevel@tonic-gate 				esum = eround;
3537c478bd9Sstevel@tonic-gate 			}
3547c478bd9Sstevel@tonic-gate 		} else if (i < 0) {
3557c478bd9Sstevel@tonic-gate 			/* scale by a negative power of ten */
3567c478bd9Sstevel@tonic-gate 			if (-i > __TBL_TENS_EXACT) {
3577c478bd9Sstevel@tonic-gate 				if (-i > __TBL_TENS_MAX) {
3587c478bd9Sstevel@tonic-gate 					__set_ieee_flags(&fb);
3597c478bd9Sstevel@tonic-gate 					return (1);
3607c478bd9Sstevel@tonic-gate 				}
3617c478bd9Sstevel@tonic-gate 				dds /= __tbl_tens[-i];
3627c478bd9Sstevel@tonic-gate 				esum = 2;
3637c478bd9Sstevel@tonic-gate 			} else {
3647c478bd9Sstevel@tonic-gate 				dds = __div_set(dds, __tbl_tens[-i], &eround);
3657c478bd9Sstevel@tonic-gate 				esum = eround;
3667c478bd9Sstevel@tonic-gate 			}
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 		dds = __arint_set_n(&dds, esum, &eround);
3697c478bd9Sstevel@tonic-gate 		if (eround == 2) {
3707c478bd9Sstevel@tonic-gate 			/* error is too large to round reliably; punt */
3717c478bd9Sstevel@tonic-gate 			__set_ieee_flags(&fb);
3727c478bd9Sstevel@tonic-gate 			return (1);
3737c478bd9Sstevel@tonic-gate 		}
3747c478bd9Sstevel@tonic-gate 		is = __double_to_digits(dds, pd->ds, 1);
3757c478bd9Sstevel@tonic-gate 		if (is > pm->ndigits) {
3767c478bd9Sstevel@tonic-gate 			/*
3777c478bd9Sstevel@tonic-gate 			 * The result rounded up to the next larger power
3787c478bd9Sstevel@tonic-gate 			 * of ten; just discard the last zero and adjust
3797c478bd9Sstevel@tonic-gate 			 * the exponent.
3807c478bd9Sstevel@tonic-gate 			 */
3817c478bd9Sstevel@tonic-gate 			pd->ds[--is] = '\0';
3827c478bd9Sstevel@tonic-gate 			i--;
3837c478bd9Sstevel@tonic-gate 		}
3847c478bd9Sstevel@tonic-gate 		pd->ndigits = is;
3857c478bd9Sstevel@tonic-gate 		pd->exponent = -i;
3867c478bd9Sstevel@tonic-gate 	}
3877c478bd9Sstevel@tonic-gate 	*ps = (eround == 0)? 0 : (1 << fp_inexact);
3887c478bd9Sstevel@tonic-gate 	__set_ieee_flags(&fb);
3897c478bd9Sstevel@tonic-gate 	return (0);
3907c478bd9Sstevel@tonic-gate }
391