LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules/_decimal/libmpdec - basearith.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 213 0.0 %
Date: 2012-12-17 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2008-2012 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             : #include <stdio.h>
      31             : #include <stdlib.h>
      32             : #include <string.h>
      33             : #include <assert.h>
      34             : #include "constants.h"
      35             : #include "memory.h"
      36             : #include "typearith.h"
      37             : #include "basearith.h"
      38             : 
      39             : 
      40             : /*********************************************************************/
      41             : /*                   Calculations in base MPD_RADIX                  */
      42             : /*********************************************************************/
      43             : 
      44             : 
      45             : /*
      46             :  * Knuth, TAOCP, Volume 2, 4.3.1:
      47             :  *    w := sum of u (len m) and v (len n)
      48             :  *    n > 0 and m >= n
      49             :  * The calling function has to handle a possible final carry.
      50             :  */
      51             : mpd_uint_t
      52           0 : _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
      53             :              mpd_size_t m, mpd_size_t n)
      54             : {
      55             :     mpd_uint_t s;
      56           0 :     mpd_uint_t carry = 0;
      57             :     mpd_size_t i;
      58             : 
      59             :     assert(n > 0 && m >= n);
      60             : 
      61             :     /* add n members of u and v */
      62           0 :     for (i = 0; i < n; i++) {
      63           0 :         s = u[i] + (v[i] + carry);
      64           0 :         carry = (s < u[i]) | (s >= MPD_RADIX);
      65           0 :         w[i] = carry ? s-MPD_RADIX : s;
      66             :     }
      67             :     /* if there is a carry, propagate it */
      68           0 :     for (; carry && i < m; i++) {
      69           0 :         s = u[i] + carry;
      70           0 :         carry = (s == MPD_RADIX);
      71           0 :         w[i] = carry ? 0 : s;
      72             :     }
      73             :     /* copy the rest of u */
      74           0 :     for (; i < m; i++) {
      75           0 :         w[i] = u[i];
      76             :     }
      77             : 
      78           0 :     return carry;
      79             : }
      80             : 
      81             : /*
      82             :  * Add the contents of u to w. Carries are propagated further. The caller
      83             :  * has to make sure that w is big enough.
      84             :  */
      85             : void
      86           0 : _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
      87             : {
      88             :     mpd_uint_t s;
      89           0 :     mpd_uint_t carry = 0;
      90             :     mpd_size_t i;
      91             : 
      92           0 :     if (n == 0) return;
      93             : 
      94             :     /* add n members of u to w */
      95           0 :     for (i = 0; i < n; i++) {
      96           0 :         s = w[i] + (u[i] + carry);
      97           0 :         carry = (s < w[i]) | (s >= MPD_RADIX);
      98           0 :         w[i] = carry ? s-MPD_RADIX : s;
      99             :     }
     100             :     /* if there is a carry, propagate it */
     101           0 :     for (; carry; i++) {
     102           0 :         s = w[i] + carry;
     103           0 :         carry = (s == MPD_RADIX);
     104           0 :         w[i] = carry ? 0 : s;
     105             :     }
     106             : }
     107             : 
     108             : /*
     109             :  * Add v to w (len m). The calling function has to handle a possible
     110             :  * final carry. Assumption: m > 0.
     111             :  */
     112             : mpd_uint_t
     113           0 : _mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v)
     114             : {
     115             :     mpd_uint_t s;
     116             :     mpd_uint_t carry;
     117             :     mpd_size_t i;
     118             : 
     119             :     assert(m > 0);
     120             : 
     121             :     /* add v to w */
     122           0 :     s = w[0] + v;
     123           0 :     carry = (s < v) | (s >= MPD_RADIX);
     124           0 :     w[0] = carry ? s-MPD_RADIX : s;
     125             : 
     126             :     /* if there is a carry, propagate it */
     127           0 :     for (i = 1; carry && i < m; i++) {
     128           0 :         s = w[i] + carry;
     129           0 :         carry = (s == MPD_RADIX);
     130           0 :         w[i] = carry ? 0 : s;
     131             :     }
     132             : 
     133           0 :     return carry;
     134             : }
     135             : 
     136             : /* Increment u. The calling function has to handle a possible carry. */
     137             : mpd_uint_t
     138           0 : _mpd_baseincr(mpd_uint_t *u, mpd_size_t n)
     139             : {
     140             :     mpd_uint_t s;
     141           0 :     mpd_uint_t carry = 1;
     142             :     mpd_size_t i;
     143             : 
     144             :     assert(n > 0);
     145             : 
     146             :     /* if there is a carry, propagate it */
     147           0 :     for (i = 0; carry && i < n; i++) {
     148           0 :         s = u[i] + carry;
     149           0 :         carry = (s == MPD_RADIX);
     150           0 :         u[i] = carry ? 0 : s;
     151             :     }
     152             : 
     153           0 :     return carry;
     154             : }
     155             : 
     156             : /*
     157             :  * Knuth, TAOCP, Volume 2, 4.3.1:
     158             :  *     w := difference of u (len m) and v (len n).
     159             :  *     number in u >= number in v;
     160             :  */
     161             : void
     162           0 : _mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
     163             :              mpd_size_t m, mpd_size_t n)
     164             : {
     165             :     mpd_uint_t d;
     166           0 :     mpd_uint_t borrow = 0;
     167             :     mpd_size_t i;
     168             : 
     169             :     assert(m > 0 && n > 0);
     170             : 
     171             :     /* subtract n members of v from u */
     172           0 :     for (i = 0; i < n; i++) {
     173           0 :         d = u[i] - (v[i] + borrow);
     174           0 :         borrow = (u[i] < d);
     175           0 :         w[i] = borrow ? d + MPD_RADIX : d;
     176             :     }
     177             :     /* if there is a borrow, propagate it */
     178           0 :     for (; borrow && i < m; i++) {
     179           0 :         d = u[i] - borrow;
     180           0 :         borrow = (u[i] == 0);
     181           0 :         w[i] = borrow ? MPD_RADIX-1 : d;
     182             :     }
     183             :     /* copy the rest of u */
     184           0 :     for (; i < m; i++) {
     185           0 :         w[i] = u[i];
     186             :     }
     187           0 : }
     188             : 
     189             : /*
     190             :  * Subtract the contents of u from w. w is larger than u. Borrows are
     191             :  * propagated further, but eventually w can absorb the final borrow.
     192             :  */
     193             : void
     194           0 : _mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
     195             : {
     196             :     mpd_uint_t d;
     197           0 :     mpd_uint_t borrow = 0;
     198             :     mpd_size_t i;
     199             : 
     200           0 :     if (n == 0) return;
     201             : 
     202             :     /* subtract n members of u from w */
     203           0 :     for (i = 0; i < n; i++) {
     204           0 :         d = w[i] - (u[i] + borrow);
     205           0 :         borrow = (w[i] < d);
     206           0 :         w[i] = borrow ? d + MPD_RADIX : d;
     207             :     }
     208             :     /* if there is a borrow, propagate it */
     209           0 :     for (; borrow; i++) {
     210           0 :         d = w[i] - borrow;
     211           0 :         borrow = (w[i] == 0);
     212           0 :         w[i] = borrow ? MPD_RADIX-1 : d;
     213             :     }
     214             : }
     215             : 
     216             : /* w := product of u (len n) and v (single word) */
     217             : void
     218           0 : _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
     219             : {
     220             :     mpd_uint_t hi, lo;
     221           0 :     mpd_uint_t carry = 0;
     222             :     mpd_size_t i;
     223             : 
     224             :     assert(n > 0);
     225             : 
     226           0 :     for (i=0; i < n; i++) {
     227             : 
     228           0 :         _mpd_mul_words(&hi, &lo, u[i], v);
     229           0 :         lo = carry + lo;
     230           0 :         if (lo < carry) hi++;
     231             : 
     232           0 :         _mpd_div_words_r(&carry, &w[i], hi, lo);
     233             :     }
     234           0 :     w[i] = carry;
     235           0 : }
     236             : 
     237             : /*
     238             :  * Knuth, TAOCP, Volume 2, 4.3.1:
     239             :  *     w := product of u (len m) and v (len n)
     240             :  *     w must be initialized to zero
     241             :  */
     242             : void
     243           0 : _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
     244             :              mpd_size_t m, mpd_size_t n)
     245             : {
     246             :     mpd_uint_t hi, lo;
     247             :     mpd_uint_t carry;
     248             :     mpd_size_t i, j;
     249             : 
     250             :     assert(m > 0 && n > 0);
     251             : 
     252           0 :     for (j=0; j < n; j++) {
     253           0 :         carry = 0;
     254           0 :         for (i=0; i < m; i++) {
     255             : 
     256           0 :             _mpd_mul_words(&hi, &lo, u[i], v[j]);
     257           0 :             lo = w[i+j] + lo;
     258           0 :             if (lo < w[i+j]) hi++;
     259           0 :             lo = carry + lo;
     260           0 :             if (lo < carry) hi++;
     261             : 
     262           0 :             _mpd_div_words_r(&carry, &w[i+j], hi, lo);
     263             :         }
     264           0 :         w[j+m] = carry;
     265             :     }
     266           0 : }
     267             : 
     268             : /*
     269             :  * Knuth, TAOCP Volume 2, 4.3.1, exercise 16:
     270             :  *     w := quotient of u (len n) divided by a single word v
     271             :  */
     272             : mpd_uint_t
     273           0 : _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
     274             : {
     275             :     mpd_uint_t hi, lo;
     276           0 :     mpd_uint_t rem = 0;
     277             :     mpd_size_t i;
     278             : 
     279             :     assert(n > 0);
     280             : 
     281           0 :     for (i=n-1; i != MPD_SIZE_MAX; i--) {
     282             : 
     283           0 :         _mpd_mul_words(&hi, &lo, rem, MPD_RADIX);
     284           0 :         lo = u[i] + lo;
     285           0 :         if (lo < u[i]) hi++;
     286             : 
     287           0 :         _mpd_div_words(&w[i], &rem, hi, lo, v);
     288             :     }
     289             : 
     290           0 :     return rem;
     291             : }
     292             : 
     293             : /*
     294             :  * Knuth, TAOCP Volume 2, 4.3.1:
     295             :  *     q, r := quotient and remainder of uconst (len nplusm)
     296             :  *             divided by vconst (len n)
     297             :  *     nplusm >= n
     298             :  *
     299             :  * If r is not NULL, r will contain the remainder. If r is NULL, the
     300             :  * return value indicates if there is a remainder: 1 for true, 0 for
     301             :  * false.  A return value of -1 indicates an error.
     302             :  */
     303             : int
     304           0 : _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
     305             :                 const mpd_uint_t *uconst, const mpd_uint_t *vconst,
     306             :                 mpd_size_t nplusm, mpd_size_t n)
     307             : {
     308             :     mpd_uint_t ustatic[MPD_MINALLOC_MAX];
     309             :     mpd_uint_t vstatic[MPD_MINALLOC_MAX];
     310           0 :     mpd_uint_t *u = ustatic;
     311           0 :     mpd_uint_t *v = vstatic;
     312             :     mpd_uint_t d, qhat, rhat, w2[2];
     313             :     mpd_uint_t hi, lo, x;
     314             :     mpd_uint_t carry;
     315             :     mpd_size_t i, j, m;
     316           0 :     int retval = 0;
     317             : 
     318             :     assert(n > 1 && nplusm >= n);
     319           0 :     m = sub_size_t(nplusm, n);
     320             : 
     321             :     /* D1: normalize */
     322           0 :     d = MPD_RADIX / (vconst[n-1] + 1);
     323             : 
     324           0 :     if (nplusm >= MPD_MINALLOC_MAX) {
     325           0 :         if ((u = mpd_alloc(nplusm+1, sizeof *u)) == NULL) {
     326           0 :             return -1;
     327             :         }
     328             :     }
     329           0 :     if (n >= MPD_MINALLOC_MAX) {
     330           0 :         if ((v = mpd_alloc(n+1, sizeof *v)) == NULL) {
     331           0 :             mpd_free(u);
     332           0 :             return -1;
     333             :         }
     334             :     }
     335             : 
     336           0 :     _mpd_shortmul(u, uconst, nplusm, d);
     337           0 :     _mpd_shortmul(v, vconst, n, d);
     338             : 
     339             :     /* D2: loop */
     340           0 :     for (j=m; j != MPD_SIZE_MAX; j--) {
     341             : 
     342             :         /* D3: calculate qhat and rhat */
     343           0 :         rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]);
     344           0 :         qhat = w2[1] * MPD_RADIX + w2[0];
     345             : 
     346             :         while (1) {
     347           0 :             if (qhat < MPD_RADIX) {
     348           0 :                 _mpd_singlemul(w2, qhat, v[n-2]);
     349           0 :                 if (w2[1] <= rhat) {
     350           0 :                     if (w2[1] != rhat || w2[0] <= u[j+n-2]) {
     351             :                         break;
     352             :                     }
     353             :                 }
     354             :             }
     355           0 :             qhat -= 1;
     356           0 :             rhat += v[n-1];
     357           0 :             if (rhat < v[n-1] || rhat >= MPD_RADIX) {
     358             :                 break;
     359             :             }
     360           0 :         }
     361             :         /* D4: multiply and subtract */
     362           0 :         carry = 0;
     363           0 :         for (i=0; i <= n; i++) {
     364             : 
     365           0 :             _mpd_mul_words(&hi, &lo, qhat, v[i]);
     366             : 
     367           0 :             lo = carry + lo;
     368           0 :             if (lo < carry) hi++;
     369             : 
     370           0 :             _mpd_div_words_r(&hi, &lo, hi, lo);
     371             : 
     372           0 :             x = u[i+j] - lo;
     373           0 :             carry = (u[i+j] < x);
     374           0 :             u[i+j] = carry ? x+MPD_RADIX : x;
     375           0 :             carry += hi;
     376             :         }
     377           0 :         q[j] = qhat;
     378             :         /* D5: test remainder */
     379           0 :         if (carry) {
     380           0 :             q[j] -= 1;
     381             :             /* D6: add back */
     382           0 :             (void)_mpd_baseadd(u+j, u+j, v, n+1, n);
     383             :         }
     384             :     }
     385             : 
     386             :     /* D8: unnormalize */
     387           0 :     if (r != NULL) {
     388           0 :         _mpd_shortdiv(r, u, n, d);
     389             :         /* we are not interested in the return value here */
     390           0 :         retval = 0;
     391             :     }
     392             :     else {
     393           0 :         retval = !_mpd_isallzero(u, n);
     394             :     }
     395             : 
     396             : 
     397           0 : if (u != ustatic) mpd_free(u);
     398           0 : if (v != vstatic) mpd_free(v);
     399           0 : return 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             :  */
     426             : void
     427           0 : _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           0 :     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           0 :     _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
     442             : 
     443           0 :     if (r != 0) {
     444             : 
     445           0 :         ph = mpd_pow10[r];
     446             : 
     447           0 :         --m; --n;
     448           0 :         _mpd_divmod_pow10(&h, &lprev, src[m--], MPD_RDIGITS-r);
     449           0 :         if (h != 0) { /* r + msdigits > rdigits <==> h != 0 */
     450           0 :             dest[n--] = h;
     451             :         }
     452             :         /* write m-1 shifted words */
     453           0 :         for (; m != MPD_SIZE_MAX; m--,n--) {
     454           0 :             _mpd_divmod_pow10(&h, &l, src[m], MPD_RDIGITS-r);
     455           0 :             dest[n] = ph * lprev + h;
     456           0 :             lprev = l;
     457             :         }
     458             :         /* write least significant word */
     459           0 :         dest[q] = ph * lprev;
     460             :     }
     461             :     else {
     462           0 :         while (--m != MPD_SIZE_MAX) {
     463           0 :             dest[m+q] = src[m];
     464             :         }
     465             :     }
     466             : 
     467           0 :     mpd_uint_zero(dest, q);
     468           0 : }
     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             :  */
     495             : mpd_uint_t
     496           0 : _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           0 :     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           0 :     _mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
     513             : 
     514           0 :     rnd = rest = 0;
     515           0 :     if (r != 0) {
     516             : 
     517           0 :         ph = mpd_pow10[MPD_RDIGITS-r];
     518             : 
     519           0 :         _mpd_divmod_pow10(&hprev, &rest, src[q], r);
     520           0 :         _mpd_divmod_pow10(&rnd, &rest, rest, r-1);
     521             : 
     522           0 :         if (rest == 0 && q > 0) {
     523           0 :             rest = !_mpd_isallzero(src, q);
     524             :         }
     525             :         /* write slen-q-1 words */
     526           0 :         for (j=0,i=q+1; i<slen; i++,j++) {
     527           0 :             _mpd_divmod_pow10(&h, &l, src[i], r);
     528           0 :             dest[j] = ph * l + hprev;
     529           0 :             hprev = h;
     530             :         }
     531             :         /* write most significant word */
     532           0 :         if (hprev != 0) { /* always the case if slen==q-1 */
     533           0 :             dest[j] = hprev;
     534             :         }
     535             :     }
     536             :     else {
     537           0 :         if (q > 0) {
     538           0 :             _mpd_divmod_pow10(&rnd, &rest, src[q-1], MPD_RDIGITS-1);
     539             :             /* is there any non-zero digit below rnd? */
     540           0 :             if (rest == 0) rest = !_mpd_isallzero(src, q-1);
     541             :         }
     542           0 :         for (j = 0; j < slen-q; j++) {
     543           0 :             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           0 :     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             :  */
     562             : mpd_uint_t
     563           0 : _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           0 :     s = w[0] + v;
     573           0 :     carry = (s < v) | (s >= b);
     574           0 :     w[0] = carry ? s-b : s;
     575             : 
     576             :     /* if there is a carry, propagate it */
     577           0 :     for (i = 1; carry && i < m; i++) {
     578           0 :         s = w[i] + carry;
     579           0 :         carry = (s == b);
     580           0 :         w[i] = carry ? 0 : s;
     581             :     }
     582             : 
     583           0 :     return carry;
     584             : }
     585             : 
     586             : /* w := product of u (len n) and v (single word). Return carry. */
     587             : mpd_uint_t
     588           0 : _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           0 :     mpd_uint_t carry = 0;
     592             :     mpd_size_t i;
     593             : 
     594             :     assert(n > 0);
     595             : 
     596           0 :     for (i=0; i < n; i++) {
     597             : 
     598           0 :         _mpd_mul_words(&hi, &lo, u[i], v);
     599           0 :         lo = carry + lo;
     600           0 :         if (lo < carry) hi++;
     601             : 
     602           0 :         _mpd_div_words_r(&carry, &w[i], hi, lo);
     603             :     }
     604             : 
     605           0 :     return carry;
     606             : }
     607             : 
     608             : /* w := product of u (len n) and v (single word) */
     609             : mpd_uint_t
     610           0 : _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           0 :     mpd_uint_t carry = 0;
     615             :     mpd_size_t i;
     616             : 
     617             :     assert(n > 0);
     618             : 
     619           0 :     for (i=0; i < n; i++) {
     620             : 
     621           0 :         _mpd_mul_words(&hi, &lo, u[i], v);
     622           0 :         lo = carry + lo;
     623           0 :         if (lo < carry) hi++;
     624             : 
     625           0 :         _mpd_div_words(&carry, &w[i], hi, lo, b);
     626             :     }
     627             : 
     628           0 :     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             :  */
     635             : mpd_uint_t
     636           0 : _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           0 :     mpd_uint_t rem = 0;
     641             :     mpd_size_t i;
     642             : 
     643             :     assert(n > 0);
     644             : 
     645           0 :     for (i=n-1; i != MPD_SIZE_MAX; i--) {
     646             : 
     647           0 :         _mpd_mul_words(&hi, &lo, rem, b);
     648           0 :         lo = u[i] + lo;
     649           0 :         if (lo < u[i]) hi++;
     650             : 
     651           0 :         _mpd_div_words(&w[i], &rem, hi, lo, v);
     652             :     }
     653             : 
     654           0 :     return rem;
     655             : }
     656             : 
     657             : 
     658             : 

Generated by: LCOV version 1.10