xref: /titanic_50/usr/src/lib/libbc/libc/gen/common/double_decim.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
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 1988 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 /* Conversion between binary and decimal floating point. */
30 
31 #include "base_conversion.h"
32 
33 /* PRIVATE FUNCTIONS */
34 
35 /*
36  * Rounds decimal record *pd according to modes in *pm, recording exceptions
37  * for inexact or overflow in *ps.  round is the round digit and sticky is 0
38  * or non-zero to indicate exact or inexact. pd->ndigits is expected to be
39  * correctly set.
40  */
41 void
decimal_round(decimal_mode * pm,decimal_record * pd,fp_exception_field_type * ps,char round,unsigned sticky)42 decimal_round(decimal_mode *pm, decimal_record *pd, fp_exception_field_type *ps,
43     char round, unsigned sticky)
44 {
45 	int             lsd, i;
46 
47 	if ((round == '0') && (sticky == 0)) {	/* Exact. */
48 		goto done;
49 	}
50 	*ps |= 1 << fp_inexact;
51 
52 	switch (pm->rd) {
53 	case fp_nearest:
54 		if (round < '5')
55 			goto done;
56 		if (round > '5')
57 			goto roundup;
58 		if (sticky != 0)
59 			goto roundup;
60 		/* Now in ambiguous case; round up if lsd is odd. */
61 		if (pd->ndigits <= 0)
62 			goto done;	/* Presumed 0. */
63 		lsd = pd->ds[pd->ndigits - 1] - '0';
64 		if ((lsd % 2) == 0)
65 			goto done;
66 		goto roundup;
67 	case fp_positive:
68 		if (pd->sign != 0)
69 			goto done;
70 		goto roundup;
71 	case fp_negative:
72 		if (pd->sign == 0)
73 			goto done;
74 		goto roundup;
75 	case fp_tozero:
76 		goto done;
77 	}
78 roundup:
79 	for (i = (pd->ndigits - 1); (pd->ds[i] == '9') && (i >= 0); i--)
80 		pd->ds[i] = '0';
81 	if (i >= 0)
82 		(pd->ds[i])++;
83 	else {			/* Rounding carry out has occurred. */
84 		pd->ds[0] = '1';
85 		if (pm->df == floating_form) {	/* For E format, simply
86 						 * adjust exponent. */
87 			pd->exponent++;
88 		} else {	/* For F format, increase length of string. */
89 			if (pd->ndigits > 0)
90 				pd->ds[pd->ndigits] = '0';
91 			pd->ndigits++;
92 		}
93 	}
94 	goto ret;
95 done:
96 	if (pd->ndigits <= 0) {	/* Create zero string. */
97 		pd->ds[0] = '0';
98 		pd->ndigits = 1;
99 	}
100 ret:
101 	pd->ds[pd->ndigits] = 0;/* Terminate string. */
102 	return;
103 }
104 
105 /*
106  * Converts an unpacked integer value *pu into a decimal string in *ds, of
107  * length returned in *ndigs. Inexactness is indicated by setting
108  * ds[ndigs-1] odd.
109  *
110  * Arguments
111  *	pu:		Input unpacked integer value input.
112  *	nsig:		Input number of significant digits required.
113  *	ds:		Output decimal integer string output
114  *			must be large enough.
115  *	nzeros:		Output number of implicit trailing zeros
116  *			produced.
117  *	ndigs:		Output number of explicit digits produced
118  *			in ds.
119  */
120 void
binary_to_decimal_integer(unpacked * pu,unsigned nsig,char ds[],unsigned * nzeros,unsigned * ndigs)121 binary_to_decimal_integer(unpacked *pu, unsigned nsig, char ds[],
122     unsigned *nzeros, unsigned *ndigs)
123 {
124 
125 	_big_float     *pd, b, d;
126 	int             e, i, is;
127 	_BIG_FLOAT_DIGIT stickyshift;
128 	char            s[4];
129 
130 	b.bsize = _BIG_FLOAT_SIZE;	/* Initialize sizes of big floats. */
131 	d.bsize = _BIG_FLOAT_SIZE;
132 	_unpacked_to_big_float(pu, &b, &e);
133 	if (e < 0) {
134 		_right_shift_base_two(&b, (short unsigned) -e, &stickyshift);
135 #ifdef DEBUG
136 		assert(stickyshift == 0);
137 #endif
138 	}
139 	_big_binary_to_big_decimal(&b, &d);
140 	if (e <= 0)
141 		pd = &d;
142 	else {
143 		_big_float_times_power(&d, 2, e, (int) nsig, &pd);
144 		switch ((unsigned int)pd) {
145 		case ((unsigned int)BIG_FLOAT_TIMES_TOOBIG):
146 			{
147 				char            bcastring[80];
148 
149 				(void) sprintf(bcastring, " binary exponent %d ", e);
150 				_base_conversion_abort(ERANGE, bcastring);
151 				break;
152 			}
153 		case ((unsigned int)BIG_FLOAT_TIMES_NOMEM):
154 			{
155 				char            bcastring[80];
156 
157 				(void) sprintf(bcastring, " binary exponent %d ", e);
158 				_base_conversion_abort(ENOMEM, bcastring);
159 				break;
160 			}
161 		default:
162 #ifdef DEBUG
163 			if (pd != &d)
164 				(void) printf(" large binary exponent %d needs heap buffer \n", e);
165 			printf(" product ");
166 			_display_big_float(pd, 10);
167 #endif
168 			break;
169 		}
170 	}
171 	_fourdigitsquick((short unsigned) pd->bsignificand[pd->blength - 1], s);
172 	for (i = 0; s[i] == '0'; i++);	/* Find first non-zero digit. */
173 	for (is = 0; i <= 3;)
174 		ds[is++] = s[i++];	/* Copy subsequent digits. */
175 
176 	for (i = (pd->blength - 2); i >= 0; i--) {	/* Convert powers of
177 							 * 10**4 to decimal
178 							 * digits. */
179 		_fourdigitsquick((short unsigned) pd->bsignificand[i], &(ds[is]));
180 		is += 4;
181 	}
182 
183 	ds[is] = 0;
184 	*ndigs = is;
185 	*nzeros = pd->bexponent;
186 	if (pd != &d)
187 		_free_big_float(pd);
188 
189 #ifdef DEBUG
190 	printf(" binary to decimal integer result %s * 10**%d \n", ds, *nzeros);
191 #endif
192 }
193 
194 /*
195  * Converts an unpacked fraction value *pu into a decimal string consisting
196  * of a) an implicit '.' b) *nzeros implicit leading zeros c) *ndigs explicit
197  * digits in ds ds contains at least nsig significant digits. nzeros + *
198  * *ndigs is at least nfrac digits after the point. Inexactness is indicated
199  * by sticking to the lsb.
200  *
201  * Arguments
202  *
203  *	pu:		Input unpacked fraction value output < 1
204  *			in magnitude.
205  *	nsig:		Input number of significant digits
206  *			required.
207  *	nfrac:		Input number of digits after point
208  *			required.
209  *	ds:		Output decimal integer string output -
210  *			must be large enough.
211  *	nzeros:		Output number of implicit leading zeros
212  *			produced.
213  *	ndigs:		Output number of explicit digits produced
214  *			in ds.
215  */
216  void
binary_to_decimal_fraction(unpacked * pu,unsigned nsig,unsigned nfrac,char ds[],int * nzeros,int * ndigs)217 binary_to_decimal_fraction(unpacked *pu, unsigned nsig, unsigned nfrac,
218     char ds[], int *nzeros, int *ndigs)
219 {
220 	_big_float     *pb, b, d;
221 	int             e, i, j, is, excess;
222 	char            s[4];
223 	int             tensig, tenpower;
224 	_BIG_FLOAT_DIGIT stickyshift;
225 
226 	*nzeros = 0;
227 	if (pu->fpclass == fp_zero) {	/* Exact zero. */
228 		for (i = 0; i <= nfrac; i++)
229 			ds[i] = '0';
230 		for (; i <= nsig; i++)
231 			ds[i] = '0';
232 		*ndigs = i;
233 		return;
234 	}
235 	b.bsize = _BIG_FLOAT_SIZE;	/* Initialize sizes of big floats. */
236 	d.bsize = _BIG_FLOAT_SIZE;
237 	_unpacked_to_big_float(pu, &b, &e);
238 	/*
239 	 * e < 0 always
240 	 */
241 	b.bexponent = e;
242 	tenpower = nsig + (int) (((17 - e - 16 * b.blength) * (unsigned long) 19729) >> 16);
243 	if (tenpower < nfrac)
244 		tenpower = nfrac;
245 	tensig = nfrac;
246 	if (nsig > tensig)
247 		tensig = nsig;
248 	tensig = 1 + (((tensig + 2) * 217706) >> 16);
249 	tensig = -tensig;
250 
251 #ifdef DEBUG
252 	printf(" binary to decimal fraction exponent 2**%d \n", e);
253 	printf(" binary to decimal fraction nsig %d nfrac %d tenpower %d tensig %d \n", nsig, nfrac, tenpower, tensig);
254 #endif
255 	_big_float_times_power(&b, 10, tenpower, tensig, &pb);
256 	switch ((unsigned int)pb) {
257 	case ((unsigned int)BIG_FLOAT_TIMES_TOOBIG):
258 		{
259 			char            bcastring[80];
260 
261 			(void) sprintf(bcastring, " decimal exponent %d ", tenpower);
262 			_base_conversion_abort(ERANGE, bcastring);
263 			break;
264 		}
265 	case ((unsigned int)BIG_FLOAT_TIMES_NOMEM):
266 		{
267 			char            bcastring[80];
268 
269 			(void) sprintf(bcastring, " decimal exponent %d ", tenpower);
270 			_base_conversion_abort(ENOMEM, bcastring);
271 			break;
272 		}
273 	default:
274 #ifdef DEBUG
275 		if (pb != &b)
276 			printf(" large decimal exponent %d needs heap buffer \n", tenpower);
277 		printf(" product ");
278 		_display_big_float(pb, 2);
279 #endif
280 		break;
281 	}
282 
283 	if (pb->bexponent <= -16) {
284 		/* Have computed appropriate decimal part; now toss fraction. */
285 		excess = (-pb->bexponent) / 16;
286 #ifdef DEBUG
287 		printf(" discard %d excess fraction bits \n", 16 * excess);
288 #endif
289 		for (i = 0; (i < excess) && (pb->bsignificand[i] == 0); i++);
290 		if (i < excess)
291 			pb->bsignificand[excess] |= 1;	/* Sticky bit for
292 							 * discarded fraction. */
293 		for (i = excess; i < pb->blength; i++)
294 			pb->bsignificand[i - excess] = pb->bsignificand[i];
295 
296 		pb->blength -= excess;
297 		pb->bexponent += 16 * excess;
298 	}
299 	if (pb->bexponent < 0) {
300 		_right_shift_base_two(pb, (short unsigned) -pb->bexponent, &stickyshift);
301 		if (stickyshift != 0)
302 			pb->bsignificand[0] |= 1;	/* Stick to lsb. */
303 	}
304 	_big_binary_to_big_decimal(pb, &d);
305 
306 	i = d.blength - 1;
307 	while (d.bsignificand[i] == 0)
308 		i--;
309 	_fourdigitsquick((short unsigned) d.bsignificand[i], s);
310 	for (j = 0; s[j] == '0'; j++);	/* Find first non-zero digit. */
311 	for (is = 0; j <= 3;)
312 		ds[is++] = s[j++];	/* Copy subsequent digits. */
313 
314 	for (i--; i >= 0; i--) {/* Convert powers of 10**4 to decimal digits. */
315 		_fourdigitsquick((short unsigned) d.bsignificand[i], &(ds[is]));
316 		is += 4;
317 	}
318 
319 	ds[is] = 0;
320 	*ndigs = is;
321 #ifdef DEBUG
322 	assert(tenpower >= is);
323 #endif
324 	*nzeros = tenpower - is;/* There were supposed to be tenpower leading
325 				 * digits, and is were found. */
326 
327 	if (pb != &b)
328 		_free_big_float(pb);
329 
330 #ifdef DEBUG
331 	printf(" binary to decimal fraction result .%s * 10**%d \n", ds, -(*nzeros));
332 #endif
333 
334 }
335 
336 void
_unpacked_to_decimal(unpacked * px,decimal_mode * pm,decimal_record * pd,fp_exception_field_type * ps)337 _unpacked_to_decimal(unpacked *px, decimal_mode *pm, decimal_record *pd,
338     fp_exception_field_type *ps)
339 {
340 	unpacked        fx, ix;
341 	unsigned        fmask, imask;
342 	int             i, intdigs, fracdigs, fraczeros, fracsigs, ids, idsbound, lzbound;
343 	unsigned        nsig, nfrac, intzeros, intsigs;
344 	char            is[_INTEGER_SIZE], fs[DECIMAL_STRING_LENGTH];
345 	char            round = '0';
346 	unsigned        sticky = 0;
347 
348 	pd->sign = px->sign;
349 	pd->fpclass = px->fpclass;
350 	if ((px->fpclass != fp_normal) && (px->fpclass != fp_subnormal))
351 		return;
352 	if ((pm->ndigits >= DECIMAL_STRING_LENGTH) ||
353 	    ((pm->df == floating_form) && (pm->ndigits < 1))) {	/* Gross overflow or bad
354 								 * spec. */
355 overflow:
356 		*ps |= 1 << fp_overflow;
357 		return;
358 	}
359 	/* Divide x up into integer part ix and fraction part fx.	 */
360 
361 	ix = *px;
362 	fx = ix;
363 	if (ix.exponent <= -1) {/* All fraction. */
364 		ix.fpclass = fp_zero;
365 	} else if (ix.exponent >= 159) {	/* All integer. */
366 		fx.fpclass = fp_zero;
367 	} else if ((ix.exponent % 32) == 31) {	/* Integer/fraction boundary
368 						 * is conveniently on a word
369 						 * boundary. */
370 		imask = (ix.exponent + 1) / 32;	/* Words 0..imask-1 are
371 						 * integer; imask..SIZE are
372 						 * fraction. */
373 		for (i = 0; i < imask; i++)
374 			fx.significand[i] = 0;
375 		for (; i < UNPACKED_SIZE; i++)
376 			ix.significand[i] = 0;
377 		_fp_normalize(&fx);
378 	} else {		/* Integer/fraction boundary falls in the
379 				 * middle of a word. */
380 		imask = (ix.exponent + 1) / 32;	/* Words 0..imask-1 are
381 						 * integer; imask is integer
382 						 * and fraction ;
383 						 * imask+1..SIZE are
384 						 * fraction. */
385 		for (i = 0; i < imask; i++)
386 			fx.significand[i] = 0;
387 		fmask = (1 << (31 - (ix.exponent % 32))) - 1;
388 		fx.significand[imask] &= fmask;
389 		ix.significand[imask] &= ~fmask;
390 		for (i = (imask + 1); i < UNPACKED_SIZE; i++)
391 			ix.significand[i] = 0;
392 		_fp_normalize(&fx);
393 	}
394 	if (ix.fpclass != fp_zero) {	/* Compute integer part of result. */
395 		if (pm->df == floating_form)
396 			nsig = pm->ndigits + 1;	/* Significant digits wanted
397 						 * for E format, plus one for
398 						 * rounding. */
399 		else
400 			nsig = _INTEGER_SIZE;	/* Significant digits wanted
401 						 * for F format == all. */
402 
403 		binary_to_decimal_integer(&ix, nsig, is, &intzeros, &intsigs);
404 	} else {
405 		intsigs = 0;
406 		intzeros = 0;
407 	}
408 	intdigs = intsigs + intzeros;
409 	fracdigs = 0;
410 	if (((pm->df == fixed_form) && (pm->ndigits >= 0)) ||
411 	    ((pm->df == floating_form) && ((pm->ndigits + 1) > intdigs))) {	/* Need to compute
412 										 * fraction part. */
413 		if (pm->df == floating_form) {	/* Need more significant
414 						 * digits. */
415 			nsig = pm->ndigits + 2 - intdigs;	/* Add two for rounding,
416 								 * sticky. */
417 			if (nsig > DECIMAL_STRING_LENGTH)
418 				nsig = DECIMAL_STRING_LENGTH;
419 			nfrac = 1;
420 		} else {	/* Need fraction digits. */
421 			nsig = 0;
422 			nfrac = pm->ndigits + 2;	/* Add two for rounding,
423 							 * sticky. */
424 			if (nfrac > DECIMAL_STRING_LENGTH)
425 				nfrac = DECIMAL_STRING_LENGTH;
426 		}
427 		binary_to_decimal_fraction(&fx, nsig, nfrac, fs, &fraczeros, &fracsigs);
428 		fracdigs = fraczeros + fracsigs;
429 	}
430 	if (pm->df == floating_form) {	/* Combine integer and fraction for E
431 					 * format. */
432 		idsbound = intsigs;
433 		if (idsbound > pm->ndigits)
434 			idsbound = pm->ndigits;
435 		for (ids = 0; ids < idsbound; ids++)
436 			pd->ds[ids] = is[ids];
437 		/* Put integer into output string. */
438 		idsbound = intsigs + intzeros;
439 		if (idsbound > pm->ndigits)
440 			idsbound = pm->ndigits;
441 		for (; ids < idsbound; ids++)
442 			pd->ds[ids] = '0';
443 		if (ids == pm->ndigits) {	/* Integer part had enough
444 						 * significant digits. */
445 			pd->ndigits = ids;
446 			pd->exponent = intdigs - ids;
447 			if (ids < intdigs) {	/* Gather rounding info. */
448 				if (ids < intsigs)
449 					round = is[ids++];
450 				else
451 					round = '0';
452 				for (; (is[ids] == '0') && (ids < intsigs); ids++);
453 				if (ids < intsigs)
454 					sticky = 1;
455 				if (fx.fpclass != fp_zero)
456 					sticky = 1;
457 			} else {/* Integer part is exact - round from
458 				 * fraction. */
459 				if (fx.fpclass != fp_zero) {
460 					int             stickystart;
461 					/* Fraction non-zero. */
462 					if (fraczeros > 0) {	/* Round digit is zero. */
463 						round = '0';
464 						stickystart = 0;	/* Stickies start with
465 									 * fs[0]. */
466 					} else {	/* Round digit is fs[0]. */
467 						round = fs[0];
468 						stickystart = 1;	/* Stickies start with
469 									 * fs[1]. */
470 					}
471 					if (sticky == 0) {	/* Search for sticky
472 								 * bits. */
473 						for (ids = stickystart; (fs[ids] == '0') && (ids < fracdigs); ids++);
474 						if (ids < fracdigs)
475 							sticky = 1;
476 					}
477 				}
478 			}
479 		} else {	/* Need more significant digits from fraction
480 				 * part. */
481 			idsbound = pm->ndigits - ids;
482 			if (ids == 0) {	/* No integer part - find first
483 					 * significant digit. */
484 				for (i = 0; fs[i] == '0'; i++);
485 				idsbound = i + idsbound + fraczeros;
486 				i += fraczeros;	/* Point i at first
487 						 * significant digit. */
488 			} else
489 				i = 0;
490 			if (idsbound > fracdigs)
491 				idsbound = fracdigs;
492 			pd->exponent = -idsbound;
493 
494 			if (fraczeros < idsbound)	/* Compute number of
495 							 * leading zeros
496 							 * required. */
497 				lzbound = fraczeros;
498 			else
499 				lzbound = idsbound;
500 			for (; (i < lzbound); i++)
501 				pd->ds[ids++] = '0';
502 			for (; (i < idsbound); i++)
503 				pd->ds[ids++] = fs[i - fraczeros];
504 			i -= fraczeros;	/* Don't worry about leading zeros
505 					 * from now on, we're just rounding */
506 			if (i < fracsigs) {	/* Gather rounding info.  */
507 				if (i < 0)
508 					round = '0';
509 				else
510 					round = fs[i];
511 				i++;
512 				if (sticky == 0) {	/* Find out if remainder
513 							 * is exact. */
514 					if (i < 0)
515 						i = 0;
516 					for (; (fs[i] == '0') && (i < fracsigs); i++);
517 					if (i < fracsigs)
518 						sticky = 1;
519 				}
520 			} else {/* Fraction part is exact - add zero digits
521 				 * if required. */
522 				for (; ids < pm->ndigits; ids++)
523 					pd->ds[ids] = '0';
524 			}
525 			pd->ndigits = ids;
526 		}
527 		decimal_round(pm, pd, ps, round, sticky);
528 	} else {		/* Combine integer and fraction for F format. */
529 		if (pm->ndigits >= 0) {	/* Normal F format. */
530 			if ((intdigs + pm->ndigits) >= DECIMAL_STRING_LENGTH)
531 				goto overflow;
532 			for (ids = 0; ids < intsigs; ids++)
533 				pd->ds[ids] = is[ids];
534 			for (; ids < intdigs; ids++)
535 				pd->ds[ids] = '0';
536 			/* Copy integer digits. */
537 			idsbound = fracdigs;
538 			if (idsbound > pm->ndigits)
539 				idsbound = pm->ndigits;
540 			if (fraczeros < idsbound)	/* Compute number of
541 							 * leading zeros
542 							 * required. */
543 				lzbound = fraczeros;
544 			else
545 				lzbound = idsbound;
546 			for (i = 0; (i < lzbound); i++)
547 				pd->ds[ids++] = '0';
548 			for (; (i < idsbound); i++)
549 				pd->ds[ids++] = fs[i - fraczeros];	/* Copy fraction digits. */
550 			for (; i < pm->ndigits; i++)
551 				pd->ds[ids++] = '0';
552 			/* Copy trailing zeros if necessary. */
553 			pd->ndigits = ids;
554 			pd->exponent = intdigs - ids;
555 			i -= fraczeros;	/* Don't worry about leading zeros
556 					 * from now on, we're just rounding */
557 			if (i < fracsigs) {	/* Gather rounding info.  */
558 				if (i < 0)
559 					round = '0';
560 				else
561 					round = fs[i];
562 				i++;
563 				if (sticky == 0) {	/* Find out if remainder
564 							 * is exact. */
565 					if (i < 0)
566 						i = 0;
567 					for (; (fs[i] == '0') && (i < fracsigs); i++);
568 					if (i < fracsigs)
569 						sticky = 1;
570 				}
571 			}
572 			decimal_round(pm, pd, ps, round, sticky);
573 		} else {	/* Bizarre F format - round to left of point. */
574 			int             roundpos = -pm->ndigits;
575 
576 			if (intdigs >= DECIMAL_STRING_LENGTH)
577 				goto overflow;
578 			if (roundpos >= DECIMAL_STRING_LENGTH)
579 				goto overflow;
580 			if (intdigs <= roundpos) {	/* Not enough integer
581 							 * digits. */
582 				if (intdigs == roundpos) {
583 					round = is[0];
584 					i = 1;
585 				} else {
586 					round = '0';
587 					i = 0;
588 				}
589 				for (; (is[i] == '0') && (i < intsigs); i++);
590 				/* Search for sticky bits. */
591 				if (i < intsigs)
592 					sticky = 1;
593 				pd->ndigits = 0;
594 			} else {/* Some integer digits do not get rounded
595 				 * away. */
596 #ifdef _NO_GOOD
597 				for (ids = 0; ids < (intsigs - roundpos); ids++)
598 					pd->ds[ids] = is[ids];
599 				for (ids = 0; ids < (intdigs - roundpos); ids++)
600 					pd->ds[ids] = '0';
601 #else
602                                  {
603                                          int             ncopy = intsigs - roundpos;
604                                          if (ncopy > 0) {
605                                                  /* Copy integer digits. */
606                                                  (void) memcpy(&(pd->ds[0]), &(is[0]), ncopy);
607                                                  ids = ncopy;
608                                          }
609                                  }
610                                  {
611                                          int             ncopy = intdigs - roundpos - ids ;
612                                          if (ncopy > 0) {
613                                                  (void) memset(&(pd->ds[ids]), '0', ncopy);
614                                                  ids += ncopy;
615                                          }
616                                  }
617 #endif /* _NO_GOOD */
618 				/* Copy integer digits. */
619 				pd->ndigits = ids;
620 				if (ids < intsigs) {	/* Inexact. */
621 					round = is[ids++];
622 					for (; (is[ids] == '0') && (ids < intsigs); ids++);
623 					/* Search for non-zero digits. */
624 					if (ids < intsigs)
625 						sticky = 1;
626 				}
627 			}
628 			if (fx.fpclass != fp_zero)
629 				sticky = 1;
630 			decimal_round(pm, pd, ps, round, sticky);
631 			for (i = pd->ndigits; i < (pd->ndigits + roundpos); i++)
632 				pd->ds[i] = '0';	/* Blank out rounded
633 							 * away digits. */
634 			pd->exponent = 0;
635 			pd->ndigits = i;
636 			pd->ds[i] = 0;	/* Terminate string. */
637 		}
638 	}
639 }
640 
641 void
double_to_decimal(double * px,decimal_mode * pm,decimal_record * pd,fp_exception_field_type * ps)642 double_to_decimal(double *px, decimal_mode *pm, decimal_record *pd,
643     fp_exception_field_type *ps)
644 {
645 	double_equivalence kluge;
646 	unpacked        u;
647 
648 	*ps = 0;		/* Initialize *ps. */
649 	kluge.x = *px;
650 	pd->sign = kluge.f.msw.sign;
651 	pd->fpclass = _class_double(px);
652 	switch (pd->fpclass) {
653 	case fp_zero:
654 		break;
655 	case fp_infinity:
656 		break;
657 	case fp_quiet:
658 		break;
659 	case fp_signaling:
660 		break;
661 	default:
662 		_unpack_double(&u, &kluge.x);
663 		_unpacked_to_decimal(&u, pm, pd, ps);
664 	}
665 }
666 
667 void
quadruple_to_decimal(quadruple * px,decimal_mode * pm,decimal_record * pd,fp_exception_field_type * ps)668 quadruple_to_decimal(quadruple *px, decimal_mode *pm, decimal_record *pd,
669     fp_exception_field_type *ps)
670 {
671 	quadruple_equivalence kluge;
672 	unpacked        u;
673 	int             i;
674 
675 	*ps = 0;		/* Initialize *ps - no exceptions. */
676 	for (i = 0; i < 4; i++)
677 #ifdef __STDC__
678 		kluge.x = *px;
679 #else
680 		kluge.x.u[i] = px->u[i];
681 #endif
682 	pd->sign = kluge.f.msw.sign;
683 	pd->fpclass = _class_quadruple(px);
684 	switch (pd->fpclass) {
685 	case fp_zero:
686 		break;
687 	case fp_infinity:
688 		break;
689 	case fp_quiet:
690 		break;
691 	case fp_signaling:
692 		break;
693 	default:
694 		_unpack_quadruple(&u, px);
695 		_unpacked_to_decimal(&u, pm, pd, ps);
696 	}
697 }
698