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