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