xref: /illumos-gate/usr/src/lib/libc/port/fp/__x_power.c (revision 1da57d55)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7257d1b4Sraf  * Common Development and Distribution License (the "License").
6*7257d1b4Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*7257d1b4Sraf 
227c478bd9Sstevel@tonic-gate /*
23*7257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
27*7257d1b4Sraf #include "lint.h"
287c478bd9Sstevel@tonic-gate #include "base_conversion.h"
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <malloc.h>
317c478bd9Sstevel@tonic-gate #include <memory.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <errno.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * Multiply a _big_float by a power of two or ten
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /* see comment in double_decim.c */
407c478bd9Sstevel@tonic-gate static unsigned int
__quorem10000(unsigned int x,unsigned short * pr)417c478bd9Sstevel@tonic-gate __quorem10000(unsigned int x, unsigned short *pr)
427c478bd9Sstevel@tonic-gate {
437c478bd9Sstevel@tonic-gate 	*pr = x % 10000;
447c478bd9Sstevel@tonic-gate 	return (x / 10000);
457c478bd9Sstevel@tonic-gate }
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  * Multiply a base-2**16 significand by multiplier.  Extend length as
497c478bd9Sstevel@tonic-gate  * necessary to accommodate carries.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate static void
__multiply_base_two(_big_float * pbf,unsigned short multiplier)527c478bd9Sstevel@tonic-gate __multiply_base_two(_big_float *pbf, unsigned short multiplier)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	unsigned int	p, carry;
557c478bd9Sstevel@tonic-gate 	int		j, length = pbf->blength;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 	carry = 0;
587c478bd9Sstevel@tonic-gate 	for (j = 0; j < length; j++) {
597c478bd9Sstevel@tonic-gate 		p = (unsigned int)pbf->bsignificand[j] * multiplier + carry;
607c478bd9Sstevel@tonic-gate 		pbf->bsignificand[j] = p & 0xffff;
617c478bd9Sstevel@tonic-gate 		carry = p >> 16;
627c478bd9Sstevel@tonic-gate 	}
637c478bd9Sstevel@tonic-gate 	if (carry != 0)
647c478bd9Sstevel@tonic-gate 		pbf->bsignificand[j++] = carry;
657c478bd9Sstevel@tonic-gate 	pbf->blength = j;
667c478bd9Sstevel@tonic-gate }
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate  * Multiply a base-10**4 significand by multiplier.  Extend length as
707c478bd9Sstevel@tonic-gate  * necessary to accommodate carries.
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate static void
__multiply_base_ten(_big_float * pbf,unsigned short multiplier)737c478bd9Sstevel@tonic-gate __multiply_base_ten(_big_float *pbf, unsigned short multiplier)
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate 	unsigned int	p, carry;
767c478bd9Sstevel@tonic-gate 	int		j, length = pbf->blength;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	carry = 0;
797c478bd9Sstevel@tonic-gate 	for (j = 0; j < length; j++) {
807c478bd9Sstevel@tonic-gate 		p = (unsigned int)pbf->bsignificand[j] * multiplier + carry;
817c478bd9Sstevel@tonic-gate 		carry = __quorem10000(p, &pbf->bsignificand[j]);
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 	while (carry != 0) {
847c478bd9Sstevel@tonic-gate 		carry = __quorem10000(carry, &pbf->bsignificand[j]);
857c478bd9Sstevel@tonic-gate 		j++;
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 	pbf->blength = j;
887c478bd9Sstevel@tonic-gate }
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /*
917c478bd9Sstevel@tonic-gate  * Multiply a base-10**4 significand by 2**multiplier.  Extend length
927c478bd9Sstevel@tonic-gate  * as necessary to accommodate carries.
937c478bd9Sstevel@tonic-gate  */
947c478bd9Sstevel@tonic-gate static void
__multiply_base_ten_by_two(_big_float * pbf,unsigned short multiplier)957c478bd9Sstevel@tonic-gate __multiply_base_ten_by_two(_big_float *pbf, unsigned short multiplier)
967c478bd9Sstevel@tonic-gate {
977c478bd9Sstevel@tonic-gate 	unsigned int	p, carry;
987c478bd9Sstevel@tonic-gate 	int		j, length = pbf->blength;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	carry = 0;
1017c478bd9Sstevel@tonic-gate 	for (j = 0; j < length; j++) {
1027c478bd9Sstevel@tonic-gate 		p = ((unsigned int)pbf->bsignificand[j] << multiplier) + carry;
1037c478bd9Sstevel@tonic-gate 		carry = __quorem10000(p, &pbf->bsignificand[j]);
1047c478bd9Sstevel@tonic-gate 	}
1057c478bd9Sstevel@tonic-gate 	while (carry != 0) {
1067c478bd9Sstevel@tonic-gate 		carry = __quorem10000(carry, &pbf->bsignificand[j]);
1077c478bd9Sstevel@tonic-gate 		j++;
1087c478bd9Sstevel@tonic-gate 	}
1097c478bd9Sstevel@tonic-gate 	pbf->blength = j;
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * Propagate carries in a base-2**16 significand.
1147c478bd9Sstevel@tonic-gate  */
1157c478bd9Sstevel@tonic-gate static void
__carry_propagate_two(unsigned int carry,unsigned short * psignificand)1167c478bd9Sstevel@tonic-gate __carry_propagate_two(unsigned int carry, unsigned short *psignificand)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate 	unsigned int	p;
1197c478bd9Sstevel@tonic-gate 	int		j;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	j = 0;
1227c478bd9Sstevel@tonic-gate 	while (carry != 0) {
1237c478bd9Sstevel@tonic-gate 		p = psignificand[j] + carry;
1247c478bd9Sstevel@tonic-gate 		psignificand[j++] = p & 0xffff;
1257c478bd9Sstevel@tonic-gate 		carry = p >> 16;
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate  * Propagate carries in a base-10**4 significand.
1317c478bd9Sstevel@tonic-gate  */
1327c478bd9Sstevel@tonic-gate static void
__carry_propagate_ten(unsigned int carry,unsigned short * psignificand)1337c478bd9Sstevel@tonic-gate __carry_propagate_ten(unsigned int carry, unsigned short *psignificand)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate 	unsigned int	p;
1367c478bd9Sstevel@tonic-gate 	int		j;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	j = 0;
1397c478bd9Sstevel@tonic-gate 	while (carry != 0) {
1407c478bd9Sstevel@tonic-gate 		p = psignificand[j] + carry;
1417c478bd9Sstevel@tonic-gate 		carry = __quorem10000(p, &psignificand[j]);
1427c478bd9Sstevel@tonic-gate 		j++;
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate /*
1477c478bd9Sstevel@tonic-gate  * Given x[] and y[], base-2**16 vectors of length n, compute the
1487c478bd9Sstevel@tonic-gate  * dot product
1497c478bd9Sstevel@tonic-gate  *
1507c478bd9Sstevel@tonic-gate  * sum (i=0,n-1) of x[i]*y[n-1-i]
1517c478bd9Sstevel@tonic-gate  *
1527c478bd9Sstevel@tonic-gate  * The product may fill as many as three base-2**16 digits; product[0]
1537c478bd9Sstevel@tonic-gate  * is the least significant, product[2] the most.
1547c478bd9Sstevel@tonic-gate  */
1557c478bd9Sstevel@tonic-gate static void
__multiply_base_two_vector(unsigned short n,unsigned short * px,unsigned short * py,unsigned short * product)1567c478bd9Sstevel@tonic-gate __multiply_base_two_vector(unsigned short n, unsigned short *px,
1577c478bd9Sstevel@tonic-gate     unsigned short *py, unsigned short *product)
1587c478bd9Sstevel@tonic-gate {
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	unsigned int	acc, p;
1617c478bd9Sstevel@tonic-gate 	unsigned short	carry;
1627c478bd9Sstevel@tonic-gate 	int		i;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	acc = 0;
1657c478bd9Sstevel@tonic-gate 	carry = 0;
1667c478bd9Sstevel@tonic-gate 	for (i = 0; i < (int)n; i++) {
1677c478bd9Sstevel@tonic-gate 		p = px[i] * py[n - 1 - i] + acc;
1687c478bd9Sstevel@tonic-gate 		if (p < acc)
1697c478bd9Sstevel@tonic-gate 			carry++;
1707c478bd9Sstevel@tonic-gate 		acc = p;
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 	product[0] = acc & 0xffff;
1737c478bd9Sstevel@tonic-gate 	product[1] = acc >> 16;
1747c478bd9Sstevel@tonic-gate 	product[2] = carry;
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate /*
1787c478bd9Sstevel@tonic-gate  * Given x[] and y[], base-10**4 vectors of length n, compute the
1797c478bd9Sstevel@tonic-gate  * dot product
1807c478bd9Sstevel@tonic-gate  *
1817c478bd9Sstevel@tonic-gate  * sum (i=0,n-1) of x[i]*y[n-1-i]
1827c478bd9Sstevel@tonic-gate  *
1837c478bd9Sstevel@tonic-gate  * The product may fill as many as three base-10**4 digits; product[0]
1847c478bd9Sstevel@tonic-gate  * is the least significant, product[2] the most.
1857c478bd9Sstevel@tonic-gate  */
1867c478bd9Sstevel@tonic-gate #define	ABASE	3000000000u	/* base of accumulator */
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate static void
__multiply_base_ten_vector(unsigned short n,unsigned short * px,unsigned short * py,unsigned short * product)1897c478bd9Sstevel@tonic-gate __multiply_base_ten_vector(unsigned short n, unsigned short *px,
1907c478bd9Sstevel@tonic-gate     unsigned short *py, unsigned short *product)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	unsigned int	acc;
1947c478bd9Sstevel@tonic-gate 	unsigned short	carry;
1957c478bd9Sstevel@tonic-gate 	int		i;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	acc = 0;
1987c478bd9Sstevel@tonic-gate 	carry = 0;
1997c478bd9Sstevel@tonic-gate 	for (i = 0; i < (int)n; i++) {
2007c478bd9Sstevel@tonic-gate 		acc = px[i] * py[n - 1 - i] + acc;
2017c478bd9Sstevel@tonic-gate 		if (acc >= ABASE) {
2027c478bd9Sstevel@tonic-gate 			carry++;
2037c478bd9Sstevel@tonic-gate 			acc -= ABASE;
2047c478bd9Sstevel@tonic-gate 		}
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 	product[0] = acc % 10000;
2077c478bd9Sstevel@tonic-gate 	acc = acc / 10000;
2087c478bd9Sstevel@tonic-gate 	product[1] = acc % 10000;
2097c478bd9Sstevel@tonic-gate 	acc = acc / 10000;
2107c478bd9Sstevel@tonic-gate 	product[2] = acc + (ABASE / 100000000) * carry;
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate  * Multiply *pbf by the n-th power of mult, which must be two or
2157c478bd9Sstevel@tonic-gate  * ten.  If mult is two, *pbf is assumed to be base 10**4; if mult
2167c478bd9Sstevel@tonic-gate  * is ten, *pbf is assumed to be base 2**16.  precision specifies
2177c478bd9Sstevel@tonic-gate  * the number of significant bits or decimal digits required in the
2187c478bd9Sstevel@tonic-gate  * result.  (The product may have more or fewer digits than this,
2197c478bd9Sstevel@tonic-gate  * but it will be accurate to at least this many.)
2207c478bd9Sstevel@tonic-gate  *
2217c478bd9Sstevel@tonic-gate  * On exit, if the product is small enough, it overwrites *pbf, and
2227c478bd9Sstevel@tonic-gate  * *pnewbf is set to pbf.  If the product is too large to fit in *pbf,
2237c478bd9Sstevel@tonic-gate  * this routine calls malloc(3M) to allocate storage and sets *pnewbf
2247c478bd9Sstevel@tonic-gate  * to point to this area; it is the caller's responsibility to free
2257c478bd9Sstevel@tonic-gate  * this storage when it is no longer needed.  Note that *pbf may be
2267c478bd9Sstevel@tonic-gate  * modified even when the routine allocates new storage.
2277c478bd9Sstevel@tonic-gate  *
2287c478bd9Sstevel@tonic-gate  * If n is too large, we set errno to ERANGE and call abort(3C).
2297c478bd9Sstevel@tonic-gate  * If an attempted malloc fails, we set errno to ENOMEM and call
2307c478bd9Sstevel@tonic-gate  * abort(3C).
2317c478bd9Sstevel@tonic-gate  */
2327c478bd9Sstevel@tonic-gate void
__big_float_times_power(_big_float * pbf,int mult,int n,int precision,_big_float ** pnewbf)2337c478bd9Sstevel@tonic-gate __big_float_times_power(_big_float *pbf, int mult, int n, int precision,
2347c478bd9Sstevel@tonic-gate     _big_float **pnewbf)
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate 	int		base, needed_precision, productsize;
2377c478bd9Sstevel@tonic-gate 	int		i, j, itlast, trailing_zeros_to_delete;
2387c478bd9Sstevel@tonic-gate 	int		tablepower[3], length[3];
2397c478bd9Sstevel@tonic-gate 	int		lengthx, lengthp, istart, istop;
2407c478bd9Sstevel@tonic-gate 	int		excess_check;
2417c478bd9Sstevel@tonic-gate 	unsigned short	*pp, *table[3], canquit;
2427c478bd9Sstevel@tonic-gate 	unsigned short	multiplier, product[3];
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	if (pbf->blength == 0) {
2457c478bd9Sstevel@tonic-gate 		*pnewbf = pbf;
2467c478bd9Sstevel@tonic-gate 		return;
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	if (mult == 2) {
2507c478bd9Sstevel@tonic-gate 		/*
2517c478bd9Sstevel@tonic-gate 		 * Handle small n cases that don't require extra
2527c478bd9Sstevel@tonic-gate 		 * storage quickly.
2537c478bd9Sstevel@tonic-gate 		 */
2547c478bd9Sstevel@tonic-gate 		if (n <= 16 && pbf->blength + 2 < pbf->bsize) {
2557c478bd9Sstevel@tonic-gate 			__multiply_base_ten_by_two(pbf, n);
2567c478bd9Sstevel@tonic-gate 			*pnewbf = pbf;
2577c478bd9Sstevel@tonic-gate 			return;
2587c478bd9Sstevel@tonic-gate 		}
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 		/* *pbf is base 10**4 */
2617c478bd9Sstevel@tonic-gate 		base = 10;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		/*
2647c478bd9Sstevel@tonic-gate 		 * Convert precision (base ten digits) to needed_precision
2657c478bd9Sstevel@tonic-gate 		 * (base 10**4 digits), allowing an additional digit at
2667c478bd9Sstevel@tonic-gate 		 * each end.
2677c478bd9Sstevel@tonic-gate 		 */
2687c478bd9Sstevel@tonic-gate 		needed_precision = 2 + (precision >> 2);
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		/*
2717c478bd9Sstevel@tonic-gate 		 * Set up pointers to the table entries and compute their
2727c478bd9Sstevel@tonic-gate 		 * lengths.
2737c478bd9Sstevel@tonic-gate 		 */
2747c478bd9Sstevel@tonic-gate 		if (n < __TBL_2_SMALL_SIZE) {
2757c478bd9Sstevel@tonic-gate 			itlast = 0;
2767c478bd9Sstevel@tonic-gate 			tablepower[0] = n;
2777c478bd9Sstevel@tonic-gate 			tablepower[1] = tablepower[2] = 0;
2787c478bd9Sstevel@tonic-gate 		} else if (n < (__TBL_2_SMALL_SIZE * __TBL_2_BIG_SIZE)) {
2797c478bd9Sstevel@tonic-gate 			itlast = 1;
2807c478bd9Sstevel@tonic-gate 			tablepower[0] = n % __TBL_2_SMALL_SIZE;
2817c478bd9Sstevel@tonic-gate 			tablepower[1] = n / __TBL_2_SMALL_SIZE;
2827c478bd9Sstevel@tonic-gate 			tablepower[2] = 0;
2837c478bd9Sstevel@tonic-gate 		} else if (n < (__TBL_2_SMALL_SIZE * __TBL_2_BIG_SIZE *
2847c478bd9Sstevel@tonic-gate 		    __TBL_2_HUGE_SIZE)) {
2857c478bd9Sstevel@tonic-gate 			itlast = 2;
2867c478bd9Sstevel@tonic-gate 			tablepower[0] = n % __TBL_2_SMALL_SIZE;
2877c478bd9Sstevel@tonic-gate 			n /= __TBL_2_SMALL_SIZE;
2887c478bd9Sstevel@tonic-gate 			tablepower[1] = n % __TBL_2_BIG_SIZE;
2897c478bd9Sstevel@tonic-gate 			tablepower[2] = n / __TBL_2_BIG_SIZE;
2907c478bd9Sstevel@tonic-gate 		} else {
2917c478bd9Sstevel@tonic-gate 			errno = ERANGE;
2927c478bd9Sstevel@tonic-gate 			abort();
2937c478bd9Sstevel@tonic-gate 		}
2947c478bd9Sstevel@tonic-gate 		pp = (unsigned short *)__tbl_2_small_start + tablepower[0];
2957c478bd9Sstevel@tonic-gate 		table[0] = (unsigned short *)__tbl_2_small_digits + pp[0];
2967c478bd9Sstevel@tonic-gate 		length[0] = pp[1] - pp[0];
2977c478bd9Sstevel@tonic-gate 		pp = (unsigned short *)__tbl_2_big_start + tablepower[1];
2987c478bd9Sstevel@tonic-gate 		table[1] = (unsigned short *)__tbl_2_big_digits + pp[0];
2997c478bd9Sstevel@tonic-gate 		length[1] = pp[1] - pp[0];
3007c478bd9Sstevel@tonic-gate 		pp = (unsigned short *)__tbl_2_huge_start + tablepower[2];
3017c478bd9Sstevel@tonic-gate 		table[2] = (unsigned short *)__tbl_2_huge_digits + pp[0];
3027c478bd9Sstevel@tonic-gate 		length[2] = pp[1] - pp[0];
3037c478bd9Sstevel@tonic-gate 	} else {
3047c478bd9Sstevel@tonic-gate 		if (n <= 4 && pbf->blength + 1 < pbf->bsize) {
3057c478bd9Sstevel@tonic-gate 			pbf->bexponent += (short)n;
3067c478bd9Sstevel@tonic-gate 			__multiply_base_two(pbf, __tbl_10_small_digits[n]);
3077c478bd9Sstevel@tonic-gate 			*pnewbf = pbf;
3087c478bd9Sstevel@tonic-gate 			return;
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 		/* *pbf is base 2**16 */
3127c478bd9Sstevel@tonic-gate 		base = 2;
3137c478bd9Sstevel@tonic-gate 		pbf->bexponent += (short)n; /* now need to multiply by 5**n */
3147c478bd9Sstevel@tonic-gate 		needed_precision = 2 + (precision >> 4);
3157c478bd9Sstevel@tonic-gate 		if (n < __TBL_10_SMALL_SIZE) {
3167c478bd9Sstevel@tonic-gate 			itlast = 0;
3177c478bd9Sstevel@tonic-gate 			tablepower[0] = n;
3187c478bd9Sstevel@tonic-gate 			tablepower[1] = tablepower[2] = 0;
3197c478bd9Sstevel@tonic-gate 		} else if (n < (__TBL_10_SMALL_SIZE * __TBL_10_BIG_SIZE)) {
3207c478bd9Sstevel@tonic-gate 			itlast = 1;
3217c478bd9Sstevel@tonic-gate 			tablepower[0] = n % __TBL_10_SMALL_SIZE;
3227c478bd9Sstevel@tonic-gate 			tablepower[1] = n / __TBL_10_SMALL_SIZE;
3237c478bd9Sstevel@tonic-gate 			tablepower[2] = 0;
3247c478bd9Sstevel@tonic-gate 		} else if (n < (__TBL_10_SMALL_SIZE * __TBL_10_BIG_SIZE *
3257c478bd9Sstevel@tonic-gate 		    __TBL_10_HUGE_SIZE)) {
3267c478bd9Sstevel@tonic-gate 			itlast = 2;
3277c478bd9Sstevel@tonic-gate 			tablepower[0] = n % __TBL_10_SMALL_SIZE;
3287c478bd9Sstevel@tonic-gate 			n /= __TBL_10_SMALL_SIZE;
3297c478bd9Sstevel@tonic-gate 			tablepower[1] = n % __TBL_10_BIG_SIZE;
3307c478bd9Sstevel@tonic-gate 			tablepower[2] = n / __TBL_10_BIG_SIZE;
3317c478bd9Sstevel@tonic-gate 		} else {
3327c478bd9Sstevel@tonic-gate 			errno = ERANGE;
3337c478bd9Sstevel@tonic-gate 			abort();
3347c478bd9Sstevel@tonic-gate 		}
3357c478bd9Sstevel@tonic-gate 		pp = (unsigned short *)__tbl_10_small_start + tablepower[0];
3367c478bd9Sstevel@tonic-gate 		table[0] = (unsigned short *)__tbl_10_small_digits + pp[0];
3377c478bd9Sstevel@tonic-gate 		length[0] = pp[1] - pp[0];
3387c478bd9Sstevel@tonic-gate 		pp = (unsigned short *)__tbl_10_big_start + tablepower[1];
3397c478bd9Sstevel@tonic-gate 		table[1] = (unsigned short *)__tbl_10_big_digits + pp[0];
3407c478bd9Sstevel@tonic-gate 		length[1] = pp[1] - pp[0];
3417c478bd9Sstevel@tonic-gate 		pp = (unsigned short *)__tbl_10_huge_start + tablepower[2];
3427c478bd9Sstevel@tonic-gate 		table[2] = (unsigned short *)__tbl_10_huge_digits + pp[0];
3437c478bd9Sstevel@tonic-gate 		length[2] = pp[1] - pp[0];
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	/* compute an upper bound on the size of the product */
3477c478bd9Sstevel@tonic-gate 	productsize = pbf->blength;
3487c478bd9Sstevel@tonic-gate 	for (i = 0; i <= itlast; i++)
3497c478bd9Sstevel@tonic-gate 		productsize += length[i];
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	if (productsize < needed_precision)
3527c478bd9Sstevel@tonic-gate 		needed_precision = productsize;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	if (productsize <= pbf->bsize) {
3557c478bd9Sstevel@tonic-gate 		*pnewbf = pbf;
3567c478bd9Sstevel@tonic-gate 	} else {
3577c478bd9Sstevel@tonic-gate 		i = sizeof (_big_float) + sizeof (unsigned short) *
3587c478bd9Sstevel@tonic-gate 		    (productsize - _BIG_FLOAT_SIZE);
3597c478bd9Sstevel@tonic-gate 		if ((*pnewbf = malloc(i)) == NULL) {
3607c478bd9Sstevel@tonic-gate 			errno = ENOMEM;
3617c478bd9Sstevel@tonic-gate 			abort();
3627c478bd9Sstevel@tonic-gate 		}
3637c478bd9Sstevel@tonic-gate 		(void) memcpy((*pnewbf)->bsignificand, pbf->bsignificand,
3647c478bd9Sstevel@tonic-gate 		    pbf->blength * sizeof (unsigned short));
3657c478bd9Sstevel@tonic-gate 		(*pnewbf)->blength = pbf->blength;
3667c478bd9Sstevel@tonic-gate 		(*pnewbf)->bexponent = pbf->bexponent;
3677c478bd9Sstevel@tonic-gate 		pbf = *pnewbf;
3687c478bd9Sstevel@tonic-gate 		pbf->bsize = productsize;
3697c478bd9Sstevel@tonic-gate 	}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	/*
3727c478bd9Sstevel@tonic-gate 	 * Now pbf points to the input and the output.  Step through
3737c478bd9Sstevel@tonic-gate 	 * each level of the tables.
3747c478bd9Sstevel@tonic-gate 	 */
3757c478bd9Sstevel@tonic-gate 	for (i = 0; i <= itlast; i++) {
3767c478bd9Sstevel@tonic-gate 		if (tablepower[i] == 0)
3777c478bd9Sstevel@tonic-gate 			continue;
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 		lengthp = length[i];
3807c478bd9Sstevel@tonic-gate 		if (lengthp == 1) {
3817c478bd9Sstevel@tonic-gate 			/* short multiplier (<= 10**4 or 2**13) */
3827c478bd9Sstevel@tonic-gate 			if (base == 10) {
3837c478bd9Sstevel@tonic-gate 				/* left shift by tablepower[i] */
3847c478bd9Sstevel@tonic-gate 				__multiply_base_ten_by_two(pbf, tablepower[i]);
3857c478bd9Sstevel@tonic-gate 			} else {
3867c478bd9Sstevel@tonic-gate 				__multiply_base_two(pbf, (table[i])[0]);
3877c478bd9Sstevel@tonic-gate 			}
3887c478bd9Sstevel@tonic-gate 			continue;
3897c478bd9Sstevel@tonic-gate 		}
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 		lengthx = pbf->blength;
3927c478bd9Sstevel@tonic-gate 		if (lengthx == 1) {
3937c478bd9Sstevel@tonic-gate 			/* short multiplicand */
3947c478bd9Sstevel@tonic-gate 			multiplier = pbf->bsignificand[0];
3957c478bd9Sstevel@tonic-gate 			(void) memcpy(pbf->bsignificand, table[i],
3967c478bd9Sstevel@tonic-gate 			    lengthp * sizeof (unsigned short));
3977c478bd9Sstevel@tonic-gate 			pbf->blength = lengthp;
3987c478bd9Sstevel@tonic-gate 			if (base == 10)
3997c478bd9Sstevel@tonic-gate 				__multiply_base_ten(pbf, multiplier);
4007c478bd9Sstevel@tonic-gate 			else
4017c478bd9Sstevel@tonic-gate 				__multiply_base_two(pbf, multiplier);
4027c478bd9Sstevel@tonic-gate 			continue;
4037c478bd9Sstevel@tonic-gate 		}
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 		/* keep track of trailing zeroes */
4067c478bd9Sstevel@tonic-gate 		trailing_zeros_to_delete = 0;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 		/* initialize for carry propagation */
4097c478bd9Sstevel@tonic-gate 		pbf->bsignificand[lengthx + lengthp - 1] = 0;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 		/*
4127c478bd9Sstevel@tonic-gate 		 * General case - the result will be accumulated in *pbf
4137c478bd9Sstevel@tonic-gate 		 * from most significant digit to least significant.
4147c478bd9Sstevel@tonic-gate 		 */
4157c478bd9Sstevel@tonic-gate 		for (j = lengthx + lengthp - 2; j >= 0; j--) {
4167c478bd9Sstevel@tonic-gate 			istart = j - lengthp + 1;
4177c478bd9Sstevel@tonic-gate 			if (istart < 0)
4187c478bd9Sstevel@tonic-gate 				istart = 0;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 			istop = lengthx - 1;
4217c478bd9Sstevel@tonic-gate 			if (istop > j)
4227c478bd9Sstevel@tonic-gate 				istop = j;
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 			pp = table[i];
4257c478bd9Sstevel@tonic-gate 			if (base == 2) {
4267c478bd9Sstevel@tonic-gate 				__multiply_base_two_vector(istop - istart + 1,
4277c478bd9Sstevel@tonic-gate 				    &(pbf->bsignificand[istart]),
4287c478bd9Sstevel@tonic-gate 				    &(pp[j - istop]), product);
4297c478bd9Sstevel@tonic-gate 				if (product[2] != 0)
4307c478bd9Sstevel@tonic-gate 					__carry_propagate_two(
4317c478bd9Sstevel@tonic-gate 					    (unsigned int)product[2],
4327c478bd9Sstevel@tonic-gate 					    &(pbf->bsignificand[j + 2]));
4337c478bd9Sstevel@tonic-gate 				if (product[1] != 0)
4347c478bd9Sstevel@tonic-gate 					__carry_propagate_two(
4357c478bd9Sstevel@tonic-gate 					    (unsigned int)product[1],
4367c478bd9Sstevel@tonic-gate 					    &(pbf->bsignificand[j + 1]));
4377c478bd9Sstevel@tonic-gate 			} else {
4387c478bd9Sstevel@tonic-gate 				__multiply_base_ten_vector(istop - istart + 1,
4397c478bd9Sstevel@tonic-gate 				    &(pbf->bsignificand[istart]),
4407c478bd9Sstevel@tonic-gate 				    &(pp[j - istop]), product);
4417c478bd9Sstevel@tonic-gate 				if (product[2] != 0)
4427c478bd9Sstevel@tonic-gate 					__carry_propagate_ten(
4437c478bd9Sstevel@tonic-gate 					    (unsigned int)product[2],
4447c478bd9Sstevel@tonic-gate 					    &(pbf->bsignificand[j + 2]));
4457c478bd9Sstevel@tonic-gate 				if (product[1] != 0)
4467c478bd9Sstevel@tonic-gate 					__carry_propagate_ten(
4477c478bd9Sstevel@tonic-gate 					    (unsigned int)product[1],
4487c478bd9Sstevel@tonic-gate 					    &(pbf->bsignificand[j + 1]));
4497c478bd9Sstevel@tonic-gate 			}
4507c478bd9Sstevel@tonic-gate 			pbf->bsignificand[j] = product[0];
4517c478bd9Sstevel@tonic-gate 			if (i < itlast || j > lengthx + lengthp - 4
4527c478bd9Sstevel@tonic-gate 			    - needed_precision)
4537c478bd9Sstevel@tonic-gate 				continue;
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 			/*
4567c478bd9Sstevel@tonic-gate 			 * On the last multiplication, it's not necessary
4577c478bd9Sstevel@tonic-gate 			 * to develop the entire product if further digits
4587c478bd9Sstevel@tonic-gate 			 * can't possibly affect significant digits.  But
4597c478bd9Sstevel@tonic-gate 			 * note that further digits can affect the product
4607c478bd9Sstevel@tonic-gate 			 * in one of two ways: (i) the sum of digits beyond
4617c478bd9Sstevel@tonic-gate 			 * the significant ones can cause a carry that would
4627c478bd9Sstevel@tonic-gate 			 * propagate into the significant digits, or (ii) no
4637c478bd9Sstevel@tonic-gate 			 * carry will occur, but there may be more nonzero
4647c478bd9Sstevel@tonic-gate 			 * digits that will need to be recorded in a sticky
4657c478bd9Sstevel@tonic-gate 			 * bit.
4667c478bd9Sstevel@tonic-gate 			 */
4677c478bd9Sstevel@tonic-gate 			excess_check = lengthx + lengthp;
4687c478bd9Sstevel@tonic-gate 			if (pbf->bsignificand[excess_check - 1] == 0)
4697c478bd9Sstevel@tonic-gate 				excess_check--;
4707c478bd9Sstevel@tonic-gate 			excess_check -= needed_precision + 4;
4717c478bd9Sstevel@tonic-gate 			canquit = ((base == 2)? 65535 : 9999) -
4727c478bd9Sstevel@tonic-gate 			    ((lengthx < lengthp)? lengthx : lengthp);
4737c478bd9Sstevel@tonic-gate 			/*
4747c478bd9Sstevel@tonic-gate 			 * If j <= excess_check, then we have all the
4757c478bd9Sstevel@tonic-gate 			 * significant digits.  If the (j + 1)-st digit
4767c478bd9Sstevel@tonic-gate 			 * is no larger than canquit, then the sum of the
4777c478bd9Sstevel@tonic-gate 			 * digits not yet computed can't carry into the
4787c478bd9Sstevel@tonic-gate 			 * significant digits.  If the j-th and (j + 1)-st
4797c478bd9Sstevel@tonic-gate 			 * digits are not both zero, then we know we are
4807c478bd9Sstevel@tonic-gate 			 * discarding nonzero digits.  (If both of these
4817c478bd9Sstevel@tonic-gate 			 * digits are zero, we need to keep forming more
4827c478bd9Sstevel@tonic-gate 			 * of the product to see whether or not there are
4837c478bd9Sstevel@tonic-gate 			 * any more nonzero digits.)
4847c478bd9Sstevel@tonic-gate 			 */
4857c478bd9Sstevel@tonic-gate 			if (j <= excess_check &&
4867c478bd9Sstevel@tonic-gate 			    pbf->bsignificand[j + 1] <= canquit &&
4877c478bd9Sstevel@tonic-gate 			    (pbf->bsignificand[j + 1] | pbf->bsignificand[j])
4887c478bd9Sstevel@tonic-gate 			    != 0) {
4897c478bd9Sstevel@tonic-gate 				/* can discard j+1, j, ... 0 */
4907c478bd9Sstevel@tonic-gate 				trailing_zeros_to_delete = j + 2;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 				/* set sticky bit */
4937c478bd9Sstevel@tonic-gate 				pbf->bsignificand[j + 2] |= 1;
4947c478bd9Sstevel@tonic-gate 				break;
4957c478bd9Sstevel@tonic-gate 			}
4967c478bd9Sstevel@tonic-gate 		}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 		/* if the product didn't carry, delete the leading zero */
4997c478bd9Sstevel@tonic-gate 		pbf->blength = lengthx + lengthp;
5007c478bd9Sstevel@tonic-gate 		if (pbf->bsignificand[pbf->blength - 1] == 0)
5017c478bd9Sstevel@tonic-gate 			pbf->blength--;
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 		/* look for additional trailing zeros to delete */
5047c478bd9Sstevel@tonic-gate 		for (; pbf->bsignificand[trailing_zeros_to_delete] == 0;
505*7257d1b4Sraf 		    trailing_zeros_to_delete++)
506*7257d1b4Sraf 			continue;
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 		if (trailing_zeros_to_delete > 0) {
5097c478bd9Sstevel@tonic-gate 			for (j = 0; j < (int)pbf->blength -
5107c478bd9Sstevel@tonic-gate 			    trailing_zeros_to_delete; j++) {
5117c478bd9Sstevel@tonic-gate 				pbf->bsignificand[j] = pbf->bsignificand[j
5127c478bd9Sstevel@tonic-gate 				    + trailing_zeros_to_delete];
5137c478bd9Sstevel@tonic-gate 			}
5147c478bd9Sstevel@tonic-gate 			pbf->blength -= trailing_zeros_to_delete;
5157c478bd9Sstevel@tonic-gate 			pbf->bexponent += trailing_zeros_to_delete <<
5167c478bd9Sstevel@tonic-gate 			    ((base == 2)? 4 : 2);
5177c478bd9Sstevel@tonic-gate 		}
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate }
520