Coverage Report

Created: 2024-11-21 07:03

/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
}