1*86bf8464Smlelstv /* $NetBSD: misc.c,v 1.11 2011/11/21 09:46:19 mlelstv Exp $ */
27684d5e0Skleink
37684d5e0Skleink /****************************************************************
47684d5e0Skleink
57684d5e0Skleink The author of this software is David M. Gay.
67684d5e0Skleink
77684d5e0Skleink Copyright (C) 1998, 1999 by Lucent Technologies
87684d5e0Skleink All Rights Reserved
97684d5e0Skleink
107684d5e0Skleink Permission to use, copy, modify, and distribute this software and
117684d5e0Skleink its documentation for any purpose and without fee is hereby
127684d5e0Skleink granted, provided that the above copyright notice appear in all
137684d5e0Skleink copies and that both that the copyright notice and this
147684d5e0Skleink permission notice and warranty disclaimer appear in supporting
157684d5e0Skleink documentation, and that the name of Lucent or any of its entities
167684d5e0Skleink not be used in advertising or publicity pertaining to
177684d5e0Skleink distribution of the software without specific, written prior
187684d5e0Skleink permission.
197684d5e0Skleink
207684d5e0Skleink LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
217684d5e0Skleink INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
227684d5e0Skleink IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
237684d5e0Skleink SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
247684d5e0Skleink WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
257684d5e0Skleink IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
267684d5e0Skleink ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
277684d5e0Skleink THIS SOFTWARE.
287684d5e0Skleink
297684d5e0Skleink ****************************************************************/
307684d5e0Skleink
317684d5e0Skleink /* Please send bug reports to David M. Gay (dmg at acm dot org,
327684d5e0Skleink * with " at " changed at "@" and " dot " changed to "."). */
337684d5e0Skleink
347684d5e0Skleink #include "gdtoaimp.h"
357684d5e0Skleink
367684d5e0Skleink static Bigint *freelist[Kmax+1];
377684d5e0Skleink #ifndef Omit_Private_Memory
387684d5e0Skleink #ifndef PRIVATE_MEM
397684d5e0Skleink #define PRIVATE_MEM 2304
407684d5e0Skleink #endif
417684d5e0Skleink #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
427684d5e0Skleink static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
437684d5e0Skleink #endif
447684d5e0Skleink
457684d5e0Skleink Bigint *
Balloc(k)467684d5e0Skleink Balloc
477684d5e0Skleink #ifdef KR_headers
48a23ced05Schristos (k) int k;
497684d5e0Skleink #else
50a23ced05Schristos (int k)
517684d5e0Skleink #endif
527684d5e0Skleink {
537684d5e0Skleink int x;
547684d5e0Skleink Bigint *rv;
557684d5e0Skleink #ifndef Omit_Private_Memory
5661e56760Schristos size_t len;
577684d5e0Skleink #endif
587684d5e0Skleink
597684d5e0Skleink ACQUIRE_DTOA_LOCK(0);
6061e56760Schristos /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */
6161e56760Schristos /* but this case seems very unlikely. */
62a23ced05Schristos if ((size_t)k <= Kmax && (rv = freelist[k]) !=0) {
637684d5e0Skleink freelist[k] = rv->next;
647684d5e0Skleink }
657684d5e0Skleink else {
66a23ced05Schristos x = 1 << k;
677684d5e0Skleink #ifdef Omit_Private_Memory
687684d5e0Skleink rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
697684d5e0Skleink #else
707684d5e0Skleink len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
717684d5e0Skleink /sizeof(double);
72a23ced05Schristos if ((size_t)k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
73ac898a26Skleink rv = (Bigint*)(void *)pmem_next;
747684d5e0Skleink pmem_next += len;
757684d5e0Skleink }
767684d5e0Skleink else
777684d5e0Skleink rv = (Bigint*)MALLOC(len*sizeof(double));
787684d5e0Skleink #endif
79*86bf8464Smlelstv if (rv == NULL) {
80*86bf8464Smlelstv FREE_DTOA_LOCK(0);
81ab625449Schristos return NULL;
82*86bf8464Smlelstv }
83a23ced05Schristos rv->k = k;
847684d5e0Skleink rv->maxwds = x;
857684d5e0Skleink }
867684d5e0Skleink FREE_DTOA_LOCK(0);
877684d5e0Skleink rv->sign = rv->wds = 0;
887684d5e0Skleink return rv;
897684d5e0Skleink }
907684d5e0Skleink
917684d5e0Skleink void
Bfree(v)927684d5e0Skleink Bfree
937684d5e0Skleink #ifdef KR_headers
947684d5e0Skleink (v) Bigint *v;
957684d5e0Skleink #else
967684d5e0Skleink (Bigint *v)
977684d5e0Skleink #endif
987684d5e0Skleink {
997684d5e0Skleink if (v) {
10061e56760Schristos if ((size_t)v->k > Kmax)
10161e56760Schristos #ifdef FREE
10261e56760Schristos FREE((void*)v);
10361e56760Schristos #else
10461e56760Schristos free((void*)v);
10561e56760Schristos #endif
10661e56760Schristos else {
1077684d5e0Skleink ACQUIRE_DTOA_LOCK(0);
1087684d5e0Skleink v->next = freelist[v->k];
1097684d5e0Skleink freelist[v->k] = v;
1107684d5e0Skleink FREE_DTOA_LOCK(0);
1117684d5e0Skleink }
1127684d5e0Skleink }
11361e56760Schristos }
1147684d5e0Skleink
1157684d5e0Skleink int
lo0bits(y)1167684d5e0Skleink lo0bits
1177684d5e0Skleink #ifdef KR_headers
1187684d5e0Skleink (y) ULong *y;
1197684d5e0Skleink #else
1207684d5e0Skleink (ULong *y)
1217684d5e0Skleink #endif
1227684d5e0Skleink {
123ac898a26Skleink int k;
124ac898a26Skleink ULong x = *y;
1257684d5e0Skleink
1267684d5e0Skleink if (x & 7) {
1277684d5e0Skleink if (x & 1)
1287684d5e0Skleink return 0;
1297684d5e0Skleink if (x & 2) {
1307684d5e0Skleink *y = x >> 1;
1317684d5e0Skleink return 1;
1327684d5e0Skleink }
1337684d5e0Skleink *y = x >> 2;
1347684d5e0Skleink return 2;
1357684d5e0Skleink }
1367684d5e0Skleink k = 0;
1377684d5e0Skleink if (!(x & 0xffff)) {
1387684d5e0Skleink k = 16;
1397684d5e0Skleink x >>= 16;
1407684d5e0Skleink }
1417684d5e0Skleink if (!(x & 0xff)) {
1427684d5e0Skleink k += 8;
1437684d5e0Skleink x >>= 8;
1447684d5e0Skleink }
1457684d5e0Skleink if (!(x & 0xf)) {
1467684d5e0Skleink k += 4;
1477684d5e0Skleink x >>= 4;
1487684d5e0Skleink }
1497684d5e0Skleink if (!(x & 0x3)) {
1507684d5e0Skleink k += 2;
1517684d5e0Skleink x >>= 2;
1527684d5e0Skleink }
1537684d5e0Skleink if (!(x & 1)) {
1547684d5e0Skleink k++;
1557684d5e0Skleink x >>= 1;
1567684d5e0Skleink if (!x)
1577684d5e0Skleink return 32;
1587684d5e0Skleink }
1597684d5e0Skleink *y = x;
1607684d5e0Skleink return k;
1617684d5e0Skleink }
1627684d5e0Skleink
1637684d5e0Skleink Bigint *
multadd(b,m,a)1647684d5e0Skleink multadd
1657684d5e0Skleink #ifdef KR_headers
1667684d5e0Skleink (b, m, a) Bigint *b; int m, a;
1677684d5e0Skleink #else
1687684d5e0Skleink (Bigint *b, int m, int a) /* multiply by m and add a */
1697684d5e0Skleink #endif
1707684d5e0Skleink {
1717684d5e0Skleink int i, wds;
1727684d5e0Skleink #ifdef ULLong
1737684d5e0Skleink ULong *x;
1747684d5e0Skleink ULLong carry, y;
1757684d5e0Skleink #else
1767684d5e0Skleink ULong carry, *x, y;
1777684d5e0Skleink #ifdef Pack_32
1787684d5e0Skleink ULong xi, z;
1797684d5e0Skleink #endif
1807684d5e0Skleink #endif
1817684d5e0Skleink Bigint *b1;
1827684d5e0Skleink
1837684d5e0Skleink wds = b->wds;
1847684d5e0Skleink x = b->x;
1857684d5e0Skleink i = 0;
1867684d5e0Skleink carry = a;
1877684d5e0Skleink do {
1887684d5e0Skleink #ifdef ULLong
1897684d5e0Skleink y = *x * (ULLong)m + carry;
1907684d5e0Skleink carry = y >> 32;
191ac898a26Skleink /* LINTED conversion */
1927684d5e0Skleink *x++ = y & 0xffffffffUL;
1937684d5e0Skleink #else
1947684d5e0Skleink #ifdef Pack_32
1957684d5e0Skleink xi = *x;
1967684d5e0Skleink y = (xi & 0xffff) * m + carry;
1977684d5e0Skleink z = (xi >> 16) * m + (y >> 16);
1987684d5e0Skleink carry = z >> 16;
1997684d5e0Skleink *x++ = (z << 16) + (y & 0xffff);
2007684d5e0Skleink #else
2017684d5e0Skleink y = *x * m + carry;
2027684d5e0Skleink carry = y >> 16;
2037684d5e0Skleink *x++ = y & 0xffff;
2047684d5e0Skleink #endif
2057684d5e0Skleink #endif
2067684d5e0Skleink }
2077684d5e0Skleink while(++i < wds);
2087684d5e0Skleink if (carry) {
2097684d5e0Skleink if (wds >= b->maxwds) {
2107684d5e0Skleink b1 = Balloc(b->k+1);
211ab625449Schristos if (b1 == NULL) {
212ab625449Schristos Bfree(b);
213ab625449Schristos return NULL;
214ab625449Schristos }
2157684d5e0Skleink Bcopy(b1, b);
2167684d5e0Skleink Bfree(b);
2177684d5e0Skleink b = b1;
2187684d5e0Skleink }
219ac898a26Skleink /* LINTED conversion */
2207684d5e0Skleink b->x[wds++] = carry;
2217684d5e0Skleink b->wds = wds;
2227684d5e0Skleink }
2237684d5e0Skleink return b;
2247684d5e0Skleink }
2257684d5e0Skleink
2267684d5e0Skleink int
hi0bits_D2A(x)2277684d5e0Skleink hi0bits_D2A
2287684d5e0Skleink #ifdef KR_headers
229ac898a26Skleink (x) ULong x;
2307684d5e0Skleink #else
231ac898a26Skleink (ULong x)
2327684d5e0Skleink #endif
2337684d5e0Skleink {
234ac898a26Skleink int k = 0;
2357684d5e0Skleink
2367684d5e0Skleink if (!(x & 0xffff0000)) {
2377684d5e0Skleink k = 16;
2387684d5e0Skleink x <<= 16;
2397684d5e0Skleink }
2407684d5e0Skleink if (!(x & 0xff000000)) {
2417684d5e0Skleink k += 8;
2427684d5e0Skleink x <<= 8;
2437684d5e0Skleink }
2447684d5e0Skleink if (!(x & 0xf0000000)) {
2457684d5e0Skleink k += 4;
2467684d5e0Skleink x <<= 4;
2477684d5e0Skleink }
2487684d5e0Skleink if (!(x & 0xc0000000)) {
2497684d5e0Skleink k += 2;
2507684d5e0Skleink x <<= 2;
2517684d5e0Skleink }
2527684d5e0Skleink if (!(x & 0x80000000)) {
2537684d5e0Skleink k++;
2547684d5e0Skleink if (!(x & 0x40000000))
2557684d5e0Skleink return 32;
2567684d5e0Skleink }
2577684d5e0Skleink return k;
2587684d5e0Skleink }
2597684d5e0Skleink
2607684d5e0Skleink Bigint *
i2b(i)2617684d5e0Skleink i2b
2627684d5e0Skleink #ifdef KR_headers
2637684d5e0Skleink (i) int i;
2647684d5e0Skleink #else
2657684d5e0Skleink (int i)
2667684d5e0Skleink #endif
2677684d5e0Skleink {
2687684d5e0Skleink Bigint *b;
2697684d5e0Skleink
2707684d5e0Skleink b = Balloc(1);
271ab625449Schristos if (b == NULL)
272ab625449Schristos return NULL;
2737684d5e0Skleink b->x[0] = i;
2747684d5e0Skleink b->wds = 1;
2757684d5e0Skleink return b;
2767684d5e0Skleink }
2777684d5e0Skleink
2787684d5e0Skleink Bigint *
mult(a,b)2797684d5e0Skleink mult
2807684d5e0Skleink #ifdef KR_headers
2817684d5e0Skleink (a, b) Bigint *a, *b;
2827684d5e0Skleink #else
2837684d5e0Skleink (Bigint *a, Bigint *b)
2847684d5e0Skleink #endif
2857684d5e0Skleink {
2867684d5e0Skleink Bigint *c;
2877684d5e0Skleink int k, wa, wb, wc;
2887684d5e0Skleink ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
2897684d5e0Skleink ULong y;
2907684d5e0Skleink #ifdef ULLong
2917684d5e0Skleink ULLong carry, z;
2927684d5e0Skleink #else
2937684d5e0Skleink ULong carry, z;
2947684d5e0Skleink #ifdef Pack_32
2957684d5e0Skleink ULong z2;
2967684d5e0Skleink #endif
2977684d5e0Skleink #endif
2987684d5e0Skleink
2997684d5e0Skleink if (a->wds < b->wds) {
3007684d5e0Skleink c = a;
3017684d5e0Skleink a = b;
3027684d5e0Skleink b = c;
3037684d5e0Skleink }
3047684d5e0Skleink k = a->k;
3057684d5e0Skleink wa = a->wds;
3067684d5e0Skleink wb = b->wds;
3077684d5e0Skleink wc = wa + wb;
3087684d5e0Skleink if (wc > a->maxwds)
3097684d5e0Skleink k++;
3107684d5e0Skleink c = Balloc(k);
311ab625449Schristos if (c == NULL)
312ab625449Schristos return NULL;
3137684d5e0Skleink for(x = c->x, xa = x + wc; x < xa; x++)
3147684d5e0Skleink *x = 0;
3157684d5e0Skleink xa = a->x;
3167684d5e0Skleink xae = xa + wa;
3177684d5e0Skleink xb = b->x;
3187684d5e0Skleink xbe = xb + wb;
3197684d5e0Skleink xc0 = c->x;
3207684d5e0Skleink #ifdef ULLong
3217684d5e0Skleink for(; xb < xbe; xc0++) {
3227684d5e0Skleink if ( (y = *xb++) !=0) {
3237684d5e0Skleink x = xa;
3247684d5e0Skleink xc = xc0;
3257684d5e0Skleink carry = 0;
3267684d5e0Skleink do {
3277684d5e0Skleink z = *x++ * (ULLong)y + *xc + carry;
3287684d5e0Skleink carry = z >> 32;
329ac898a26Skleink /* LINTED conversion */
3307684d5e0Skleink *xc++ = z & 0xffffffffUL;
3317684d5e0Skleink }
3327684d5e0Skleink while(x < xae);
333ac898a26Skleink /* LINTED conversion */
3347684d5e0Skleink *xc = carry;
3357684d5e0Skleink }
3367684d5e0Skleink }
3377684d5e0Skleink #else
3387684d5e0Skleink #ifdef Pack_32
3397684d5e0Skleink for(; xb < xbe; xb++, xc0++) {
3407684d5e0Skleink if ( (y = *xb & 0xffff) !=0) {
3417684d5e0Skleink x = xa;
3427684d5e0Skleink xc = xc0;
3437684d5e0Skleink carry = 0;
3447684d5e0Skleink do {
3457684d5e0Skleink z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
3467684d5e0Skleink carry = z >> 16;
3477684d5e0Skleink z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
3487684d5e0Skleink carry = z2 >> 16;
3497684d5e0Skleink Storeinc(xc, z2, z);
3507684d5e0Skleink }
3517684d5e0Skleink while(x < xae);
3527684d5e0Skleink *xc = carry;
3537684d5e0Skleink }
3547684d5e0Skleink if ( (y = *xb >> 16) !=0) {
3557684d5e0Skleink x = xa;
3567684d5e0Skleink xc = xc0;
3577684d5e0Skleink carry = 0;
3587684d5e0Skleink z2 = *xc;
3597684d5e0Skleink do {
3607684d5e0Skleink z = (*x & 0xffff) * y + (*xc >> 16) + carry;
3617684d5e0Skleink carry = z >> 16;
3627684d5e0Skleink Storeinc(xc, z, z2);
3637684d5e0Skleink z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
3647684d5e0Skleink carry = z2 >> 16;
3657684d5e0Skleink }
3667684d5e0Skleink while(x < xae);
3677684d5e0Skleink *xc = z2;
3687684d5e0Skleink }
3697684d5e0Skleink }
3707684d5e0Skleink #else
3717684d5e0Skleink for(; xb < xbe; xc0++) {
3727684d5e0Skleink if ( (y = *xb++) !=0) {
3737684d5e0Skleink x = xa;
3747684d5e0Skleink xc = xc0;
3757684d5e0Skleink carry = 0;
3767684d5e0Skleink do {
3777684d5e0Skleink z = *x++ * y + *xc + carry;
3787684d5e0Skleink carry = z >> 16;
3797684d5e0Skleink *xc++ = z & 0xffff;
3807684d5e0Skleink }
3817684d5e0Skleink while(x < xae);
3827684d5e0Skleink *xc = carry;
3837684d5e0Skleink }
3847684d5e0Skleink }
3857684d5e0Skleink #endif
3867684d5e0Skleink #endif
3877684d5e0Skleink for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
3887684d5e0Skleink c->wds = wc;
3897684d5e0Skleink return c;
3907684d5e0Skleink }
3917684d5e0Skleink
3927684d5e0Skleink static Bigint *p5s;
3937684d5e0Skleink
3947684d5e0Skleink Bigint *
pow5mult(b,k)3957684d5e0Skleink pow5mult
3967684d5e0Skleink #ifdef KR_headers
3977684d5e0Skleink (b, k) Bigint *b; int k;
3987684d5e0Skleink #else
3997684d5e0Skleink (Bigint *b, int k)
4007684d5e0Skleink #endif
4017684d5e0Skleink {
4027684d5e0Skleink Bigint *b1, *p5, *p51;
4037684d5e0Skleink int i;
404b24124a7Schristos static CONST int p05[3] = { 5, 25, 125 };
4057684d5e0Skleink
406ab625449Schristos if ( (i = k & 3) !=0) {
4077684d5e0Skleink b = multadd(b, p05[i-1], 0);
408ab625449Schristos if (b == NULL)
409ab625449Schristos return NULL;
410ab625449Schristos }
4117684d5e0Skleink
412ac898a26Skleink if (!(k = (unsigned int)k >> 2))
4137684d5e0Skleink return b;
4147684d5e0Skleink if ((p5 = p5s) == 0) {
4157684d5e0Skleink /* first time */
4167684d5e0Skleink #ifdef MULTIPLE_THREADS
4177684d5e0Skleink ACQUIRE_DTOA_LOCK(1);
4187684d5e0Skleink if (!(p5 = p5s)) {
4197684d5e0Skleink p5 = p5s = i2b(625);
420b2707ef3Schristos if (p5 == NULL) {
421b2707ef3Schristos FREE_DTOA_LOCK(1);
422ab625449Schristos return NULL;
423b2707ef3Schristos }
4247684d5e0Skleink p5->next = 0;
4257684d5e0Skleink }
4267684d5e0Skleink FREE_DTOA_LOCK(1);
4277684d5e0Skleink #else
4287684d5e0Skleink p5 = p5s = i2b(625);
429ab625449Schristos if (p5 == NULL)
430ab625449Schristos return NULL;
4317684d5e0Skleink p5->next = 0;
4327684d5e0Skleink #endif
4337684d5e0Skleink }
4347684d5e0Skleink for(;;) {
4357684d5e0Skleink if (k & 1) {
4367684d5e0Skleink b1 = mult(b, p5);
437ab625449Schristos if (b1 == NULL)
438ab625449Schristos return NULL;
439f0c33b33Schristos Bfree(b);
4407684d5e0Skleink b = b1;
4417684d5e0Skleink }
442ac898a26Skleink if (!(k = (unsigned int)k >> 1))
4437684d5e0Skleink break;
4447684d5e0Skleink if ((p51 = p5->next) == 0) {
4457684d5e0Skleink #ifdef MULTIPLE_THREADS
4467684d5e0Skleink ACQUIRE_DTOA_LOCK(1);
4477684d5e0Skleink if (!(p51 = p5->next)) {
4487684d5e0Skleink p51 = p5->next = mult(p5,p5);
44934407547Smartin if (p51 == NULL) {
45034407547Smartin FREE_DTOA_LOCK(1);
451ab625449Schristos return NULL;
45234407547Smartin }
4537684d5e0Skleink p51->next = 0;
4547684d5e0Skleink }
4557684d5e0Skleink FREE_DTOA_LOCK(1);
4567684d5e0Skleink #else
4577684d5e0Skleink p51 = p5->next = mult(p5,p5);
458ab625449Schristos if (p51 == NULL)
459ab625449Schristos return NULL;
4607684d5e0Skleink p51->next = 0;
4617684d5e0Skleink #endif
4627684d5e0Skleink }
4637684d5e0Skleink p5 = p51;
4647684d5e0Skleink }
4657684d5e0Skleink return b;
4667684d5e0Skleink }
4677684d5e0Skleink
4687684d5e0Skleink Bigint *
lshift(b,k)4697684d5e0Skleink lshift
4707684d5e0Skleink #ifdef KR_headers
4717684d5e0Skleink (b, k) Bigint *b; int k;
4727684d5e0Skleink #else
4737684d5e0Skleink (Bigint *b, int k)
4747684d5e0Skleink #endif
4757684d5e0Skleink {
4767684d5e0Skleink int i, k1, n, n1;
4777684d5e0Skleink Bigint *b1;
4787684d5e0Skleink ULong *x, *x1, *xe, z;
4797684d5e0Skleink
480ac898a26Skleink n = (unsigned int)k >> kshift;
4817684d5e0Skleink k1 = b->k;
4827684d5e0Skleink n1 = n + b->wds + 1;
4837684d5e0Skleink for(i = b->maxwds; n1 > i; i <<= 1)
4847684d5e0Skleink k1++;
4857684d5e0Skleink b1 = Balloc(k1);
486ab625449Schristos if (b1 == NULL)
487ab625449Schristos return NULL;
4887684d5e0Skleink x1 = b1->x;
4897684d5e0Skleink for(i = 0; i < n; i++)
4907684d5e0Skleink *x1++ = 0;
4917684d5e0Skleink x = b->x;
4927684d5e0Skleink xe = x + b->wds;
4937684d5e0Skleink if (k &= kmask) {
4947684d5e0Skleink #ifdef Pack_32
4957684d5e0Skleink k1 = 32 - k;
4967684d5e0Skleink z = 0;
4977684d5e0Skleink do {
4987684d5e0Skleink *x1++ = *x << k | z;
4997684d5e0Skleink z = *x++ >> k1;
5007684d5e0Skleink }
5017684d5e0Skleink while(x < xe);
5027684d5e0Skleink if ((*x1 = z) !=0)
5037684d5e0Skleink ++n1;
5047684d5e0Skleink #else
5057684d5e0Skleink k1 = 16 - k;
5067684d5e0Skleink z = 0;
5077684d5e0Skleink do {
5087684d5e0Skleink *x1++ = *x << k & 0xffff | z;
5097684d5e0Skleink z = *x++ >> k1;
5107684d5e0Skleink }
5117684d5e0Skleink while(x < xe);
5127684d5e0Skleink if (*x1 = z)
5137684d5e0Skleink ++n1;
5147684d5e0Skleink #endif
5157684d5e0Skleink }
5167684d5e0Skleink else do
5177684d5e0Skleink *x1++ = *x++;
5187684d5e0Skleink while(x < xe);
5197684d5e0Skleink b1->wds = n1 - 1;
5207684d5e0Skleink Bfree(b);
5217684d5e0Skleink return b1;
5227684d5e0Skleink }
5237684d5e0Skleink
5247684d5e0Skleink int
cmp(a,b)5257684d5e0Skleink cmp
5267684d5e0Skleink #ifdef KR_headers
5277684d5e0Skleink (a, b) Bigint *a, *b;
5287684d5e0Skleink #else
5297684d5e0Skleink (Bigint *a, Bigint *b)
5307684d5e0Skleink #endif
5317684d5e0Skleink {
5327684d5e0Skleink ULong *xa, *xa0, *xb, *xb0;
5337684d5e0Skleink int i, j;
5347684d5e0Skleink
5357684d5e0Skleink i = a->wds;
5367684d5e0Skleink j = b->wds;
5377684d5e0Skleink #ifdef DEBUG
5387684d5e0Skleink if (i > 1 && !a->x[i-1])
5397684d5e0Skleink Bug("cmp called with a->x[a->wds-1] == 0");
5407684d5e0Skleink if (j > 1 && !b->x[j-1])
5417684d5e0Skleink Bug("cmp called with b->x[b->wds-1] == 0");
5427684d5e0Skleink #endif
5437684d5e0Skleink if (i -= j)
5447684d5e0Skleink return i;
5457684d5e0Skleink xa0 = a->x;
5467684d5e0Skleink xa = xa0 + j;
5477684d5e0Skleink xb0 = b->x;
5487684d5e0Skleink xb = xb0 + j;
5497684d5e0Skleink for(;;) {
5507684d5e0Skleink if (*--xa != *--xb)
5517684d5e0Skleink return *xa < *xb ? -1 : 1;
5527684d5e0Skleink if (xa <= xa0)
5537684d5e0Skleink break;
5547684d5e0Skleink }
5557684d5e0Skleink return 0;
5567684d5e0Skleink }
5577684d5e0Skleink
5587684d5e0Skleink Bigint *
diff(a,b)5597684d5e0Skleink diff
5607684d5e0Skleink #ifdef KR_headers
5617684d5e0Skleink (a, b) Bigint *a, *b;
5627684d5e0Skleink #else
5637684d5e0Skleink (Bigint *a, Bigint *b)
5647684d5e0Skleink #endif
5657684d5e0Skleink {
5667684d5e0Skleink Bigint *c;
5677684d5e0Skleink int i, wa, wb;
5687684d5e0Skleink ULong *xa, *xae, *xb, *xbe, *xc;
5697684d5e0Skleink #ifdef ULLong
5707684d5e0Skleink ULLong borrow, y;
5717684d5e0Skleink #else
5727684d5e0Skleink ULong borrow, y;
5737684d5e0Skleink #ifdef Pack_32
5747684d5e0Skleink ULong z;
5757684d5e0Skleink #endif
5767684d5e0Skleink #endif
5777684d5e0Skleink
5787684d5e0Skleink i = cmp(a,b);
5797684d5e0Skleink if (!i) {
5807684d5e0Skleink c = Balloc(0);
581ab625449Schristos if (c == NULL)
582ab625449Schristos return NULL;
5837684d5e0Skleink c->wds = 1;
5847684d5e0Skleink c->x[0] = 0;
5857684d5e0Skleink return c;
5867684d5e0Skleink }
5877684d5e0Skleink if (i < 0) {
5887684d5e0Skleink c = a;
5897684d5e0Skleink a = b;
5907684d5e0Skleink b = c;
5917684d5e0Skleink i = 1;
5927684d5e0Skleink }
5937684d5e0Skleink else
5947684d5e0Skleink i = 0;
5957684d5e0Skleink c = Balloc(a->k);
596ab625449Schristos if (c == NULL)
597ab625449Schristos return NULL;
5987684d5e0Skleink c->sign = i;
5997684d5e0Skleink wa = a->wds;
6007684d5e0Skleink xa = a->x;
6017684d5e0Skleink xae = xa + wa;
6027684d5e0Skleink wb = b->wds;
6037684d5e0Skleink xb = b->x;
6047684d5e0Skleink xbe = xb + wb;
6057684d5e0Skleink xc = c->x;
6067684d5e0Skleink borrow = 0;
6077684d5e0Skleink #ifdef ULLong
6087684d5e0Skleink do {
6097684d5e0Skleink y = (ULLong)*xa++ - *xb++ - borrow;
6107684d5e0Skleink borrow = y >> 32 & 1UL;
611ac898a26Skleink /* LINTED conversion */
6127684d5e0Skleink *xc++ = y & 0xffffffffUL;
6137684d5e0Skleink }
6147684d5e0Skleink while(xb < xbe);
6157684d5e0Skleink while(xa < xae) {
6167684d5e0Skleink y = *xa++ - borrow;
6177684d5e0Skleink borrow = y >> 32 & 1UL;
618ac898a26Skleink /* LINTED conversion */
6197684d5e0Skleink *xc++ = y & 0xffffffffUL;
6207684d5e0Skleink }
6217684d5e0Skleink #else
6227684d5e0Skleink #ifdef Pack_32
6237684d5e0Skleink do {
6247684d5e0Skleink y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
6257684d5e0Skleink borrow = (y & 0x10000) >> 16;
6267684d5e0Skleink z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
6277684d5e0Skleink borrow = (z & 0x10000) >> 16;
6287684d5e0Skleink Storeinc(xc, z, y);
6297684d5e0Skleink }
6307684d5e0Skleink while(xb < xbe);
6317684d5e0Skleink while(xa < xae) {
6327684d5e0Skleink y = (*xa & 0xffff) - borrow;
6337684d5e0Skleink borrow = (y & 0x10000) >> 16;
6347684d5e0Skleink z = (*xa++ >> 16) - borrow;
6357684d5e0Skleink borrow = (z & 0x10000) >> 16;
6367684d5e0Skleink Storeinc(xc, z, y);
6377684d5e0Skleink }
6387684d5e0Skleink #else
6397684d5e0Skleink do {
6407684d5e0Skleink y = *xa++ - *xb++ - borrow;
6417684d5e0Skleink borrow = (y & 0x10000) >> 16;
6427684d5e0Skleink *xc++ = y & 0xffff;
6437684d5e0Skleink }
6447684d5e0Skleink while(xb < xbe);
6457684d5e0Skleink while(xa < xae) {
6467684d5e0Skleink y = *xa++ - borrow;
6477684d5e0Skleink borrow = (y & 0x10000) >> 16;
6487684d5e0Skleink *xc++ = y & 0xffff;
6497684d5e0Skleink }
6507684d5e0Skleink #endif
6517684d5e0Skleink #endif
6527684d5e0Skleink while(!*--xc)
6537684d5e0Skleink wa--;
6547684d5e0Skleink c->wds = wa;
6557684d5e0Skleink return c;
6567684d5e0Skleink }
6577684d5e0Skleink
6587684d5e0Skleink double
b2d(a,e)6597684d5e0Skleink b2d
6607684d5e0Skleink #ifdef KR_headers
6617684d5e0Skleink (a, e) Bigint *a; int *e;
6627684d5e0Skleink #else
6637684d5e0Skleink (Bigint *a, int *e)
6647684d5e0Skleink #endif
6657684d5e0Skleink {
6667684d5e0Skleink ULong *xa, *xa0, w, y, z;
6677684d5e0Skleink int k;
66861e56760Schristos U d;
6697684d5e0Skleink #ifdef VAX
6707684d5e0Skleink ULong d0, d1;
6717684d5e0Skleink #else
67261e56760Schristos #define d0 word0(&d)
67361e56760Schristos #define d1 word1(&d)
6747684d5e0Skleink #endif
6757684d5e0Skleink
6767684d5e0Skleink xa0 = a->x;
6777684d5e0Skleink xa = xa0 + a->wds;
6787684d5e0Skleink y = *--xa;
6797684d5e0Skleink #ifdef DEBUG
6807684d5e0Skleink if (!y) Bug("zero y in b2d");
6817684d5e0Skleink #endif
6827684d5e0Skleink k = hi0bits(y);
6837684d5e0Skleink *e = 32 - k;
6847684d5e0Skleink #ifdef Pack_32
6857684d5e0Skleink if (k < Ebits) {
686ac898a26Skleink d0 = Exp_1 | y >> (Ebits - k);
6877684d5e0Skleink w = xa > xa0 ? *--xa : 0;
688ac898a26Skleink d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
6897684d5e0Skleink goto ret_d;
6907684d5e0Skleink }
6917684d5e0Skleink z = xa > xa0 ? *--xa : 0;
6927684d5e0Skleink if (k -= Ebits) {
693ac898a26Skleink d0 = Exp_1 | y << k | z >> (32 - k);
6947684d5e0Skleink y = xa > xa0 ? *--xa : 0;
695ac898a26Skleink d1 = z << k | y >> (32 - k);
6967684d5e0Skleink }
6977684d5e0Skleink else {
6987684d5e0Skleink d0 = Exp_1 | y;
6997684d5e0Skleink d1 = z;
7007684d5e0Skleink }
7017684d5e0Skleink #else
7027684d5e0Skleink if (k < Ebits + 16) {
7037684d5e0Skleink z = xa > xa0 ? *--xa : 0;
7047684d5e0Skleink d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
7057684d5e0Skleink w = xa > xa0 ? *--xa : 0;
7067684d5e0Skleink y = xa > xa0 ? *--xa : 0;
7077684d5e0Skleink d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
7087684d5e0Skleink goto ret_d;
7097684d5e0Skleink }
7107684d5e0Skleink z = xa > xa0 ? *--xa : 0;
7117684d5e0Skleink w = xa > xa0 ? *--xa : 0;
7127684d5e0Skleink k -= Ebits + 16;
7137684d5e0Skleink d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
7147684d5e0Skleink y = xa > xa0 ? *--xa : 0;
7157684d5e0Skleink d1 = w << k + 16 | y << k;
7167684d5e0Skleink #endif
7177684d5e0Skleink ret_d:
7187684d5e0Skleink #ifdef VAX
71961e56760Schristos word0(&d) = d0 >> 16 | d0 << 16;
72061e56760Schristos word1(&d) = d1 >> 16 | d1 << 16;
7217684d5e0Skleink #endif
72261e56760Schristos return dval(&d);
7237684d5e0Skleink }
7247684d5e0Skleink #undef d0
7257684d5e0Skleink #undef d1
7267684d5e0Skleink
7277684d5e0Skleink Bigint *
d2b(dd,e,bits)7287684d5e0Skleink d2b
7297684d5e0Skleink #ifdef KR_headers
73061e56760Schristos (dd, e, bits) double dd; int *e, *bits;
7317684d5e0Skleink #else
73261e56760Schristos (double dd, int *e, int *bits)
7337684d5e0Skleink #endif
7347684d5e0Skleink {
7357684d5e0Skleink Bigint *b;
73661e56760Schristos U d;
7377684d5e0Skleink #ifndef Sudden_Underflow
7387684d5e0Skleink int i;
7397684d5e0Skleink #endif
7407684d5e0Skleink int de, k;
7417684d5e0Skleink ULong *x, y, z;
7427684d5e0Skleink #ifdef VAX
7437684d5e0Skleink ULong d0, d1;
7447684d5e0Skleink #else
74561e56760Schristos #define d0 word0(&d)
74661e56760Schristos #define d1 word1(&d)
74761e56760Schristos #endif
74861e56760Schristos d.d = dd;
74961e56760Schristos #ifdef VAX
75061e56760Schristos d0 = word0(&d) >> 16 | word0(&d) << 16;
75161e56760Schristos d1 = word1(&d) >> 16 | word1(&d) << 16;
7527684d5e0Skleink #endif
7537684d5e0Skleink
7547684d5e0Skleink #ifdef Pack_32
7557684d5e0Skleink b = Balloc(1);
7567684d5e0Skleink #else
7577684d5e0Skleink b = Balloc(2);
7587684d5e0Skleink #endif
759ab625449Schristos if (b == NULL)
760ab625449Schristos return NULL;
7617684d5e0Skleink x = b->x;
7627684d5e0Skleink
7637684d5e0Skleink z = d0 & Frac_mask;
7647684d5e0Skleink d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
7657684d5e0Skleink #ifdef Sudden_Underflow
7667684d5e0Skleink de = (int)(d0 >> Exp_shift);
7677684d5e0Skleink #ifndef IBM
7687684d5e0Skleink z |= Exp_msk11;
7697684d5e0Skleink #endif
7707684d5e0Skleink #else
7717684d5e0Skleink if ( (de = (int)(d0 >> Exp_shift)) !=0)
7727684d5e0Skleink z |= Exp_msk1;
7737684d5e0Skleink #endif
7747684d5e0Skleink #ifdef Pack_32
7757684d5e0Skleink if ( (y = d1) !=0) {
7767684d5e0Skleink if ( (k = lo0bits(&y)) !=0) {
777ac898a26Skleink x[0] = y | z << (32 - k);
7787684d5e0Skleink z >>= k;
7797684d5e0Skleink }
7807684d5e0Skleink else
7817684d5e0Skleink x[0] = y;
7827684d5e0Skleink #ifndef Sudden_Underflow
7837684d5e0Skleink i =
7847684d5e0Skleink #endif
7857684d5e0Skleink b->wds = (x[1] = z) !=0 ? 2 : 1;
7867684d5e0Skleink }
7877684d5e0Skleink else {
7887684d5e0Skleink k = lo0bits(&z);
7897684d5e0Skleink x[0] = z;
7907684d5e0Skleink #ifndef Sudden_Underflow
7917684d5e0Skleink i =
7927684d5e0Skleink #endif
7937684d5e0Skleink b->wds = 1;
7947684d5e0Skleink k += 32;
7957684d5e0Skleink }
7967684d5e0Skleink #else
7977684d5e0Skleink if ( (y = d1) !=0) {
7987684d5e0Skleink if ( (k = lo0bits(&y)) !=0)
7997684d5e0Skleink if (k >= 16) {
8007684d5e0Skleink x[0] = y | z << 32 - k & 0xffff;
8017684d5e0Skleink x[1] = z >> k - 16 & 0xffff;
8027684d5e0Skleink x[2] = z >> k;
8037684d5e0Skleink i = 2;
8047684d5e0Skleink }
8057684d5e0Skleink else {
8067684d5e0Skleink x[0] = y & 0xffff;
8077684d5e0Skleink x[1] = y >> 16 | z << 16 - k & 0xffff;
8087684d5e0Skleink x[2] = z >> k & 0xffff;
8097684d5e0Skleink x[3] = z >> k+16;
8107684d5e0Skleink i = 3;
8117684d5e0Skleink }
8127684d5e0Skleink else {
8137684d5e0Skleink x[0] = y & 0xffff;
8147684d5e0Skleink x[1] = y >> 16;
8157684d5e0Skleink x[2] = z & 0xffff;
8167684d5e0Skleink x[3] = z >> 16;
8177684d5e0Skleink i = 3;
8187684d5e0Skleink }
8197684d5e0Skleink }
8207684d5e0Skleink else {
8217684d5e0Skleink #ifdef DEBUG
8227684d5e0Skleink if (!z)
8237684d5e0Skleink Bug("Zero passed to d2b");
8247684d5e0Skleink #endif
8257684d5e0Skleink k = lo0bits(&z);
8267684d5e0Skleink if (k >= 16) {
8277684d5e0Skleink x[0] = z;
8287684d5e0Skleink i = 0;
8297684d5e0Skleink }
8307684d5e0Skleink else {
8317684d5e0Skleink x[0] = z & 0xffff;
8327684d5e0Skleink x[1] = z >> 16;
8337684d5e0Skleink i = 1;
8347684d5e0Skleink }
8357684d5e0Skleink k += 32;
8367684d5e0Skleink }
8377684d5e0Skleink while(!x[i])
8387684d5e0Skleink --i;
8397684d5e0Skleink b->wds = i + 1;
8407684d5e0Skleink #endif
8417684d5e0Skleink #ifndef Sudden_Underflow
8427684d5e0Skleink if (de) {
8437684d5e0Skleink #endif
8447684d5e0Skleink #ifdef IBM
8457684d5e0Skleink *e = (de - Bias - (P-1) << 2) + k;
84661e56760Schristos *bits = 4*P + 8 - k - hi0bits(word0(&d) & Frac_mask);
8477684d5e0Skleink #else
8487684d5e0Skleink *e = de - Bias - (P-1) + k;
8497684d5e0Skleink *bits = P - k;
8507684d5e0Skleink #endif
8517684d5e0Skleink #ifndef Sudden_Underflow
8527684d5e0Skleink }
8537684d5e0Skleink else {
8547684d5e0Skleink *e = de - Bias - (P-1) + 1 + k;
8557684d5e0Skleink #ifdef Pack_32
8567684d5e0Skleink *bits = 32*i - hi0bits(x[i-1]);
8577684d5e0Skleink #else
8587684d5e0Skleink *bits = (i+2)*16 - hi0bits(x[i]);
8597684d5e0Skleink #endif
8607684d5e0Skleink }
8617684d5e0Skleink #endif
8627684d5e0Skleink return b;
8637684d5e0Skleink }
8647684d5e0Skleink #undef d0
8657684d5e0Skleink #undef d1
8667684d5e0Skleink
8677684d5e0Skleink CONST double
8687684d5e0Skleink #ifdef IEEE_Arith
8697684d5e0Skleink bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
8707684d5e0Skleink CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256
8717684d5e0Skleink };
8727684d5e0Skleink #else
8737684d5e0Skleink #ifdef IBM
8747684d5e0Skleink bigtens[] = { 1e16, 1e32, 1e64 };
8757684d5e0Skleink CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
8767684d5e0Skleink #else
8777684d5e0Skleink bigtens[] = { 1e16, 1e32 };
8787684d5e0Skleink CONST double tinytens[] = { 1e-16, 1e-32 };
8797684d5e0Skleink #endif
8807684d5e0Skleink #endif
8817684d5e0Skleink
8827684d5e0Skleink CONST double
8837684d5e0Skleink tens[] = {
8847684d5e0Skleink 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
8857684d5e0Skleink 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
8867684d5e0Skleink 1e20, 1e21, 1e22
8877684d5e0Skleink #ifdef VAX
8887684d5e0Skleink , 1e23, 1e24
8897684d5e0Skleink #endif
8907684d5e0Skleink };
8917684d5e0Skleink
8927684d5e0Skleink char *
8937684d5e0Skleink #ifdef KR_headers
strcp_D2A(a,b)8947684d5e0Skleink strcp_D2A(a, b) char *a; char *b;
8957684d5e0Skleink #else
8967684d5e0Skleink strcp_D2A(char *a, CONST char *b)
8977684d5e0Skleink #endif
8987684d5e0Skleink {
899ac898a26Skleink while((*a = *b++))
9007684d5e0Skleink a++;
9017684d5e0Skleink return a;
9027684d5e0Skleink }
9037684d5e0Skleink
9047684d5e0Skleink #ifdef NO_STRING_H
9057684d5e0Skleink
9067684d5e0Skleink Char *
9077684d5e0Skleink #ifdef KR_headers
memcpy_D2A(a,b,len)9087684d5e0Skleink memcpy_D2A(a, b, len) Char *a; Char *b; size_t len;
9097684d5e0Skleink #else
9107684d5e0Skleink memcpy_D2A(void *a1, void *b1, size_t len)
9117684d5e0Skleink #endif
9127684d5e0Skleink {
913ac898a26Skleink char *a = (char*)a1, *ae = a + len;
914ac898a26Skleink char *b = (char*)b1, *a0 = a;
9157684d5e0Skleink while(a < ae)
9167684d5e0Skleink *a++ = *b++;
9177684d5e0Skleink return a0;
9187684d5e0Skleink }
9197684d5e0Skleink
9207684d5e0Skleink #endif /* NO_STRING_H */
921