Home | History | Annotate | Download | only in common
      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 #include "base_conversion.h"
     30 
     31 #ifdef DEBUG
     32 
     33 void
     34 _display_big_float(_big_float *pbf, unsigned base)
     35 {
     36 	int             i;
     37 
     38 	for (i = 0; i < pbf->blength; i++) {
     39 		switch (base) {
     40 		case 2:
     41 			printf(" + %d * 2** %d", pbf->bsignificand[i], (16 * i + pbf->bexponent));
     42 			break;
     43 		case 10:
     44 			printf(" + %d * 10** %d", pbf->bsignificand[i], (4 * i + pbf->bexponent));
     45 			break;
     46 		}
     47 		if ((i % 4) == 3)
     48 			printf("\n");
     49 	}
     50 	printf("\n");
     51 }
     52 
     53 #endif
     54 
     55 void
     56 _integerstring_to_big_decimal(char ds[], unsigned ndigs, unsigned nzin,
     57     unsigned *pnzout, _big_float *pd)
     58 {
     59 	/*
     60 	 * Convert ndigs decimal digits from ds, and up to 3 trailing zeros,
     61 	 * into a decimal big_float in *pd.  nzin tells how many implicit
     62 	 * trailing zeros may be used, while *pnzout tells how many were
     63 	 * actually absorbed.  Up to 3 are used if available so that
     64 	 * (ndigs+*pnzout) % 4 = 0.
     65 	 */
     66 
     67 	int             extras, taken, id, ids;
     68 
     69 #ifdef DEBUG
     70 	printf(" _integerstring_to_big_decimal: ndigs %d nzin %d ds %s \n", ndigs, nzin, ds);
     71 #endif
     72 
     73 	/* Compute how many trailing zeros we're going to put in *pd. */
     74 
     75 	extras = ndigs % 4;
     76 	if ((extras > 0) && (nzin != 0)) {
     77 		taken = 4 - extras;
     78 		if (taken > nzin)
     79 			taken = nzin;
     80 	} else
     81 		taken = 0;
     82 
     83 	*pnzout = nzin - taken;
     84 
     85 #define IDIGIT(i) ((i < 0) ? 0 : ((i < ndigs) ? (ds[i] - '0') : 0))
     86 
     87 	pd->bexponent = 0;
     88 	pd->blength = (ndigs + taken + 3) / 4;
     89 
     90 	ids = (ndigs + taken) - 4 * pd->blength;
     91 	id = pd->blength - 1;
     92 
     93 #ifdef DEBUG
     94 	printf(" _integerstring_to_big_decimal exponent %d ids %d id %d \n", pd->bexponent, ids, id);
     95 #endif
     96 
     97 	pd->bsignificand[id] = 1000 * IDIGIT(ids) + 100 * IDIGIT(ids + 1) + 10 * IDIGIT(ids + 2) + IDIGIT(ids + 3);
     98 	ids += 4;
     99 
    100 	for (; ids < (int) (ndigs + taken - 4); ids += 4) {	/* Additional digits to
    101 								 * be found. Main loop. */
    102 		id--;
    103 		pd->bsignificand[id] = 1000 * ds[ids] + 100 * ds[ids + 1] + 10 * ds[ids + 2] + ds[ids + 3] - 1111 * '0';
    104 	}
    105 
    106 #ifdef DEBUG
    107 	assert((id == 1) || (id == 0));
    108 #endif
    109 	if (id != 0)
    110 		pd->bsignificand[0] = 1000 * IDIGIT(ids) + 100 * IDIGIT(ids + 1) + 10 * IDIGIT(ids + 2) + IDIGIT(ids + 3);
    111 
    112 #ifdef DEBUG
    113 	printf(" _integerstring_to_big_decimal: ");
    114 	_display_big_float(pd, 10);
    115 #endif
    116 }
    117 
    118 void
    119 _fractionstring_to_big_decimal(char ds[], unsigned ndigs, unsigned nzin,
    120     _big_float *pbf)
    121 {
    122 	/*
    123 	 * Converts a decimal string containing an implicit point, nzin
    124 	 * leading implicit zeros, and ndigs explicit digits, into a big
    125 	 * float.
    126 	 */
    127 
    128 	int             ids, ibf;
    129 
    130 #ifdef DEBUG
    131 	printf(" _fractionstring_to_big_decimal ndigs %d nzin %d s %s \n", ndigs, nzin, ds);
    132 #endif
    133 
    134 	pbf->bexponent = -(int) (nzin + ndigs);
    135 	pbf->blength = (ndigs + 3) / 4;
    136 
    137 	ids = nzin + ndigs - 4 * pbf->blength;
    138 	ibf = pbf->blength - 1;
    139 
    140 #ifdef DEBUG
    141 	printf(" _fractionstring_to_big_decimal exponent %d ids %d ibf %d \n", pbf->bexponent, ids, ibf);
    142 #endif
    143 
    144 #define FDIGIT(i) ((i < nzin) ? 0 : ((i < (nzin+ndigs)) ? (ds[i-nzin] - '0') : 0))
    145 
    146 	pbf->bsignificand[ibf] = 1000 * FDIGIT(ids) + 100 * FDIGIT(ids + 1) + 10 * FDIGIT(ids + 2) + FDIGIT(ids + 3);
    147 	ids += 4;
    148 
    149 	for (; ids < (int) (nzin + ndigs - 4); ids += 4) {	/* Additional digits to
    150 								 * be found. Main loop. */
    151 		ibf--;
    152 		pbf->bsignificand[ibf] = 1000 * ds[ids - nzin] + 100 * ds[ids + 1 - nzin] + 10 * ds[ids + 2 - nzin] + ds[ids + 3 - nzin] - 1111 * '0';
    153 	}
    154 
    155 	if (ibf > 0) {
    156 #ifdef DEBUG
    157 		assert(ibf == 1);
    158 #endif
    159 		pbf->bsignificand[0] = 1000 * FDIGIT(ids) + 100 * FDIGIT(ids + 1) + 10 * FDIGIT(ids + 2) + FDIGIT(ids + 3);
    160 	} else {
    161 #ifdef DEBUG
    162 		assert(ibf == 0);
    163 #endif
    164 	}
    165 
    166 #ifdef DEBUG
    167 	printf(" _fractionstring_to_big_decimal: ");
    168 	_display_big_float(pbf, 10);
    169 #endif
    170 }
    171 
    172 void
    173 _mul_10000short(_big_float *pbf, long unsigned carry)
    174 {
    175 	int             j;
    176 	long unsigned   p;
    177 
    178 	for (j = 0; j < pbf->blength; j++) {
    179 		p = _prod_10000_b65536(pbf->bsignificand[j], carry);
    180 		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    181 		carry = p >> 16;
    182 	}
    183 	while (carry != 0) {
    184 		p = _carry_out_b10000(carry);
    185 		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    186 		carry = p >> 16;
    187 	}
    188 	pbf->blength = j;
    189 }
    190 
    191 void
    192 _big_decimal_to_big_binary(_big_float *pd, _big_float *pb)
    193 {
    194 	/* Convert _big_float from decimal form to binary form. */
    195 
    196 	int             id, idbound;
    197 	_BIG_FLOAT_DIGIT sticky, carry;
    198 	_BIG_FLOAT_DIGIT multiplier;
    199 
    200 #ifdef DEBUG
    201 	assert(pd->bexponent >= -3);
    202 	assert(pd->bexponent <= 3);
    203 #endif
    204 	pb->bexponent = 0;
    205 	pb->blength = 1;
    206 	id = pd->blength - 1;
    207 	if ((id == 0) && (pd->bexponent < 0)) {
    208 		pb->bsignificand[0] = 0;
    209 	} else {
    210 		pb->bsignificand[0] = pd->bsignificand[id--];
    211 		idbound = (pd->bexponent < 0) ? 1 : 0;	/* How far to carry next
    212 							 * for loop depends on
    213 							 * whether last digit
    214 							 * requires special
    215 							 * treatment. */
    216 		for (; id >= idbound; id--) {
    217 			_mul_10000short(pb, (long unsigned) pd->bsignificand[id]);
    218 		}
    219 	}
    220 	if (pd->bexponent < 0) {/* Have to save some integer bits, discard
    221 				 * and stick some fraction bits at the end. */
    222 #ifdef DEBUG
    223 		assert(id == 0);
    224 #endif
    225 		sticky = 0;
    226 		carry = pd->bsignificand[0];
    227 		multiplier = 10000;
    228 		switch (pd->bexponent) {
    229 		case -1:
    230 			sticky = carry % 10;
    231 			carry /= 10;
    232 			multiplier = 1000;
    233 			break;
    234 		case -2:
    235 			sticky = carry % 100;
    236 			carry /= 100;
    237 			multiplier = 100;
    238 			break;
    239 		case -3:
    240 			sticky = carry % 1000;
    241 			carry /= 1000;
    242 			multiplier = 10;
    243 			break;
    244 		}
    245 		_multiply_base_two(pb, multiplier, (long unsigned) carry);
    246 		if (sticky != 0)
    247 			pb->bsignificand[0] |= 1;	/* Save lost bits. */
    248 	} else if (pd->bexponent > 0) {	/* Have to append some zeros. */
    249 		switch (pd->bexponent) {
    250 		case 1:
    251 			multiplier = 10;
    252 			break;
    253 		case 2:
    254 			multiplier = 100;
    255 			break;
    256 		case 3:
    257 			multiplier = 1000;
    258 			break;
    259 		}
    260 		carry = 0;
    261 		_multiply_base_two(pb, multiplier, (long unsigned) carry);
    262 	}
    263 #ifdef DEBUG
    264 	printf(" _big_decimal_to_big_binary ");
    265 	_display_big_float(pb, 2);
    266 #endif
    267 }
    268 
    269 void
    270 _big_binary_to_unpacked(_big_float *pb, unpacked *pu)
    271 {
    272 	/* Convert a binary big_float to a binary_unpacked.	 */
    273 
    274 	int             ib, iu;
    275 
    276 #ifdef DEBUG
    277 	assert(pb->bsignificand[pb->blength - 1] != 0);	/* Assert pb is
    278 							 * normalized. */
    279 #endif
    280 
    281 	iu = 0;
    282 	for (ib = pb->blength - 1; ((ib - 1) >= 0) && (iu < UNPACKED_SIZE); ib -= 2) {
    283 		pu->significand[iu++] = pb->bsignificand[ib] << 16 | pb->bsignificand[ib - 1];
    284 	}
    285 	if (iu < UNPACKED_SIZE) {	/* The big float fits in the unpacked
    286 					 * with no rounding. 	 */
    287 		if (ib == 0)
    288 			pu->significand[iu++] = pb->bsignificand[ib] << 16;
    289 		for (; iu < UNPACKED_SIZE; iu++)
    290 			pu->significand[iu] = 0;
    291 	} else {		/* The big float is too big; chop, stick, and
    292 				 * normalize. */
    293 		while (pb->bsignificand[ib] == 0)
    294 			ib--;
    295 		if (ib >= 0)
    296 			pu->significand[UNPACKED_SIZE - 1] |= 1;	/* Stick lsb if nonzero
    297 									 * found. */
    298 	}
    299 
    300 	pu->exponent = 16 * pb->blength + pb->bexponent - 1;
    301 	_fp_normalize(pu);
    302 
    303 #ifdef DEBUG
    304 	printf(" _big_binary_to_unpacked \n");
    305 	_display_unpacked(pu);
    306 #endif
    307 }
    308