Home | History | Annotate | Download | only in common
      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