/src/mpdecimal-4.0.0/libmpdec/basearith.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2008-2024 Stefan Krah. All rights reserved. |
3 | | * |
4 | | * Redistribution and use in source and binary forms, with or without |
5 | | * modification, are permitted provided that the following conditions |
6 | | * are met: |
7 | | * |
8 | | * 1. Redistributions of source code must retain the above copyright |
9 | | * notice, this list of conditions and the following disclaimer. |
10 | | * 2. Redistributions in binary form must reproduce the above copyright |
11 | | * notice, this list of conditions and the following disclaimer in the |
12 | | * documentation and/or other materials provided with the distribution. |
13 | | * |
14 | | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
15 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
17 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
18 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
19 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
20 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
21 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
22 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
23 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
24 | | * SUCH DAMAGE. |
25 | | */ |
26 | | |
27 | | |
28 | | #include <assert.h> |
29 | | #include <stdio.h> |
30 | | |
31 | | #include "basearith.h" |
32 | | #include "constants.h" |
33 | | #include "mpdecimal.h" |
34 | | #include "typearith.h" |
35 | | |
36 | | |
37 | | /*********************************************************************/ |
38 | | /* Calculations in base MPD_RADIX */ |
39 | | /*********************************************************************/ |
40 | | |
41 | | /* |
42 | | * Knuth, TAOCP, Volume 2, 4.3.1: |
43 | | * w := sum of u (len m) and v (len n) |
44 | | * n > 0 and m >= n |
45 | | * The calling function has to handle a possible final carry. |
46 | | */ |
47 | | mpd_uint_t |
48 | | _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v, |
49 | | mpd_size_t m, mpd_size_t n) |
50 | 229 | { |
51 | 229 | mpd_uint_t s; |
52 | 229 | mpd_uint_t carry = 0; |
53 | 229 | mpd_size_t i; |
54 | | |
55 | 229 | assert(n > 0 && m >= n); |
56 | | |
57 | | /* add n members of u and v */ |
58 | 2.97k | for (i = 0; i < n; i++) { |
59 | 2.75k | s = u[i] + (v[i] + carry); |
60 | 2.75k | carry = (s < u[i]) | (s >= MPD_RADIX); |
61 | 2.75k | w[i] = carry ? s-MPD_RADIX : s; |
62 | 2.75k | } |
63 | | /* if there is a carry, propagate it */ |
64 | 269 | for (; carry && i < m; i++) { |
65 | 40 | s = u[i] + carry; |
66 | 40 | carry = (s == MPD_RADIX); |
67 | 40 | w[i] = carry ? 0 : s; |
68 | 40 | } |
69 | | /* copy the rest of u */ |
70 | 6.63k | for (; i < m; i++) { |
71 | 6.40k | w[i] = u[i]; |
72 | 6.40k | } |
73 | | |
74 | 229 | return carry; |
75 | 229 | } |
76 | | |
77 | | /* |
78 | | * Add the contents of u to w. Carries are propagated further. The caller |
79 | | * has to make sure that w is big enough. |
80 | | */ |
81 | | void |
82 | | _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n) |
83 | 0 | { |
84 | 0 | mpd_uint_t s; |
85 | 0 | mpd_uint_t carry = 0; |
86 | 0 | mpd_size_t i; |
87 | |
|
88 | 0 | if (n == 0) return; |
89 | | |
90 | | /* add n members of u to w */ |
91 | 0 | for (i = 0; i < n; i++) { |
92 | 0 | s = w[i] + (u[i] + carry); |
93 | 0 | carry = (s < w[i]) | (s >= MPD_RADIX); |
94 | 0 | w[i] = carry ? s-MPD_RADIX : s; |
95 | 0 | } |
96 | | /* if there is a carry, propagate it */ |
97 | 0 | for (; carry; i++) { |
98 | 0 | s = w[i] + carry; |
99 | 0 | carry = (s == MPD_RADIX); |
100 | 0 | w[i] = carry ? 0 : s; |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | | /* |
105 | | * Add v to w (len m). The calling function has to handle a possible |
106 | | * final carry. Assumption: m > 0. |
107 | | */ |
108 | | mpd_uint_t |
109 | | _mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v) |
110 | 0 | { |
111 | 0 | mpd_uint_t s; |
112 | 0 | mpd_uint_t carry; |
113 | 0 | mpd_size_t i; |
114 | |
|
115 | 0 | assert(m > 0); |
116 | | |
117 | | /* add v to w */ |
118 | 0 | s = w[0] + v; |
119 | 0 | carry = (s < v) | (s >= MPD_RADIX); |
120 | 0 | w[0] = carry ? s-MPD_RADIX : s; |
121 | | |
122 | | /* if there is a carry, propagate it */ |
123 | 0 | for (i = 1; carry && i < m; i++) { |
124 | 0 | s = w[i] + carry; |
125 | 0 | carry = (s == MPD_RADIX); |
126 | 0 | w[i] = carry ? 0 : s; |
127 | 0 | } |
128 | |
|
129 | 0 | return carry; |
130 | 0 | } |
131 | | |
132 | | /* Increment u. The calling function has to handle a possible carry. */ |
133 | | mpd_uint_t |
134 | | _mpd_baseincr(mpd_uint_t *u, mpd_size_t n) |
135 | 71 | { |
136 | 71 | mpd_uint_t s; |
137 | 71 | mpd_uint_t carry = 1; |
138 | 71 | mpd_size_t i; |
139 | | |
140 | 71 | assert(n > 0); |
141 | | |
142 | | /* if there is a carry, propagate it */ |
143 | 169 | for (i = 0; carry && i < n; i++) { |
144 | 98 | s = u[i] + carry; |
145 | 98 | carry = (s == MPD_RADIX); |
146 | 98 | u[i] = carry ? 0 : s; |
147 | 98 | } |
148 | | |
149 | 71 | return carry; |
150 | 71 | } |
151 | | |
152 | | /* |
153 | | * Knuth, TAOCP, Volume 2, 4.3.1: |
154 | | * w := difference of u (len m) and v (len n). |
155 | | * number in u >= number in v; |
156 | | */ |
157 | | void |
158 | | _mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v, |
159 | | mpd_size_t m, mpd_size_t n) |
160 | 231 | { |
161 | 231 | mpd_uint_t d; |
162 | 231 | mpd_uint_t borrow = 0; |
163 | 231 | mpd_size_t i; |
164 | | |
165 | 231 | assert(m > 0 && n > 0); |
166 | | |
167 | | /* subtract n members of v from u */ |
168 | 1.60k | for (i = 0; i < n; i++) { |
169 | 1.37k | d = u[i] - (v[i] + borrow); |
170 | 1.37k | borrow = (u[i] < d); |
171 | 1.37k | w[i] = borrow ? d + MPD_RADIX : d; |
172 | 1.37k | } |
173 | | /* if there is a borrow, propagate it */ |
174 | 1.43k | for (; borrow && i < m; i++) { |
175 | 1.20k | d = u[i] - borrow; |
176 | 1.20k | borrow = (u[i] == 0); |
177 | 1.20k | w[i] = borrow ? MPD_RADIX-1 : d; |
178 | 1.20k | } |
179 | | /* copy the rest of u */ |
180 | 4.75k | for (; i < m; i++) { |
181 | 4.52k | w[i] = u[i]; |
182 | 4.52k | } |
183 | 231 | } |
184 | | |
185 | | /* |
186 | | * Subtract the contents of u from w. w is larger than u. Borrows are |
187 | | * propagated further, but eventually w can absorb the final borrow. |
188 | | */ |
189 | | void |
190 | | _mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n) |
191 | 0 | { |
192 | 0 | mpd_uint_t d; |
193 | 0 | mpd_uint_t borrow = 0; |
194 | 0 | mpd_size_t i; |
195 | |
|
196 | 0 | if (n == 0) return; |
197 | | |
198 | | /* subtract n members of u from w */ |
199 | 0 | for (i = 0; i < n; i++) { |
200 | 0 | d = w[i] - (u[i] + borrow); |
201 | 0 | borrow = (w[i] < d); |
202 | 0 | w[i] = borrow ? d + MPD_RADIX : d; |
203 | 0 | } |
204 | | /* if there is a borrow, propagate it */ |
205 | 0 | for (; borrow; i++) { |
206 | 0 | d = w[i] - borrow; |
207 | 0 | borrow = (w[i] == 0); |
208 | 0 | w[i] = borrow ? MPD_RADIX-1 : d; |
209 | 0 | } |
210 | 0 | } |
211 | | |
212 | | /* w := product of u (len n) and v (single word) */ |
213 | | void |
214 | | _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v) |
215 | 5.30M | { |
216 | 5.30M | mpd_uint_t hi, lo; |
217 | 5.30M | mpd_uint_t carry = 0; |
218 | 5.30M | mpd_size_t i; |
219 | | |
220 | 5.30M | assert(n > 0); |
221 | | |
222 | 244M | for (i=0; i < n; i++) { |
223 | | |
224 | 239M | _mpd_mul_words(&hi, &lo, u[i], v); |
225 | 239M | lo = carry + lo; |
226 | 239M | if (lo < carry) hi++; |
227 | | |
228 | 239M | _mpd_div_words_r(&carry, &w[i], hi, lo); |
229 | 239M | } |
230 | 5.30M | w[i] = carry; |
231 | 5.30M | } |
232 | | |
233 | | /* |
234 | | * Knuth, TAOCP, Volume 2, 4.3.1: |
235 | | * w := product of u (len m) and v (len n) |
236 | | * w must be initialized to zero |
237 | | */ |
238 | | void |
239 | | _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v, |
240 | | mpd_size_t m, mpd_size_t n) |
241 | 2.12M | { |
242 | 2.12M | mpd_uint_t hi, lo; |
243 | 2.12M | mpd_uint_t carry; |
244 | 2.12M | mpd_size_t i, j; |
245 | | |
246 | 2.12M | assert(m > 0 && n > 0); |
247 | | |
248 | 81.0M | for (j=0; j < n; j++) { |
249 | 78.9M | carry = 0; |
250 | 3.55G | for (i=0; i < m; i++) { |
251 | | |
252 | 3.47G | _mpd_mul_words(&hi, &lo, u[i], v[j]); |
253 | 3.47G | lo = w[i+j] + lo; |
254 | 3.47G | if (lo < w[i+j]) hi++; |
255 | 3.47G | lo = carry + lo; |
256 | 3.47G | if (lo < carry) hi++; |
257 | | |
258 | 3.47G | _mpd_div_words_r(&carry, &w[i+j], hi, lo); |
259 | 3.47G | } |
260 | 78.9M | w[j+m] = carry; |
261 | 78.9M | } |
262 | 2.12M | } |
263 | | |
264 | | /* |
265 | | * Knuth, TAOCP Volume 2, 4.3.1, exercise 16: |
266 | | * w := quotient of u (len n) divided by a single word v |
267 | | */ |
268 | | mpd_uint_t |
269 | | _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v) |
270 | 85.9M | { |
271 | 85.9M | mpd_uint_t hi, lo; |
272 | 85.9M | mpd_uint_t rem = 0; |
273 | 85.9M | mpd_size_t i; |
274 | | |
275 | 85.9M | assert(n > 0); |
276 | | |
277 | 361M | for (i=n-1; i != MPD_SIZE_MAX; i--) { |
278 | | |
279 | 275M | _mpd_mul_words(&hi, &lo, rem, MPD_RADIX); |
280 | 275M | lo = u[i] + lo; |
281 | 275M | if (lo < u[i]) hi++; |
282 | | |
283 | 275M | _mpd_div_words(&w[i], &rem, hi, lo, v); |
284 | 275M | } |
285 | | |
286 | 85.9M | return rem; |
287 | 85.9M | } |
288 | | |
289 | | /* |
290 | | * Knuth, TAOCP Volume 2, 4.3.1: |
291 | | * q, r := quotient and remainder of uconst (len nplusm) |
292 | | * divided by vconst (len n) |
293 | | * nplusm >= n |
294 | | * |
295 | | * If r is not NULL, r will contain the remainder. If r is NULL, the |
296 | | * return value indicates if there is a remainder: 1 for true, 0 for |
297 | | * false. A return value of -1 indicates an error. |
298 | | */ |
299 | | int |
300 | | _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r, |
301 | | const mpd_uint_t *uconst, const mpd_uint_t *vconst, |
302 | | mpd_size_t nplusm, mpd_size_t n) |
303 | 2.65M | { |
304 | 2.65M | mpd_uint_t ustatic[MPD_MINALLOC_MAX]; |
305 | 2.65M | mpd_uint_t vstatic[MPD_MINALLOC_MAX]; |
306 | 2.65M | mpd_uint_t *u = ustatic; |
307 | 2.65M | mpd_uint_t *v = vstatic; |
308 | 2.65M | mpd_uint_t d, qhat, rhat, w2[2]; |
309 | 2.65M | mpd_uint_t hi, lo, x; |
310 | 2.65M | mpd_uint_t carry; |
311 | 2.65M | mpd_size_t i, j, m; |
312 | 2.65M | int retval = 0; |
313 | | |
314 | 2.65M | assert(n > 1 && nplusm >= n); |
315 | 2.65M | m = sub_size_t(nplusm, n); |
316 | | |
317 | | /* D1: normalize */ |
318 | 2.65M | d = MPD_RADIX / (vconst[n-1] + 1); |
319 | | |
320 | 2.65M | if (nplusm >= MPD_MINALLOC_MAX) { |
321 | 1.62M | if ((u = mpd_alloc(nplusm+1, sizeof *u)) == NULL) { |
322 | 0 | return -1; |
323 | 0 | } |
324 | 1.62M | } |
325 | 2.65M | if (n >= MPD_MINALLOC_MAX) { |
326 | 10 | if ((v = mpd_alloc(n+1, sizeof *v)) == NULL) { |
327 | 0 | mpd_free(u); |
328 | 0 | return -1; |
329 | 0 | } |
330 | 10 | } |
331 | | |
332 | 2.65M | _mpd_shortmul(u, uconst, nplusm, d); |
333 | 2.65M | _mpd_shortmul(v, vconst, n, d); |
334 | | |
335 | | /* D2: loop */ |
336 | 84.2M | for (j=m; j != MPD_SIZE_MAX; j--) { |
337 | | |
338 | | /* D3: calculate qhat and rhat */ |
339 | 81.6M | rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]); |
340 | 81.6M | qhat = w2[1] * MPD_RADIX + w2[0]; |
341 | | |
342 | 82.0M | while (1) { |
343 | 82.0M | if (qhat < MPD_RADIX) { |
344 | 82.0M | _mpd_singlemul(w2, qhat, v[n-2]); |
345 | 82.0M | if (w2[1] <= rhat) { |
346 | 69.9M | if (w2[1] != rhat || w2[0] <= u[j+n-2]) { |
347 | 69.9M | break; |
348 | 69.9M | } |
349 | 69.9M | } |
350 | 82.0M | } |
351 | 12.1M | qhat -= 1; |
352 | 12.1M | rhat += v[n-1]; |
353 | 12.1M | if (rhat < v[n-1] || rhat >= MPD_RADIX) { |
354 | 11.6M | break; |
355 | 11.6M | } |
356 | 12.1M | } |
357 | | /* D4: multiply and subtract */ |
358 | 81.6M | carry = 0; |
359 | 3.70G | for (i=0; i <= n; i++) { |
360 | | |
361 | 3.62G | _mpd_mul_words(&hi, &lo, qhat, v[i]); |
362 | | |
363 | 3.62G | lo = carry + lo; |
364 | 3.62G | if (lo < carry) hi++; |
365 | | |
366 | 3.62G | _mpd_div_words_r(&hi, &lo, hi, lo); |
367 | | |
368 | 3.62G | x = u[i+j] - lo; |
369 | 3.62G | carry = (u[i+j] < x); |
370 | 3.62G | u[i+j] = carry ? x+MPD_RADIX : x; |
371 | 3.62G | carry += hi; |
372 | 3.62G | } |
373 | 81.6M | q[j] = qhat; |
374 | | /* D5: test remainder */ |
375 | 81.6M | if (carry) { |
376 | 33 | q[j] -= 1; |
377 | | /* D6: add back */ |
378 | 33 | (void)_mpd_baseadd(u+j, u+j, v, n+1, n); |
379 | 33 | } |
380 | 81.6M | } |
381 | | |
382 | | /* D8: unnormalize */ |
383 | 2.65M | if (r != NULL) { |
384 | 2.65M | _mpd_shortdiv(r, u, n, d); |
385 | | /* we are not interested in the return value here */ |
386 | 2.65M | retval = 0; |
387 | 2.65M | } |
388 | 120 | else { |
389 | 120 | retval = !_mpd_isallzero(u, n); |
390 | 120 | } |
391 | | |
392 | | |
393 | 2.65M | if (u != ustatic) mpd_free(u); |
394 | 2.65M | if (v != vstatic) mpd_free(v); |
395 | 2.65M | return retval; |
396 | 2.65M | } |
397 | | |
398 | | /* |
399 | | * Left shift of src by 'shift' digits; src may equal dest. |
400 | | * |
401 | | * dest := area of n mpd_uint_t with space for srcdigits+shift digits. |
402 | | * src := coefficient with length m. |
403 | | * |
404 | | * The case splits in the function are non-obvious. The following |
405 | | * equations might help: |
406 | | * |
407 | | * Let msdigits denote the number of digits in the most significant |
408 | | * word of src. Then 1 <= msdigits <= rdigits. |
409 | | * |
410 | | * 1) shift = q * rdigits + r |
411 | | * 2) srcdigits = qsrc * rdigits + msdigits |
412 | | * 3) destdigits = shift + srcdigits |
413 | | * = q * rdigits + r + qsrc * rdigits + msdigits |
414 | | * = q * rdigits + (qsrc * rdigits + (r + msdigits)) |
415 | | * |
416 | | * The result has q zero words, followed by the coefficient that is left- |
417 | | * shifted by r. The case r == 0 is trivial. For r > 0, it is important |
418 | | * to keep in mind that we always read m source words, but write m+1 |
419 | | * destination words if r + msdigits > rdigits, m words otherwise. |
420 | | */ |
421 | | void |
422 | | _mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n, mpd_size_t m, |
423 | | mpd_size_t shift) |
424 | 194 | { |
425 | | #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) |
426 | | /* spurious uninitialized warnings */ |
427 | | mpd_uint_t l=l, lprev=lprev, h=h; |
428 | | #else |
429 | 194 | mpd_uint_t l, lprev, h; |
430 | 194 | #endif |
431 | 194 | mpd_uint_t q, r; |
432 | 194 | mpd_uint_t ph; |
433 | | |
434 | 194 | assert(m > 0 && n >= m); |
435 | | |
436 | 194 | _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS); |
437 | | |
438 | 194 | if (r != 0) { |
439 | | |
440 | 181 | ph = mpd_pow10[r]; |
441 | | |
442 | 181 | --m; --n; |
443 | 181 | _mpd_divmod_pow10(&h, &lprev, src[m--], MPD_RDIGITS-r); |
444 | 181 | if (h != 0) { /* r + msdigits > rdigits <==> h != 0 */ |
445 | 60 | dest[n--] = h; |
446 | 60 | } |
447 | | /* write m-1 shifted words */ |
448 | 3.91k | for (; m != MPD_SIZE_MAX; m--,n--) { |
449 | 3.73k | _mpd_divmod_pow10(&h, &l, src[m], MPD_RDIGITS-r); |
450 | 3.73k | dest[n] = ph * lprev + h; |
451 | 3.73k | lprev = l; |
452 | 3.73k | } |
453 | | /* write least significant word */ |
454 | 181 | dest[q] = ph * lprev; |
455 | 181 | } |
456 | 13 | else { |
457 | 195 | while (--m != MPD_SIZE_MAX) { |
458 | 182 | dest[m+q] = src[m]; |
459 | 182 | } |
460 | 13 | } |
461 | | |
462 | 194 | mpd_uint_zero(dest, q); |
463 | 194 | } |
464 | | |
465 | | /* |
466 | | * Right shift of src by 'shift' digits; src may equal dest. |
467 | | * Assumption: srcdigits-shift > 0. |
468 | | * |
469 | | * dest := area with space for srcdigits-shift digits. |
470 | | * src := coefficient with length 'slen'. |
471 | | * |
472 | | * The case splits in the function rely on the following equations: |
473 | | * |
474 | | * Let msdigits denote the number of digits in the most significant |
475 | | * word of src. Then 1 <= msdigits <= rdigits. |
476 | | * |
477 | | * 1) shift = q * rdigits + r |
478 | | * 2) srcdigits = qsrc * rdigits + msdigits |
479 | | * 3) destdigits = srcdigits - shift |
480 | | * = qsrc * rdigits + msdigits - (q * rdigits + r) |
481 | | * = (qsrc - q) * rdigits + msdigits - r |
482 | | * |
483 | | * Since destdigits > 0 and 1 <= msdigits <= rdigits: |
484 | | * |
485 | | * 4) qsrc >= q |
486 | | * 5) qsrc == q ==> msdigits > r |
487 | | * |
488 | | * The result has slen-q words if msdigits > r, slen-q-1 words otherwise. |
489 | | */ |
490 | | mpd_uint_t |
491 | | _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen, |
492 | | mpd_size_t shift) |
493 | 194 | { |
494 | | #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) |
495 | | /* spurious uninitialized warnings */ |
496 | | mpd_uint_t l=l, h=h, hprev=hprev; /* low, high, previous high */ |
497 | | #else |
498 | 194 | mpd_uint_t l, h, hprev; /* low, high, previous high */ |
499 | 194 | #endif |
500 | 194 | mpd_uint_t rnd, rest; /* rounding digit, rest */ |
501 | 194 | mpd_uint_t q, r; |
502 | 194 | mpd_size_t i, j; |
503 | 194 | mpd_uint_t ph; |
504 | | |
505 | 194 | assert(slen > 0); |
506 | | |
507 | 194 | _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS); |
508 | | |
509 | 194 | rnd = rest = 0; |
510 | 194 | if (r != 0) { |
511 | | |
512 | 186 | ph = mpd_pow10[MPD_RDIGITS-r]; |
513 | | |
514 | 186 | _mpd_divmod_pow10(&hprev, &rest, src[q], r); |
515 | 186 | _mpd_divmod_pow10(&rnd, &rest, rest, r-1); |
516 | | |
517 | 186 | if (rest == 0 && q > 0) { |
518 | 33 | rest = !_mpd_isallzero(src, q); |
519 | 33 | } |
520 | | /* write slen-q-1 words */ |
521 | 805k | for (j=0,i=q+1; i<slen; i++,j++) { |
522 | 805k | _mpd_divmod_pow10(&h, &l, src[i], r); |
523 | 805k | dest[j] = ph * l + hprev; |
524 | 805k | hprev = h; |
525 | 805k | } |
526 | | /* write most significant word */ |
527 | 186 | if (hprev != 0) { /* always the case if slen==q-1 */ |
528 | 160 | dest[j] = hprev; |
529 | 160 | } |
530 | 186 | } |
531 | 8 | else { |
532 | 8 | if (q > 0) { |
533 | 8 | _mpd_divmod_pow10(&rnd, &rest, src[q-1], MPD_RDIGITS-1); |
534 | | /* is there any non-zero digit below rnd? */ |
535 | 8 | if (rest == 0) rest = !_mpd_isallzero(src, q-1); |
536 | 8 | } |
537 | 50 | for (j = 0; j < slen-q; j++) { |
538 | 42 | dest[j] = src[q+j]; |
539 | 42 | } |
540 | 8 | } |
541 | | |
542 | | /* 0-4 ==> rnd+rest < 0.5 */ |
543 | | /* 5 ==> rnd+rest == 0.5 */ |
544 | | /* 6-9 ==> rnd+rest > 0.5 */ |
545 | 194 | return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd; |
546 | 194 | } |
547 | | |
548 | | /*********************************************************************/ |
549 | | /* Calculations in base b */ |
550 | | /*********************************************************************/ |
551 | | |
552 | | /* |
553 | | * Add v to w (len m). The calling function has to handle a possible |
554 | | * final carry. Assumption: m > 0. |
555 | | */ |
556 | | mpd_uint_t |
557 | | _mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v, mpd_uint_t b) |
558 | 0 | { |
559 | 0 | mpd_uint_t s; |
560 | 0 | mpd_uint_t carry; |
561 | 0 | mpd_size_t i; |
562 | |
|
563 | 0 | assert(m > 0); |
564 | | |
565 | | /* add v to w */ |
566 | 0 | s = w[0] + v; |
567 | 0 | carry = (s < v) | (s >= b); |
568 | 0 | w[0] = carry ? s-b : s; |
569 | | |
570 | | /* if there is a carry, propagate it */ |
571 | 0 | for (i = 1; carry && i < m; i++) { |
572 | 0 | s = w[i] + carry; |
573 | 0 | carry = (s == b); |
574 | 0 | w[i] = carry ? 0 : s; |
575 | 0 | } |
576 | |
|
577 | 0 | return carry; |
578 | 0 | } |
579 | | |
580 | | /* w := product of u (len n) and v (single word). Return carry. */ |
581 | | mpd_uint_t |
582 | | _mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v) |
583 | 0 | { |
584 | 0 | mpd_uint_t hi, lo; |
585 | 0 | mpd_uint_t carry = 0; |
586 | 0 | mpd_size_t i; |
587 | |
|
588 | 0 | assert(n > 0); |
589 | |
|
590 | 0 | for (i=0; i < n; i++) { |
591 | |
|
592 | 0 | _mpd_mul_words(&hi, &lo, u[i], v); |
593 | 0 | lo = carry + lo; |
594 | 0 | if (lo < carry) hi++; |
595 | |
|
596 | 0 | _mpd_div_words_r(&carry, &w[i], hi, lo); |
597 | 0 | } |
598 | |
|
599 | 0 | return carry; |
600 | 0 | } |
601 | | |
602 | | /* w := product of u (len n) and v (single word) */ |
603 | | mpd_uint_t |
604 | | _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, |
605 | | mpd_uint_t v, mpd_uint_t b) |
606 | 0 | { |
607 | 0 | mpd_uint_t hi, lo; |
608 | 0 | mpd_uint_t carry = 0; |
609 | 0 | mpd_size_t i; |
610 | |
|
611 | 0 | assert(n > 0); |
612 | |
|
613 | 0 | for (i=0; i < n; i++) { |
614 | |
|
615 | 0 | _mpd_mul_words(&hi, &lo, u[i], v); |
616 | 0 | lo = carry + lo; |
617 | 0 | if (lo < carry) hi++; |
618 | |
|
619 | 0 | _mpd_div_words(&carry, &w[i], hi, lo, b); |
620 | 0 | } |
621 | |
|
622 | 0 | return carry; |
623 | 0 | } |
624 | | |
625 | | /* |
626 | | * Knuth, TAOCP Volume 2, 4.3.1, exercise 16: |
627 | | * w := quotient of u (len n) divided by a single word v |
628 | | */ |
629 | | mpd_uint_t |
630 | | _mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, |
631 | | mpd_uint_t v, mpd_uint_t b) |
632 | 0 | { |
633 | 0 | mpd_uint_t hi, lo; |
634 | 0 | mpd_uint_t rem = 0; |
635 | 0 | mpd_size_t i; |
636 | |
|
637 | 0 | assert(n > 0); |
638 | |
|
639 | 0 | for (i=n-1; i != MPD_SIZE_MAX; i--) { |
640 | |
|
641 | 0 | _mpd_mul_words(&hi, &lo, rem, b); |
642 | 0 | lo = u[i] + lo; |
643 | 0 | if (lo < u[i]) hi++; |
644 | |
|
645 | 0 | _mpd_div_words(&w[i], &rem, hi, lo, v); |
646 | 0 | } |
647 | |
|
648 | 0 | return rem; |
649 | 0 | } |