1*ab625449Schristos /* $NetBSD: dmisc.c,v 1.4 2008/03/21 23:13:48 christos Exp $ */
27684d5e0Skleink
37684d5e0Skleink /****************************************************************
47684d5e0Skleink
57684d5e0Skleink The author of this software is David M. Gay.
67684d5e0Skleink
77684d5e0Skleink Copyright (C) 1998 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 #ifndef MULTIPLE_THREADS
377684d5e0Skleink char *dtoa_result;
387684d5e0Skleink #endif
397684d5e0Skleink
407684d5e0Skleink char *
417684d5e0Skleink #ifdef KR_headers
rv_alloc(i)42818764fcSchristos rv_alloc(i) size_t i;
437684d5e0Skleink #else
44818764fcSchristos rv_alloc(size_t i)
457684d5e0Skleink #endif
467684d5e0Skleink {
47818764fcSchristos size_t j;
48818764fcSchristos int k, *r;
497684d5e0Skleink
507684d5e0Skleink j = sizeof(ULong);
517684d5e0Skleink for(k = 0;
527684d5e0Skleink sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
537684d5e0Skleink j <<= 1)
547684d5e0Skleink k++;
55ac898a26Skleink r = (int*)(void*)Balloc(k);
56*ab625449Schristos if (r == NULL)
57*ab625449Schristos return NULL;
587684d5e0Skleink *r = k;
597684d5e0Skleink return
607684d5e0Skleink #ifndef MULTIPLE_THREADS
617684d5e0Skleink dtoa_result =
627684d5e0Skleink #endif
63ac898a26Skleink (char *)(void *)(r+1);
647684d5e0Skleink }
657684d5e0Skleink
667684d5e0Skleink char *
677684d5e0Skleink #ifdef KR_headers
nrv_alloc(s,rve,n)68818764fcSchristos nrv_alloc(s, rve, n) CONST char *s; char **rve; size_t n;
697684d5e0Skleink #else
70818764fcSchristos nrv_alloc(CONST char *s, char **rve, size_t n)
717684d5e0Skleink #endif
727684d5e0Skleink {
737684d5e0Skleink char *rv, *t;
747684d5e0Skleink
757684d5e0Skleink t = rv = rv_alloc(n);
76*ab625449Schristos if (t == NULL)
77*ab625449Schristos return NULL;
787684d5e0Skleink while((*t = *s++) !=0)
797684d5e0Skleink t++;
807684d5e0Skleink if (rve)
817684d5e0Skleink *rve = t;
827684d5e0Skleink return rv;
837684d5e0Skleink }
847684d5e0Skleink
857684d5e0Skleink /* freedtoa(s) must be used to free values s returned by dtoa
867684d5e0Skleink * when MULTIPLE_THREADS is #defined. It should be used in all cases,
877684d5e0Skleink * but for consistency with earlier versions of dtoa, it is optional
887684d5e0Skleink * when MULTIPLE_THREADS is not defined.
897684d5e0Skleink */
907684d5e0Skleink
917684d5e0Skleink void
927684d5e0Skleink #ifdef KR_headers
freedtoa(s)937684d5e0Skleink freedtoa(s) char *s;
947684d5e0Skleink #else
957684d5e0Skleink freedtoa(char *s)
967684d5e0Skleink #endif
977684d5e0Skleink {
98ac898a26Skleink Bigint *b = (Bigint *)(void *)((int *)(void *)s - 1);
99ac898a26Skleink b->maxwds = 1 << (b->k = *(int*)(void*)b);
1007684d5e0Skleink Bfree(b);
1017684d5e0Skleink #ifndef MULTIPLE_THREADS
1027684d5e0Skleink if (s == dtoa_result)
1037684d5e0Skleink dtoa_result = 0;
1047684d5e0Skleink #endif
1057684d5e0Skleink }
1067684d5e0Skleink
1077684d5e0Skleink int
quorem(b,S)1087684d5e0Skleink quorem
1097684d5e0Skleink #ifdef KR_headers
1107684d5e0Skleink (b, S) Bigint *b, *S;
1117684d5e0Skleink #else
1127684d5e0Skleink (Bigint *b, Bigint *S)
1137684d5e0Skleink #endif
1147684d5e0Skleink {
1157684d5e0Skleink int n;
1167684d5e0Skleink ULong *bx, *bxe, q, *sx, *sxe;
1177684d5e0Skleink #ifdef ULLong
1187684d5e0Skleink ULLong borrow, carry, y, ys;
1197684d5e0Skleink #else
1207684d5e0Skleink ULong borrow, carry, y, ys;
1217684d5e0Skleink #ifdef Pack_32
1227684d5e0Skleink ULong si, z, zs;
1237684d5e0Skleink #endif
1247684d5e0Skleink #endif
1257684d5e0Skleink
1267684d5e0Skleink n = S->wds;
1277684d5e0Skleink #ifdef DEBUG
1287684d5e0Skleink /*debug*/ if (b->wds > n)
1297684d5e0Skleink /*debug*/ Bug("oversize b in quorem");
1307684d5e0Skleink #endif
1317684d5e0Skleink if (b->wds < n)
1327684d5e0Skleink return 0;
1337684d5e0Skleink sx = S->x;
1347684d5e0Skleink sxe = sx + --n;
1357684d5e0Skleink bx = b->x;
1367684d5e0Skleink bxe = bx + n;
1377684d5e0Skleink q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
1387684d5e0Skleink #ifdef DEBUG
1397684d5e0Skleink /*debug*/ if (q > 9)
1407684d5e0Skleink /*debug*/ Bug("oversized quotient in quorem");
1417684d5e0Skleink #endif
1427684d5e0Skleink if (q) {
1437684d5e0Skleink borrow = 0;
1447684d5e0Skleink carry = 0;
1457684d5e0Skleink do {
1467684d5e0Skleink #ifdef ULLong
1477684d5e0Skleink ys = *sx++ * (ULLong)q + carry;
1487684d5e0Skleink carry = ys >> 32;
149ac898a26Skleink /* LINTED conversion */
1507684d5e0Skleink y = *bx - (ys & 0xffffffffUL) - borrow;
1517684d5e0Skleink borrow = y >> 32 & 1UL;
152ac898a26Skleink /* LINTED conversion */
1537684d5e0Skleink *bx++ = y & 0xffffffffUL;
1547684d5e0Skleink #else
1557684d5e0Skleink #ifdef Pack_32
1567684d5e0Skleink si = *sx++;
1577684d5e0Skleink ys = (si & 0xffff) * q + carry;
1587684d5e0Skleink zs = (si >> 16) * q + (ys >> 16);
1597684d5e0Skleink carry = zs >> 16;
1607684d5e0Skleink y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
1617684d5e0Skleink borrow = (y & 0x10000) >> 16;
1627684d5e0Skleink z = (*bx >> 16) - (zs & 0xffff) - borrow;
1637684d5e0Skleink borrow = (z & 0x10000) >> 16;
1647684d5e0Skleink Storeinc(bx, z, y);
1657684d5e0Skleink #else
1667684d5e0Skleink ys = *sx++ * q + carry;
1677684d5e0Skleink carry = ys >> 16;
1687684d5e0Skleink y = *bx - (ys & 0xffff) - borrow;
1697684d5e0Skleink borrow = (y & 0x10000) >> 16;
1707684d5e0Skleink *bx++ = y & 0xffff;
1717684d5e0Skleink #endif
1727684d5e0Skleink #endif
1737684d5e0Skleink }
1747684d5e0Skleink while(sx <= sxe);
1757684d5e0Skleink if (!*bxe) {
1767684d5e0Skleink bx = b->x;
1777684d5e0Skleink while(--bxe > bx && !*bxe)
1787684d5e0Skleink --n;
1797684d5e0Skleink b->wds = n;
1807684d5e0Skleink }
1817684d5e0Skleink }
1827684d5e0Skleink if (cmp(b, S) >= 0) {
1837684d5e0Skleink q++;
1847684d5e0Skleink borrow = 0;
1857684d5e0Skleink carry = 0;
1867684d5e0Skleink bx = b->x;
1877684d5e0Skleink sx = S->x;
1887684d5e0Skleink do {
1897684d5e0Skleink #ifdef ULLong
1907684d5e0Skleink ys = *sx++ + carry;
1917684d5e0Skleink carry = ys >> 32;
192ac898a26Skleink /* LINTED conversion */
1937684d5e0Skleink y = *bx - (ys & 0xffffffffUL) - borrow;
1947684d5e0Skleink borrow = y >> 32 & 1UL;
195ac898a26Skleink /* LINTED conversion */
1967684d5e0Skleink *bx++ = y & 0xffffffffUL;
1977684d5e0Skleink #else
1987684d5e0Skleink #ifdef Pack_32
1997684d5e0Skleink si = *sx++;
2007684d5e0Skleink ys = (si & 0xffff) + carry;
2017684d5e0Skleink zs = (si >> 16) + (ys >> 16);
2027684d5e0Skleink carry = zs >> 16;
2037684d5e0Skleink y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
2047684d5e0Skleink borrow = (y & 0x10000) >> 16;
2057684d5e0Skleink z = (*bx >> 16) - (zs & 0xffff) - borrow;
2067684d5e0Skleink borrow = (z & 0x10000) >> 16;
2077684d5e0Skleink Storeinc(bx, z, y);
2087684d5e0Skleink #else
2097684d5e0Skleink ys = *sx++ + carry;
2107684d5e0Skleink carry = ys >> 16;
2117684d5e0Skleink y = *bx - (ys & 0xffff) - borrow;
2127684d5e0Skleink borrow = (y & 0x10000) >> 16;
2137684d5e0Skleink *bx++ = y & 0xffff;
2147684d5e0Skleink #endif
2157684d5e0Skleink #endif
2167684d5e0Skleink }
2177684d5e0Skleink while(sx <= sxe);
2187684d5e0Skleink bx = b->x;
2197684d5e0Skleink bxe = bx + n;
2207684d5e0Skleink if (!*bxe) {
2217684d5e0Skleink while(--bxe > bx && !*bxe)
2227684d5e0Skleink --n;
2237684d5e0Skleink b->wds = n;
2247684d5e0Skleink }
2257684d5e0Skleink }
2267684d5e0Skleink return q;
2277684d5e0Skleink }
228