xref: /illumos-gate/usr/src/lib/libc/port/fp/double_decim.c (revision 628e3cbed6489fa1db545d8524a06cd6535af456)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Conversion from binary to decimal floating point
31  */
32 
33 #include "lint.h"
34 #include <stdlib.h>
35 #include "base_conversion.h"
36 
37 /*
38  * Any sensible programmer would inline the following routine where
39  * it is used below.  Unfortunately, the Sun SPARC compilers are not
40  * consistent in generating efficient code for this, so inlining it
41  * as written can cause the *_to_decimal functions to take twice as
42  * long in some cases.
43  *
44  * We might be tempted, then, to rewrite the source to match the most
45  * efficient code the compilers generate and inline that.  Alas, the
46  * most efficient code on SPARC uses 32x32->64 bit multiply, which
47  * can't be expressed directly in source code.  We could use long long,
48  * which would imply 64x64->64 bit multiply; this would work perfectly
49  * well on SPARC in v8plus mode.  But as of Solaris 10, libc for SPARC
50  * is still built in v8 mode, and of course, x86 is another story.
51  *
52  * We could also choose to use an inline template to get the most
53  * efficient code without incurring the full cost of a function call.
54  * Since I expect that would not buy much performance gain, and I
55  * prefer to avoid using inline templates for things that can be
56  * written in a perfectly straightforward way in C, I've settled
57  * for this implementation.  I hope that someday the compilers will
58  * get less flaky and/or someone will come up with a better way to
59  * do this.
60  */
61 static unsigned int
62 __quorem10000(unsigned int x, unsigned short *pr)
63 {
64 	*pr = x % 10000;
65 	return (x / 10000);
66 }
67 
68 /*
69  * Convert the integer part of a nonzero base-2^16 _big_float *pb
70  * to base 10^4 in **ppd.  The converted value is accurate to nsig
71  * significant digits.  On exit, *sticky is nonzero if *pb had a
72  * nonzero fractional part.  If pb->exponent > 0 and **ppd is not
73  * large enough to hold the final converted value (i.e., the con-
74  * verted significand scaled by 2^pb->exponent), then on exit,
75  * *ppd will point to a newly allocated _big_float, which must be
76  * freed by the caller.  (The number of significant digits we need
77  * should fit in pd, but __big_float_times_power may allocate new
78  * storage anyway because we could be multiplying by as much as
79  * 2^16271, which would require more than 4000 digits.)
80  *
81  * This routine does not check that **ppd is large enough to hold
82  * the result of converting the significand of *pb.
83  */
84 static void
85 __big_binary_to_big_decimal(_big_float *pb, int nsig, _big_float **ppd,
86     int *sticky)
87 {
88 	_big_float	*pd;
89 	int		i, j, len, s;
90 	unsigned int	carry;
91 
92 	pd = *ppd;
93 
94 	/* convert pb a digit at a time, most significant first */
95 	if (pb->bexponent + ((pb->blength - 1) << 4) >= 0) {
96 		carry = pb->bsignificand[pb->blength - 1];
97 		pd->bsignificand[1] = __quorem10000(carry,
98 		    &pd->bsignificand[0]);
99 		len = (pd->bsignificand[1])? 2 : 1;
100 		for (i = pb->blength - 2; i >= 0 &&
101 		    pb->bexponent + (i << 4) >= 0; i--) {
102 			/* multiply pd by 2^16 and add next digit */
103 			carry = pb->bsignificand[i];
104 			for (j = 0; j < len; j++) {
105 				carry += (unsigned int)pd->bsignificand[j]
106 				    << 16;
107 				carry = __quorem10000(carry,
108 				    &pd->bsignificand[j]);
109 			}
110 			while (carry != 0) {
111 				carry = __quorem10000(carry,
112 				    &pd->bsignificand[j]);
113 				j++;
114 			}
115 			len = j;
116 		}
117 	} else {
118 		i = pb->blength - 1;
119 		len = 0;
120 	}
121 
122 	/* convert any partial digit */
123 	if (i >= 0 && pb->bexponent + (i << 4) > -16) {
124 		s = pb->bexponent + (i << 4) + 16;
125 		/* multiply pd by 2^s and add partial digit */
126 		carry = pb->bsignificand[i] >> (16 - s);
127 		for (j = 0; j < len; j++) {
128 			carry += (unsigned int)pd->bsignificand[j] << s;
129 			carry = __quorem10000(carry, &pd->bsignificand[j]);
130 		}
131 		while (carry != 0) {
132 			carry = __quorem10000(carry, &pd->bsignificand[j]);
133 			j++;
134 		}
135 		len = j;
136 		s = pb->bsignificand[i] & ((1 << (16 - s)) - 1);
137 		i--;
138 	} else {
139 		s = 0;
140 	}
141 
142 	pd->blength = len;
143 	pd->bexponent = 0;
144 
145 	/* continue accumulating sticky flag */
146 	while (i >= 0)
147 		s |= pb->bsignificand[i--];
148 	*sticky = s;
149 
150 	if (pb->bexponent > 0) {
151 		/* scale pd by 2^pb->bexponent */
152 		__big_float_times_power(pd, 2, pb->bexponent, nsig, ppd);
153 	}
154 }
155 
156 /*
157  * Convert a base-10^4 _big_float *pf to a decimal string in *pd,
158  * rounding according to the modes in *pm and recording any exceptions
159  * in *ps.  If sticky is nonzero, then additional nonzero digits are
160  * assumed to follow those in *pf.  pd->sign must have already been
161  * filled in, and pd->fpclass is not modified.  The resulting string
162  * is stored in pd->ds, terminated by a null byte.  The length of this
163  * string is stored in pd->ndigits, and the corresponding exponent
164  * is stored in pd->exponent.  If the converted value is not exact,
165  * the inexact flag is set in *ps.
166  *
167  * When pm->df == fixed_form, we may discover that the result would
168  * have more than DECIMAL_STRING_LENGTH - 1 digits.  In this case,
169  * we put DECIMAL_STRING_LENGTH - 1 digits into *pd, adjusting both
170  * the exponent and the decimal place at which the value is rounded
171  * as need be, and we set the overflow flag in *ps.  (Raising overflow
172  * is a bug, but we have to do it to maintain backward compatibility.)
173  *
174  * *pf may be modified.
175  */
176 static void
177 __big_decimal_to_string(_big_float *pf, int sticky, decimal_mode *pm,
178     decimal_record *pd, fp_exception_field_type *ps)
179 {
180 	unsigned short	d;
181 	int		e, er, efirst, elast, i, is, j;
182 	char		s[4], round;
183 
184 	/* set e = floor(log10(*pf)) */
185 	i = pf->blength - 1;
186 	if (i < 0) {
187 		e = pf->bexponent = -DECIMAL_STRING_LENGTH - 2;
188 	} else {
189 		e = pf->bexponent + (i << 2);
190 		d = pf->bsignificand[i];
191 		if (d >= 1000)
192 			e += 3;
193 		else if (d >= 100)
194 			e += 2;
195 		else if (d >= 10)
196 			e++;
197 	}
198 
199 	/*
200 	 * Determine the power of ten after which to round and the
201 	 * powers corresponding to the first and last digits desired
202 	 * in the result.
203 	 */
204 	if (pm->df == fixed_form) {
205 		/* F format */
206 		er = -pm->ndigits;
207 		if (er < 0) {
208 			efirst = (e >= 0)? e : -1;
209 			elast = er;
210 		} else {
211 			efirst = (e >= er)? e : ((er > 0)? er - 1 : 0);
212 			elast = 0;
213 		}
214 
215 		/* check for possible overflow of pd->ds */
216 		if (efirst - elast >= DECIMAL_STRING_LENGTH - 1) {
217 			efirst = e;
218 			elast = e - DECIMAL_STRING_LENGTH + 2;
219 			if (er < elast)
220 				er = elast;
221 			*ps |= 1 << fp_overflow;
222 		}
223 	} else {
224 		/* E format */
225 		efirst = e;
226 		elast = er = e - pm->ndigits + 1;
227 	}
228 
229 	/* retrieve digits down to the (er - 1) place */
230 	is = 0;
231 	for (e = efirst; e >= pf->bexponent + (pf->blength << 2) &&
232 	    e >= er - 1; e--)
233 		pd->ds[is++] = '0';
234 
235 	i = pf->blength - 1;
236 	j = 3 - ((e - pf->bexponent) & 3);
237 	if (j > 0 && e >= er - 1) {
238 		__four_digits_quick(pf->bsignificand[i], s);
239 		while (j <= 3 && e >= er - 1) {
240 			pd->ds[is++] = s[j++];
241 			e--;
242 		}
243 		while (j <= 3)
244 			sticky |= (s[j++] - '0');
245 		i--;
246 	}
247 
248 	while ((i | (e - er - 2)) >= 0) {  /* i >= 0 && e >= er + 2 */
249 		__four_digits_quick(pf->bsignificand[i], pd->ds + is);
250 		is += 4;
251 		e -= 4;
252 		i--;
253 	}
254 
255 	if (i >= 0) {
256 		if (e >= er - 1) {
257 			__four_digits_quick(pf->bsignificand[i], s);
258 			for (j = 0; e >= er - 1; j++) {
259 				pd->ds[is++] = s[j];
260 				e--;
261 			}
262 			while (j <= 3)
263 				sticky |= (s[j++] - '0');
264 			i--;
265 		}
266 	} else {
267 		while (e-- >= er - 1)
268 			pd->ds[is++] = '0';
269 	}
270 
271 	/* collect rounding information */
272 	round = pd->ds[--is];
273 	while (i >= 0)
274 		sticky |= pf->bsignificand[i--];
275 
276 	/* add more trailing zeroes if need be */
277 	for (e = er - 1; e >= elast; e--)
278 		pd->ds[is++] = '0';
279 
280 	pd->exponent = elast;
281 	pd->ndigits = is;
282 	pd->ds[is] = '\0';
283 
284 	/* round */
285 	if (round == '0' && sticky == 0)
286 		return;
287 
288 	*ps |= 1 << fp_inexact;
289 
290 	switch (pm->rd) {
291 	case fp_nearest:
292 		if (round < '5' || (round == '5' && sticky == 0 &&
293 		    (is <= 0 || (pd->ds[is - 1] & 1) == 0)))
294 			return;
295 		break;
296 
297 	case fp_positive:
298 		if (pd->sign)
299 			return;
300 		break;
301 
302 	case fp_negative:
303 		if (!pd->sign)
304 			return;
305 		break;
306 
307 	default:
308 		return;
309 	}
310 
311 	/* round up */
312 	for (i = efirst - er; i >= 0 && pd->ds[i] == '9'; i--)
313 		pd->ds[i] = '0';
314 	if (i >= 0) {
315 		(pd->ds[i])++;
316 	} else {
317 		/* rounding carry out has occurred */
318 		pd->ds[0] = '1';
319 		if (pm->df == floating_form) {
320 			pd->exponent++;
321 		} else if (is == DECIMAL_STRING_LENGTH - 1) {
322 			pd->exponent++;
323 			*ps |= 1 << fp_overflow;
324 		} else {
325 			if (is > 0)
326 				pd->ds[is] = '0';
327 			is++;
328 			pd->ndigits = is;
329 			pd->ds[is] = '\0';
330 		}
331 	}
332 }
333 
334 /*
335  * Convert a binary floating point value represented by *pf to a
336  * decimal record *pd according to the modes in *pm.  Any exceptions
337  * incurred are passed back via *ps.
338  */
339 static void
340 __bigfloat_to_decimal(_big_float *bf, decimal_mode *pm, decimal_record *pd,
341     fp_exception_field_type *ps)
342 {
343 	_big_float	*pbf, *pbd, d;
344 	int		sticky, powten, sigbits, sigdigits, i;
345 
346 	/*
347 	 * If pm->ndigits is too large or too small, set the overflow
348 	 * flag in *ps and do nothing.  (Raising overflow is a bug,
349 	 * but we have to do it to maintain backward compatibility.)
350 	 */
351 	if (pm->ndigits >= DECIMAL_STRING_LENGTH || pm->ndigits <=
352 	    ((pm->df == floating_form)? 0 : -DECIMAL_STRING_LENGTH)) {
353 		*ps = 1 << fp_overflow;
354 		return;
355 	}
356 
357 	pbf = bf;
358 	powten = 0;
359 
360 	/* pre-scale to get the digits we want into the integer part */
361 	if (pm->df == fixed_form) {
362 		/* F format */
363 		if (pm->ndigits >= 0 && bf->bexponent < 0) {
364 			/*
365 			 * Scale by 10^min(-bf->bexponent, pm->ndigits + 1).
366 			 */
367 			powten = pm->ndigits + 1;
368 			if (powten > -bf->bexponent)
369 				powten = -bf->bexponent;
370 			/*
371 			 * Take sigbits large enough to get all integral
372 			 * digits correct.
373 			 */
374 			sigbits = bf->bexponent + (bf->blength << 4) +
375 			    (((powten * 217706) + 65535) >> 16);
376 			if (sigbits < 1)
377 				sigbits = 1;
378 			__big_float_times_power(bf, 10, powten, sigbits, &pbf);
379 		}
380 		sigdigits = DECIMAL_STRING_LENGTH + 1;
381 	} else {
382 		/* E format */
383 		if (bf->bexponent < 0) {
384 			/* i is a lower bound on log2(x) */
385 			i = bf->bexponent + ((bf->blength - 1) << 4);
386 			if (i <= 0 || ((i * 19728) >> 16) < pm->ndigits + 1) {
387 				/*
388 				 * Scale by 10^min(-bf->bexponent,
389 				 * pm->ndigits + 1 + u) where u is
390 				 * an upper bound on -log10(x).
391 				 */
392 				powten = pm->ndigits + 1;
393 				if (i < 0)
394 					powten += ((-i * 19729) + 65535) >> 16;
395 				else if (i > 0)
396 					powten -= (i * 19728) >> 16;
397 				if (powten > -bf->bexponent)
398 					powten = -bf->bexponent;
399 				/*
400 				 * Take sigbits large enough to get
401 				 * all integral digits correct.
402 				 */
403 				sigbits = i + 16 +
404 				    (((powten * 217706) + 65535) >> 16);
405 				__big_float_times_power(bf, 10, powten,
406 				    sigbits, &pbf);
407 			}
408 		}
409 		sigdigits = pm->ndigits + 2;
410 	}
411 
412 	/* convert to base 10^4 */
413 	d.bsize = _BIG_FLOAT_SIZE;
414 	pbd = &d;
415 	__big_binary_to_big_decimal(pbf, sigdigits, &pbd, &sticky);
416 
417 	/* adjust pbd->bexponent based on the scale factor above */
418 	pbd->bexponent -= powten;
419 
420 	/* convert to ASCII */
421 	__big_decimal_to_string(pbd, sticky, pm, pd, ps);
422 
423 	if (pbf != bf)
424 		(void) free((void *)pbf);
425 	if (pbd != &d)
426 		(void) free((void *)pbd);
427 }
428 
429 /* remove trailing zeroes from the significand of p */
430 static void
431 __shorten(_big_float *p)
432 {
433 	int	length = p->blength;
434 	int	zeros, i;
435 
436 	/* count trailing zeros */
437 	for (zeros = 0; zeros < length && p->bsignificand[zeros] == 0; zeros++)
438 		;
439 	if (zeros) {
440 		length -= zeros;
441 		p->bexponent += zeros << 4;
442 		for (i = 0; i < length; i++)
443 			p->bsignificand[i] = p->bsignificand[i + zeros];
444 		p->blength = length;
445 	}
446 }
447 
448 /*
449  * Unpack a normal or subnormal double into a _big_float.
450  */
451 static void
452 __double_to_bigfloat(double *px, _big_float *pf)
453 {
454 	double_equivalence	*x;
455 
456 	x = (double_equivalence *)px;
457 	pf->bsize = _BIG_FLOAT_SIZE;
458 	pf->bexponent = x->f.msw.exponent - DOUBLE_BIAS - 52;
459 	pf->blength = 4;
460 	pf->bsignificand[0] = x->f.significand2 & 0xffff;
461 	pf->bsignificand[1] = x->f.significand2 >> 16;
462 	pf->bsignificand[2] = x->f.msw.significand & 0xffff;
463 	pf->bsignificand[3] = x->f.msw.significand >> 16;
464 	if (x->f.msw.exponent == 0) {
465 		pf->bexponent++;
466 		while (pf->bsignificand[pf->blength - 1] == 0)
467 			pf->blength--;
468 	} else {
469 		pf->bsignificand[3] += 0x10;
470 	}
471 	__shorten(pf);
472 }
473 
474 /*
475  * Unpack a normal or subnormal extended into a _big_float.
476  */
477 static void
478 __extended_to_bigfloat(extended *px, _big_float *pf)
479 {
480 	extended_equivalence	*x;
481 
482 	x = (extended_equivalence *)px;
483 	pf->bsize = _BIG_FLOAT_SIZE;
484 	pf->bexponent = x->f.msw.exponent - EXTENDED_BIAS - 63;
485 	pf->blength = 4;
486 	pf->bsignificand[0] = x->f.significand2 & 0xffff;
487 	pf->bsignificand[1] = x->f.significand2 >> 16;
488 	pf->bsignificand[2] = x->f.significand & 0xffff;
489 	pf->bsignificand[3] = x->f.significand >> 16;
490 	if (x->f.msw.exponent == 0) {
491 		pf->bexponent++;
492 		while (pf->bsignificand[pf->blength - 1] == 0)
493 			pf->blength--;
494 	}
495 	__shorten(pf);
496 }
497 
498 /*
499  * Unpack a normal or subnormal quad into a _big_float.
500  */
501 static void
502 __quadruple_to_bigfloat(quadruple *px, _big_float *pf)
503 {
504 	quadruple_equivalence	*x;
505 
506 	x = (quadruple_equivalence *)px;
507 	pf->bsize = _BIG_FLOAT_SIZE;
508 	pf->bexponent = x->f.msw.exponent - QUAD_BIAS - 112;
509 	pf->bsignificand[0] = x->f.significand4 & 0xffff;
510 	pf->bsignificand[1] = x->f.significand4 >> 16;
511 	pf->bsignificand[2] = x->f.significand3 & 0xffff;
512 	pf->bsignificand[3] = x->f.significand3 >> 16;
513 	pf->bsignificand[4] = x->f.significand2 & 0xffff;
514 	pf->bsignificand[5] = x->f.significand2 >> 16;
515 	pf->bsignificand[6] = x->f.msw.significand;
516 	if (x->f.msw.exponent == 0) {
517 		pf->blength = 7;
518 		pf->bexponent++;
519 		while (pf->bsignificand[pf->blength - 1] == 0)
520 			pf->blength--;
521 	} else {
522 		pf->blength = 8;
523 		pf->bsignificand[7] = 1;
524 	}
525 	__shorten(pf);
526 }
527 
528 /* PUBLIC ROUTINES */
529 
530 void
531 single_to_decimal(single *px, decimal_mode *pm, decimal_record *pd,
532     fp_exception_field_type *ps)
533 {
534 	single_equivalence	*kluge;
535 	_big_float		bf;
536 	fp_exception_field_type	ef;
537 	double			x;
538 
539 	kluge = (single_equivalence *)px;
540 	pd->sign = kluge->f.msw.sign;
541 
542 	/* decide what to do based on the class of x */
543 	if (kluge->f.msw.exponent == 0) {	/* 0 or subnormal */
544 		if (kluge->f.msw.significand == 0) {
545 			pd->fpclass = fp_zero;
546 			*ps = 0;
547 			return;
548 		} else {
549 #if defined(__sparc)
550 			int	i;
551 
552 			pd->fpclass = fp_subnormal;
553 			/*
554 			 * On SPARC, simply converting *px to double
555 			 * can flush a subnormal value to zero when
556 			 * nonstandard mode is enabled, so we have
557 			 * to go through all this nonsense instead.
558 			 */
559 			i = *(int *)px;
560 			x = (double)(i & ~0x80000000);
561 			if (i < 0)
562 				x = -x;
563 			x *= 1.401298464324817070923730e-45; /* 2^-149 */
564 			ef = 0;
565 			if (__fast_double_to_decimal(&x, pm, pd, &ef)) {
566 				__double_to_bigfloat(&x, &bf);
567 				__bigfloat_to_decimal(&bf, pm, pd, &ef);
568 			}
569 			if (ef != 0)
570 				__base_conversion_set_exception(ef);
571 			*ps = ef;
572 			return;
573 #else
574 			pd->fpclass = fp_subnormal;
575 #endif
576 		}
577 	} else if (kluge->f.msw.exponent == 0xff) {	/* inf or nan */
578 		if (kluge->f.msw.significand == 0)
579 			pd->fpclass = fp_infinity;
580 		else if (kluge->f.msw.significand >= 0x400000)
581 			pd->fpclass = fp_quiet;
582 		else
583 			pd->fpclass = fp_signaling;
584 		*ps = 0;
585 		return;
586 	} else {
587 		pd->fpclass = fp_normal;
588 	}
589 
590 	ef = 0;
591 	x = *px;
592 	if (__fast_double_to_decimal(&x, pm, pd, &ef)) {
593 		__double_to_bigfloat(&x, &bf);
594 		__bigfloat_to_decimal(&bf, pm, pd, &ef);
595 	}
596 	if (ef != 0)
597 		__base_conversion_set_exception(ef);
598 	*ps = ef;
599 }
600 
601 void
602 double_to_decimal(double *px, decimal_mode *pm, decimal_record *pd,
603     fp_exception_field_type *ps)
604 {
605 	double_equivalence	*kluge;
606 	_big_float		bf;
607 	fp_exception_field_type	ef;
608 
609 	kluge = (double_equivalence *)px;
610 	pd->sign = kluge->f.msw.sign;
611 
612 	/* decide what to do based on the class of x */
613 	if (kluge->f.msw.exponent == 0) {	/* 0 or subnormal */
614 		if (kluge->f.msw.significand == 0 &&
615 		    kluge->f.significand2 == 0) {
616 			pd->fpclass = fp_zero;
617 			*ps = 0;
618 			return;
619 		} else {
620 			pd->fpclass = fp_subnormal;
621 		}
622 	} else if (kluge->f.msw.exponent == 0x7ff) {	/* inf or nan */
623 		if (kluge->f.msw.significand == 0 &&
624 		    kluge->f.significand2 == 0)
625 			pd->fpclass = fp_infinity;
626 		else if (kluge->f.msw.significand >= 0x80000)
627 			pd->fpclass = fp_quiet;
628 		else
629 			pd->fpclass = fp_signaling;
630 		*ps = 0;
631 		return;
632 	} else {
633 		pd->fpclass = fp_normal;
634 	}
635 
636 	ef = 0;
637 	if (__fast_double_to_decimal(px, pm, pd, &ef)) {
638 		__double_to_bigfloat(px, &bf);
639 		__bigfloat_to_decimal(&bf, pm, pd, &ef);
640 	}
641 	if (ef != 0)
642 		__base_conversion_set_exception(ef);
643 	*ps = ef;
644 }
645 
646 void
647 extended_to_decimal(extended *px, decimal_mode *pm, decimal_record *pd,
648     fp_exception_field_type *ps)
649 {
650 	extended_equivalence	*kluge;
651 	_big_float		bf;
652 	fp_exception_field_type	ef;
653 
654 	kluge = (extended_equivalence *)px;
655 	pd->sign = kluge->f.msw.sign;
656 
657 	/* decide what to do based on the class of x */
658 	if (kluge->f.msw.exponent == 0) {	/* 0 or subnormal */
659 		if ((kluge->f.significand | kluge->f.significand2) == 0) {
660 			pd->fpclass = fp_zero;
661 			*ps = 0;
662 			return;
663 		} else {
664 			/*
665 			 * x could be a pseudo-denormal, but the distinction
666 			 * doesn't matter
667 			 */
668 			pd->fpclass = fp_subnormal;
669 		}
670 	} else if ((kluge->f.significand & 0x80000000) == 0) {
671 		/*
672 		 * In Intel's extended format, if the exponent is
673 		 * nonzero but the explicit integer bit is zero, this
674 		 * is an "unsupported format" bit pattern; treat it
675 		 * like a signaling NaN.
676 		 */
677 		pd->fpclass = fp_signaling;
678 		*ps = 0;
679 		return;
680 	} else if (kluge->f.msw.exponent == 0x7fff) {	/* inf or nan */
681 		if (((kluge->f.significand & 0x7fffffff) |
682 		    kluge->f.significand2) == 0)
683 			pd->fpclass = fp_infinity;
684 		else if ((kluge->f.significand & 0x7fffffff) >= 0x40000000)
685 			pd->fpclass = fp_quiet;
686 		else
687 			pd->fpclass = fp_signaling;
688 		*ps = 0;
689 		return;
690 	} else {
691 		pd->fpclass = fp_normal;
692 	}
693 
694 	ef = 0;
695 	__extended_to_bigfloat(px, &bf);
696 	__bigfloat_to_decimal(&bf, pm, pd, &ef);
697 	if (ef != 0)
698 		__base_conversion_set_exception(ef);
699 	*ps = ef;
700 }
701 
702 void
703 quadruple_to_decimal(quadruple *px, decimal_mode *pm, decimal_record *pd,
704     fp_exception_field_type *ps)
705 {
706 	quadruple_equivalence	*kluge;
707 	_big_float		bf;
708 	fp_exception_field_type	ef;
709 
710 	kluge = (quadruple_equivalence *)px;
711 	pd->sign = kluge->f.msw.sign;
712 
713 	/* decide what to do based on the class of x */
714 	if (kluge->f.msw.exponent == 0) {	/* 0 or subnormal */
715 		if (kluge->f.msw.significand == 0 &&
716 		    (kluge->f.significand2 | kluge->f.significand3 |
717 		    kluge->f.significand4) == 0) {
718 			pd->fpclass = fp_zero;
719 			*ps = 0;
720 			return;
721 		} else {
722 			pd->fpclass = fp_subnormal;
723 		}
724 	} else if (kluge->f.msw.exponent == 0x7fff) {	/* inf or nan */
725 		if (kluge->f.msw.significand == 0 &&
726 		    (kluge->f.significand2 | kluge->f.significand3 |
727 		    kluge->f.significand4) == 0)
728 			pd->fpclass = fp_infinity;
729 		else if (kluge->f.msw.significand >= 0x8000)
730 			pd->fpclass = fp_quiet;
731 		else
732 			pd->fpclass = fp_signaling;
733 		*ps = 0;
734 		return;
735 	} else {
736 		pd->fpclass = fp_normal;
737 	}
738 
739 	ef = 0;
740 	__quadruple_to_bigfloat(px, &bf);
741 	__bigfloat_to_decimal(&bf, pm, pd, &ef);
742 	if (ef != 0)
743 		__base_conversion_set_exception(ef);
744 	*ps = ef;
745 }
746