• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
_mpd_baseadd(mpd_uint_t * w,const mpd_uint_t * u,const mpd_uint_t * v,mpd_size_t m,mpd_size_t n)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 {
51     mpd_uint_t s;
52     mpd_uint_t carry = 0;
53     mpd_size_t i;
54 
55     assert(n > 0 && m >= n);
56 
57     /* add n members of u and v */
58     for (i = 0; i < n; i++) {
59         s = u[i] + (v[i] + carry);
60         carry = (s < u[i]) | (s >= MPD_RADIX);
61         w[i] = carry ? s-MPD_RADIX : s;
62     }
63     /* if there is a carry, propagate it */
64     for (; carry && i < m; i++) {
65         s = u[i] + carry;
66         carry = (s == MPD_RADIX);
67         w[i] = carry ? 0 : s;
68     }
69     /* copy the rest of u */
70     for (; i < m; i++) {
71         w[i] = u[i];
72     }
73 
74     return carry;
75 }
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
_mpd_baseaddto(mpd_uint_t * w,const mpd_uint_t * u,mpd_size_t n)82 _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
83 {
84     mpd_uint_t s;
85     mpd_uint_t carry = 0;
86     mpd_size_t i;
87 
88     if (n == 0) return;
89 
90     /* add n members of u to w */
91     for (i = 0; i < n; i++) {
92         s = w[i] + (u[i] + carry);
93         carry = (s < w[i]) | (s >= MPD_RADIX);
94         w[i] = carry ? s-MPD_RADIX : s;
95     }
96     /* if there is a carry, propagate it */
97     for (; carry; i++) {
98         s = w[i] + carry;
99         carry = (s == MPD_RADIX);
100         w[i] = carry ? 0 : s;
101     }
102 }
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
_mpd_shortadd(mpd_uint_t * w,mpd_size_t m,mpd_uint_t v)109 _mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v)
110 {
111     mpd_uint_t s;
112     mpd_uint_t carry;
113     mpd_size_t i;
114 
115     assert(m > 0);
116 
117     /* add v to w */
118     s = w[0] + v;
119     carry = (s < v) | (s >= MPD_RADIX);
120     w[0] = carry ? s-MPD_RADIX : s;
121 
122     /* if there is a carry, propagate it */
123     for (i = 1; carry && i < m; i++) {
124         s = w[i] + carry;
125         carry = (s == MPD_RADIX);
126         w[i] = carry ? 0 : s;
127     }
128 
129     return carry;
130 }
131 
132 /* Increment u. The calling function has to handle a possible carry. */
133 mpd_uint_t
_mpd_baseincr(mpd_uint_t * u,mpd_size_t n)134 _mpd_baseincr(mpd_uint_t *u, mpd_size_t n)
135 {
136     mpd_uint_t s;
137     mpd_uint_t carry = 1;
138     mpd_size_t i;
139 
140     assert(n > 0);
141 
142     /* if there is a carry, propagate it */
143     for (i = 0; carry && i < n; i++) {
144         s = u[i] + carry;
145         carry = (s == MPD_RADIX);
146         u[i] = carry ? 0 : s;
147     }
148 
149     return carry;
150 }
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
_mpd_basesub(mpd_uint_t * w,const mpd_uint_t * u,const mpd_uint_t * v,mpd_size_t m,mpd_size_t n)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 {
161     mpd_uint_t d;
162     mpd_uint_t borrow = 0;
163     mpd_size_t i;
164 
165     assert(m > 0 && n > 0);
166 
167     /* subtract n members of v from u */
168     for (i = 0; i < n; i++) {
169         d = u[i] - (v[i] + borrow);
170         borrow = (u[i] < d);
171         w[i] = borrow ? d + MPD_RADIX : d;
172     }
173     /* if there is a borrow, propagate it */
174     for (; borrow && i < m; i++) {
175         d = u[i] - borrow;
176         borrow = (u[i] == 0);
177         w[i] = borrow ? MPD_RADIX-1 : d;
178     }
179     /* copy the rest of u */
180     for (; i < m; i++) {
181         w[i] = u[i];
182     }
183 }
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
_mpd_basesubfrom(mpd_uint_t * w,const mpd_uint_t * u,mpd_size_t n)190 _mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
191 {
192     mpd_uint_t d;
193     mpd_uint_t borrow = 0;
194     mpd_size_t i;
195 
196     if (n == 0) return;
197 
198     /* subtract n members of u from w */
199     for (i = 0; i < n; i++) {
200         d = w[i] - (u[i] + borrow);
201         borrow = (w[i] < d);
202         w[i] = borrow ? d + MPD_RADIX : d;
203     }
204     /* if there is a borrow, propagate it */
205     for (; borrow; i++) {
206         d = w[i] - borrow;
207         borrow = (w[i] == 0);
208         w[i] = borrow ? MPD_RADIX-1 : d;
209     }
210 }
211 
212 /* w := product of u (len n) and v (single word) */
213 void
_mpd_shortmul(mpd_uint_t * w,const mpd_uint_t * u,mpd_size_t n,mpd_uint_t v)214 _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
215 {
216     mpd_uint_t hi, lo;
217     mpd_uint_t carry = 0;
218     mpd_size_t i;
219 
220     assert(n > 0);
221 
222     for (i=0; i < n; i++) {
223 
224         _mpd_mul_words(&hi, &lo, u[i], v);
225         lo = carry + lo;
226         if (lo < carry) hi++;
227 
228         _mpd_div_words_r(&carry, &w[i], hi, lo);
229     }
230     w[i] = carry;
231 }
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
_mpd_basemul(mpd_uint_t * w,const mpd_uint_t * u,const mpd_uint_t * v,mpd_size_t m,mpd_size_t n)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 {
242     mpd_uint_t hi, lo;
243     mpd_uint_t carry;
244     mpd_size_t i, j;
245 
246     assert(m > 0 && n > 0);
247 
248     for (j=0; j < n; j++) {
249         carry = 0;
250         for (i=0; i < m; i++) {
251 
252             _mpd_mul_words(&hi, &lo, u[i], v[j]);
253             lo = w[i+j] + lo;
254             if (lo < w[i+j]) hi++;
255             lo = carry + lo;
256             if (lo < carry) hi++;
257 
258             _mpd_div_words_r(&carry, &w[i+j], hi, lo);
259         }
260         w[j+m] = carry;
261     }
262 }
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
_mpd_shortdiv(mpd_uint_t * w,const mpd_uint_t * u,mpd_size_t n,mpd_uint_t v)269 _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
270 {
271     mpd_uint_t hi, lo;
272     mpd_uint_t rem = 0;
273     mpd_size_t i;
274 
275     assert(n > 0);
276 
277     for (i=n-1; i != MPD_SIZE_MAX; i--) {
278 
279         _mpd_mul_words(&hi, &lo, rem, MPD_RADIX);
280         lo = u[i] + lo;
281         if (lo < u[i]) hi++;
282 
283         _mpd_div_words(&w[i], &rem, hi, lo, v);
284     }
285 
286     return rem;
287 }
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
_mpd_basedivmod(mpd_uint_t * q,mpd_uint_t * r,const mpd_uint_t * uconst,const mpd_uint_t * vconst,mpd_size_t nplusm,mpd_size_t n)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 {
304     mpd_uint_t ustatic[MPD_MINALLOC_MAX];
305     mpd_uint_t vstatic[MPD_MINALLOC_MAX];
306     mpd_uint_t *u = ustatic;
307     mpd_uint_t *v = vstatic;
308     mpd_uint_t d, qhat, rhat, w2[2];
309     mpd_uint_t hi, lo, x;
310     mpd_uint_t carry;
311     mpd_size_t i, j, m;
312     int retval = 0;
313 
314     assert(n > 1 && nplusm >= n);
315     m = sub_size_t(nplusm, n);
316 
317     /* D1: normalize */
318     d = MPD_RADIX / (vconst[n-1] + 1);
319 
320     if (nplusm >= MPD_MINALLOC_MAX) {
321         if ((u = mpd_alloc(nplusm+1, sizeof *u)) == NULL) {
322             return -1;
323         }
324     }
325     if (n >= MPD_MINALLOC_MAX) {
326         if ((v = mpd_alloc(n+1, sizeof *v)) == NULL) {
327             mpd_free(u);
328             return -1;
329         }
330     }
331 
332     _mpd_shortmul(u, uconst, nplusm, d);
333     _mpd_shortmul(v, vconst, n, d);
334 
335     /* D2: loop */
336     for (j=m; j != MPD_SIZE_MAX; j--) {
337 
338         /* D3: calculate qhat and rhat */
339         rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]);
340         qhat = w2[1] * MPD_RADIX + w2[0];
341 
342         while (1) {
343             if (qhat < MPD_RADIX) {
344                 _mpd_singlemul(w2, qhat, v[n-2]);
345                 if (w2[1] <= rhat) {
346                     if (w2[1] != rhat || w2[0] <= u[j+n-2]) {
347                         break;
348                     }
349                 }
350             }
351             qhat -= 1;
352             rhat += v[n-1];
353             if (rhat < v[n-1] || rhat >= MPD_RADIX) {
354                 break;
355             }
356         }
357         /* D4: multiply and subtract */
358         carry = 0;
359         for (i=0; i <= n; i++) {
360 
361             _mpd_mul_words(&hi, &lo, qhat, v[i]);
362 
363             lo = carry + lo;
364             if (lo < carry) hi++;
365 
366             _mpd_div_words_r(&hi, &lo, hi, lo);
367 
368             x = u[i+j] - lo;
369             carry = (u[i+j] < x);
370             u[i+j] = carry ? x+MPD_RADIX : x;
371             carry += hi;
372         }
373         q[j] = qhat;
374         /* D5: test remainder */
375         if (carry) {
376             q[j] -= 1;
377             /* D6: add back */
378             (void)_mpd_baseadd(u+j, u+j, v, n+1, n);
379         }
380     }
381 
382     /* D8: unnormalize */
383     if (r != NULL) {
384         _mpd_shortdiv(r, u, n, d);
385         /* we are not interested in the return value here */
386         retval = 0;
387     }
388     else {
389         retval = !_mpd_isallzero(u, n);
390     }
391 
392 
393 if (u != ustatic) mpd_free(u);
394 if (v != vstatic) mpd_free(v);
395 return retval;
396 }
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
_mpd_baseshiftl(mpd_uint_t * dest,mpd_uint_t * src,mpd_size_t n,mpd_size_t m,mpd_size_t shift)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 {
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     mpd_uint_t l, lprev, h;
430 #endif
431     mpd_uint_t q, r;
432     mpd_uint_t ph;
433 
434     assert(m > 0 && n >= m);
435 
436     _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
437 
438     if (r != 0) {
439 
440         ph = mpd_pow10[r];
441 
442         --m; --n;
443         _mpd_divmod_pow10(&h, &lprev, src[m--], MPD_RDIGITS-r);
444         if (h != 0) { /* r + msdigits > rdigits <==> h != 0 */
445             dest[n--] = h;
446         }
447         /* write m-1 shifted words */
448         for (; m != MPD_SIZE_MAX; m--,n--) {
449             _mpd_divmod_pow10(&h, &l, src[m], MPD_RDIGITS-r);
450             dest[n] = ph * lprev + h;
451             lprev = l;
452         }
453         /* write least significant word */
454         dest[q] = ph * lprev;
455     }
456     else {
457         while (--m != MPD_SIZE_MAX) {
458             dest[m+q] = src[m];
459         }
460     }
461 
462     mpd_uint_zero(dest, q);
463 }
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
_mpd_baseshiftr(mpd_uint_t * dest,mpd_uint_t * src,mpd_size_t slen,mpd_size_t shift)491 _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
492                 mpd_size_t shift)
493 {
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     mpd_uint_t l, h, hprev; /* low, high, previous high */
499 #endif
500     mpd_uint_t rnd, rest;   /* rounding digit, rest */
501     mpd_uint_t q, r;
502     mpd_size_t i, j;
503     mpd_uint_t ph;
504 
505     assert(slen > 0);
506 
507     _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
508 
509     rnd = rest = 0;
510     if (r != 0) {
511 
512         ph = mpd_pow10[MPD_RDIGITS-r];
513 
514         _mpd_divmod_pow10(&hprev, &rest, src[q], r);
515         _mpd_divmod_pow10(&rnd, &rest, rest, r-1);
516 
517         if (rest == 0 && q > 0) {
518             rest = !_mpd_isallzero(src, q);
519         }
520         /* write slen-q-1 words */
521         for (j=0,i=q+1; i<slen; i++,j++) {
522             _mpd_divmod_pow10(&h, &l, src[i], r);
523             dest[j] = ph * l + hprev;
524             hprev = h;
525         }
526         /* write most significant word */
527         if (hprev != 0) { /* always the case if slen==q-1 */
528             dest[j] = hprev;
529         }
530     }
531     else {
532         if (q > 0) {
533             _mpd_divmod_pow10(&rnd, &rest, src[q-1], MPD_RDIGITS-1);
534             /* is there any non-zero digit below rnd? */
535             if (rest == 0) rest = !_mpd_isallzero(src, q-1);
536         }
537         for (j = 0; j < slen-q; j++) {
538             dest[j] = src[q+j];
539         }
540     }
541 
542     /* 0-4  ==> rnd+rest < 0.5   */
543     /* 5    ==> rnd+rest == 0.5  */
544     /* 6-9  ==> rnd+rest > 0.5   */
545     return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd;
546 }
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
_mpd_shortadd_b(mpd_uint_t * w,mpd_size_t m,mpd_uint_t v,mpd_uint_t b)557 _mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v, mpd_uint_t b)
558 {
559     mpd_uint_t s;
560     mpd_uint_t carry;
561     mpd_size_t i;
562 
563     assert(m > 0);
564 
565     /* add v to w */
566     s = w[0] + v;
567     carry = (s < v) | (s >= b);
568     w[0] = carry ? s-b : s;
569 
570     /* if there is a carry, propagate it */
571     for (i = 1; carry && i < m; i++) {
572         s = w[i] + carry;
573         carry = (s == b);
574         w[i] = carry ? 0 : s;
575     }
576 
577     return carry;
578 }
579 
580 /* w := product of u (len n) and v (single word). Return carry. */
581 mpd_uint_t
_mpd_shortmul_c(mpd_uint_t * w,const mpd_uint_t * u,mpd_size_t n,mpd_uint_t v)582 _mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
583 {
584     mpd_uint_t hi, lo;
585     mpd_uint_t carry = 0;
586     mpd_size_t i;
587 
588     assert(n > 0);
589 
590     for (i=0; i < n; i++) {
591 
592         _mpd_mul_words(&hi, &lo, u[i], v);
593         lo = carry + lo;
594         if (lo < carry) hi++;
595 
596         _mpd_div_words_r(&carry, &w[i], hi, lo);
597     }
598 
599     return carry;
600 }
601 
602 /* w := product of u (len n) and v (single word) */
603 mpd_uint_t
_mpd_shortmul_b(mpd_uint_t * w,const mpd_uint_t * u,mpd_size_t n,mpd_uint_t v,mpd_uint_t b)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 {
607     mpd_uint_t hi, lo;
608     mpd_uint_t carry = 0;
609     mpd_size_t i;
610 
611     assert(n > 0);
612 
613     for (i=0; i < n; i++) {
614 
615         _mpd_mul_words(&hi, &lo, u[i], v);
616         lo = carry + lo;
617         if (lo < carry) hi++;
618 
619         _mpd_div_words(&carry, &w[i], hi, lo, b);
620     }
621 
622     return carry;
623 }
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
_mpd_shortdiv_b(mpd_uint_t * w,const mpd_uint_t * u,mpd_size_t n,mpd_uint_t v,mpd_uint_t b)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 {
633     mpd_uint_t hi, lo;
634     mpd_uint_t rem = 0;
635     mpd_size_t i;
636 
637     assert(n > 0);
638 
639     for (i=n-1; i != MPD_SIZE_MAX; i--) {
640 
641         _mpd_mul_words(&hi, &lo, rem, b);
642         lo = u[i] + lo;
643         if (lo < u[i]) hi++;
644 
645         _mpd_div_words(&w[i], &rem, hi, lo, v);
646     }
647 
648     return rem;
649 }
650