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 /*
     32  * Fundamental utilities of base conversion required for sprintf - but too
     33  * complex or too seldom used to be worth assembly language coding.
     34  */
     35 
     36 /* p = x * y + c ; return (p/10000 << 16 | p%10000) */
     37 unsigned long
     38 _prodc_b10000(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y, unsigned long c)
     39 {
     40 	unsigned long   p = x * (unsigned long) y + c;
     41 
     42 	return ((p / 10000) << 16) | (p % 10000);
     43 }
     44 
     45 /* p = x * y ; return p */
     46 unsigned long
     47 _prod_b65536(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y)
     48 {
     49 	return (x * (unsigned long)y);
     50 }
     51 
     52 /* p = x * y ; return (p/10000 << 16 | p%10000) */
     53 unsigned long
     54 _prod_b10000(_BIG_FLOAT_DIGIT x, _BIG_FLOAT_DIGIT y)
     55 {
     56 	unsigned long   p = x * (unsigned long) y;
     57 
     58 	return ((p / 10000) << 16) | (p % 10000);
     59 }
     60 
     61 /* p = x << n + c ; return (p/10000 << 16 | p%10000) */
     62 unsigned long
     63 _lshift_b10000(_BIG_FLOAT_DIGIT x, short unsigned n, long unsigned c)
     64 {
     65 	unsigned long   p = (((unsigned long) x) << n) + c;
     66 
     67 	return ((p / 10000) << 16) | (p % 10000);
     68 }
     69 
     70 /* p = x * 10000 + c ; return p */
     71 unsigned long
     72 _prod_10000_b65536(_BIG_FLOAT_DIGIT x, long unsigned c)
     73 {
     74 	return (x * (unsigned long) 10000 + c);
     75 }
     76 
     77 /* p = x << 16 + c ; return (p/10000 << 16 | p%10000) */
     78 unsigned long
     79 _prod_65536_b10000(_BIG_FLOAT_DIGIT x, long unsigned c)
     80 {
     81 	unsigned long   p = (((unsigned long) x) << 16) + c;
     82 
     83 	return ((p / 10000) << 16) | (p % 10000);
     84 }
     85 
     86 /* p = c ; return (p/10000 << 16 | p%10000) */
     87 unsigned long
     88 _carry_out_b10000(unsigned long c)
     89 {
     90 	return ((c / 10000) << 16) | (c % 10000);
     91 }
     92 
     93 void
     94 _left_shift_base_ten(_big_float *pbf, short unsigned multiplier)
     95 {
     96 	/*
     97 	 * Multiply a base-10**4 significand by 2<<multiplier.  Extend length
     98 	 * as necessary to accommodate carries.
     99 	 */
    100 
    101 	short unsigned  length = pbf->blength;
    102 	int             j;
    103 	unsigned long   carry;
    104 	long            p;
    105 
    106 	carry = 0;
    107 	for (j = 0; j < length; j++) {
    108 		p = _lshift_b10000((_BIG_FLOAT_DIGIT) pbf->bsignificand[j], multiplier, carry);
    109 		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    110 		carry = p >> 16;
    111 	}
    112 	while (carry != 0) {
    113 		p = _carry_out_b10000(carry);
    114 		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    115 		carry = p >> 16;
    116 	}
    117 	pbf->blength = j;
    118 }
    119 
    120 void
    121 _left_shift_base_two(_big_float *pbf, short unsigned multiplier)
    122 {
    123 	/*
    124 	 * Multiply a base-2**16 significand by 2<<multiplier.  Extend length
    125 	 * as necessary to accommodate carries.
    126 	 */
    127 
    128 	short unsigned  length = pbf->blength;
    129 	long unsigned   p;
    130 	int             j;
    131 	unsigned long   carry;
    132 
    133 	carry = 0;
    134 	for (j = 0; j < length; j++) {
    135 		p = _lshift_b65536(pbf->bsignificand[j], multiplier, carry);
    136 		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    137 		carry = p >> 16;
    138 	}
    139 	if (carry != 0) {
    140 		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (_carry_out_b65536(carry) & 0xffff);
    141 	}
    142 	pbf->blength = j;
    143 }
    144 
    145 void
    146 _right_shift_base_two(_big_float *pbf, short unsigned multiplier,
    147     _BIG_FLOAT_DIGIT *sticky)
    148 {
    149 	/* *pb = *pb / 2**multiplier	to normalize.	15 <= multiplier <= 1 */
    150 	/* Any bits shifted out got to *sticky. */
    151 
    152 	long unsigned   p;
    153 	int             j;
    154 	unsigned long   carry;
    155 
    156 	carry = 0;
    157 	for (j = pbf->blength - 1; j >= 0; j--) {
    158 		p = _rshift_b65536(pbf->bsignificand[j], multiplier, carry);
    159 		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p >> 16);
    160 		carry = p & 0xffff;
    161 	}
    162 	*sticky = (_BIG_FLOAT_DIGIT) carry;
    163 }
    164 
    165 void
    166 _multiply_base_ten(_big_float *pbf, _BIG_FLOAT_DIGIT multiplier)
    167 {
    168 	/*
    169 	 * Multiply a base-10**4 significand by multiplier.  Extend length as
    170 	 * necessary to accommodate carries.
    171 	 */
    172 
    173 	int             j;
    174 	unsigned long   carry;
    175 	long            p;
    176 
    177 	carry = 0;
    178 	for (j = 0; j < pbf->blength; j++) {
    179 		p = _prodc_b10000((_BIG_FLOAT_DIGIT) pbf->bsignificand[j], multiplier, 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 _multiply_base_two(_big_float *pbf, _BIG_FLOAT_DIGIT multiplier,
    193     long unsigned carry)
    194 {
    195 	/*
    196 	 * Multiply a base-2**16 significand by multiplier.  Extend length as
    197 	 * necessary to accommodate carries.
    198 	 */
    199 
    200 	short unsigned  length = pbf->blength;
    201 	long unsigned   p;
    202 	int             j;
    203 
    204 	for (j = 0; j < length; j++) {
    205 		p = _prodc_b65536(pbf->bsignificand[j], multiplier, carry);
    206 		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    207 		carry = p >> 16;
    208 	}
    209 	if (carry != 0) {
    210 		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (_carry_out_b65536(carry) & 0xffff);
    211 	}
    212 	pbf->blength = j;
    213 }
    214 
    215 void
    216 _multiply_base_ten_by_two(_big_float *pbf, short unsigned multiplier)
    217 {
    218 	/*
    219 	 * Multiply a base-10**4 significand by 2**multiplier.  Extend length
    220 	 * as necessary to accommodate carries.
    221 	 */
    222 
    223 	short unsigned  length = pbf->blength;
    224 	int             j;
    225 	long unsigned   carry, p;
    226 
    227 	carry = 0;
    228 	for (j = 0; j < length; j++) {
    229 		p = _lshift_b10000(pbf->bsignificand[j], multiplier, carry);
    230 		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    231 		carry = p >> 16;
    232 	}
    233 	while (carry != 0) {
    234 		p = _carry_out_b10000(carry);
    235 		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    236 		carry = p >> 16;
    237 	}
    238 	pbf->blength = j;
    239 }
    240 
    241 void
    242 _unpacked_to_big_float(unpacked *pu, _big_float *pb, int *pe)
    243 {
    244 	/*
    245 	 * Converts pu into a bigfloat *pb of minimal length; exponent *pe
    246 	 * such that pu = *pb * 2 ** *pe
    247 	 */
    248 
    249 	int             iz, it;
    250 
    251 	for (iz = (UNPACKED_SIZE - 2); pu->significand[iz] == 0; iz--);	/* Find lsw. */
    252 
    253 	for (it = 0; it <= iz; it++) {
    254 		pb->bsignificand[2 * (iz - it)] = pu->significand[it] & 0xffff;
    255 		pb->bsignificand[2 * (iz - it) + 1] = pu->significand[it] >> 16;
    256 	}
    257 
    258 	pb->blength = 2 * iz + 2;
    259 	if (pb->bsignificand[0] == 0) {
    260 		for (it = 1; it < pb->blength; it++)
    261 			pb->bsignificand[it - 1] = pb->bsignificand[it];
    262 		pb->blength--;
    263 	}
    264 	*pe = pu->exponent + 1 - 16 * pb->blength;
    265 	pb->bexponent = 0;
    266 
    267 #ifdef DEBUG
    268 	printf(" unpacked to big float 2**%d * ", *pe);
    269 	_display_big_float(pb, 2);
    270 #endif
    271 }
    272 
    273 void
    274 _mul_65536short(_big_float *pbf, unsigned long carry)
    275 {
    276 	/* *pbf *= 65536 ; += carry ; */
    277 
    278 	long unsigned   p;
    279 	int             j;
    280 
    281 	for (j = 0; j < pbf->blength; j++) {
    282 		p = _prod_65536_b10000(pbf->bsignificand[j], carry);
    283 		pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    284 		carry = p >> 16;
    285 	}
    286 	while (carry != 0) {
    287 		p = _carry_out_b10000(carry);
    288 		pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff);
    289 		carry = p >> 16;
    290 	}
    291 	pbf->blength = j;
    292 }
    293 
    294 void
    295 _big_binary_to_big_decimal(_big_float *pb, _big_float *pd)
    296 {
    297 	/* Convert _big_float from binary form to decimal form. */
    298 
    299 	int             i;
    300 
    301 	pd->bsignificand[0] = pb->bsignificand[pb->blength - 1] % 10000;
    302 	if (pd->bsignificand[0] == pb->bsignificand[pb->blength - 1]) {
    303 		pd->blength = 1;
    304 	} else {
    305 		pd->blength = 2;
    306 		pd->bsignificand[1] = pb->bsignificand[pb->blength - 1] / 10000;
    307 	}
    308 	for (i = pb->blength - 2; i >= 0; i--) {	/* Multiply by 2**16 and
    309 							 * add next significand. */
    310 		_mul_65536short(pd, (unsigned long) pb->bsignificand[i]);
    311 	}
    312 	for (i = 0; i <= (pb->bexponent - 16); i += 16) {	/* Multiply by 2**16 for
    313 								 * each trailing zero. */
    314 		_mul_65536short(pd, (unsigned long) 0);
    315 	}
    316 	if (pb->bexponent > i)
    317 		_left_shift_base_ten(pd, (short unsigned) (pb->bexponent - i));
    318 	pd->bexponent = 0;
    319 
    320 #ifdef DEBUG
    321 	printf(" _big_binary_to_big_decimal ");
    322 	_display_big_float(pd, 10);
    323 #endif
    324 }
    325