/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1988 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* Conversion between binary and decimal floating point. */
#include "base_conversion.h"
/* PRIVATE FUNCTIONS */
/*
* Rounds decimal record *pd according to modes in *pm, recording exceptions
* for inexact or overflow in *ps. round is the round digit and sticky is 0
* or non-zero to indicate exact or inexact. pd->ndigits is expected to be
* correctly set.
*/
void
{
int lsd, i;
goto done;
}
case fp_nearest:
if (round < '5')
goto done;
if (round > '5')
goto roundup;
if (sticky != 0)
goto roundup;
/* Now in ambiguous case; round up if lsd is odd. */
goto done; /* Presumed 0. */
if ((lsd % 2) == 0)
goto done;
goto roundup;
case fp_positive:
goto done;
goto roundup;
case fp_negative:
goto done;
goto roundup;
case fp_tozero:
goto done;
}
if (i >= 0)
else { /* Rounding carry out has occurred. */
* adjust exponent. */
} else { /* For F format, increase length of string. */
}
}
goto ret;
done:
}
ret:
return;
}
/*
* Converts an unpacked integer value *pu into a decimal string in *ds, of
* length returned in *ndigs. Inexactness is indicated by setting
* ds[ndigs-1] odd.
*
* Arguments
* pu: Input unpacked integer value input.
* nsig: Input number of significant digits required.
* ds: Output decimal integer string output
* must be large enough.
* nzeros: Output number of implicit trailing zeros
* produced.
* ndigs: Output number of explicit digits produced
* in ds.
*/
void
{
int e, i, is;
char s[4];
d.bsize = _BIG_FLOAT_SIZE;
_unpacked_to_big_float(pu, &b, &e);
if (e < 0) {
_right_shift_base_two(&b, (short unsigned) -e, &stickyshift);
#ifdef DEBUG
assert(stickyshift == 0);
#endif
}
_big_binary_to_big_decimal(&b, &d);
if (e <= 0)
pd = &d;
else {
switch ((unsigned int)pd) {
case ((unsigned int)BIG_FLOAT_TIMES_TOOBIG):
{
break;
}
case ((unsigned int)BIG_FLOAT_TIMES_NOMEM):
{
break;
}
default:
#ifdef DEBUG
if (pd != &d)
(void) printf(" large binary exponent %d needs heap buffer \n", e);
printf(" product ");
#endif
break;
}
}
for (i = 0; s[i] == '0'; i++); /* Find first non-zero digit. */
for (is = 0; i <= 3;)
* 10**4 to decimal
* digits. */
is += 4;
}
if (pd != &d)
#ifdef DEBUG
#endif
}
/*
* Converts an unpacked fraction value *pu into a decimal string consisting
* of a) an implicit '.' b) *nzeros implicit leading zeros c) *ndigs explicit
* digits in ds ds contains at least nsig significant digits. nzeros + *
* *ndigs is at least nfrac digits after the point. Inexactness is indicated
* by sticking to the lsb.
*
* Arguments
*
* pu: Input unpacked fraction value output < 1
* in magnitude.
* nsig: Input number of significant digits
* required.
* nfrac: Input number of digits after point
* required.
* ds: Output decimal integer string output -
* must be large enough.
* nzeros: Output number of implicit leading zeros
* produced.
* ndigs: Output number of explicit digits produced
* in ds.
*/
void
{
char s[4];
*nzeros = 0;
for (i = 0; i <= nfrac; i++)
ds[i] = '0';
for (; i <= nsig; i++)
ds[i] = '0';
*ndigs = i;
return;
}
d.bsize = _BIG_FLOAT_SIZE;
_unpacked_to_big_float(pu, &b, &e);
/*
* e < 0 always
*/
b.bexponent = e;
#ifdef DEBUG
printf(" binary to decimal fraction exponent 2**%d \n", e);
printf(" binary to decimal fraction nsig %d nfrac %d tenpower %d tensig %d \n", nsig, nfrac, tenpower, tensig);
#endif
switch ((unsigned int)pb) {
case ((unsigned int)BIG_FLOAT_TIMES_TOOBIG):
{
break;
}
case ((unsigned int)BIG_FLOAT_TIMES_NOMEM):
{
break;
}
default:
#ifdef DEBUG
if (pb != &b)
printf(" product ");
#endif
break;
}
/* Have computed appropriate decimal part; now toss fraction. */
#ifdef DEBUG
#endif
if (i < excess)
* discarded fraction. */
}
if (stickyshift != 0)
}
_big_binary_to_big_decimal(pb, &d);
i = d.blength - 1;
while (d.bsignificand[i] == 0)
i--;
_fourdigitsquick((short unsigned) d.bsignificand[i], s);
for (j = 0; s[j] == '0'; j++); /* Find first non-zero digit. */
for (is = 0; j <= 3;)
for (i--; i >= 0; i--) {/* Convert powers of 10**4 to decimal digits. */
is += 4;
}
#ifdef DEBUG
#endif
* digits, and is were found. */
if (pb != &b)
#ifdef DEBUG
#endif
}
void
{
unsigned sticky = 0;
return;
* spec. */
return;
}
/* Divide x up into integer part ix and fraction part fx. */
* is conveniently on a word
* boundary. */
* integer; imask..SIZE are
* fraction. */
for (i = 0; i < imask; i++)
fx.significand[i] = 0;
for (; i < UNPACKED_SIZE; i++)
ix.significand[i] = 0;
_fp_normalize(&fx);
* middle of a word. */
* integer; imask is integer
* and fraction ;
* imask+1..SIZE are
* fraction. */
for (i = 0; i < imask; i++)
fx.significand[i] = 0;
ix.significand[i] = 0;
_fp_normalize(&fx);
}
* for E format, plus one for
* rounding. */
else
* for F format == all. */
} else {
intsigs = 0;
intzeros = 0;
}
fracdigs = 0;
* fraction part. */
* digits. */
* sticky. */
if (nsig > DECIMAL_STRING_LENGTH)
nfrac = 1;
} else { /* Need fraction digits. */
nsig = 0;
* sticky. */
if (nfrac > DECIMAL_STRING_LENGTH)
}
}
* format. */
/* Put integer into output string. */
* significant digits. */
else
round = '0';
sticky = 1;
sticky = 1;
} else {/* Integer part is exact - round from
* fraction. */
int stickystart;
/* Fraction non-zero. */
if (fraczeros > 0) { /* Round digit is zero. */
round = '0';
stickystart = 0; /* Stickies start with
* fs[0]. */
} else { /* Round digit is fs[0]. */
* fs[1]. */
}
if (sticky == 0) { /* Search for sticky
* bits. */
sticky = 1;
}
}
}
} else { /* Need more significant digits from fraction
* part. */
if (ids == 0) { /* No integer part - find first
* significant digit. */
for (i = 0; fs[i] == '0'; i++);
i += fraczeros; /* Point i at first
* significant digit. */
} else
i = 0;
* leading zeros
* required. */
else
for (; (i < lzbound); i++)
for (; (i < idsbound); i++)
i -= fraczeros; /* Don't worry about leading zeros
* from now on, we're just rounding */
if (i < fracsigs) { /* Gather rounding info. */
if (i < 0)
round = '0';
else
i++;
if (sticky == 0) { /* Find out if remainder
* is exact. */
if (i < 0)
i = 0;
if (i < fracsigs)
sticky = 1;
}
} else {/* Fraction part is exact - add zero digits
* if required. */
}
}
} else { /* Combine integer and fraction for F format. */
goto overflow;
/* Copy integer digits. */
* leading zeros
* required. */
else
for (i = 0; (i < lzbound); i++)
for (; (i < idsbound); i++)
/* Copy trailing zeros if necessary. */
i -= fraczeros; /* Don't worry about leading zeros
* from now on, we're just rounding */
if (i < fracsigs) { /* Gather rounding info. */
if (i < 0)
round = '0';
else
i++;
if (sticky == 0) { /* Find out if remainder
* is exact. */
if (i < 0)
i = 0;
if (i < fracsigs)
sticky = 1;
}
}
} else { /* Bizarre F format - round to left of point. */
if (intdigs >= DECIMAL_STRING_LENGTH)
goto overflow;
if (roundpos >= DECIMAL_STRING_LENGTH)
goto overflow;
* digits. */
i = 1;
} else {
round = '0';
i = 0;
}
/* Search for sticky bits. */
if (i < intsigs)
sticky = 1;
} else {/* Some integer digits do not get rounded
* away. */
#ifdef _NO_GOOD
#else
{
if (ncopy > 0) {
/* Copy integer digits. */
}
}
{
if (ncopy > 0) {
}
}
#endif /* _NO_GOOD */
/* Copy integer digits. */
/* Search for non-zero digits. */
sticky = 1;
}
}
sticky = 1;
* away digits. */
}
}
}
void
{
unpacked u;
*ps = 0; /* Initialize *ps. */
case fp_zero:
break;
case fp_infinity:
break;
case fp_quiet:
break;
case fp_signaling:
break;
default:
_unpack_double(&u, &kluge.x);
}
}
void
{
unpacked u;
int i;
*ps = 0; /* Initialize *ps - no exceptions. */
for (i = 0; i < 4; i++)
#ifdef __STDC__
#else
#endif
case fp_zero:
break;
case fp_infinity:
break;
case fp_quiet:
break;
case fp_signaling:
break;
default:
_unpack_quadruple(&u, px);
}
}