1 1.4 christos /* $NetBSD: dmisc.c,v 1.4 2008/03/21 23:13:48 christos Exp $ */ 2 1.1 kleink 3 1.1 kleink /**************************************************************** 4 1.1 kleink 5 1.1 kleink The author of this software is David M. Gay. 6 1.1 kleink 7 1.1 kleink Copyright (C) 1998 by Lucent Technologies 8 1.1 kleink All Rights Reserved 9 1.1 kleink 10 1.1 kleink Permission to use, copy, modify, and distribute this software and 11 1.1 kleink its documentation for any purpose and without fee is hereby 12 1.1 kleink granted, provided that the above copyright notice appear in all 13 1.1 kleink copies and that both that the copyright notice and this 14 1.1 kleink permission notice and warranty disclaimer appear in supporting 15 1.1 kleink documentation, and that the name of Lucent or any of its entities 16 1.1 kleink not be used in advertising or publicity pertaining to 17 1.1 kleink distribution of the software without specific, written prior 18 1.1 kleink permission. 19 1.1 kleink 20 1.1 kleink LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 21 1.1 kleink INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 22 1.1 kleink IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 23 1.1 kleink SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 24 1.1 kleink WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 25 1.1 kleink IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 26 1.1 kleink ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 27 1.1 kleink THIS SOFTWARE. 28 1.1 kleink 29 1.1 kleink ****************************************************************/ 30 1.1 kleink 31 1.1 kleink /* Please send bug reports to David M. Gay (dmg at acm dot org, 32 1.1 kleink * with " at " changed at "@" and " dot " changed to "."). */ 33 1.1 kleink 34 1.1 kleink #include "gdtoaimp.h" 35 1.1 kleink 36 1.1 kleink #ifndef MULTIPLE_THREADS 37 1.1 kleink char *dtoa_result; 38 1.1 kleink #endif 39 1.1 kleink 40 1.1 kleink char * 41 1.1 kleink #ifdef KR_headers 42 1.3 christos rv_alloc(i) size_t i; 43 1.1 kleink #else 44 1.3 christos rv_alloc(size_t i) 45 1.1 kleink #endif 46 1.1 kleink { 47 1.3 christos size_t j; 48 1.3 christos int k, *r; 49 1.1 kleink 50 1.1 kleink j = sizeof(ULong); 51 1.1 kleink for(k = 0; 52 1.1 kleink sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i; 53 1.1 kleink j <<= 1) 54 1.1 kleink k++; 55 1.2 kleink r = (int*)(void*)Balloc(k); 56 1.4 christos if (r == NULL) 57 1.4 christos return NULL; 58 1.1 kleink *r = k; 59 1.1 kleink return 60 1.1 kleink #ifndef MULTIPLE_THREADS 61 1.1 kleink dtoa_result = 62 1.1 kleink #endif 63 1.2 kleink (char *)(void *)(r+1); 64 1.1 kleink } 65 1.1 kleink 66 1.1 kleink char * 67 1.1 kleink #ifdef KR_headers 68 1.3 christos nrv_alloc(s, rve, n) CONST char *s; char **rve; size_t n; 69 1.1 kleink #else 70 1.3 christos nrv_alloc(CONST char *s, char **rve, size_t n) 71 1.1 kleink #endif 72 1.1 kleink { 73 1.1 kleink char *rv, *t; 74 1.1 kleink 75 1.1 kleink t = rv = rv_alloc(n); 76 1.4 christos if (t == NULL) 77 1.4 christos return NULL; 78 1.1 kleink while((*t = *s++) !=0) 79 1.1 kleink t++; 80 1.1 kleink if (rve) 81 1.1 kleink *rve = t; 82 1.1 kleink return rv; 83 1.1 kleink } 84 1.1 kleink 85 1.1 kleink /* freedtoa(s) must be used to free values s returned by dtoa 86 1.1 kleink * when MULTIPLE_THREADS is #defined. It should be used in all cases, 87 1.1 kleink * but for consistency with earlier versions of dtoa, it is optional 88 1.1 kleink * when MULTIPLE_THREADS is not defined. 89 1.1 kleink */ 90 1.1 kleink 91 1.1 kleink void 92 1.1 kleink #ifdef KR_headers 93 1.1 kleink freedtoa(s) char *s; 94 1.1 kleink #else 95 1.1 kleink freedtoa(char *s) 96 1.1 kleink #endif 97 1.1 kleink { 98 1.2 kleink Bigint *b = (Bigint *)(void *)((int *)(void *)s - 1); 99 1.2 kleink b->maxwds = 1 << (b->k = *(int*)(void*)b); 100 1.1 kleink Bfree(b); 101 1.1 kleink #ifndef MULTIPLE_THREADS 102 1.1 kleink if (s == dtoa_result) 103 1.1 kleink dtoa_result = 0; 104 1.1 kleink #endif 105 1.1 kleink } 106 1.1 kleink 107 1.1 kleink int 108 1.1 kleink quorem 109 1.1 kleink #ifdef KR_headers 110 1.1 kleink (b, S) Bigint *b, *S; 111 1.1 kleink #else 112 1.1 kleink (Bigint *b, Bigint *S) 113 1.1 kleink #endif 114 1.1 kleink { 115 1.1 kleink int n; 116 1.1 kleink ULong *bx, *bxe, q, *sx, *sxe; 117 1.1 kleink #ifdef ULLong 118 1.1 kleink ULLong borrow, carry, y, ys; 119 1.1 kleink #else 120 1.1 kleink ULong borrow, carry, y, ys; 121 1.1 kleink #ifdef Pack_32 122 1.1 kleink ULong si, z, zs; 123 1.1 kleink #endif 124 1.1 kleink #endif 125 1.1 kleink 126 1.1 kleink n = S->wds; 127 1.1 kleink #ifdef DEBUG 128 1.1 kleink /*debug*/ if (b->wds > n) 129 1.1 kleink /*debug*/ Bug("oversize b in quorem"); 130 1.1 kleink #endif 131 1.1 kleink if (b->wds < n) 132 1.1 kleink return 0; 133 1.1 kleink sx = S->x; 134 1.1 kleink sxe = sx + --n; 135 1.1 kleink bx = b->x; 136 1.1 kleink bxe = bx + n; 137 1.1 kleink q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ 138 1.1 kleink #ifdef DEBUG 139 1.1 kleink /*debug*/ if (q > 9) 140 1.1 kleink /*debug*/ Bug("oversized quotient in quorem"); 141 1.1 kleink #endif 142 1.1 kleink if (q) { 143 1.1 kleink borrow = 0; 144 1.1 kleink carry = 0; 145 1.1 kleink do { 146 1.1 kleink #ifdef ULLong 147 1.1 kleink ys = *sx++ * (ULLong)q + carry; 148 1.1 kleink carry = ys >> 32; 149 1.2 kleink /* LINTED conversion */ 150 1.1 kleink y = *bx - (ys & 0xffffffffUL) - borrow; 151 1.1 kleink borrow = y >> 32 & 1UL; 152 1.2 kleink /* LINTED conversion */ 153 1.1 kleink *bx++ = y & 0xffffffffUL; 154 1.1 kleink #else 155 1.1 kleink #ifdef Pack_32 156 1.1 kleink si = *sx++; 157 1.1 kleink ys = (si & 0xffff) * q + carry; 158 1.1 kleink zs = (si >> 16) * q + (ys >> 16); 159 1.1 kleink carry = zs >> 16; 160 1.1 kleink y = (*bx & 0xffff) - (ys & 0xffff) - borrow; 161 1.1 kleink borrow = (y & 0x10000) >> 16; 162 1.1 kleink z = (*bx >> 16) - (zs & 0xffff) - borrow; 163 1.1 kleink borrow = (z & 0x10000) >> 16; 164 1.1 kleink Storeinc(bx, z, y); 165 1.1 kleink #else 166 1.1 kleink ys = *sx++ * q + carry; 167 1.1 kleink carry = ys >> 16; 168 1.1 kleink y = *bx - (ys & 0xffff) - borrow; 169 1.1 kleink borrow = (y & 0x10000) >> 16; 170 1.1 kleink *bx++ = y & 0xffff; 171 1.1 kleink #endif 172 1.1 kleink #endif 173 1.1 kleink } 174 1.1 kleink while(sx <= sxe); 175 1.1 kleink if (!*bxe) { 176 1.1 kleink bx = b->x; 177 1.1 kleink while(--bxe > bx && !*bxe) 178 1.1 kleink --n; 179 1.1 kleink b->wds = n; 180 1.1 kleink } 181 1.1 kleink } 182 1.1 kleink if (cmp(b, S) >= 0) { 183 1.1 kleink q++; 184 1.1 kleink borrow = 0; 185 1.1 kleink carry = 0; 186 1.1 kleink bx = b->x; 187 1.1 kleink sx = S->x; 188 1.1 kleink do { 189 1.1 kleink #ifdef ULLong 190 1.1 kleink ys = *sx++ + carry; 191 1.1 kleink carry = ys >> 32; 192 1.2 kleink /* LINTED conversion */ 193 1.1 kleink y = *bx - (ys & 0xffffffffUL) - borrow; 194 1.1 kleink borrow = y >> 32 & 1UL; 195 1.2 kleink /* LINTED conversion */ 196 1.1 kleink *bx++ = y & 0xffffffffUL; 197 1.1 kleink #else 198 1.1 kleink #ifdef Pack_32 199 1.1 kleink si = *sx++; 200 1.1 kleink ys = (si & 0xffff) + carry; 201 1.1 kleink zs = (si >> 16) + (ys >> 16); 202 1.1 kleink carry = zs >> 16; 203 1.1 kleink y = (*bx & 0xffff) - (ys & 0xffff) - borrow; 204 1.1 kleink borrow = (y & 0x10000) >> 16; 205 1.1 kleink z = (*bx >> 16) - (zs & 0xffff) - borrow; 206 1.1 kleink borrow = (z & 0x10000) >> 16; 207 1.1 kleink Storeinc(bx, z, y); 208 1.1 kleink #else 209 1.1 kleink ys = *sx++ + carry; 210 1.1 kleink carry = ys >> 16; 211 1.1 kleink y = *bx - (ys & 0xffff) - borrow; 212 1.1 kleink borrow = (y & 0x10000) >> 16; 213 1.1 kleink *bx++ = y & 0xffff; 214 1.1 kleink #endif 215 1.1 kleink #endif 216 1.1 kleink } 217 1.1 kleink while(sx <= sxe); 218 1.1 kleink bx = b->x; 219 1.1 kleink bxe = bx + n; 220 1.1 kleink if (!*bxe) { 221 1.1 kleink while(--bxe > bx && !*bxe) 222 1.1 kleink --n; 223 1.1 kleink b->wds = n; 224 1.1 kleink } 225 1.1 kleink } 226 1.1 kleink return q; 227 1.1 kleink } 228