xref: /onnv-gate/usr/src/lib/libbc/libc/gen/common/decimal_bin.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 1988-1995, by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma	ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /* Conversion between binary and decimal floating point. */
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #include "base_conversion.h"
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate void
decimal_to_binary_integer(ds,ndigs,nzeros,nsig,pb)34*0Sstevel@tonic-gate decimal_to_binary_integer(ds, ndigs, nzeros, nsig, pb)
35*0Sstevel@tonic-gate 	char            ds[];	/* Input decimal integer string. */
36*0Sstevel@tonic-gate unsigned        ndigs;		/* Input number of explicit digits in ds. */
37*0Sstevel@tonic-gate unsigned        nzeros;		/* Input number of implicit trailing zeros. */
38*0Sstevel@tonic-gate unsigned        nsig;		/* Input number of significant bits required. */
39*0Sstevel@tonic-gate _big_float     *pb;		/* Pointer to big_float to receive result. */
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate /*
42*0Sstevel@tonic-gate  * Converts a decimal integer string ds with ndigs explicit leading digits
43*0Sstevel@tonic-gate  * and nzeros implicit trailing zeros to a _big_float **pb, which only
44*0Sstevel@tonic-gate  * requires nsig significand bits.
45*0Sstevel@tonic-gate  */
46*0Sstevel@tonic-gate /* Inexactness is indicated by pb->bsignificand[0] |= 1. */
47*0Sstevel@tonic-gate /*
48*0Sstevel@tonic-gate  * If the input is too big for a big_float, pb->bexponent is set to 0x7fff.
49*0Sstevel@tonic-gate  */
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate {
52*0Sstevel@tonic-gate 	unsigned        nzout;
53*0Sstevel@tonic-gate 	_big_float      d, *pbout;
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate 	d.bsize = _BIG_FLOAT_SIZE;
56*0Sstevel@tonic-gate 	_integerstring_to_big_decimal(ds, ndigs, nzeros, &nzout, &d);
57*0Sstevel@tonic-gate 	_big_decimal_to_big_binary(&d, pb);
58*0Sstevel@tonic-gate 	if (nzout != 0) {
59*0Sstevel@tonic-gate 		_big_float_times_power(pb, 10, (int) nzout, (int) nsig, &pbout);
60*0Sstevel@tonic-gate 		switch ((unsigned int)pbout) {
61*0Sstevel@tonic-gate 		case ((unsigned int)BIG_FLOAT_TIMES_TOOBIG):
62*0Sstevel@tonic-gate #ifdef DEBUG
63*0Sstevel@tonic-gate 			(void) printf(" decimal_to_binary_integer: decimal exponent %d too large for tables ", nzout);
64*0Sstevel@tonic-gate #endif
65*0Sstevel@tonic-gate 			pb->bexponent = 0x7fff;
66*0Sstevel@tonic-gate 			break;
67*0Sstevel@tonic-gate 		case ((unsigned int)BIG_FLOAT_TIMES_NOMEM):
68*0Sstevel@tonic-gate 			{
69*0Sstevel@tonic-gate 				char            bcastring[80];
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 				(void) sprintf(bcastring, " decimal exponent %d ", nzout);
72*0Sstevel@tonic-gate 				_base_conversion_abort(ENOMEM, bcastring);
73*0Sstevel@tonic-gate 				break;
74*0Sstevel@tonic-gate 			}
75*0Sstevel@tonic-gate 		default:
76*0Sstevel@tonic-gate #ifdef DEBUG
77*0Sstevel@tonic-gate 			if (pbout != pb)
78*0Sstevel@tonic-gate 				(void) printf(" decimal_to_binary_integer: large decimal exponent %d needs heap buffer \n", nzout);
79*0Sstevel@tonic-gate 			printf(" decimal_to_binary_integer: product ");
80*0Sstevel@tonic-gate 			_display_big_float(pb, 2);
81*0Sstevel@tonic-gate #endif
82*0Sstevel@tonic-gate 			if (pbout != pb) {	/* We don't really need such
83*0Sstevel@tonic-gate 						 * a large product; the
84*0Sstevel@tonic-gate 						 * target can't be more than
85*0Sstevel@tonic-gate 						 * a quad! */
86*0Sstevel@tonic-gate 				int             i, allweneed;
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 				allweneed = 2 + (nsig + 2) / 16;
89*0Sstevel@tonic-gate 				for (i = 0; i < allweneed; i++)
90*0Sstevel@tonic-gate 					pb->bsignificand[i] = pbout->bsignificand[i + pbout->blength - allweneed];
91*0Sstevel@tonic-gate 				for (i = 0; (pbout->bsignificand[i] == 0); i++);
92*0Sstevel@tonic-gate 				if (i < (pbout->blength - allweneed))
93*0Sstevel@tonic-gate 					pb->bsignificand[0] |= 1;	/* Stick discarded bits. */
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate 				pb->blength = allweneed;
96*0Sstevel@tonic-gate 				pb->bexponent = pbout->bexponent + 16 * (pbout->blength - allweneed);
97*0Sstevel@tonic-gate #ifdef DEBUG
98*0Sstevel@tonic-gate 				printf(" decimal_to_binary_integer: removed %d excess digits from product \n", pbout->blength - allweneed);
99*0Sstevel@tonic-gate 				_display_big_float(pb, 2);
100*0Sstevel@tonic-gate #endif
101*0Sstevel@tonic-gate 				_free_big_float(pbout);
102*0Sstevel@tonic-gate 			}
103*0Sstevel@tonic-gate 			break;
104*0Sstevel@tonic-gate 		}
105*0Sstevel@tonic-gate 	}
106*0Sstevel@tonic-gate }
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate void
decimal_to_binary_fraction(ds,ndigs,nzeros,nsig,pb)109*0Sstevel@tonic-gate decimal_to_binary_fraction(ds, ndigs, nzeros, nsig, pb)
110*0Sstevel@tonic-gate 	char            ds[];	/* Decimal integer string input. */
111*0Sstevel@tonic-gate unsigned        ndigs;		/* Number of explicit digits to read. */
112*0Sstevel@tonic-gate unsigned        nzeros;		/* Number of implicit leading zeros before
113*0Sstevel@tonic-gate 				 * digits. */
114*0Sstevel@tonic-gate unsigned        nsig;		/* Number of significant bits needed. */
115*0Sstevel@tonic-gate _big_float     *pb;		/* Pointer to intended big_float result. */
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate /*
118*0Sstevel@tonic-gate  * Converts an explicit decimal string *ds[0]..*ds[ndigs-1] preceded by
119*0Sstevel@tonic-gate  * nzeros implicit leading zeros after the point into a big_float at *pb. If
120*0Sstevel@tonic-gate  * the input does not fit exactly in a big_float, the least significant bit
121*0Sstevel@tonic-gate  * of pbout->significand is stuck on. If the input is too big for the base
122*0Sstevel@tonic-gate  * conversion tables, pb->bexponent is set to 0x7fff.
123*0Sstevel@tonic-gate  */
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate {
126*0Sstevel@tonic-gate 	unsigned        twopower, twosig;
127*0Sstevel@tonic-gate 	int             i, excess;
128*0Sstevel@tonic-gate 	_big_float      d, *pdout;
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	d.bsize = _BIG_FLOAT_SIZE;
131*0Sstevel@tonic-gate 	_fractionstring_to_big_decimal(ds, ndigs, nzeros, &d);
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	twopower = nsig + 3 + (((nzeros + 1) * (unsigned long) 217706) >> 16);
134*0Sstevel@tonic-gate 	twosig = 1 + (((nsig + 2) * (unsigned long) 19729) >> 16);
135*0Sstevel@tonic-gate 
136*0Sstevel@tonic-gate #ifdef DEBUG
137*0Sstevel@tonic-gate 	printf(" decimal_to_binary_fraction sigbits %d twopower %d twosig %d \n",
138*0Sstevel@tonic-gate 	       nsig, twopower, twosig);
139*0Sstevel@tonic-gate #endif
140*0Sstevel@tonic-gate 	_big_float_times_power(&d, 2, (int) twopower, (int) twosig, &pdout);
141*0Sstevel@tonic-gate 	switch ((unsigned int)pdout) {
142*0Sstevel@tonic-gate 	case ((unsigned int)BIG_FLOAT_TIMES_TOOBIG):
143*0Sstevel@tonic-gate #ifdef DEBUG
144*0Sstevel@tonic-gate 		(void) printf(" decimal_to_binary_fraction binary exponent %d too large for tables ", twopower);
145*0Sstevel@tonic-gate #endif
146*0Sstevel@tonic-gate 		pb->bexponent = 0x7fff;
147*0Sstevel@tonic-gate 		goto ret;
148*0Sstevel@tonic-gate 	case ((unsigned int)BIG_FLOAT_TIMES_NOMEM):
149*0Sstevel@tonic-gate 		{
150*0Sstevel@tonic-gate 			char            bcastring[80];
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate 			(void) sprintf(bcastring, " binary exponent %d ", twopower);
153*0Sstevel@tonic-gate 			_base_conversion_abort(ENOMEM, bcastring);
154*0Sstevel@tonic-gate 			break;
155*0Sstevel@tonic-gate 		}
156*0Sstevel@tonic-gate 	default:
157*0Sstevel@tonic-gate #ifdef DEBUG
158*0Sstevel@tonic-gate 		if (&d != pdout)
159*0Sstevel@tonic-gate 			printf(" decimal_to_binary_fraction large binary exponent %d needs heap buffer \n", twopower);
160*0Sstevel@tonic-gate 		printf(" product ");
161*0Sstevel@tonic-gate 		_display_big_float(pdout, 10);
162*0Sstevel@tonic-gate #endif
163*0Sstevel@tonic-gate 		break;
164*0Sstevel@tonic-gate 	}
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 	if (pdout->bexponent <= -4) {
168*0Sstevel@tonic-gate 		/* Have computed appropriate decimal part; now toss fraction. */
169*0Sstevel@tonic-gate 		excess = (-pdout->bexponent) / 4;
170*0Sstevel@tonic-gate #ifdef DEBUG
171*0Sstevel@tonic-gate 		printf(" discard %d excess fraction digits \n", 4 * excess);
172*0Sstevel@tonic-gate #endif
173*0Sstevel@tonic-gate 		for (i = 0; (i < excess) && ((pdout)->bsignificand[i] == 0); i++);
174*0Sstevel@tonic-gate 		if (i < excess)
175*0Sstevel@tonic-gate 			(pdout)->bsignificand[excess] |= 1;	/* Sticky bit for
176*0Sstevel@tonic-gate 								 * discarded fraction. */
177*0Sstevel@tonic-gate 		for (i = excess; i < (pdout)->blength; i++)
178*0Sstevel@tonic-gate 			(pdout)->bsignificand[i - excess] = (pdout)->bsignificand[i];
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate 		(pdout)->blength -= excess;
181*0Sstevel@tonic-gate 		(pdout)->bexponent += 4 * excess;
182*0Sstevel@tonic-gate 	}
183*0Sstevel@tonic-gate 	_big_decimal_to_big_binary(pdout, pb);
184*0Sstevel@tonic-gate 	if (pdout != &d)
185*0Sstevel@tonic-gate 		_free_big_float(pdout);
186*0Sstevel@tonic-gate 	pb->bexponent = -twopower;
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate ret:
189*0Sstevel@tonic-gate 	return;
190*0Sstevel@tonic-gate }
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate void
decimal_to_unpacked(px,pd,significant_bits)193*0Sstevel@tonic-gate decimal_to_unpacked(px, pd, significant_bits)
194*0Sstevel@tonic-gate 	unpacked       *px;
195*0Sstevel@tonic-gate 	decimal_record *pd;
196*0Sstevel@tonic-gate 	unsigned        significant_bits;
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate /*
199*0Sstevel@tonic-gate  * Converts *pd to *px so that *px can be correctly rounded. significant_bits
200*0Sstevel@tonic-gate  * tells how many bits will be significant in the final result to avoid
201*0Sstevel@tonic-gate  * superfluous computation. Inexactness is communicated by sticking on the
202*0Sstevel@tonic-gate  * lsb of px->significand[UNPACKED_SIZE-1]. Integer buffer overflow is
203*0Sstevel@tonic-gate  * indicated with a huge positive exponent.
204*0Sstevel@tonic-gate  */
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate {
207*0Sstevel@tonic-gate 	int             frac_bits, sigint;
208*0Sstevel@tonic-gate 	unsigned        length, ndigs, ntz, nlz, ifrac, nfrac;
209*0Sstevel@tonic-gate 	_big_float      bi, bf, *ptounpacked = &bi;
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	px->sign = pd->sign;
212*0Sstevel@tonic-gate 	px->fpclass = pd->fpclass;
213*0Sstevel@tonic-gate 	if ((px->fpclass != fp_normal) && (px->fpclass != fp_subnormal))
214*0Sstevel@tonic-gate 		goto ret;
215*0Sstevel@tonic-gate 	for (length = 0; pd->ds[length] != 0; length++);
216*0Sstevel@tonic-gate 	if (length == 0) {	/* A zero significand slipped by. */
217*0Sstevel@tonic-gate 		px->fpclass = fp_zero;
218*0Sstevel@tonic-gate 		goto ret;
219*0Sstevel@tonic-gate 	}
220*0Sstevel@tonic-gate 	/* Length contains the number of explicit digits in string. */
221*0Sstevel@tonic-gate 	if (pd->exponent >= 0) {/* All integer digits. */
222*0Sstevel@tonic-gate 		ndigs = length;
223*0Sstevel@tonic-gate 		ntz = pd->exponent;	/* Trailing zeros. */
224*0Sstevel@tonic-gate 		ifrac = 0;
225*0Sstevel@tonic-gate 		nfrac = 0;	/* No fraction digits. */
226*0Sstevel@tonic-gate 		nlz = 0;
227*0Sstevel@tonic-gate 	} else if (length <= -pd->exponent) {	/* No integer digits. */
228*0Sstevel@tonic-gate 		ndigs = 0;
229*0Sstevel@tonic-gate 		ntz = 0;
230*0Sstevel@tonic-gate 		ifrac = 0;
231*0Sstevel@tonic-gate 		nfrac = length;
232*0Sstevel@tonic-gate 		nlz = -pd->exponent - length;	/* Leading zeros. */
233*0Sstevel@tonic-gate 	} else {		/* Some integer digits, some fraction digits. */
234*0Sstevel@tonic-gate 		ndigs = length + pd->exponent;
235*0Sstevel@tonic-gate 		ntz = 0;
236*0Sstevel@tonic-gate 		ifrac = ndigs;
237*0Sstevel@tonic-gate 		nfrac = -pd->exponent;
238*0Sstevel@tonic-gate 		nlz = 0;
239*0Sstevel@tonic-gate 		while ((pd->ds[ifrac] == '0') && (nfrac != 0)) {
240*0Sstevel@tonic-gate 			ifrac++;
241*0Sstevel@tonic-gate 			nfrac--;
242*0Sstevel@tonic-gate 			nlz++;
243*0Sstevel@tonic-gate 		}		/* Remove leading zeros. */
244*0Sstevel@tonic-gate 	}
245*0Sstevel@tonic-gate 	if (ndigs != 0) {	/* Convert integer digits. */
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 		bi.bsize = _BIG_FLOAT_SIZE;
248*0Sstevel@tonic-gate 		decimal_to_binary_integer(pd->ds, ndigs, ntz, significant_bits, &bi);
249*0Sstevel@tonic-gate 		if (bi.bexponent == 0x7fff) {	/* Too big for buffer. */
250*0Sstevel@tonic-gate 			px->exponent = 0x000fffff;
251*0Sstevel@tonic-gate 			px->significand[0] = 0x80000000;
252*0Sstevel@tonic-gate 			goto ret;
253*0Sstevel@tonic-gate 		}
254*0Sstevel@tonic-gate 		sigint = 16 * (bi.blength + bi.bexponent - 1);
255*0Sstevel@tonic-gate 		if (sigint < 0)
256*0Sstevel@tonic-gate 			sigint = 0;
257*0Sstevel@tonic-gate 	} else {		/* No integer digits. */
258*0Sstevel@tonic-gate 		bi.blength = 0;
259*0Sstevel@tonic-gate 		bi.bsignificand[0] = 0;
260*0Sstevel@tonic-gate 		bi.bexponent = 0;
261*0Sstevel@tonic-gate 		sigint = 0;
262*0Sstevel@tonic-gate 	}
263*0Sstevel@tonic-gate 	frac_bits = significant_bits - sigint + 2;
264*0Sstevel@tonic-gate 	bf.blength = 0;
265*0Sstevel@tonic-gate 	if ((nfrac != 0) && (frac_bits > 0)) {	/* Convert fraction digits,
266*0Sstevel@tonic-gate 						 * even if we only need a
267*0Sstevel@tonic-gate 						 * round or sticky.  */
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 		bf.bsize = _BIG_FLOAT_SIZE;
270*0Sstevel@tonic-gate 		decimal_to_binary_fraction(&(pd->ds[ifrac]), nfrac, nlz, (unsigned) frac_bits, &bf);
271*0Sstevel@tonic-gate 	} else {		/* Only need fraction bits for sticky. */
272*0Sstevel@tonic-gate 		if (nfrac != 0)
273*0Sstevel@tonic-gate 			bi.bsignificand[0] |= 1;	/* Stick for fraction. */
274*0Sstevel@tonic-gate 	}
275*0Sstevel@tonic-gate 	if (bi.blength == 0) {	/* No integer digits; all fraction. */
276*0Sstevel@tonic-gate 		if (bf.bexponent == 0x7fff) {	/* Buffer overflowed. */
277*0Sstevel@tonic-gate 			px->exponent = -0x000fffff;
278*0Sstevel@tonic-gate 			px->significand[0] = 0x80000000;
279*0Sstevel@tonic-gate 			goto ret;
280*0Sstevel@tonic-gate 		}
281*0Sstevel@tonic-gate 		ptounpacked = &bf;	/* Exceptional case - all fraction. */
282*0Sstevel@tonic-gate 		goto punpack;
283*0Sstevel@tonic-gate 	}
284*0Sstevel@tonic-gate 	if (bf.blength != 0) {	/* Combine integer and fraction bits. */
285*0Sstevel@tonic-gate 		int             expdiff = bi.bexponent - (bf.bexponent + 16 * (bf.blength - 1));	/* Exponent difference. */
286*0Sstevel@tonic-gate 		int             uneeded = 2 + (significant_bits + 2) / 16;	/* Number of big float
287*0Sstevel@tonic-gate 										 * digits needed. */
288*0Sstevel@tonic-gate 		int             nmove, leftshift, i, if0;
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate #ifdef DEBUG
291*0Sstevel@tonic-gate 		printf(" bi+bf exponent diff is %d \n", expdiff);
292*0Sstevel@tonic-gate 		printf(" need %d big float digits \n", uneeded);
293*0Sstevel@tonic-gate 		assert(bi.blength != 0);
294*0Sstevel@tonic-gate 		assert(bf.blength != 0);
295*0Sstevel@tonic-gate 		assert(bi.bsignificand[bi.blength - 1] != 0);	/* Normalized bi. */
296*0Sstevel@tonic-gate 		assert(bf.bsignificand[bf.blength - 1] != 0);	/* Normalized bf. */
297*0Sstevel@tonic-gate 		assert(bi.bexponent >= 0);	/* bi is all integer */
298*0Sstevel@tonic-gate 		assert(((-bf.bexponent - 16 * (bf.blength - 1)) >= 16) ||
299*0Sstevel@tonic-gate 		       ((bf.bsignificand[bf.blength - 1] >> (-bf.bexponent - 16 * (bf.blength - 1))) == 0));
300*0Sstevel@tonic-gate 		/* assert either bf << 1 or bf < 1 */
301*0Sstevel@tonic-gate 		/*
302*0Sstevel@tonic-gate 		 * Assert that integer and fraction parts don't overlap by
303*0Sstevel@tonic-gate 		 * more than one big digit.
304*0Sstevel@tonic-gate 		 */
305*0Sstevel@tonic-gate 		assert(expdiff > 0);
306*0Sstevel@tonic-gate 		assert(uneeded <= (2 * UNPACKED_SIZE));
307*0Sstevel@tonic-gate #endif
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate 		if (bi.blength >= uneeded) {	/* bi will overflow unpacked,
311*0Sstevel@tonic-gate 						 * so bf is just a sticky. */
312*0Sstevel@tonic-gate 			bi.bsignificand[0] |= 1;
313*0Sstevel@tonic-gate 			goto punpack;
314*0Sstevel@tonic-gate 		}
315*0Sstevel@tonic-gate 		leftshift = 16 - (expdiff % 16);
316*0Sstevel@tonic-gate 		if (leftshift > 0) {	/* shift bf to align with bi. */
317*0Sstevel@tonic-gate 			expdiff += 16 * bf.blength;
318*0Sstevel@tonic-gate 			_left_shift_base_two(&bf, (short unsigned) leftshift);
319*0Sstevel@tonic-gate 			expdiff -= 16 * bf.blength;	/* If bf.blength is
320*0Sstevel@tonic-gate 							 * longer, adjust
321*0Sstevel@tonic-gate 							 * expdiff. */
322*0Sstevel@tonic-gate 		}
323*0Sstevel@tonic-gate 		expdiff += leftshift;
324*0Sstevel@tonic-gate 		expdiff /= 16;	/* Remaining expdiff in _BIG_FLOAT_DIGITS. */
325*0Sstevel@tonic-gate 		expdiff--;
326*0Sstevel@tonic-gate #ifdef DEBUG
327*0Sstevel@tonic-gate 		assert(expdiff >= 0);	/* expdiff is now equal to the size
328*0Sstevel@tonic-gate 					 * of the hole between bi and bf. */
329*0Sstevel@tonic-gate #endif
330*0Sstevel@tonic-gate 		nmove = uneeded - bi.blength;
331*0Sstevel@tonic-gate 		/* nmove is the number of words to add to bi. */
332*0Sstevel@tonic-gate 		if (nmove < 0)
333*0Sstevel@tonic-gate 			nmove = 0;
334*0Sstevel@tonic-gate 		if (nmove > (expdiff + bf.blength))
335*0Sstevel@tonic-gate 			nmove = (expdiff + bf.blength);
336*0Sstevel@tonic-gate #ifdef DEBUG
337*0Sstevel@tonic-gate 		printf(" increase bi by %d words to merge \n", nmove);
338*0Sstevel@tonic-gate #endif
339*0Sstevel@tonic-gate 		if (nmove == 0)
340*0Sstevel@tonic-gate 			i = -1;
341*0Sstevel@tonic-gate 		else
342*0Sstevel@tonic-gate 			for (i = (bi.blength - 1 + nmove); i >= nmove; i--)
343*0Sstevel@tonic-gate 				bi.bsignificand[i] = bi.bsignificand[i - nmove];
344*0Sstevel@tonic-gate 		for (; (i >= 0) && (expdiff > 0); i--) {	/* Fill hole with zeros. */
345*0Sstevel@tonic-gate 			expdiff--;
346*0Sstevel@tonic-gate 			bi.bsignificand[i] = 0;
347*0Sstevel@tonic-gate 		}
348*0Sstevel@tonic-gate 		if0 = i;
349*0Sstevel@tonic-gate 		for (; i >= 0; i--)
350*0Sstevel@tonic-gate 			bi.bsignificand[i] = bf.bsignificand[i + bf.blength - 1 - if0];
351*0Sstevel@tonic-gate 		for (i = (bf.blength - 2 - if0); bf.bsignificand[i] == 0; i--);
352*0Sstevel@tonic-gate 		/* Find first non-zero. */
353*0Sstevel@tonic-gate 		if (i >= 0)
354*0Sstevel@tonic-gate 			bi.bsignificand[0] |= 1;	/* If non-zero found,
355*0Sstevel@tonic-gate 							 * stick it. */
356*0Sstevel@tonic-gate 		bi.blength += nmove;
357*0Sstevel@tonic-gate 		bi.bexponent -= 16 * nmove;
358*0Sstevel@tonic-gate 		goto punpack;
359*0Sstevel@tonic-gate 	}
360*0Sstevel@tonic-gate punpack:
361*0Sstevel@tonic-gate 	ptounpacked->bsignificand[0] |= pd->more;	/* Stick in any lost
362*0Sstevel@tonic-gate 							 * digits. */
363*0Sstevel@tonic-gate 
364*0Sstevel@tonic-gate #ifdef DEBUG
365*0Sstevel@tonic-gate 	printf(" merged bi and bf: ");
366*0Sstevel@tonic-gate 	_display_big_float(ptounpacked, 2);
367*0Sstevel@tonic-gate #endif
368*0Sstevel@tonic-gate 
369*0Sstevel@tonic-gate 	_big_binary_to_unpacked(ptounpacked, px);
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate ret:
372*0Sstevel@tonic-gate 	return;
373*0Sstevel@tonic-gate }
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate /* PUBLIC FUNCTIONS */
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate /*
378*0Sstevel@tonic-gate  * decimal_to_floating routines convert the decimal record at *pd to the
379*0Sstevel@tonic-gate  * floating type item at *px, observing the modes specified in *pm and
380*0Sstevel@tonic-gate  * setting exceptions in *ps.
381*0Sstevel@tonic-gate  *
382*0Sstevel@tonic-gate  * pd->sign and pd->fpclass are always taken into account.
383*0Sstevel@tonic-gate  *
384*0Sstevel@tonic-gate  * pd->exponent, pd->ds and pd->ndigits are used when pd->fpclass is
385*0Sstevel@tonic-gate  * fp_normal or fp_subnormal.  In these cases pd->ds is expected to
386*0Sstevel@tonic-gate  * contain one or more ascii digits followed by a null and pd->ndigits
387*0Sstevel@tonic-gate  * is assumed to be the length of the string pd->ds.  Notice that for
388*0Sstevel@tonic-gate  * efficiency reasons, the assumption that pd->ndigits == strlen(pd->ds)
389*0Sstevel@tonic-gate  * is NEVER verified.
390*0Sstevel@tonic-gate  *
391*0Sstevel@tonic-gate  * px is set to a correctly rounded approximation to
392*0Sstevel@tonic-gate  * (sign)*(ds)*10**(exponent) If pd->more != 0 then additional nonzero digits
393*0Sstevel@tonic-gate  * are assumed to follow those in ds; fp_inexact is set accordingly.
394*0Sstevel@tonic-gate  *
395*0Sstevel@tonic-gate  * Thus if pd->exponent == -2 and pd->ds = "1234", *px will get 12.34 rounded to
396*0Sstevel@tonic-gate  * storage precision.
397*0Sstevel@tonic-gate  *
398*0Sstevel@tonic-gate  * px is correctly rounded according to the IEEE rounding modes in pm->rd.  *ps
399*0Sstevel@tonic-gate  * is set to contain fp_inexact, fp_underflow, or fp_overflow if any of these
400*0Sstevel@tonic-gate  * arise.
401*0Sstevel@tonic-gate  *
402*0Sstevel@tonic-gate  * pm->df and pm->ndigits are never used.
403*0Sstevel@tonic-gate  *
404*0Sstevel@tonic-gate  */
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate void
decimal_to_single(px,pm,pd,ps)407*0Sstevel@tonic-gate decimal_to_single(px, pm, pd, ps)
408*0Sstevel@tonic-gate 	single         *px;
409*0Sstevel@tonic-gate 	decimal_mode   *pm;
410*0Sstevel@tonic-gate 	decimal_record *pd;
411*0Sstevel@tonic-gate 	fp_exception_field_type *ps;
412*0Sstevel@tonic-gate {
413*0Sstevel@tonic-gate 	single_equivalence kluge;
414*0Sstevel@tonic-gate 	unpacked        u;
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 	*ps = 0;		/* Initialize to no floating-point
417*0Sstevel@tonic-gate 				 * exceptions. */
418*0Sstevel@tonic-gate 	kluge.f.msw.sign = pd->sign ? 1 : 0;
419*0Sstevel@tonic-gate 	switch (pd->fpclass) {
420*0Sstevel@tonic-gate 	case fp_zero:
421*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
422*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
423*0Sstevel@tonic-gate 		break;
424*0Sstevel@tonic-gate 	case fp_infinity:
425*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0xff;
426*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
427*0Sstevel@tonic-gate 		break;
428*0Sstevel@tonic-gate 	case fp_quiet:
429*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0xff;
430*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0x7fffff;
431*0Sstevel@tonic-gate 		break;
432*0Sstevel@tonic-gate 	case fp_signaling:
433*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0xff;
434*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0x3fffff;
435*0Sstevel@tonic-gate 		break;
436*0Sstevel@tonic-gate 	default:
437*0Sstevel@tonic-gate 		if (pd->exponent > SINGLE_MAXE) {	/* Guaranteed overflow. */
438*0Sstevel@tonic-gate 			u.sign = pd->sign == 0 ? 0 : 1;
439*0Sstevel@tonic-gate 			u.fpclass = fp_normal;
440*0Sstevel@tonic-gate 			u.exponent = 0x000fffff;
441*0Sstevel@tonic-gate 			u.significand[0] = 0x80000000;
442*0Sstevel@tonic-gate 		} else if (pd->exponent >= -SINGLE_MAXE) {	/* Guaranteed in range. */
443*0Sstevel@tonic-gate 			goto inrange;
444*0Sstevel@tonic-gate 		} else if (pd->exponent <= (-SINGLE_MAXE - DECIMAL_STRING_LENGTH)) {	/* Guaranteed deep
445*0Sstevel@tonic-gate 											 * underflow. */
446*0Sstevel@tonic-gate 			goto underflow;
447*0Sstevel@tonic-gate 		} else {	/* Deep underflow possible, depending on
448*0Sstevel@tonic-gate 				 * string length. */
449*0Sstevel@tonic-gate 			int             i;
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate 			for (i = 0; (pd->ds[i] != 0) && (i < (-pd->exponent - SINGLE_MAXE)); i++);
452*0Sstevel@tonic-gate 			if (i < (-pd->exponent - SINGLE_MAXE)) {	/* Deep underflow */
453*0Sstevel@tonic-gate 		underflow:
454*0Sstevel@tonic-gate 				u.sign = pd->sign == 0 ? 0 : 1;
455*0Sstevel@tonic-gate 				u.fpclass = fp_normal;
456*0Sstevel@tonic-gate 				u.exponent = -0x000fffff;
457*0Sstevel@tonic-gate 				u.significand[0] = 0x80000000;
458*0Sstevel@tonic-gate 			} else {/* In range. */
459*0Sstevel@tonic-gate 		inrange:
460*0Sstevel@tonic-gate 				decimal_to_unpacked(&u, pd, 24);
461*0Sstevel@tonic-gate 			}
462*0Sstevel@tonic-gate 		}
463*0Sstevel@tonic-gate 		_fp_current_exceptions = 0;
464*0Sstevel@tonic-gate 		_fp_current_direction = pm->rd;
465*0Sstevel@tonic-gate 		_pack_single(&u, &kluge.x);
466*0Sstevel@tonic-gate 		*ps = _fp_current_exceptions;
467*0Sstevel@tonic-gate 	}
468*0Sstevel@tonic-gate 	*px = kluge.x;
469*0Sstevel@tonic-gate }
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate void
decimal_to_double(px,pm,pd,ps)472*0Sstevel@tonic-gate decimal_to_double(px, pm, pd, ps)
473*0Sstevel@tonic-gate 	double         *px;
474*0Sstevel@tonic-gate 	decimal_mode   *pm;
475*0Sstevel@tonic-gate 	decimal_record *pd;
476*0Sstevel@tonic-gate 	fp_exception_field_type *ps;
477*0Sstevel@tonic-gate {
478*0Sstevel@tonic-gate 	double_equivalence kluge;
479*0Sstevel@tonic-gate 	unpacked        u;
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate 	*ps = 0;		/* Initialize to no floating-point
482*0Sstevel@tonic-gate 				 * exceptions. */
483*0Sstevel@tonic-gate 	kluge.f.msw.sign = pd->sign ? 1 : 0;
484*0Sstevel@tonic-gate 	switch (pd->fpclass) {
485*0Sstevel@tonic-gate 	case fp_zero:
486*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
487*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
488*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
489*0Sstevel@tonic-gate 		break;
490*0Sstevel@tonic-gate 	case fp_infinity:
491*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7ff;
492*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
493*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
494*0Sstevel@tonic-gate 		break;
495*0Sstevel@tonic-gate 	case fp_quiet:
496*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7ff;
497*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0xfffff;
498*0Sstevel@tonic-gate 		kluge.f.significand2 = 0xffffffff;
499*0Sstevel@tonic-gate 		break;
500*0Sstevel@tonic-gate 	case fp_signaling:
501*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7ff;
502*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0x7ffff;
503*0Sstevel@tonic-gate 		kluge.f.significand2 = 0xffffffff;
504*0Sstevel@tonic-gate 		break;
505*0Sstevel@tonic-gate 	default:
506*0Sstevel@tonic-gate 		if (pd->exponent > DOUBLE_MAXE) {	/* Guaranteed overflow. */
507*0Sstevel@tonic-gate 			u.sign = pd->sign == 0 ? 0 : 1;
508*0Sstevel@tonic-gate 			u.fpclass = fp_normal;
509*0Sstevel@tonic-gate 			u.exponent = 0x000fffff;
510*0Sstevel@tonic-gate 			u.significand[0] = 0x80000000;
511*0Sstevel@tonic-gate 		} else if (pd->exponent >= -DOUBLE_MAXE) {	/* Guaranteed in range. */
512*0Sstevel@tonic-gate 			goto inrange;
513*0Sstevel@tonic-gate 		} else if (pd->exponent <= (-DOUBLE_MAXE - DECIMAL_STRING_LENGTH)) {	/* Guaranteed deep
514*0Sstevel@tonic-gate 											 * underflow. */
515*0Sstevel@tonic-gate 			goto underflow;
516*0Sstevel@tonic-gate 		} else {	/* Deep underflow possible, depending on
517*0Sstevel@tonic-gate 				 * string length. */
518*0Sstevel@tonic-gate 			int             i;
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 			for (i = 0; (pd->ds[i] != 0) && (i < (-pd->exponent - DOUBLE_MAXE)); i++);
521*0Sstevel@tonic-gate 			if (i < (-pd->exponent - DOUBLE_MAXE)) {	/* Deep underflow */
522*0Sstevel@tonic-gate 		underflow:
523*0Sstevel@tonic-gate 				u.sign = pd->sign == 0 ? 0 : 1;
524*0Sstevel@tonic-gate 				u.fpclass = fp_normal;
525*0Sstevel@tonic-gate 				u.exponent = -0x000fffff;
526*0Sstevel@tonic-gate 				u.significand[0] = 0x80000000;
527*0Sstevel@tonic-gate 			} else {/* In range. */
528*0Sstevel@tonic-gate 		inrange:
529*0Sstevel@tonic-gate 				decimal_to_unpacked(&u, pd, 53);
530*0Sstevel@tonic-gate 			}
531*0Sstevel@tonic-gate 		}
532*0Sstevel@tonic-gate 		_fp_current_exceptions = 0;
533*0Sstevel@tonic-gate 		_fp_current_direction = pm->rd;
534*0Sstevel@tonic-gate 		_pack_double(&u, &kluge.x);
535*0Sstevel@tonic-gate 		*ps = _fp_current_exceptions;
536*0Sstevel@tonic-gate 	}
537*0Sstevel@tonic-gate 	*px = kluge.x;
538*0Sstevel@tonic-gate }
539*0Sstevel@tonic-gate 
540*0Sstevel@tonic-gate void
decimal_to_extended(px,pm,pd,ps)541*0Sstevel@tonic-gate decimal_to_extended(px, pm, pd, ps)
542*0Sstevel@tonic-gate 	extended       *px;
543*0Sstevel@tonic-gate 	decimal_mode   *pm;
544*0Sstevel@tonic-gate 	decimal_record *pd;
545*0Sstevel@tonic-gate 	fp_exception_field_type *ps;
546*0Sstevel@tonic-gate {
547*0Sstevel@tonic-gate 	extended_equivalence kluge;
548*0Sstevel@tonic-gate 	unpacked        u;
549*0Sstevel@tonic-gate 
550*0Sstevel@tonic-gate 	*ps = 0;		/* Initialize to no floating-point
551*0Sstevel@tonic-gate 				 * exceptions. */
552*0Sstevel@tonic-gate 	kluge.f.msw.sign = pd->sign ? 1 : 0;
553*0Sstevel@tonic-gate 	switch (pd->fpclass) {
554*0Sstevel@tonic-gate 	case fp_zero:
555*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
556*0Sstevel@tonic-gate 		kluge.f.significand = 0;
557*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
558*0Sstevel@tonic-gate 		break;
559*0Sstevel@tonic-gate 	case fp_infinity:
560*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
561*0Sstevel@tonic-gate 		kluge.f.significand = 0;
562*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
563*0Sstevel@tonic-gate 		break;
564*0Sstevel@tonic-gate 	case fp_quiet:
565*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
566*0Sstevel@tonic-gate 		kluge.f.significand = 0xffffffff;
567*0Sstevel@tonic-gate 		kluge.f.significand2 = 0xffffffff;
568*0Sstevel@tonic-gate 		break;
569*0Sstevel@tonic-gate 	case fp_signaling:
570*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
571*0Sstevel@tonic-gate 		kluge.f.significand = 0x3fffffff;
572*0Sstevel@tonic-gate 		kluge.f.significand2 = 0xffffffff;
573*0Sstevel@tonic-gate 		break;
574*0Sstevel@tonic-gate 	default:
575*0Sstevel@tonic-gate 		if (pd->exponent > EXTENDED_MAXE) {	/* Guaranteed overflow. */
576*0Sstevel@tonic-gate 			u.sign = pd->sign == 0 ? 0 : 1;
577*0Sstevel@tonic-gate 			u.fpclass = fp_normal;
578*0Sstevel@tonic-gate 			u.exponent = 0x000fffff;
579*0Sstevel@tonic-gate 			u.significand[0] = 0x80000000;
580*0Sstevel@tonic-gate 		} else if (pd->exponent >= -EXTENDED_MAXE) {	/* Guaranteed in range. */
581*0Sstevel@tonic-gate 			goto inrange;
582*0Sstevel@tonic-gate 		} else if (pd->exponent <= (-EXTENDED_MAXE - DECIMAL_STRING_LENGTH)) {	/* Guaranteed deep
583*0Sstevel@tonic-gate 											 * underflow. */
584*0Sstevel@tonic-gate 			goto underflow;
585*0Sstevel@tonic-gate 		} else {	/* Deep underflow possible, depending on
586*0Sstevel@tonic-gate 				 * string length. */
587*0Sstevel@tonic-gate 			int             i;
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate 			for (i = 0; (pd->ds[i] != 0) && (i < (-pd->exponent - EXTENDED_MAXE)); i++);
590*0Sstevel@tonic-gate 			if (i < (-pd->exponent - EXTENDED_MAXE)) {	/* Deep underflow */
591*0Sstevel@tonic-gate 		underflow:
592*0Sstevel@tonic-gate 				u.sign = pd->sign == 0 ? 0 : 1;
593*0Sstevel@tonic-gate 				u.fpclass = fp_normal;
594*0Sstevel@tonic-gate 				u.exponent = -0x000fffff;
595*0Sstevel@tonic-gate 				u.significand[0] = 0x80000000;
596*0Sstevel@tonic-gate 			} else {/* In range. */
597*0Sstevel@tonic-gate 		inrange:
598*0Sstevel@tonic-gate 				decimal_to_unpacked(&u, pd, 64);
599*0Sstevel@tonic-gate 			}
600*0Sstevel@tonic-gate 		}
601*0Sstevel@tonic-gate 		_fp_current_exceptions = 0;
602*0Sstevel@tonic-gate 		_fp_current_direction = pm->rd;
603*0Sstevel@tonic-gate 		_fp_current_precision = fp_extended;
604*0Sstevel@tonic-gate 		_pack_extended(&u, px);
605*0Sstevel@tonic-gate 		*ps = _fp_current_exceptions;
606*0Sstevel@tonic-gate 		return;
607*0Sstevel@tonic-gate 	}
608*0Sstevel@tonic-gate 	(*px)[0] = kluge.x[0];
609*0Sstevel@tonic-gate 	(*px)[1] = kluge.x[1];
610*0Sstevel@tonic-gate 	(*px)[2] = kluge.x[2];
611*0Sstevel@tonic-gate }
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate void
decimal_to_quadruple(px,pm,pd,ps)614*0Sstevel@tonic-gate decimal_to_quadruple(px, pm, pd, ps)
615*0Sstevel@tonic-gate 	quadruple      *px;
616*0Sstevel@tonic-gate 	decimal_mode   *pm;
617*0Sstevel@tonic-gate 	decimal_record *pd;
618*0Sstevel@tonic-gate 	fp_exception_field_type *ps;
619*0Sstevel@tonic-gate {
620*0Sstevel@tonic-gate 	quadruple_equivalence kluge;
621*0Sstevel@tonic-gate 	unpacked        u;
622*0Sstevel@tonic-gate 	int             i;
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate 	*ps = 0;		/* Initialize to no floating-point
625*0Sstevel@tonic-gate 				 * exceptions. */
626*0Sstevel@tonic-gate 	kluge.f.msw.sign = pd->sign ? 1 : 0;
627*0Sstevel@tonic-gate 	switch (pd->fpclass) {
628*0Sstevel@tonic-gate 	case fp_zero:
629*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0;
630*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
631*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
632*0Sstevel@tonic-gate 		kluge.f.significand3 = 0;
633*0Sstevel@tonic-gate 		kluge.f.significand4 = 0;
634*0Sstevel@tonic-gate 		break;
635*0Sstevel@tonic-gate 	case fp_infinity:
636*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
637*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0;
638*0Sstevel@tonic-gate 		kluge.f.significand2 = 0;
639*0Sstevel@tonic-gate 		kluge.f.significand3 = 0;
640*0Sstevel@tonic-gate 		kluge.f.significand4 = 0;
641*0Sstevel@tonic-gate 		break;
642*0Sstevel@tonic-gate 	case fp_quiet:
643*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
644*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0xffff;
645*0Sstevel@tonic-gate 		kluge.f.significand2 = 0xffffffff;
646*0Sstevel@tonic-gate 		kluge.f.significand3 = 0xffffffff;
647*0Sstevel@tonic-gate 		kluge.f.significand4 = 0xffffffff;
648*0Sstevel@tonic-gate 		break;
649*0Sstevel@tonic-gate 	case fp_signaling:
650*0Sstevel@tonic-gate 		kluge.f.msw.exponent = 0x7fff;
651*0Sstevel@tonic-gate 		kluge.f.msw.significand = 0x7fff;
652*0Sstevel@tonic-gate 		kluge.f.significand2 = 0xffffffff;
653*0Sstevel@tonic-gate 		kluge.f.significand3 = 0xffffffff;
654*0Sstevel@tonic-gate 		kluge.f.significand4 = 0xffffffff;
655*0Sstevel@tonic-gate 		break;
656*0Sstevel@tonic-gate 	default:
657*0Sstevel@tonic-gate 		if (pd->exponent > QUAD_MAXE) {	/* Guaranteed overflow. */
658*0Sstevel@tonic-gate 			u.sign = pd->sign == 0 ? 0 : 1;
659*0Sstevel@tonic-gate 			u.fpclass = fp_normal;
660*0Sstevel@tonic-gate 			u.exponent = 0x000fffff;
661*0Sstevel@tonic-gate 			u.significand[0] = 0x80000000;
662*0Sstevel@tonic-gate 		} else if (pd->exponent >= -QUAD_MAXE) {	/* Guaranteed in range. */
663*0Sstevel@tonic-gate 			goto inrange;
664*0Sstevel@tonic-gate 		} else if (pd->exponent <= (-QUAD_MAXE - DECIMAL_STRING_LENGTH)) {	/* Guaranteed deep
665*0Sstevel@tonic-gate 											 * underflow. */
666*0Sstevel@tonic-gate 			goto underflow;
667*0Sstevel@tonic-gate 		} else {	/* Deep underflow possible, depending on
668*0Sstevel@tonic-gate 				 * string length. */
669*0Sstevel@tonic-gate 
670*0Sstevel@tonic-gate 			for (i = 0; (pd->ds[i] != 0) && (i < (-pd->exponent - QUAD_MAXE)); i++);
671*0Sstevel@tonic-gate 			if (i < (-pd->exponent - QUAD_MAXE)) {	/* Deep underflow */
672*0Sstevel@tonic-gate 		underflow:
673*0Sstevel@tonic-gate 				u.sign = pd->sign == 0 ? 0 : 1;
674*0Sstevel@tonic-gate 				u.fpclass = fp_normal;
675*0Sstevel@tonic-gate 				u.exponent = -0x000fffff;
676*0Sstevel@tonic-gate 				u.significand[0] = 0x80000000;
677*0Sstevel@tonic-gate 			} else {/* In range. */
678*0Sstevel@tonic-gate 		inrange:
679*0Sstevel@tonic-gate 				decimal_to_unpacked(&u, pd, 113);
680*0Sstevel@tonic-gate 			}
681*0Sstevel@tonic-gate 		}
682*0Sstevel@tonic-gate 		_fp_current_exceptions = 0;
683*0Sstevel@tonic-gate 		_fp_current_direction = pm->rd;
684*0Sstevel@tonic-gate 		_pack_quadruple(&u, px);
685*0Sstevel@tonic-gate 		*ps = _fp_current_exceptions;
686*0Sstevel@tonic-gate 		return;
687*0Sstevel@tonic-gate 	}
688*0Sstevel@tonic-gate #ifdef __STDC__
689*0Sstevel@tonic-gate 	*px = kluge.x;
690*0Sstevel@tonic-gate #else
691*0Sstevel@tonic-gate 	for (i = 0; i < 4; i++)
692*0Sstevel@tonic-gate 		px->u[i] = kluge.x.u[i];
693*0Sstevel@tonic-gate #endif
694*0Sstevel@tonic-gate }
695