17b36286aSmartynas /****************************************************************
27b36286aSmartynas
37b36286aSmartynas The author of this software is David M. Gay.
47b36286aSmartynas
57b36286aSmartynas Copyright (C) 1998, 1999 by Lucent Technologies
67b36286aSmartynas All Rights Reserved
77b36286aSmartynas
87b36286aSmartynas Permission to use, copy, modify, and distribute this software and
97b36286aSmartynas its documentation for any purpose and without fee is hereby
107b36286aSmartynas granted, provided that the above copyright notice appear in all
117b36286aSmartynas copies and that both that the copyright notice and this
127b36286aSmartynas permission notice and warranty disclaimer appear in supporting
137b36286aSmartynas documentation, and that the name of Lucent or any of its entities
147b36286aSmartynas not be used in advertising or publicity pertaining to
157b36286aSmartynas distribution of the software without specific, written prior
167b36286aSmartynas permission.
177b36286aSmartynas
187b36286aSmartynas LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
197b36286aSmartynas INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
207b36286aSmartynas IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
217b36286aSmartynas SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
227b36286aSmartynas WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
237b36286aSmartynas IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
247b36286aSmartynas ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
257b36286aSmartynas THIS SOFTWARE.
267b36286aSmartynas
277b36286aSmartynas ****************************************************************/
287b36286aSmartynas
297b36286aSmartynas /* Please send bug reports to David M. Gay (dmg at acm dot org,
307b36286aSmartynas * with " at " changed at "@" and " dot " changed to "."). */
317b36286aSmartynas
327b36286aSmartynas #include "gdtoaimp.h"
337b36286aSmartynas
347b36286aSmartynas static Bigint *freelist[Kmax+1];
357b36286aSmartynas #ifndef Omit_Private_Memory
367b36286aSmartynas #ifndef PRIVATE_MEM
377b36286aSmartynas #define PRIVATE_MEM 2304
387b36286aSmartynas #endif
397b36286aSmartynas #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
407b36286aSmartynas static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
417b36286aSmartynas #endif
427b36286aSmartynas
43076bdf1eSderaadt #ifdef MULTIPLE_THREADS
44076bdf1eSderaadt static void *__dtoa_locks[] = { NULL, NULL };
45076bdf1eSderaadt #endif
46076bdf1eSderaadt
477b36286aSmartynas Bigint *
Balloc(k)487b36286aSmartynas Balloc
497b36286aSmartynas #ifdef KR_headers
507b36286aSmartynas (k) int k;
517b36286aSmartynas #else
527b36286aSmartynas (int k)
537b36286aSmartynas #endif
547b36286aSmartynas {
557b36286aSmartynas int x;
567b36286aSmartynas Bigint *rv;
577b36286aSmartynas #ifndef Omit_Private_Memory
587b36286aSmartynas unsigned int len;
597b36286aSmartynas #endif
607b36286aSmartynas
617b36286aSmartynas ACQUIRE_DTOA_LOCK(0);
621a653cbcSmartynas /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
631a653cbcSmartynas /* but this case seems very unlikely. */
64f4514f75Smartynas if (k <= Kmax && (rv = freelist[k]) !=0) {
657b36286aSmartynas freelist[k] = rv->next;
667b36286aSmartynas }
677b36286aSmartynas else {
687b36286aSmartynas x = 1 << k;
697b36286aSmartynas #ifdef Omit_Private_Memory
707b36286aSmartynas rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
71384cfdc1Smartynas if (rv == NULL)
72384cfdc1Smartynas return (NULL);
737b36286aSmartynas #else
747b36286aSmartynas len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
757b36286aSmartynas /sizeof(double);
76f4514f75Smartynas if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
777b36286aSmartynas rv = (Bigint*)pmem_next;
787b36286aSmartynas pmem_next += len;
797b36286aSmartynas }
80384cfdc1Smartynas else {
817b36286aSmartynas rv = (Bigint*)MALLOC(len*sizeof(double));
82384cfdc1Smartynas if (rv == NULL)
83384cfdc1Smartynas return (NULL);
84384cfdc1Smartynas }
857b36286aSmartynas #endif
867b36286aSmartynas rv->k = k;
877b36286aSmartynas rv->maxwds = x;
887b36286aSmartynas }
897b36286aSmartynas FREE_DTOA_LOCK(0);
907b36286aSmartynas rv->sign = rv->wds = 0;
917b36286aSmartynas return rv;
927b36286aSmartynas }
937b36286aSmartynas
947b36286aSmartynas void
Bfree(v)957b36286aSmartynas Bfree
967b36286aSmartynas #ifdef KR_headers
977b36286aSmartynas (v) Bigint *v;
987b36286aSmartynas #else
997b36286aSmartynas (Bigint *v)
1007b36286aSmartynas #endif
1017b36286aSmartynas {
1027b36286aSmartynas if (v) {
1031a653cbcSmartynas if (v->k > Kmax)
1041a653cbcSmartynas #ifdef FREE
105*3240e6a8Sguenther FREE(v);
1061a653cbcSmartynas #else
107*3240e6a8Sguenther free(v);
1081a653cbcSmartynas #endif
1091a653cbcSmartynas else {
1107b36286aSmartynas ACQUIRE_DTOA_LOCK(0);
1117b36286aSmartynas v->next = freelist[v->k];
1127b36286aSmartynas freelist[v->k] = v;
1137b36286aSmartynas FREE_DTOA_LOCK(0);
1147b36286aSmartynas }
1157b36286aSmartynas }
1161a653cbcSmartynas }
1177b36286aSmartynas
1187b36286aSmartynas int
lo0bits(y)1197b36286aSmartynas lo0bits
1207b36286aSmartynas #ifdef KR_headers
1217b36286aSmartynas (y) ULong *y;
1227b36286aSmartynas #else
1237b36286aSmartynas (ULong *y)
1247b36286aSmartynas #endif
1257b36286aSmartynas {
1261a653cbcSmartynas int k;
1271a653cbcSmartynas ULong x = *y;
1287b36286aSmartynas
1297b36286aSmartynas if (x & 7) {
1307b36286aSmartynas if (x & 1)
1317b36286aSmartynas return 0;
1327b36286aSmartynas if (x & 2) {
1337b36286aSmartynas *y = x >> 1;
1347b36286aSmartynas return 1;
1357b36286aSmartynas }
1367b36286aSmartynas *y = x >> 2;
1377b36286aSmartynas return 2;
1387b36286aSmartynas }
1397b36286aSmartynas k = 0;
1407b36286aSmartynas if (!(x & 0xffff)) {
1417b36286aSmartynas k = 16;
1427b36286aSmartynas x >>= 16;
1437b36286aSmartynas }
1447b36286aSmartynas if (!(x & 0xff)) {
1457b36286aSmartynas k += 8;
1467b36286aSmartynas x >>= 8;
1477b36286aSmartynas }
1487b36286aSmartynas if (!(x & 0xf)) {
1497b36286aSmartynas k += 4;
1507b36286aSmartynas x >>= 4;
1517b36286aSmartynas }
1527b36286aSmartynas if (!(x & 0x3)) {
1537b36286aSmartynas k += 2;
1547b36286aSmartynas x >>= 2;
1557b36286aSmartynas }
1567b36286aSmartynas if (!(x & 1)) {
1577b36286aSmartynas k++;
1587b36286aSmartynas x >>= 1;
1597b36286aSmartynas if (!x)
1607b36286aSmartynas return 32;
1617b36286aSmartynas }
1627b36286aSmartynas *y = x;
1637b36286aSmartynas return k;
1647b36286aSmartynas }
1657b36286aSmartynas
1667b36286aSmartynas Bigint *
multadd(b,m,a)1677b36286aSmartynas multadd
1687b36286aSmartynas #ifdef KR_headers
1697b36286aSmartynas (b, m, a) Bigint *b; int m, a;
1707b36286aSmartynas #else
1717b36286aSmartynas (Bigint *b, int m, int a) /* multiply by m and add a */
1727b36286aSmartynas #endif
1737b36286aSmartynas {
1747b36286aSmartynas int i, wds;
1757b36286aSmartynas #ifdef ULLong
1767b36286aSmartynas ULong *x;
1777b36286aSmartynas ULLong carry, y;
1787b36286aSmartynas #else
1797b36286aSmartynas ULong carry, *x, y;
1807b36286aSmartynas #ifdef Pack_32
1817b36286aSmartynas ULong xi, z;
1827b36286aSmartynas #endif
1837b36286aSmartynas #endif
1847b36286aSmartynas Bigint *b1;
1857b36286aSmartynas
1867b36286aSmartynas wds = b->wds;
1877b36286aSmartynas x = b->x;
1887b36286aSmartynas i = 0;
1897b36286aSmartynas carry = a;
1907b36286aSmartynas do {
1917b36286aSmartynas #ifdef ULLong
1927b36286aSmartynas y = *x * (ULLong)m + carry;
1937b36286aSmartynas carry = y >> 32;
1947b36286aSmartynas *x++ = y & 0xffffffffUL;
1957b36286aSmartynas #else
1967b36286aSmartynas #ifdef Pack_32
1977b36286aSmartynas xi = *x;
1987b36286aSmartynas y = (xi & 0xffff) * m + carry;
1997b36286aSmartynas z = (xi >> 16) * m + (y >> 16);
2007b36286aSmartynas carry = z >> 16;
2017b36286aSmartynas *x++ = (z << 16) + (y & 0xffff);
2027b36286aSmartynas #else
2037b36286aSmartynas y = *x * m + carry;
2047b36286aSmartynas carry = y >> 16;
2057b36286aSmartynas *x++ = y & 0xffff;
2067b36286aSmartynas #endif
2077b36286aSmartynas #endif
2087b36286aSmartynas }
2097b36286aSmartynas while(++i < wds);
2107b36286aSmartynas if (carry) {
2117b36286aSmartynas if (wds >= b->maxwds) {
2127b36286aSmartynas b1 = Balloc(b->k+1);
213384cfdc1Smartynas if (b1 == NULL)
214384cfdc1Smartynas return (NULL);
2157b36286aSmartynas Bcopy(b1, b);
2167b36286aSmartynas Bfree(b);
2177b36286aSmartynas b = b1;
2187b36286aSmartynas }
2197b36286aSmartynas b->x[wds++] = carry;
2207b36286aSmartynas b->wds = wds;
2217b36286aSmartynas }
2227b36286aSmartynas return b;
2237b36286aSmartynas }
2247b36286aSmartynas
2257b36286aSmartynas int
hi0bits_D2A(x)2267b36286aSmartynas hi0bits_D2A
2277b36286aSmartynas #ifdef KR_headers
2281a653cbcSmartynas (x) ULong x;
2297b36286aSmartynas #else
2301a653cbcSmartynas (ULong x)
2317b36286aSmartynas #endif
2327b36286aSmartynas {
2331a653cbcSmartynas int k = 0;
2347b36286aSmartynas
2357b36286aSmartynas if (!(x & 0xffff0000)) {
2367b36286aSmartynas k = 16;
2377b36286aSmartynas x <<= 16;
2387b36286aSmartynas }
2397b36286aSmartynas if (!(x & 0xff000000)) {
2407b36286aSmartynas k += 8;
2417b36286aSmartynas x <<= 8;
2427b36286aSmartynas }
2437b36286aSmartynas if (!(x & 0xf0000000)) {
2447b36286aSmartynas k += 4;
2457b36286aSmartynas x <<= 4;
2467b36286aSmartynas }
2477b36286aSmartynas if (!(x & 0xc0000000)) {
2487b36286aSmartynas k += 2;
2497b36286aSmartynas x <<= 2;
2507b36286aSmartynas }
2517b36286aSmartynas if (!(x & 0x80000000)) {
2527b36286aSmartynas k++;
2537b36286aSmartynas if (!(x & 0x40000000))
2547b36286aSmartynas return 32;
2557b36286aSmartynas }
2567b36286aSmartynas return k;
2577b36286aSmartynas }
2587b36286aSmartynas
2597b36286aSmartynas Bigint *
i2b(i)2607b36286aSmartynas i2b
2617b36286aSmartynas #ifdef KR_headers
2627b36286aSmartynas (i) int i;
2637b36286aSmartynas #else
2647b36286aSmartynas (int i)
2657b36286aSmartynas #endif
2667b36286aSmartynas {
2677b36286aSmartynas Bigint *b;
2687b36286aSmartynas
2697b36286aSmartynas b = Balloc(1);
270384cfdc1Smartynas if (b == NULL)
271384cfdc1Smartynas return (NULL);
2727b36286aSmartynas b->x[0] = i;
2737b36286aSmartynas b->wds = 1;
2747b36286aSmartynas return b;
2757b36286aSmartynas }
2767b36286aSmartynas
2777b36286aSmartynas Bigint *
mult(a,b)2787b36286aSmartynas mult
2797b36286aSmartynas #ifdef KR_headers
2807b36286aSmartynas (a, b) Bigint *a, *b;
2817b36286aSmartynas #else
2827b36286aSmartynas (Bigint *a, Bigint *b)
2837b36286aSmartynas #endif
2847b36286aSmartynas {
2857b36286aSmartynas Bigint *c;
2867b36286aSmartynas int k, wa, wb, wc;
2877b36286aSmartynas ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
2887b36286aSmartynas ULong y;
2897b36286aSmartynas #ifdef ULLong
2907b36286aSmartynas ULLong carry, z;
2917b36286aSmartynas #else
2927b36286aSmartynas ULong carry, z;
2937b36286aSmartynas #ifdef Pack_32
2947b36286aSmartynas ULong z2;
2957b36286aSmartynas #endif
2967b36286aSmartynas #endif
2977b36286aSmartynas
2987b36286aSmartynas if (a->wds < b->wds) {
2997b36286aSmartynas c = a;
3007b36286aSmartynas a = b;
3017b36286aSmartynas b = c;
3027b36286aSmartynas }
3037b36286aSmartynas k = a->k;
3047b36286aSmartynas wa = a->wds;
3057b36286aSmartynas wb = b->wds;
3067b36286aSmartynas wc = wa + wb;
3077b36286aSmartynas if (wc > a->maxwds)
3087b36286aSmartynas k++;
3097b36286aSmartynas c = Balloc(k);
310384cfdc1Smartynas if (c == NULL)
311384cfdc1Smartynas return (NULL);
3127b36286aSmartynas for(x = c->x, xa = x + wc; x < xa; x++)
3137b36286aSmartynas *x = 0;
3147b36286aSmartynas xa = a->x;
3157b36286aSmartynas xae = xa + wa;
3167b36286aSmartynas xb = b->x;
3177b36286aSmartynas xbe = xb + wb;
3187b36286aSmartynas xc0 = c->x;
3197b36286aSmartynas #ifdef ULLong
3207b36286aSmartynas for(; xb < xbe; xc0++) {
3217b36286aSmartynas if ( (y = *xb++) !=0) {
3227b36286aSmartynas x = xa;
3237b36286aSmartynas xc = xc0;
3247b36286aSmartynas carry = 0;
3257b36286aSmartynas do {
3267b36286aSmartynas z = *x++ * (ULLong)y + *xc + carry;
3277b36286aSmartynas carry = z >> 32;
3287b36286aSmartynas *xc++ = z & 0xffffffffUL;
3297b36286aSmartynas }
3307b36286aSmartynas while(x < xae);
3317b36286aSmartynas *xc = carry;
3327b36286aSmartynas }
3337b36286aSmartynas }
3347b36286aSmartynas #else
3357b36286aSmartynas #ifdef Pack_32
3367b36286aSmartynas for(; xb < xbe; xb++, xc0++) {
3377b36286aSmartynas if ( (y = *xb & 0xffff) !=0) {
3387b36286aSmartynas x = xa;
3397b36286aSmartynas xc = xc0;
3407b36286aSmartynas carry = 0;
3417b36286aSmartynas do {
3427b36286aSmartynas z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
3437b36286aSmartynas carry = z >> 16;
3447b36286aSmartynas z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
3457b36286aSmartynas carry = z2 >> 16;
3467b36286aSmartynas Storeinc(xc, z2, z);
3477b36286aSmartynas }
3487b36286aSmartynas while(x < xae);
3497b36286aSmartynas *xc = carry;
3507b36286aSmartynas }
3517b36286aSmartynas if ( (y = *xb >> 16) !=0) {
3527b36286aSmartynas x = xa;
3537b36286aSmartynas xc = xc0;
3547b36286aSmartynas carry = 0;
3557b36286aSmartynas z2 = *xc;
3567b36286aSmartynas do {
3577b36286aSmartynas z = (*x & 0xffff) * y + (*xc >> 16) + carry;
3587b36286aSmartynas carry = z >> 16;
3597b36286aSmartynas Storeinc(xc, z, z2);
3607b36286aSmartynas z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
3617b36286aSmartynas carry = z2 >> 16;
3627b36286aSmartynas }
3637b36286aSmartynas while(x < xae);
3647b36286aSmartynas *xc = z2;
3657b36286aSmartynas }
3667b36286aSmartynas }
3677b36286aSmartynas #else
3687b36286aSmartynas for(; xb < xbe; xc0++) {
3697b36286aSmartynas if ( (y = *xb++) !=0) {
3707b36286aSmartynas x = xa;
3717b36286aSmartynas xc = xc0;
3727b36286aSmartynas carry = 0;
3737b36286aSmartynas do {
3747b36286aSmartynas z = *x++ * y + *xc + carry;
3757b36286aSmartynas carry = z >> 16;
3767b36286aSmartynas *xc++ = z & 0xffff;
3777b36286aSmartynas }
3787b36286aSmartynas while(x < xae);
3797b36286aSmartynas *xc = carry;
3807b36286aSmartynas }
3817b36286aSmartynas }
3827b36286aSmartynas #endif
3837b36286aSmartynas #endif
3847b36286aSmartynas for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
3857b36286aSmartynas c->wds = wc;
3867b36286aSmartynas return c;
3877b36286aSmartynas }
3887b36286aSmartynas
3897b36286aSmartynas static Bigint *p5s;
3907b36286aSmartynas
3917b36286aSmartynas Bigint *
pow5mult(b,k)3927b36286aSmartynas pow5mult
3937b36286aSmartynas #ifdef KR_headers
3947b36286aSmartynas (b, k) Bigint *b; int k;
3957b36286aSmartynas #else
3967b36286aSmartynas (Bigint *b, int k)
3977b36286aSmartynas #endif
3987b36286aSmartynas {
3997b36286aSmartynas Bigint *b1, *p5, *p51;
4007b36286aSmartynas int i;
4017b36286aSmartynas static int p05[3] = { 5, 25, 125 };
4027b36286aSmartynas
403384cfdc1Smartynas if ( (i = k & 3) !=0) {
4047b36286aSmartynas b = multadd(b, p05[i-1], 0);
405384cfdc1Smartynas if (b == NULL)
406384cfdc1Smartynas return (NULL);
407384cfdc1Smartynas }
4087b36286aSmartynas
4097b36286aSmartynas if (!(k >>= 2))
4107b36286aSmartynas return b;
4117b36286aSmartynas if ((p5 = p5s) == 0) {
4127b36286aSmartynas /* first time */
4137b36286aSmartynas #ifdef MULTIPLE_THREADS
4147b36286aSmartynas ACQUIRE_DTOA_LOCK(1);
4157b36286aSmartynas if (!(p5 = p5s)) {
4167b36286aSmartynas p5 = p5s = i2b(625);
417384cfdc1Smartynas if (p5 == NULL)
418384cfdc1Smartynas return (NULL);
4197b36286aSmartynas p5->next = 0;
4207b36286aSmartynas }
4217b36286aSmartynas FREE_DTOA_LOCK(1);
4227b36286aSmartynas #else
4237b36286aSmartynas p5 = p5s = i2b(625);
424384cfdc1Smartynas if (p5 == NULL)
425384cfdc1Smartynas return (NULL);
4267b36286aSmartynas p5->next = 0;
4277b36286aSmartynas #endif
4287b36286aSmartynas }
4297b36286aSmartynas for(;;) {
4307b36286aSmartynas if (k & 1) {
4317b36286aSmartynas b1 = mult(b, p5);
432384cfdc1Smartynas if (b1 == NULL)
433384cfdc1Smartynas return (NULL);
4347b36286aSmartynas Bfree(b);
4357b36286aSmartynas b = b1;
4367b36286aSmartynas }
4377b36286aSmartynas if (!(k >>= 1))
4387b36286aSmartynas break;
4397b36286aSmartynas if ((p51 = p5->next) == 0) {
4407b36286aSmartynas #ifdef MULTIPLE_THREADS
4417b36286aSmartynas ACQUIRE_DTOA_LOCK(1);
4427b36286aSmartynas if (!(p51 = p5->next)) {
4437b36286aSmartynas p51 = p5->next = mult(p5,p5);
444384cfdc1Smartynas if (p51 == NULL)
445384cfdc1Smartynas return (NULL);
4467b36286aSmartynas p51->next = 0;
4477b36286aSmartynas }
4487b36286aSmartynas FREE_DTOA_LOCK(1);
4497b36286aSmartynas #else
4507b36286aSmartynas p51 = p5->next = mult(p5,p5);
451384cfdc1Smartynas if (p51 == NULL)
452384cfdc1Smartynas return (NULL);
4537b36286aSmartynas p51->next = 0;
4547b36286aSmartynas #endif
4557b36286aSmartynas }
4567b36286aSmartynas p5 = p51;
4577b36286aSmartynas }
4587b36286aSmartynas return b;
4597b36286aSmartynas }
4607b36286aSmartynas
4617b36286aSmartynas Bigint *
lshift(b,k)4627b36286aSmartynas lshift
4637b36286aSmartynas #ifdef KR_headers
4647b36286aSmartynas (b, k) Bigint *b; int k;
4657b36286aSmartynas #else
4667b36286aSmartynas (Bigint *b, int k)
4677b36286aSmartynas #endif
4687b36286aSmartynas {
4697b36286aSmartynas int i, k1, n, n1;
4707b36286aSmartynas Bigint *b1;
4717b36286aSmartynas ULong *x, *x1, *xe, z;
4727b36286aSmartynas
4737b36286aSmartynas n = k >> kshift;
4747b36286aSmartynas k1 = b->k;
4757b36286aSmartynas n1 = n + b->wds + 1;
4767b36286aSmartynas for(i = b->maxwds; n1 > i; i <<= 1)
4777b36286aSmartynas k1++;
4787b36286aSmartynas b1 = Balloc(k1);
479384cfdc1Smartynas if (b1 == NULL)
480384cfdc1Smartynas return (NULL);
4817b36286aSmartynas x1 = b1->x;
4827b36286aSmartynas for(i = 0; i < n; i++)
4837b36286aSmartynas *x1++ = 0;
4847b36286aSmartynas x = b->x;
4857b36286aSmartynas xe = x + b->wds;
4867b36286aSmartynas if (k &= kmask) {
4877b36286aSmartynas #ifdef Pack_32
4887b36286aSmartynas k1 = 32 - k;
4897b36286aSmartynas z = 0;
4907b36286aSmartynas do {
4917b36286aSmartynas *x1++ = *x << k | z;
4927b36286aSmartynas z = *x++ >> k1;
4937b36286aSmartynas }
4947b36286aSmartynas while(x < xe);
4957b36286aSmartynas if ((*x1 = z) !=0)
4967b36286aSmartynas ++n1;
4977b36286aSmartynas #else
4987b36286aSmartynas k1 = 16 - k;
4997b36286aSmartynas z = 0;
5007b36286aSmartynas do {
5017b36286aSmartynas *x1++ = *x << k & 0xffff | z;
5027b36286aSmartynas z = *x++ >> k1;
5037b36286aSmartynas }
5047b36286aSmartynas while(x < xe);
5057b36286aSmartynas if (*x1 = z)
5067b36286aSmartynas ++n1;
5077b36286aSmartynas #endif
5087b36286aSmartynas }
5097b36286aSmartynas else do
5107b36286aSmartynas *x1++ = *x++;
5117b36286aSmartynas while(x < xe);
5127b36286aSmartynas b1->wds = n1 - 1;
5137b36286aSmartynas Bfree(b);
5147b36286aSmartynas return b1;
5157b36286aSmartynas }
5167b36286aSmartynas
5177b36286aSmartynas int
cmp(a,b)5187b36286aSmartynas cmp
5197b36286aSmartynas #ifdef KR_headers
5207b36286aSmartynas (a, b) Bigint *a, *b;
5217b36286aSmartynas #else
5227b36286aSmartynas (Bigint *a, Bigint *b)
5237b36286aSmartynas #endif
5247b36286aSmartynas {
5257b36286aSmartynas ULong *xa, *xa0, *xb, *xb0;
5267b36286aSmartynas int i, j;
5277b36286aSmartynas
5287b36286aSmartynas i = a->wds;
5297b36286aSmartynas j = b->wds;
5307b36286aSmartynas #ifdef DEBUG
5317b36286aSmartynas if (i > 1 && !a->x[i-1])
5327b36286aSmartynas Bug("cmp called with a->x[a->wds-1] == 0");
5337b36286aSmartynas if (j > 1 && !b->x[j-1])
5347b36286aSmartynas Bug("cmp called with b->x[b->wds-1] == 0");
5357b36286aSmartynas #endif
5367b36286aSmartynas if (i -= j)
5377b36286aSmartynas return i;
5387b36286aSmartynas xa0 = a->x;
5397b36286aSmartynas xa = xa0 + j;
5407b36286aSmartynas xb0 = b->x;
5417b36286aSmartynas xb = xb0 + j;
5427b36286aSmartynas for(;;) {
5437b36286aSmartynas if (*--xa != *--xb)
5447b36286aSmartynas return *xa < *xb ? -1 : 1;
5457b36286aSmartynas if (xa <= xa0)
5467b36286aSmartynas break;
5477b36286aSmartynas }
5487b36286aSmartynas return 0;
5497b36286aSmartynas }
5507b36286aSmartynas
5517b36286aSmartynas Bigint *
diff(a,b)5527b36286aSmartynas diff
5537b36286aSmartynas #ifdef KR_headers
5547b36286aSmartynas (a, b) Bigint *a, *b;
5557b36286aSmartynas #else
5567b36286aSmartynas (Bigint *a, Bigint *b)
5577b36286aSmartynas #endif
5587b36286aSmartynas {
5597b36286aSmartynas Bigint *c;
5607b36286aSmartynas int i, wa, wb;
5617b36286aSmartynas ULong *xa, *xae, *xb, *xbe, *xc;
5627b36286aSmartynas #ifdef ULLong
5637b36286aSmartynas ULLong borrow, y;
5647b36286aSmartynas #else
5657b36286aSmartynas ULong borrow, y;
5667b36286aSmartynas #ifdef Pack_32
5677b36286aSmartynas ULong z;
5687b36286aSmartynas #endif
5697b36286aSmartynas #endif
5707b36286aSmartynas
5717b36286aSmartynas i = cmp(a,b);
5727b36286aSmartynas if (!i) {
5737b36286aSmartynas c = Balloc(0);
574384cfdc1Smartynas if (c == NULL)
575384cfdc1Smartynas return (NULL);
5767b36286aSmartynas c->wds = 1;
5777b36286aSmartynas c->x[0] = 0;
5787b36286aSmartynas return c;
5797b36286aSmartynas }
5807b36286aSmartynas if (i < 0) {
5817b36286aSmartynas c = a;
5827b36286aSmartynas a = b;
5837b36286aSmartynas b = c;
5847b36286aSmartynas i = 1;
5857b36286aSmartynas }
5867b36286aSmartynas else
5877b36286aSmartynas i = 0;
5887b36286aSmartynas c = Balloc(a->k);
589384cfdc1Smartynas if (c == NULL)
590384cfdc1Smartynas return (NULL);
5917b36286aSmartynas c->sign = i;
5927b36286aSmartynas wa = a->wds;
5937b36286aSmartynas xa = a->x;
5947b36286aSmartynas xae = xa + wa;
5957b36286aSmartynas wb = b->wds;
5967b36286aSmartynas xb = b->x;
5977b36286aSmartynas xbe = xb + wb;
5987b36286aSmartynas xc = c->x;
5997b36286aSmartynas borrow = 0;
6007b36286aSmartynas #ifdef ULLong
6017b36286aSmartynas do {
6027b36286aSmartynas y = (ULLong)*xa++ - *xb++ - borrow;
6037b36286aSmartynas borrow = y >> 32 & 1UL;
6047b36286aSmartynas *xc++ = y & 0xffffffffUL;
6057b36286aSmartynas }
6067b36286aSmartynas while(xb < xbe);
6077b36286aSmartynas while(xa < xae) {
6087b36286aSmartynas y = *xa++ - borrow;
6097b36286aSmartynas borrow = y >> 32 & 1UL;
6107b36286aSmartynas *xc++ = y & 0xffffffffUL;
6117b36286aSmartynas }
6127b36286aSmartynas #else
6137b36286aSmartynas #ifdef Pack_32
6147b36286aSmartynas do {
6157b36286aSmartynas y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
6167b36286aSmartynas borrow = (y & 0x10000) >> 16;
6177b36286aSmartynas z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
6187b36286aSmartynas borrow = (z & 0x10000) >> 16;
6197b36286aSmartynas Storeinc(xc, z, y);
6207b36286aSmartynas }
6217b36286aSmartynas while(xb < xbe);
6227b36286aSmartynas while(xa < xae) {
6237b36286aSmartynas y = (*xa & 0xffff) - borrow;
6247b36286aSmartynas borrow = (y & 0x10000) >> 16;
6257b36286aSmartynas z = (*xa++ >> 16) - borrow;
6267b36286aSmartynas borrow = (z & 0x10000) >> 16;
6277b36286aSmartynas Storeinc(xc, z, y);
6287b36286aSmartynas }
6297b36286aSmartynas #else
6307b36286aSmartynas do {
6317b36286aSmartynas y = *xa++ - *xb++ - borrow;
6327b36286aSmartynas borrow = (y & 0x10000) >> 16;
6337b36286aSmartynas *xc++ = y & 0xffff;
6347b36286aSmartynas }
6357b36286aSmartynas while(xb < xbe);
6367b36286aSmartynas while(xa < xae) {
6377b36286aSmartynas y = *xa++ - borrow;
6387b36286aSmartynas borrow = (y & 0x10000) >> 16;
6397b36286aSmartynas *xc++ = y & 0xffff;
6407b36286aSmartynas }
6417b36286aSmartynas #endif
6427b36286aSmartynas #endif
6437b36286aSmartynas while(!*--xc)
6447b36286aSmartynas wa--;
6457b36286aSmartynas c->wds = wa;
6467b36286aSmartynas return c;
6477b36286aSmartynas }
6487b36286aSmartynas
6497b36286aSmartynas double
b2d(a,e)6507b36286aSmartynas b2d
6517b36286aSmartynas #ifdef KR_headers
6527b36286aSmartynas (a, e) Bigint *a; int *e;
6537b36286aSmartynas #else
6547b36286aSmartynas (Bigint *a, int *e)
6557b36286aSmartynas #endif
6567b36286aSmartynas {
6577b36286aSmartynas ULong *xa, *xa0, w, y, z;
6587b36286aSmartynas int k;
6591a653cbcSmartynas U d;
6607b36286aSmartynas #ifdef VAX
6617b36286aSmartynas ULong d0, d1;
6627b36286aSmartynas #else
6631a653cbcSmartynas #define d0 word0(&d)
6641a653cbcSmartynas #define d1 word1(&d)
6657b36286aSmartynas #endif
6667b36286aSmartynas
6677b36286aSmartynas xa0 = a->x;
6687b36286aSmartynas xa = xa0 + a->wds;
6697b36286aSmartynas y = *--xa;
6707b36286aSmartynas #ifdef DEBUG
6717b36286aSmartynas if (!y) Bug("zero y in b2d");
6727b36286aSmartynas #endif
6737b36286aSmartynas k = hi0bits(y);
6747b36286aSmartynas *e = 32 - k;
6757b36286aSmartynas #ifdef Pack_32
6767b36286aSmartynas if (k < Ebits) {
6771a653cbcSmartynas d0 = Exp_1 | y >> (Ebits - k);
6787b36286aSmartynas w = xa > xa0 ? *--xa : 0;
6791a653cbcSmartynas d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
6807b36286aSmartynas goto ret_d;
6817b36286aSmartynas }
6827b36286aSmartynas z = xa > xa0 ? *--xa : 0;
6837b36286aSmartynas if (k -= Ebits) {
6841a653cbcSmartynas d0 = Exp_1 | y << k | z >> (32 - k);
6857b36286aSmartynas y = xa > xa0 ? *--xa : 0;
6861a653cbcSmartynas d1 = z << k | y >> (32 - k);
6877b36286aSmartynas }
6887b36286aSmartynas else {
6897b36286aSmartynas d0 = Exp_1 | y;
6907b36286aSmartynas d1 = z;
6917b36286aSmartynas }
6927b36286aSmartynas #else
6937b36286aSmartynas if (k < Ebits + 16) {
6947b36286aSmartynas z = xa > xa0 ? *--xa : 0;
6957b36286aSmartynas d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
6967b36286aSmartynas w = xa > xa0 ? *--xa : 0;
6977b36286aSmartynas y = xa > xa0 ? *--xa : 0;
6987b36286aSmartynas d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
6997b36286aSmartynas goto ret_d;
7007b36286aSmartynas }
7017b36286aSmartynas z = xa > xa0 ? *--xa : 0;
7027b36286aSmartynas w = xa > xa0 ? *--xa : 0;
7037b36286aSmartynas k -= Ebits + 16;
7047b36286aSmartynas d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
7057b36286aSmartynas y = xa > xa0 ? *--xa : 0;
7067b36286aSmartynas d1 = w << k + 16 | y << k;
7077b36286aSmartynas #endif
7087b36286aSmartynas ret_d:
7097b36286aSmartynas #ifdef VAX
7101a653cbcSmartynas word0(&d) = d0 >> 16 | d0 << 16;
7111a653cbcSmartynas word1(&d) = d1 >> 16 | d1 << 16;
7127b36286aSmartynas #endif
7131a653cbcSmartynas return dval(&d);
7147b36286aSmartynas }
7157b36286aSmartynas #undef d0
7167b36286aSmartynas #undef d1
7177b36286aSmartynas
7187b36286aSmartynas Bigint *
d2b(dd,e,bits)7197b36286aSmartynas d2b
7207b36286aSmartynas #ifdef KR_headers
7211a653cbcSmartynas (dd, e, bits) double dd; int *e, *bits;
7227b36286aSmartynas #else
7231a653cbcSmartynas (double dd, int *e, int *bits)
7247b36286aSmartynas #endif
7257b36286aSmartynas {
7267b36286aSmartynas Bigint *b;
7271a653cbcSmartynas U d;
7287b36286aSmartynas #ifndef Sudden_Underflow
7297b36286aSmartynas int i;
7307b36286aSmartynas #endif
7317b36286aSmartynas int de, k;
7327b36286aSmartynas ULong *x, y, z;
7337b36286aSmartynas #ifdef VAX
7347b36286aSmartynas ULong d0, d1;
7357b36286aSmartynas #else
7361a653cbcSmartynas #define d0 word0(&d)
7371a653cbcSmartynas #define d1 word1(&d)
7381a653cbcSmartynas #endif
7391a653cbcSmartynas d.d = dd;
7401a653cbcSmartynas #ifdef VAX
7411a653cbcSmartynas d0 = word0(&d) >> 16 | word0(&d) << 16;
7421a653cbcSmartynas d1 = word1(&d) >> 16 | word1(&d) << 16;
7437b36286aSmartynas #endif
7447b36286aSmartynas
7457b36286aSmartynas #ifdef Pack_32
7467b36286aSmartynas b = Balloc(1);
7477b36286aSmartynas #else
7487b36286aSmartynas b = Balloc(2);
7497b36286aSmartynas #endif
750384cfdc1Smartynas if (b == NULL)
751384cfdc1Smartynas return (NULL);
7527b36286aSmartynas x = b->x;
7537b36286aSmartynas
7547b36286aSmartynas z = d0 & Frac_mask;
7557b36286aSmartynas d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
7567b36286aSmartynas #ifdef Sudden_Underflow
7577b36286aSmartynas de = (int)(d0 >> Exp_shift);
7587b36286aSmartynas #ifndef IBM
7597b36286aSmartynas z |= Exp_msk11;
7607b36286aSmartynas #endif
7617b36286aSmartynas #else
7627b36286aSmartynas if ( (de = (int)(d0 >> Exp_shift)) !=0)
7637b36286aSmartynas z |= Exp_msk1;
7647b36286aSmartynas #endif
7657b36286aSmartynas #ifdef Pack_32
7667b36286aSmartynas if ( (y = d1) !=0) {
7677b36286aSmartynas if ( (k = lo0bits(&y)) !=0) {
7681a653cbcSmartynas x[0] = y | z << (32 - k);
7697b36286aSmartynas z >>= k;
7707b36286aSmartynas }
7717b36286aSmartynas else
7727b36286aSmartynas x[0] = y;
7737b36286aSmartynas #ifndef Sudden_Underflow
7747b36286aSmartynas i =
7757b36286aSmartynas #endif
7767b36286aSmartynas b->wds = (x[1] = z) !=0 ? 2 : 1;
7777b36286aSmartynas }
7787b36286aSmartynas else {
7797b36286aSmartynas k = lo0bits(&z);
7807b36286aSmartynas x[0] = z;
7817b36286aSmartynas #ifndef Sudden_Underflow
7827b36286aSmartynas i =
7837b36286aSmartynas #endif
7847b36286aSmartynas b->wds = 1;
7857b36286aSmartynas k += 32;
7867b36286aSmartynas }
7877b36286aSmartynas #else
7887b36286aSmartynas if ( (y = d1) !=0) {
7897b36286aSmartynas if ( (k = lo0bits(&y)) !=0)
7907b36286aSmartynas if (k >= 16) {
7917b36286aSmartynas x[0] = y | z << 32 - k & 0xffff;
7927b36286aSmartynas x[1] = z >> k - 16 & 0xffff;
7937b36286aSmartynas x[2] = z >> k;
7947b36286aSmartynas i = 2;
7957b36286aSmartynas }
7967b36286aSmartynas else {
7977b36286aSmartynas x[0] = y & 0xffff;
7987b36286aSmartynas x[1] = y >> 16 | z << 16 - k & 0xffff;
7997b36286aSmartynas x[2] = z >> k & 0xffff;
8007b36286aSmartynas x[3] = z >> k+16;
8017b36286aSmartynas i = 3;
8027b36286aSmartynas }
8037b36286aSmartynas else {
8047b36286aSmartynas x[0] = y & 0xffff;
8057b36286aSmartynas x[1] = y >> 16;
8067b36286aSmartynas x[2] = z & 0xffff;
8077b36286aSmartynas x[3] = z >> 16;
8087b36286aSmartynas i = 3;
8097b36286aSmartynas }
8107b36286aSmartynas }
8117b36286aSmartynas else {
8127b36286aSmartynas #ifdef DEBUG
8137b36286aSmartynas if (!z)
8147b36286aSmartynas Bug("Zero passed to d2b");
8157b36286aSmartynas #endif
8167b36286aSmartynas k = lo0bits(&z);
8177b36286aSmartynas if (k >= 16) {
8187b36286aSmartynas x[0] = z;
8197b36286aSmartynas i = 0;
8207b36286aSmartynas }
8217b36286aSmartynas else {
8227b36286aSmartynas x[0] = z & 0xffff;
8237b36286aSmartynas x[1] = z >> 16;
8247b36286aSmartynas i = 1;
8257b36286aSmartynas }
8267b36286aSmartynas k += 32;
8277b36286aSmartynas }
8287b36286aSmartynas while(!x[i])
8297b36286aSmartynas --i;
8307b36286aSmartynas b->wds = i + 1;
8317b36286aSmartynas #endif
8327b36286aSmartynas #ifndef Sudden_Underflow
8337b36286aSmartynas if (de) {
8347b36286aSmartynas #endif
8357b36286aSmartynas #ifdef IBM
8367b36286aSmartynas *e = (de - Bias - (P-1) << 2) + k;
8371a653cbcSmartynas *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
8387b36286aSmartynas #else
8397b36286aSmartynas *e = de - Bias - (P-1) + k;
8407b36286aSmartynas *bits = P - k;
8417b36286aSmartynas #endif
8427b36286aSmartynas #ifndef Sudden_Underflow
8437b36286aSmartynas }
8447b36286aSmartynas else {
8457b36286aSmartynas *e = de - Bias - (P-1) + 1 + k;
8467b36286aSmartynas #ifdef Pack_32
8477b36286aSmartynas *bits = 32*i - hi0bits(x[i-1]);
8487b36286aSmartynas #else
8497b36286aSmartynas *bits = (i+2)*16 - hi0bits(x[i]);
8507b36286aSmartynas #endif
8517b36286aSmartynas }
8527b36286aSmartynas #endif
8537b36286aSmartynas return b;
8547b36286aSmartynas }
8557b36286aSmartynas #undef d0
8567b36286aSmartynas #undef d1
8577b36286aSmartynas
8587b36286aSmartynas CONST double
8597b36286aSmartynas #ifdef IEEE_Arith
8607b36286aSmartynas bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
8617b36286aSmartynas CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
8627b36286aSmartynas };
8637b36286aSmartynas #else
8647b36286aSmartynas #ifdef IBM
8657b36286aSmartynas bigtens[] = { 1e16, 1e32, 1e64 };
8667b36286aSmartynas CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
8677b36286aSmartynas #else
8687b36286aSmartynas bigtens[] = { 1e16, 1e32 };
8697b36286aSmartynas CONST double tinytens[] = { 1e-16, 1e-32 };
8707b36286aSmartynas #endif
8717b36286aSmartynas #endif
8727b36286aSmartynas
8737b36286aSmartynas CONST double
8747b36286aSmartynas tens[] = {
8757b36286aSmartynas 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
8767b36286aSmartynas 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
8777b36286aSmartynas 1e20, 1e21, 1e22
8787b36286aSmartynas #ifdef VAX
8797b36286aSmartynas , 1e23, 1e24
8807b36286aSmartynas #endif
8817b36286aSmartynas };
8827b36286aSmartynas
883b3b7ef2eSguenther #ifdef NO_STRING_H
884b3b7ef2eSguenther
8857b36286aSmartynas char *
8867b36286aSmartynas #ifdef KR_headers
strcp_D2A(a,b)8877b36286aSmartynas strcp_D2A(a, b) char *a; char *b;
8887b36286aSmartynas #else
8897b36286aSmartynas strcp_D2A(char *a, CONST char *b)
8907b36286aSmartynas #endif
8917b36286aSmartynas {
8921a653cbcSmartynas while((*a = *b++))
8937b36286aSmartynas a++;
8947b36286aSmartynas return a;
8957b36286aSmartynas }
8967b36286aSmartynas
8977b36286aSmartynas Char *
8987b36286aSmartynas #ifdef KR_headers
memcpy_D2A(a,b,len)8997b36286aSmartynas memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
9007b36286aSmartynas #else
9017b36286aSmartynas memcpy_D2A(void *a1, void *b1, size_t len)
9027b36286aSmartynas #endif
9037b36286aSmartynas {
9041a653cbcSmartynas char *a = (char*)a1, *ae = a + len;
9051a653cbcSmartynas char *b = (char*)b1, *a0 = a;
9067b36286aSmartynas while(a < ae)
9077b36286aSmartynas *a++ = *b++;
9087b36286aSmartynas return a0;
9097b36286aSmartynas }
9107b36286aSmartynas
9117b36286aSmartynas #endif /* NO_STRING_H */
912