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