xref: /illumos-gate/usr/src/lib/libc/port/fp/__flt_decim.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Short cut for conversion from double precision to decimal
31*7c478bd9Sstevel@tonic-gate  * floating point
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include "synonyms.h"
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
37*7c478bd9Sstevel@tonic-gate #include "base_conversion.h"
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate /*
40*7c478bd9Sstevel@tonic-gate  * Powers of ten rounded up.  If i is the largest index such that
41*7c478bd9Sstevel@tonic-gate  * tbl_decade[i] <= x, then:
42*7c478bd9Sstevel@tonic-gate  *
43*7c478bd9Sstevel@tonic-gate  *  if i == 0 then x < 10^-49
44*7c478bd9Sstevel@tonic-gate  *  else if i == TBL_DECADE_MAX then x >= 10^67
45*7c478bd9Sstevel@tonic-gate  *  else 10^(i-TBL_DECADE_OFFSET) <= x < 10^(i-TBL_DECADE_OFFSET+1)
46*7c478bd9Sstevel@tonic-gate  */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #define	TBL_DECADE_OFFSET	50
49*7c478bd9Sstevel@tonic-gate #define	TBL_DECADE_MAX		117
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate static const double tbl_decade[TBL_DECADE_MAX + 1] = {
52*7c478bd9Sstevel@tonic-gate 	0.0,
53*7c478bd9Sstevel@tonic-gate 	1.00000000000000012631e-49, 1.00000000000000012631e-48,
54*7c478bd9Sstevel@tonic-gate 	1.00000000000000009593e-47, 1.00000000000000002300e-46,
55*7c478bd9Sstevel@tonic-gate 	1.00000000000000013968e-45, 1.00000000000000007745e-44,
56*7c478bd9Sstevel@tonic-gate 	1.00000000000000007745e-43, 1.00000000000000003762e-42,
57*7c478bd9Sstevel@tonic-gate 	1.00000000000000000576e-41, 1.00000000000000013321e-40,
58*7c478bd9Sstevel@tonic-gate 	1.00000000000000009243e-39, 1.00000000000000009243e-38,
59*7c478bd9Sstevel@tonic-gate 	1.00000000000000006632e-37, 1.00000000000000010809e-36,
60*7c478bd9Sstevel@tonic-gate 	1.00000000000000000786e-35, 1.00000000000000014150e-34,
61*7c478bd9Sstevel@tonic-gate 	1.00000000000000005597e-33, 1.00000000000000005597e-32,
62*7c478bd9Sstevel@tonic-gate 	1.00000000000000008334e-31, 1.00000000000000008334e-30,
63*7c478bd9Sstevel@tonic-gate 	1.00000000000000008334e-29, 1.00000000000000008334e-28,
64*7c478bd9Sstevel@tonic-gate 	1.00000000000000003849e-27, 1.00000000000000003849e-26,
65*7c478bd9Sstevel@tonic-gate 	1.00000000000000003849e-25, 1.00000000000000010737e-24,
66*7c478bd9Sstevel@tonic-gate 	1.00000000000000010737e-23, 1.00000000000000004860e-22,
67*7c478bd9Sstevel@tonic-gate 	1.00000000000000009562e-21, 1.00000000000000009562e-20,
68*7c478bd9Sstevel@tonic-gate 	1.00000000000000009562e-19, 1.00000000000000007154e-18,
69*7c478bd9Sstevel@tonic-gate 	1.00000000000000007154e-17, 1.00000000000000010236e-16,
70*7c478bd9Sstevel@tonic-gate 	1.00000000000000007771e-15, 1.00000000000000015659e-14,
71*7c478bd9Sstevel@tonic-gate 	1.00000000000000003037e-13, 1.00000000000000018184e-12,
72*7c478bd9Sstevel@tonic-gate 	1.00000000000000010106e-11, 1.00000000000000003643e-10,
73*7c478bd9Sstevel@tonic-gate 	1.00000000000000006228e-09, 1.00000000000000002092e-08,
74*7c478bd9Sstevel@tonic-gate 	1.00000000000000008710e-07, 1.00000000000000016651e-06,
75*7c478bd9Sstevel@tonic-gate 	1.00000000000000008180e-05, 1.00000000000000004792e-04,
76*7c478bd9Sstevel@tonic-gate 	1.00000000000000002082e-03, 1.00000000000000002082e-02,
77*7c478bd9Sstevel@tonic-gate 	1.00000000000000005551e-01, 1.00000000000000000000e+00,
78*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+01, 1.00000000000000000000e+02,
79*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+03, 1.00000000000000000000e+04,
80*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+05, 1.00000000000000000000e+06,
81*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+07, 1.00000000000000000000e+08,
82*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+09, 1.00000000000000000000e+10,
83*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+11, 1.00000000000000000000e+12,
84*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+13, 1.00000000000000000000e+14,
85*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+15, 1.00000000000000000000e+16,
86*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+17, 1.00000000000000000000e+18,
87*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+19, 1.00000000000000000000e+20,
88*7c478bd9Sstevel@tonic-gate 	1.00000000000000000000e+21, 1.00000000000000000000e+22,
89*7c478bd9Sstevel@tonic-gate 	1.00000000000000008389e+23, 1.00000000000000011744e+24,
90*7c478bd9Sstevel@tonic-gate 	1.00000000000000009060e+25, 1.00000000000000004765e+26,
91*7c478bd9Sstevel@tonic-gate 	1.00000000000000001329e+27, 1.00000000000000017821e+28,
92*7c478bd9Sstevel@tonic-gate 	1.00000000000000009025e+29, 1.00000000000000001988e+30,
93*7c478bd9Sstevel@tonic-gate 	1.00000000000000007618e+31, 1.00000000000000005366e+32,
94*7c478bd9Sstevel@tonic-gate 	1.00000000000000008969e+33, 1.00000000000000006087e+34,
95*7c478bd9Sstevel@tonic-gate 	1.00000000000000015310e+35, 1.00000000000000004242e+36,
96*7c478bd9Sstevel@tonic-gate 	1.00000000000000007194e+37, 1.00000000000000016638e+38,
97*7c478bd9Sstevel@tonic-gate 	1.00000000000000009082e+39, 1.00000000000000003038e+40,
98*7c478bd9Sstevel@tonic-gate 	1.00000000000000000620e+41, 1.00000000000000004489e+42,
99*7c478bd9Sstevel@tonic-gate 	1.00000000000000001394e+43, 1.00000000000000008821e+44,
100*7c478bd9Sstevel@tonic-gate 	1.00000000000000008821e+45, 1.00000000000000011990e+46,
101*7c478bd9Sstevel@tonic-gate 	1.00000000000000004385e+47, 1.00000000000000004385e+48,
102*7c478bd9Sstevel@tonic-gate 	1.00000000000000007630e+49, 1.00000000000000007630e+50,
103*7c478bd9Sstevel@tonic-gate 	1.00000000000000015937e+51, 1.00000000000000012614e+52,
104*7c478bd9Sstevel@tonic-gate 	1.00000000000000020590e+53, 1.00000000000000007829e+54,
105*7c478bd9Sstevel@tonic-gate 	1.00000000000000001024e+55, 1.00000000000000009190e+56,
106*7c478bd9Sstevel@tonic-gate 	1.00000000000000004835e+57, 1.00000000000000008319e+58,
107*7c478bd9Sstevel@tonic-gate 	1.00000000000000008319e+59, 1.00000000000000012779e+60,
108*7c478bd9Sstevel@tonic-gate 	1.00000000000000009211e+61, 1.00000000000000003502e+62,
109*7c478bd9Sstevel@tonic-gate 	1.00000000000000005786e+63, 1.00000000000000002132e+64,
110*7c478bd9Sstevel@tonic-gate 	1.00000000000000010901e+65, 1.00000000000000013239e+66,
111*7c478bd9Sstevel@tonic-gate 	1.00000000000000013239e+67
112*7c478bd9Sstevel@tonic-gate };
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate /*
115*7c478bd9Sstevel@tonic-gate  * Convert a positive double precision integer x <= 2147483647999999744
116*7c478bd9Sstevel@tonic-gate  * (the largest double less than 2^31 * 10^9; this implementation works
117*7c478bd9Sstevel@tonic-gate  * up to the largest double less than 2^25 * 10^12) to a string of ASCII
118*7c478bd9Sstevel@tonic-gate  * decimal digits, adding leading zeroes so that the result has at least
119*7c478bd9Sstevel@tonic-gate  * n digits.  The string is terminated by a null byte, and its length
120*7c478bd9Sstevel@tonic-gate  * is returned.
121*7c478bd9Sstevel@tonic-gate  *
122*7c478bd9Sstevel@tonic-gate  * This routine assumes round-to-nearest mode is in effect and any
123*7c478bd9Sstevel@tonic-gate  * exceptions raised will be ignored.
124*7c478bd9Sstevel@tonic-gate  */
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate #define	tenm4	tbl_decade[TBL_DECADE_OFFSET - 4]
127*7c478bd9Sstevel@tonic-gate #define	ten4	tbl_decade[TBL_DECADE_OFFSET + 4]
128*7c478bd9Sstevel@tonic-gate #define	tenm12	tbl_decade[TBL_DECADE_OFFSET - 12]
129*7c478bd9Sstevel@tonic-gate #define	ten12	tbl_decade[TBL_DECADE_OFFSET + 12]
130*7c478bd9Sstevel@tonic-gate #define	one	tbl_decade[TBL_DECADE_OFFSET]
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate static int
133*7c478bd9Sstevel@tonic-gate __double_to_digits(double x, char *s, int n)
134*7c478bd9Sstevel@tonic-gate {
135*7c478bd9Sstevel@tonic-gate 	double		y;
136*7c478bd9Sstevel@tonic-gate 	int		d[5], i, j;
137*7c478bd9Sstevel@tonic-gate 	char		*ss, tmp[4];
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	/* decompose x into four-digit chunks */
140*7c478bd9Sstevel@tonic-gate 	y = (int)(x * tenm12);
141*7c478bd9Sstevel@tonic-gate 	x -= y * ten12;
142*7c478bd9Sstevel@tonic-gate 	if (x < 0.0) {
143*7c478bd9Sstevel@tonic-gate 		y -= one;
144*7c478bd9Sstevel@tonic-gate 		x += ten12;
145*7c478bd9Sstevel@tonic-gate 	}
146*7c478bd9Sstevel@tonic-gate 	d[0] = (int)(y * tenm4);
147*7c478bd9Sstevel@tonic-gate 	d[1] = (int)(y - d[0] * ten4);
148*7c478bd9Sstevel@tonic-gate 	y = (int)(x * tenm4);
149*7c478bd9Sstevel@tonic-gate 	d[4] = (int)(x - y * ten4);
150*7c478bd9Sstevel@tonic-gate 	d[2] = (int)(y * tenm4);
151*7c478bd9Sstevel@tonic-gate 	d[3] = (int)(y - d[2] * ten4);
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	/*
154*7c478bd9Sstevel@tonic-gate 	 * Find the first nonzero chunk or the point at which to start
155*7c478bd9Sstevel@tonic-gate 	 * converting so we have n digits, whichever comes first.
156*7c478bd9Sstevel@tonic-gate 	 */
157*7c478bd9Sstevel@tonic-gate 	ss = s;
158*7c478bd9Sstevel@tonic-gate 	if (n > 20) {
159*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < n - 20; j++)
160*7c478bd9Sstevel@tonic-gate 			*ss++ = '0';
161*7c478bd9Sstevel@tonic-gate 		i = 0;
162*7c478bd9Sstevel@tonic-gate 	} else {
163*7c478bd9Sstevel@tonic-gate 		for (i = 0; d[i] == 0 && n <= ((4 - i) << 2); i++)
164*7c478bd9Sstevel@tonic-gate 			;
165*7c478bd9Sstevel@tonic-gate 		__four_digits_quick(d[i], tmp);
166*7c478bd9Sstevel@tonic-gate 		for (j = 0; tmp[j] == '0' && n <= ((4 - i) << 2) + 3 - j; j++)
167*7c478bd9Sstevel@tonic-gate 			;
168*7c478bd9Sstevel@tonic-gate 		while (j < 4)
169*7c478bd9Sstevel@tonic-gate 			*ss++ = tmp[j++];
170*7c478bd9Sstevel@tonic-gate 		i++;
171*7c478bd9Sstevel@tonic-gate 	}
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	/* continue converting four-digit chunks */
174*7c478bd9Sstevel@tonic-gate 	while (i < 5) {
175*7c478bd9Sstevel@tonic-gate 		__four_digits_quick(d[i], ss);
176*7c478bd9Sstevel@tonic-gate 		ss += 4;
177*7c478bd9Sstevel@tonic-gate 		i++;
178*7c478bd9Sstevel@tonic-gate 	}
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	*ss = '\0';
181*7c478bd9Sstevel@tonic-gate 	return (ss - s);
182*7c478bd9Sstevel@tonic-gate }
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate /*
185*7c478bd9Sstevel@tonic-gate  * Round a positive double precision number *x to the nearest integer,
186*7c478bd9Sstevel@tonic-gate  * returning the result and passing back an indication of accuracy in
187*7c478bd9Sstevel@tonic-gate  * *pe.  On entry, nrx is the number of rounding errors already com-
188*7c478bd9Sstevel@tonic-gate  * mitted in forming *x.  On exit, *pe is 0 if *x was already integral
189*7c478bd9Sstevel@tonic-gate  * and exact, 1 if the result is the correctly rounded integer value
190*7c478bd9Sstevel@tonic-gate  * but not exact, and 2 if error in *x precludes determining the cor-
191*7c478bd9Sstevel@tonic-gate  * rectly rounded integer value (i.e., the error might be larger than
192*7c478bd9Sstevel@tonic-gate  * 1/2 - |*x - rx|, where rx is the nearest integer to *x).
193*7c478bd9Sstevel@tonic-gate  */
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate static union {
196*7c478bd9Sstevel@tonic-gate 	unsigned int	i[2];
197*7c478bd9Sstevel@tonic-gate 	double		d;
198*7c478bd9Sstevel@tonic-gate } C[] = {
199*7c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
200*7c478bd9Sstevel@tonic-gate 	{ 0x00000000, 0x43300000 },
201*7c478bd9Sstevel@tonic-gate 	{ 0x00000000, 0x3ca00000 },
202*7c478bd9Sstevel@tonic-gate 	{ 0x00000000, 0x3fe00000 },
203*7c478bd9Sstevel@tonic-gate 	{ 0xffffffff, 0x3fdfffff },
204*7c478bd9Sstevel@tonic-gate #else
205*7c478bd9Sstevel@tonic-gate 	{ 0x43300000, 0x00000000 },
206*7c478bd9Sstevel@tonic-gate 	{ 0x3ca00000, 0x00000000 },
207*7c478bd9Sstevel@tonic-gate 	{ 0x3fe00000, 0x00000000 },
208*7c478bd9Sstevel@tonic-gate 	{ 0x3fdfffff, 0xffffffff },	/* nextafter(1/2, 0) */
209*7c478bd9Sstevel@tonic-gate #endif
210*7c478bd9Sstevel@tonic-gate };
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate #define	two52	C[0].d
213*7c478bd9Sstevel@tonic-gate #define	twom53	C[1].d
214*7c478bd9Sstevel@tonic-gate #define	half	C[2].d
215*7c478bd9Sstevel@tonic-gate #define	halfdec	C[3].d
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate static double
218*7c478bd9Sstevel@tonic-gate __arint_set_n(double *x, int nrx, int *pe)
219*7c478bd9Sstevel@tonic-gate {
220*7c478bd9Sstevel@tonic-gate 	int	hx;
221*7c478bd9Sstevel@tonic-gate 	double	rx, rmx;
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
224*7c478bd9Sstevel@tonic-gate 	hx = *(1+(int *)x);
225*7c478bd9Sstevel@tonic-gate #else
226*7c478bd9Sstevel@tonic-gate 	hx = *(int *)x;
227*7c478bd9Sstevel@tonic-gate #endif
228*7c478bd9Sstevel@tonic-gate 	if (hx >= 0x43300000) {
229*7c478bd9Sstevel@tonic-gate 		/* x >= 2^52, so it's already integral */
230*7c478bd9Sstevel@tonic-gate 		if (nrx == 0)
231*7c478bd9Sstevel@tonic-gate 			*pe = 0;
232*7c478bd9Sstevel@tonic-gate 		else if (nrx == 1 && hx < 0x43400000)
233*7c478bd9Sstevel@tonic-gate 			*pe = 1;
234*7c478bd9Sstevel@tonic-gate 		else
235*7c478bd9Sstevel@tonic-gate 			*pe = 2;
236*7c478bd9Sstevel@tonic-gate 		return (*x);
237*7c478bd9Sstevel@tonic-gate 	} else if (hx < 0x3fe00000) {
238*7c478bd9Sstevel@tonic-gate 		/* x < 1/2 */
239*7c478bd9Sstevel@tonic-gate 		if (nrx > 1 && hx == 0x3fdfffff)
240*7c478bd9Sstevel@tonic-gate 			*pe = (*x == halfdec)? 2 : 1;
241*7c478bd9Sstevel@tonic-gate 		else
242*7c478bd9Sstevel@tonic-gate 			*pe = 1;
243*7c478bd9Sstevel@tonic-gate 		return (0.0);
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	rx = (*x + two52) - two52;
247*7c478bd9Sstevel@tonic-gate 	if (nrx == 0) {
248*7c478bd9Sstevel@tonic-gate 		*pe = (rx == *x)? 0 : 1;
249*7c478bd9Sstevel@tonic-gate 	} else {
250*7c478bd9Sstevel@tonic-gate 		rmx = rx - *x;
251*7c478bd9Sstevel@tonic-gate 		if (rmx < 0.0)
252*7c478bd9Sstevel@tonic-gate 			rmx = -rmx;
253*7c478bd9Sstevel@tonic-gate 		*pe = (nrx * twom53 * *x < half - rmx)? 1 : 2;
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate 	return (rx);
256*7c478bd9Sstevel@tonic-gate }
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate /*
259*7c478bd9Sstevel@tonic-gate  * Attempt to convert dd to a decimal record *pd according to the
260*7c478bd9Sstevel@tonic-gate  * modes in *pm using double precision floating point.  Return zero
261*7c478bd9Sstevel@tonic-gate  * and sets *ps to reflect any exceptions incurred if successful.
262*7c478bd9Sstevel@tonic-gate  * Return a nonzero value if unsuccessful.
263*7c478bd9Sstevel@tonic-gate  */
264*7c478bd9Sstevel@tonic-gate int
265*7c478bd9Sstevel@tonic-gate __fast_double_to_decimal(double *dd, decimal_mode *pm, decimal_record *pd,
266*7c478bd9Sstevel@tonic-gate     fp_exception_field_type *ps)
267*7c478bd9Sstevel@tonic-gate {
268*7c478bd9Sstevel@tonic-gate 	int			i, is, esum, eround, hd;
269*7c478bd9Sstevel@tonic-gate 	double			dds;
270*7c478bd9Sstevel@tonic-gate 	__ieee_flags_type	fb;
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	if (pm->rd != fp_nearest)
273*7c478bd9Sstevel@tonic-gate 		return (1);
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	if (pm->df == fixed_form) {
276*7c478bd9Sstevel@tonic-gate 		/* F format */
277*7c478bd9Sstevel@tonic-gate 		if (pm->ndigits < 0 || pm->ndigits > __TBL_TENS_MAX)
278*7c478bd9Sstevel@tonic-gate 			return (1);
279*7c478bd9Sstevel@tonic-gate 		__get_ieee_flags(&fb);
280*7c478bd9Sstevel@tonic-gate 		dds = __dabs(dd);
281*7c478bd9Sstevel@tonic-gate 		esum = 0;
282*7c478bd9Sstevel@tonic-gate 		if (pm->ndigits) {
283*7c478bd9Sstevel@tonic-gate 			/* scale by a positive power of ten */
284*7c478bd9Sstevel@tonic-gate 			if (pm->ndigits > __TBL_TENS_EXACT) {
285*7c478bd9Sstevel@tonic-gate 				dds *= __tbl_tens[pm->ndigits];
286*7c478bd9Sstevel@tonic-gate 				esum = 2;
287*7c478bd9Sstevel@tonic-gate 			} else {
288*7c478bd9Sstevel@tonic-gate 				dds = __mul_set(dds, __tbl_tens[pm->ndigits],
289*7c478bd9Sstevel@tonic-gate 				    &eround);
290*7c478bd9Sstevel@tonic-gate 				esum = eround;
291*7c478bd9Sstevel@tonic-gate 			}
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 		if (dds > 2147483647999999744.0) {
294*7c478bd9Sstevel@tonic-gate 			__set_ieee_flags(&fb);
295*7c478bd9Sstevel@tonic-gate 			return (1);
296*7c478bd9Sstevel@tonic-gate 		}
297*7c478bd9Sstevel@tonic-gate 		dds = __arint_set_n(&dds, esum, &eround);
298*7c478bd9Sstevel@tonic-gate 		if (eround == 2) {
299*7c478bd9Sstevel@tonic-gate 			/* error is too large to round reliably; punt */
300*7c478bd9Sstevel@tonic-gate 			__set_ieee_flags(&fb);
301*7c478bd9Sstevel@tonic-gate 			return (1);
302*7c478bd9Sstevel@tonic-gate 		}
303*7c478bd9Sstevel@tonic-gate 		if (dds == 0.0) {
304*7c478bd9Sstevel@tonic-gate 			is = (pm->ndigits > 0)? pm->ndigits : 1;
305*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < is; i++)
306*7c478bd9Sstevel@tonic-gate 				pd->ds[i] = '0';
307*7c478bd9Sstevel@tonic-gate 			pd->ds[is] = '\0';
308*7c478bd9Sstevel@tonic-gate 			eround++;
309*7c478bd9Sstevel@tonic-gate 		} else {
310*7c478bd9Sstevel@tonic-gate 			is = __double_to_digits(dds, pd->ds, pm->ndigits);
311*7c478bd9Sstevel@tonic-gate 		}
312*7c478bd9Sstevel@tonic-gate 		pd->ndigits = is;
313*7c478bd9Sstevel@tonic-gate 		pd->exponent = -pm->ndigits;
314*7c478bd9Sstevel@tonic-gate 	} else {
315*7c478bd9Sstevel@tonic-gate 		/* E format */
316*7c478bd9Sstevel@tonic-gate 		if (pm->ndigits < 1 || pm->ndigits > 18)
317*7c478bd9Sstevel@tonic-gate 			return (1);
318*7c478bd9Sstevel@tonic-gate 		__get_ieee_flags(&fb);
319*7c478bd9Sstevel@tonic-gate 		dds = __dabs(dd);
320*7c478bd9Sstevel@tonic-gate 		/* find the decade containing dds */
321*7c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
322*7c478bd9Sstevel@tonic-gate 		hd = *(1+(int *)dd);
323*7c478bd9Sstevel@tonic-gate #else
324*7c478bd9Sstevel@tonic-gate 		hd = *(int *)dd;
325*7c478bd9Sstevel@tonic-gate #endif
326*7c478bd9Sstevel@tonic-gate 		hd = (hd >> 20) & 0x7ff;
327*7c478bd9Sstevel@tonic-gate 		if (hd >= 0x400) {
328*7c478bd9Sstevel@tonic-gate 			if (hd > 0x4e0)
329*7c478bd9Sstevel@tonic-gate 				i = TBL_DECADE_MAX;
330*7c478bd9Sstevel@tonic-gate 			else
331*7c478bd9Sstevel@tonic-gate 				i = TBL_DECADE_MAX - ((0x4e0 - hd) >> 2);
332*7c478bd9Sstevel@tonic-gate 		} else {
333*7c478bd9Sstevel@tonic-gate 			if (hd < 0x358)
334*7c478bd9Sstevel@tonic-gate 				i = 0;
335*7c478bd9Sstevel@tonic-gate 			else
336*7c478bd9Sstevel@tonic-gate 				i = TBL_DECADE_OFFSET - ((0x3ff - hd) >> 2);
337*7c478bd9Sstevel@tonic-gate 		}
338*7c478bd9Sstevel@tonic-gate 		while (dds < tbl_decade[i])
339*7c478bd9Sstevel@tonic-gate 			i--;
340*7c478bd9Sstevel@tonic-gate 		/* determine the power of ten by which to scale */
341*7c478bd9Sstevel@tonic-gate 		i = pm->ndigits - 1 - (i - TBL_DECADE_OFFSET);
342*7c478bd9Sstevel@tonic-gate 		esum = 0;
343*7c478bd9Sstevel@tonic-gate 		if (i > 0) {
344*7c478bd9Sstevel@tonic-gate 			/* scale by a positive power of ten */
345*7c478bd9Sstevel@tonic-gate 			if (i > __TBL_TENS_EXACT) {
346*7c478bd9Sstevel@tonic-gate 				if (i > __TBL_TENS_MAX) {
347*7c478bd9Sstevel@tonic-gate 					__set_ieee_flags(&fb);
348*7c478bd9Sstevel@tonic-gate 					return (1);
349*7c478bd9Sstevel@tonic-gate 				}
350*7c478bd9Sstevel@tonic-gate 				dds *= __tbl_tens[i];
351*7c478bd9Sstevel@tonic-gate 				esum = 2;
352*7c478bd9Sstevel@tonic-gate 			} else {
353*7c478bd9Sstevel@tonic-gate 				dds = __mul_set(dds, __tbl_tens[i], &eround);
354*7c478bd9Sstevel@tonic-gate 				esum = eround;
355*7c478bd9Sstevel@tonic-gate 			}
356*7c478bd9Sstevel@tonic-gate 		} else if (i < 0) {
357*7c478bd9Sstevel@tonic-gate 			/* scale by a negative power of ten */
358*7c478bd9Sstevel@tonic-gate 			if (-i > __TBL_TENS_EXACT) {
359*7c478bd9Sstevel@tonic-gate 				if (-i > __TBL_TENS_MAX) {
360*7c478bd9Sstevel@tonic-gate 					__set_ieee_flags(&fb);
361*7c478bd9Sstevel@tonic-gate 					return (1);
362*7c478bd9Sstevel@tonic-gate 				}
363*7c478bd9Sstevel@tonic-gate 				dds /= __tbl_tens[-i];
364*7c478bd9Sstevel@tonic-gate 				esum = 2;
365*7c478bd9Sstevel@tonic-gate 			} else {
366*7c478bd9Sstevel@tonic-gate 				dds = __div_set(dds, __tbl_tens[-i], &eround);
367*7c478bd9Sstevel@tonic-gate 				esum = eround;
368*7c478bd9Sstevel@tonic-gate 			}
369*7c478bd9Sstevel@tonic-gate 		}
370*7c478bd9Sstevel@tonic-gate 		dds = __arint_set_n(&dds, esum, &eround);
371*7c478bd9Sstevel@tonic-gate 		if (eround == 2) {
372*7c478bd9Sstevel@tonic-gate 			/* error is too large to round reliably; punt */
373*7c478bd9Sstevel@tonic-gate 			__set_ieee_flags(&fb);
374*7c478bd9Sstevel@tonic-gate 			return (1);
375*7c478bd9Sstevel@tonic-gate 		}
376*7c478bd9Sstevel@tonic-gate 		is = __double_to_digits(dds, pd->ds, 1);
377*7c478bd9Sstevel@tonic-gate 		if (is > pm->ndigits) {
378*7c478bd9Sstevel@tonic-gate 			/*
379*7c478bd9Sstevel@tonic-gate 			 * The result rounded up to the next larger power
380*7c478bd9Sstevel@tonic-gate 			 * of ten; just discard the last zero and adjust
381*7c478bd9Sstevel@tonic-gate 			 * the exponent.
382*7c478bd9Sstevel@tonic-gate 			 */
383*7c478bd9Sstevel@tonic-gate 			pd->ds[--is] = '\0';
384*7c478bd9Sstevel@tonic-gate 			i--;
385*7c478bd9Sstevel@tonic-gate 		}
386*7c478bd9Sstevel@tonic-gate 		pd->ndigits = is;
387*7c478bd9Sstevel@tonic-gate 		pd->exponent = -i;
388*7c478bd9Sstevel@tonic-gate 	}
389*7c478bd9Sstevel@tonic-gate 	*ps = (eround == 0)? 0 : (1 << fp_inexact);
390*7c478bd9Sstevel@tonic-gate 	__set_ieee_flags(&fb);
391*7c478bd9Sstevel@tonic-gate 	return (0);
392*7c478bd9Sstevel@tonic-gate }
393