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