dmisc.c revision 1.1 1 1.1 kleink /* $NetBSD: dmisc.c,v 1.1 2006/01/25 15:18:40 kleink 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.1 kleink rv_alloc(i) int i;
43 1.1 kleink #else
44 1.1 kleink rv_alloc(int i)
45 1.1 kleink #endif
46 1.1 kleink {
47 1.1 kleink int j, k, *r;
48 1.1 kleink
49 1.1 kleink j = sizeof(ULong);
50 1.1 kleink for(k = 0;
51 1.1 kleink sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
52 1.1 kleink j <<= 1)
53 1.1 kleink k++;
54 1.1 kleink r = (int*)Balloc(k);
55 1.1 kleink *r = k;
56 1.1 kleink return
57 1.1 kleink #ifndef MULTIPLE_THREADS
58 1.1 kleink dtoa_result =
59 1.1 kleink #endif
60 1.1 kleink (char *)(r+1);
61 1.1 kleink }
62 1.1 kleink
63 1.1 kleink char *
64 1.1 kleink #ifdef KR_headers
65 1.1 kleink nrv_alloc(s, rve, n) char *s, **rve; int n;
66 1.1 kleink #else
67 1.1 kleink nrv_alloc(char *s, char **rve, int n)
68 1.1 kleink #endif
69 1.1 kleink {
70 1.1 kleink char *rv, *t;
71 1.1 kleink
72 1.1 kleink t = rv = rv_alloc(n);
73 1.1 kleink while((*t = *s++) !=0)
74 1.1 kleink t++;
75 1.1 kleink if (rve)
76 1.1 kleink *rve = t;
77 1.1 kleink return rv;
78 1.1 kleink }
79 1.1 kleink
80 1.1 kleink /* freedtoa(s) must be used to free values s returned by dtoa
81 1.1 kleink * when MULTIPLE_THREADS is #defined. It should be used in all cases,
82 1.1 kleink * but for consistency with earlier versions of dtoa, it is optional
83 1.1 kleink * when MULTIPLE_THREADS is not defined.
84 1.1 kleink */
85 1.1 kleink
86 1.1 kleink void
87 1.1 kleink #ifdef KR_headers
88 1.1 kleink freedtoa(s) char *s;
89 1.1 kleink #else
90 1.1 kleink freedtoa(char *s)
91 1.1 kleink #endif
92 1.1 kleink {
93 1.1 kleink Bigint *b = (Bigint *)((int *)s - 1);
94 1.1 kleink b->maxwds = 1 << (b->k = *(int*)b);
95 1.1 kleink Bfree(b);
96 1.1 kleink #ifndef MULTIPLE_THREADS
97 1.1 kleink if (s == dtoa_result)
98 1.1 kleink dtoa_result = 0;
99 1.1 kleink #endif
100 1.1 kleink }
101 1.1 kleink
102 1.1 kleink int
103 1.1 kleink quorem
104 1.1 kleink #ifdef KR_headers
105 1.1 kleink (b, S) Bigint *b, *S;
106 1.1 kleink #else
107 1.1 kleink (Bigint *b, Bigint *S)
108 1.1 kleink #endif
109 1.1 kleink {
110 1.1 kleink int n;
111 1.1 kleink ULong *bx, *bxe, q, *sx, *sxe;
112 1.1 kleink #ifdef ULLong
113 1.1 kleink ULLong borrow, carry, y, ys;
114 1.1 kleink #else
115 1.1 kleink ULong borrow, carry, y, ys;
116 1.1 kleink #ifdef Pack_32
117 1.1 kleink ULong si, z, zs;
118 1.1 kleink #endif
119 1.1 kleink #endif
120 1.1 kleink
121 1.1 kleink n = S->wds;
122 1.1 kleink #ifdef DEBUG
123 1.1 kleink /*debug*/ if (b->wds > n)
124 1.1 kleink /*debug*/ Bug("oversize b in quorem");
125 1.1 kleink #endif
126 1.1 kleink if (b->wds < n)
127 1.1 kleink return 0;
128 1.1 kleink sx = S->x;
129 1.1 kleink sxe = sx + --n;
130 1.1 kleink bx = b->x;
131 1.1 kleink bxe = bx + n;
132 1.1 kleink q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
133 1.1 kleink #ifdef DEBUG
134 1.1 kleink /*debug*/ if (q > 9)
135 1.1 kleink /*debug*/ Bug("oversized quotient in quorem");
136 1.1 kleink #endif
137 1.1 kleink if (q) {
138 1.1 kleink borrow = 0;
139 1.1 kleink carry = 0;
140 1.1 kleink do {
141 1.1 kleink #ifdef ULLong
142 1.1 kleink ys = *sx++ * (ULLong)q + carry;
143 1.1 kleink carry = ys >> 32;
144 1.1 kleink y = *bx - (ys & 0xffffffffUL) - borrow;
145 1.1 kleink borrow = y >> 32 & 1UL;
146 1.1 kleink *bx++ = y & 0xffffffffUL;
147 1.1 kleink #else
148 1.1 kleink #ifdef Pack_32
149 1.1 kleink si = *sx++;
150 1.1 kleink ys = (si & 0xffff) * q + carry;
151 1.1 kleink zs = (si >> 16) * q + (ys >> 16);
152 1.1 kleink carry = zs >> 16;
153 1.1 kleink y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
154 1.1 kleink borrow = (y & 0x10000) >> 16;
155 1.1 kleink z = (*bx >> 16) - (zs & 0xffff) - borrow;
156 1.1 kleink borrow = (z & 0x10000) >> 16;
157 1.1 kleink Storeinc(bx, z, y);
158 1.1 kleink #else
159 1.1 kleink ys = *sx++ * q + carry;
160 1.1 kleink carry = ys >> 16;
161 1.1 kleink y = *bx - (ys & 0xffff) - borrow;
162 1.1 kleink borrow = (y & 0x10000) >> 16;
163 1.1 kleink *bx++ = y & 0xffff;
164 1.1 kleink #endif
165 1.1 kleink #endif
166 1.1 kleink }
167 1.1 kleink while(sx <= sxe);
168 1.1 kleink if (!*bxe) {
169 1.1 kleink bx = b->x;
170 1.1 kleink while(--bxe > bx && !*bxe)
171 1.1 kleink --n;
172 1.1 kleink b->wds = n;
173 1.1 kleink }
174 1.1 kleink }
175 1.1 kleink if (cmp(b, S) >= 0) {
176 1.1 kleink q++;
177 1.1 kleink borrow = 0;
178 1.1 kleink carry = 0;
179 1.1 kleink bx = b->x;
180 1.1 kleink sx = S->x;
181 1.1 kleink do {
182 1.1 kleink #ifdef ULLong
183 1.1 kleink ys = *sx++ + carry;
184 1.1 kleink carry = ys >> 32;
185 1.1 kleink y = *bx - (ys & 0xffffffffUL) - borrow;
186 1.1 kleink borrow = y >> 32 & 1UL;
187 1.1 kleink *bx++ = y & 0xffffffffUL;
188 1.1 kleink #else
189 1.1 kleink #ifdef Pack_32
190 1.1 kleink si = *sx++;
191 1.1 kleink ys = (si & 0xffff) + carry;
192 1.1 kleink zs = (si >> 16) + (ys >> 16);
193 1.1 kleink carry = zs >> 16;
194 1.1 kleink y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
195 1.1 kleink borrow = (y & 0x10000) >> 16;
196 1.1 kleink z = (*bx >> 16) - (zs & 0xffff) - borrow;
197 1.1 kleink borrow = (z & 0x10000) >> 16;
198 1.1 kleink Storeinc(bx, z, y);
199 1.1 kleink #else
200 1.1 kleink ys = *sx++ + carry;
201 1.1 kleink carry = ys >> 16;
202 1.1 kleink y = *bx - (ys & 0xffff) - borrow;
203 1.1 kleink borrow = (y & 0x10000) >> 16;
204 1.1 kleink *bx++ = y & 0xffff;
205 1.1 kleink #endif
206 1.1 kleink #endif
207 1.1 kleink }
208 1.1 kleink while(sx <= sxe);
209 1.1 kleink bx = b->x;
210 1.1 kleink bxe = bx + n;
211 1.1 kleink if (!*bxe) {
212 1.1 kleink while(--bxe > bx && !*bxe)
213 1.1 kleink --n;
214 1.1 kleink b->wds = n;
215 1.1 kleink }
216 1.1 kleink }
217 1.1 kleink return q;
218 1.1 kleink }
219