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