LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules/_decimal/libmpdec - typearith.h (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 61 0.0 %
Date: 2012-12-17 Functions: 0 12 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             : #ifndef TYPEARITH_H
      30             : #define TYPEARITH_H
      31             : 
      32             : 
      33             : #include "mpdecimal.h"
      34             : 
      35             : 
      36             : /*****************************************************************************/
      37             : /*                 Low level native arithmetic on basic types                */
      38             : /*****************************************************************************/
      39             : 
      40             : 
      41             : /** ------------------------------------------------------------
      42             :  **           Double width multiplication and division
      43             :  ** ------------------------------------------------------------
      44             :  */
      45             : 
      46             : #if defined(CONFIG_64)
      47             : #if defined(ANSI)
      48             : #if defined(HAVE_UINT128_T)
      49             : static inline void
      50             : _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
      51             : {
      52             :     __uint128_t hl;
      53             : 
      54             :     hl = (__uint128_t)a * b;
      55             : 
      56             :     *hi = hl >> 64;
      57             :     *lo = (mpd_uint_t)hl;
      58             : }
      59             : 
      60             : static inline void
      61             : _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
      62             :                mpd_uint_t d)
      63             : {
      64             :     __uint128_t hl;
      65             : 
      66             :     hl = ((__uint128_t)hi<<64) + lo;
      67             :     *q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
      68             :     *r = (mpd_uint_t)(hl - (__uint128_t)(*q) * d);
      69             : }
      70             : #else
      71             : static inline void
      72             : _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
      73             : {
      74             :     uint32_t w[4], carry;
      75             :     uint32_t ah, al, bh, bl;
      76             :     uint64_t hl;
      77             : 
      78             :     ah = (uint32_t)(a>>32); al = (uint32_t)a;
      79             :     bh = (uint32_t)(b>>32); bl = (uint32_t)b;
      80             : 
      81             :     hl = (uint64_t)al * bl;
      82             :     w[0] = (uint32_t)hl;
      83             :     carry = (uint32_t)(hl>>32);
      84             : 
      85             :     hl = (uint64_t)ah * bl + carry;
      86             :     w[1] = (uint32_t)hl;
      87             :     w[2] = (uint32_t)(hl>>32);
      88             : 
      89             :     hl = (uint64_t)al * bh + w[1];
      90             :     w[1] = (uint32_t)hl;
      91             :     carry = (uint32_t)(hl>>32);
      92             : 
      93             :     hl = ((uint64_t)ah * bh + w[2]) + carry;
      94             :     w[2] = (uint32_t)hl;
      95             :     w[3] = (uint32_t)(hl>>32);
      96             : 
      97             :     *hi = ((uint64_t)w[3]<<32) + w[2];
      98             :     *lo = ((uint64_t)w[1]<<32) + w[0];
      99             : }
     100             : 
     101             : /*
     102             :  * By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c.txt
     103             :  * http://www.hackersdelight.org/permissions.htm:
     104             :  * "You are free to use, copy, and distribute any of the code on this web
     105             :  *  site, whether modified by you or not. You need not give attribution."
     106             :  *
     107             :  * Slightly modified, comments are mine.
     108             :  */
     109             : static inline int
     110             : nlz(uint64_t x)
     111             : {
     112             :     int n;
     113             : 
     114             :     if (x == 0) return(64);
     115             : 
     116             :     n = 0;
     117             :     if (x <= 0x00000000FFFFFFFF) {n = n +32; x = x <<32;}
     118             :     if (x <= 0x0000FFFFFFFFFFFF) {n = n +16; x = x <<16;}
     119             :     if (x <= 0x00FFFFFFFFFFFFFF) {n = n + 8; x = x << 8;}
     120             :     if (x <= 0x0FFFFFFFFFFFFFFF) {n = n + 4; x = x << 4;}
     121             :     if (x <= 0x3FFFFFFFFFFFFFFF) {n = n + 2; x = x << 2;}
     122             :     if (x <= 0x7FFFFFFFFFFFFFFF) {n = n + 1;}
     123             : 
     124             :     return n;
     125             : }
     126             : 
     127             : static inline void
     128             : _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
     129             :                mpd_uint_t v)
     130             : {
     131             :     const mpd_uint_t b = 4294967296;
     132             :     mpd_uint_t un1, un0,
     133             :                vn1, vn0,
     134             :                q1, q0,
     135             :                un32, un21, un10,
     136             :                rhat, t;
     137             :     int s;
     138             : 
     139             :     assert(u1 < v);
     140             : 
     141             :     s = nlz(v);
     142             :     v = v << s;
     143             :     vn1 = v >> 32;
     144             :     vn0 = v & 0xFFFFFFFF;
     145             : 
     146             :     t = (s == 0) ? 0 : u0 >> (64 - s);
     147             :     un32 = (u1 << s) | t;
     148             :     un10 = u0 << s;
     149             : 
     150             :     un1 = un10 >> 32;
     151             :     un0 = un10 & 0xFFFFFFFF;
     152             : 
     153             :     q1 = un32 / vn1;
     154             :     rhat = un32 - q1*vn1;
     155             : again1:
     156             :     if (q1 >= b || q1*vn0 > b*rhat + un1) {
     157             :         q1 = q1 - 1;
     158             :         rhat = rhat + vn1;
     159             :         if (rhat < b) goto again1;
     160             :     }
     161             : 
     162             :     /*
     163             :      *  Before again1 we had:
     164             :      *      (1) q1*vn1   + rhat         = un32
     165             :      *      (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
     166             :      *
     167             :      *  The statements inside the if-clause do not change the value
     168             :      *  of the left-hand side of (2), and the loop is only exited
     169             :      *  if q1*vn0 <= rhat*b + un1, so:
     170             :      *
     171             :      *      (3) q1*vn1*b + q1*vn0 <= un32*b + un1
     172             :      *      (4)              q1*v <= un32*b + un1
     173             :      *      (5)                 0 <= un32*b + un1 - q1*v
     174             :      *
     175             :      *  By (5) we are certain that the possible add-back step from
     176             :      *  Knuth's algorithm D is never required.
     177             :      *
     178             :      *  Since the final quotient is less than 2**64, the following
     179             :      *  must be true:
     180             :      *
     181             :      *      (6) un32*b + un1 - q1*v <= UINT64_MAX
     182             :      *
     183             :      *  This means that in the following line, the high words
     184             :      *  of un32*b and q1*v can be discarded without any effect
     185             :      *  on the result.
     186             :      */
     187             :     un21 = un32*b + un1 - q1*v;
     188             : 
     189             :     q0 = un21 / vn1;
     190             :     rhat = un21 - q0*vn1;
     191             : again2:
     192             :     if (q0 >= b || q0*vn0 > b*rhat + un0) {
     193             :         q0 = q0 - 1;
     194             :         rhat = rhat + vn1;
     195             :         if (rhat < b) goto again2;
     196             :     }
     197             : 
     198             :     *q = q1*b + q0;
     199             :     *r = (un21*b + un0 - q0*v) >> s;
     200             : }
     201             : #endif
     202             : 
     203             : /* END ANSI */
     204             : #elif defined(ASM)
     205             : static inline void
     206             : _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
     207             : {
     208             :     mpd_uint_t h, l;
     209             : 
     210             :     asm ( "mulq %3\n\t"
     211             :           : "=d" (h), "=a" (l)
     212             :           : "%a" (a), "rm" (b)
     213             :           : "cc"
     214             :     );
     215             : 
     216             :     *hi = h;
     217             :     *lo = l;
     218             : }
     219             : 
     220             : static inline void
     221             : _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
     222             :                mpd_uint_t d)
     223             : {
     224             :     mpd_uint_t qq, rr;
     225             : 
     226             :     asm ( "divq %4\n\t"
     227             :           : "=a" (qq), "=d" (rr)
     228             :           : "a" (lo), "d" (hi), "rm" (d)
     229             :           : "cc"
     230             :     );
     231             : 
     232             :     *q = qq;
     233             :     *r = rr;
     234             : }
     235             : /* END GCC ASM */
     236             : #elif defined(MASM)
     237             : #include <intrin.h>
     238             : #pragma intrinsic(_umul128)
     239             : 
     240             : static inline void
     241             : _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
     242             : {
     243             :     *lo = _umul128(a, b, hi);
     244             : }
     245             : 
     246             : void _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
     247             :                     mpd_uint_t d);
     248             : 
     249             : /* END MASM (_MSC_VER) */
     250             : #else
     251             :   #error "need platform specific 128 bit multiplication and division"
     252             : #endif
     253             : 
     254             : #define DIVMOD(q, r, v, d) *q = v / d; *r = v - *q * d
     255             : static inline void
     256             : _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
     257             : {
     258             :     assert(exp <= 19);
     259             : 
     260             :     if (exp <= 9) {
     261             :         if (exp <= 4) {
     262             :             switch (exp) {
     263             :             case 0: *q = v; *r = 0; break;
     264             :             case 1: DIVMOD(q, r, v, 10UL); break;
     265             :             case 2: DIVMOD(q, r, v, 100UL); break;
     266             :             case 3: DIVMOD(q, r, v, 1000UL); break;
     267             :             case 4: DIVMOD(q, r, v, 10000UL); break;
     268             :             }
     269             :         }
     270             :         else {
     271             :             switch (exp) {
     272             :             case 5: DIVMOD(q, r, v, 100000UL); break;
     273             :             case 6: DIVMOD(q, r, v, 1000000UL); break;
     274             :             case 7: DIVMOD(q, r, v, 10000000UL); break;
     275             :             case 8: DIVMOD(q, r, v, 100000000UL); break;
     276             :             case 9: DIVMOD(q, r, v, 1000000000UL); break;
     277             :             }
     278             :         }
     279             :     }
     280             :     else {
     281             :         if (exp <= 14) {
     282             :             switch (exp) {
     283             :             case 10: DIVMOD(q, r, v, 10000000000ULL); break;
     284             :             case 11: DIVMOD(q, r, v, 100000000000ULL); break;
     285             :             case 12: DIVMOD(q, r, v, 1000000000000ULL); break;
     286             :             case 13: DIVMOD(q, r, v, 10000000000000ULL); break;
     287             :             case 14: DIVMOD(q, r, v, 100000000000000ULL); break;
     288             :             }
     289             :         }
     290             :         else {
     291             :             switch (exp) {
     292             :             case 15: DIVMOD(q, r, v, 1000000000000000ULL); break;
     293             :             case 16: DIVMOD(q, r, v, 10000000000000000ULL); break;
     294             :             case 17: DIVMOD(q, r, v, 100000000000000000ULL); break;
     295             :             case 18: DIVMOD(q, r, v, 1000000000000000000ULL); break;
     296             :             case 19: DIVMOD(q, r, v, 10000000000000000000ULL); break; /* GCOV_NOT_REACHED */
     297             :             }
     298             :         }
     299             :     }
     300             : }
     301             : 
     302             : /* END CONFIG_64 */
     303             : #elif defined(CONFIG_32)
     304             : #if defined(ANSI)
     305             : #if !defined(LEGACY_COMPILER)
     306             : static inline void
     307             : _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
     308             : {
     309             :     mpd_uuint_t hl;
     310             : 
     311             :     hl = (mpd_uuint_t)a * b;
     312             : 
     313             :     *hi = hl >> 32;
     314             :     *lo = (mpd_uint_t)hl;
     315             : }
     316             : 
     317             : static inline void
     318             : _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
     319             :                mpd_uint_t d)
     320             : {
     321             :     mpd_uuint_t hl;
     322             : 
     323             :     hl = ((mpd_uuint_t)hi<<32) + lo;
     324             :     *q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
     325             :     *r = (mpd_uint_t)(hl - (mpd_uuint_t)(*q) * d);
     326             : }
     327             : /* END ANSI + uint64_t */
     328             : #else
     329             : static inline void
     330             : _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
     331             : {
     332             :     uint16_t w[4], carry;
     333             :     uint16_t ah, al, bh, bl;
     334             :     uint32_t hl;
     335             : 
     336             :     ah = (uint16_t)(a>>16); al = (uint16_t)a;
     337             :     bh = (uint16_t)(b>>16); bl = (uint16_t)b;
     338             : 
     339             :     hl = (uint32_t)al * bl;
     340             :     w[0] = (uint16_t)hl;
     341             :     carry = (uint16_t)(hl>>16);
     342             : 
     343             :     hl = (uint32_t)ah * bl + carry;
     344             :     w[1] = (uint16_t)hl;
     345             :     w[2] = (uint16_t)(hl>>16);
     346             : 
     347             :     hl = (uint32_t)al * bh + w[1];
     348             :     w[1] = (uint16_t)hl;
     349             :     carry = (uint16_t)(hl>>16);
     350             : 
     351             :     hl = ((uint32_t)ah * bh + w[2]) + carry;
     352             :     w[2] = (uint16_t)hl;
     353             :     w[3] = (uint16_t)(hl>>16);
     354             : 
     355             :     *hi = ((uint32_t)w[3]<<16) + w[2];
     356             :     *lo = ((uint32_t)w[1]<<16) + w[0];
     357             : }
     358             : 
     359             : /*
     360             :  * By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c.txt
     361             :  * http://www.hackersdelight.org/permissions.htm:
     362             :  * "You are free to use, copy, and distribute any of the code on this web
     363             :  *  site, whether modified by you or not. You need not give attribution."
     364             :  *
     365             :  * Slightly modified, comments are mine.
     366             :  */
     367             : static inline int
     368             : nlz(uint32_t x)
     369             : {
     370             :     int n;
     371             : 
     372             :     if (x == 0) return(32);
     373             : 
     374             :     n = 0;
     375             :     if (x <= 0x0000FFFF) {n = n +16; x = x <<16;}
     376             :     if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;}
     377             :     if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;}
     378             :     if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;}
     379             :     if (x <= 0x7FFFFFFF) {n = n + 1;}
     380             : 
     381             :     return n;
     382             : }
     383             : 
     384             : static inline void
     385             : _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
     386             :                mpd_uint_t v)
     387             : {
     388             :     const mpd_uint_t b = 65536;
     389             :     mpd_uint_t un1, un0,
     390             :                vn1, vn0,
     391             :                q1, q0,
     392             :                un32, un21, un10,
     393             :                rhat, t;
     394             :     int s;
     395             : 
     396             :     assert(u1 < v);
     397             : 
     398             :     s = nlz(v);
     399             :     v = v << s;
     400             :     vn1 = v >> 16;
     401             :     vn0 = v & 0xFFFF;
     402             : 
     403             :     t = (s == 0) ? 0 : u0 >> (32 - s);
     404             :     un32 = (u1 << s) | t;
     405             :     un10 = u0 << s;
     406             : 
     407             :     un1 = un10 >> 16;
     408             :     un0 = un10 & 0xFFFF;
     409             : 
     410             :     q1 = un32 / vn1;
     411             :     rhat = un32 - q1*vn1;
     412             : again1:
     413             :     if (q1 >= b || q1*vn0 > b*rhat + un1) {
     414             :         q1 = q1 - 1;
     415             :         rhat = rhat + vn1;
     416             :         if (rhat < b) goto again1;
     417             :     }
     418             : 
     419             :     /*
     420             :      *  Before again1 we had:
     421             :      *      (1) q1*vn1   + rhat         = un32
     422             :      *      (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
     423             :      *
     424             :      *  The statements inside the if-clause do not change the value
     425             :      *  of the left-hand side of (2), and the loop is only exited
     426             :      *  if q1*vn0 <= rhat*b + un1, so:
     427             :      *
     428             :      *      (3) q1*vn1*b + q1*vn0 <= un32*b + un1
     429             :      *      (4)              q1*v <= un32*b + un1
     430             :      *      (5)                 0 <= un32*b + un1 - q1*v
     431             :      *
     432             :      *  By (5) we are certain that the possible add-back step from
     433             :      *  Knuth's algorithm D is never required.
     434             :      *
     435             :      *  Since the final quotient is less than 2**32, the following
     436             :      *  must be true:
     437             :      *
     438             :      *      (6) un32*b + un1 - q1*v <= UINT32_MAX
     439             :      *
     440             :      *  This means that in the following line, the high words
     441             :      *  of un32*b and q1*v can be discarded without any effect
     442             :      *  on the result.
     443             :      */
     444             :     un21 = un32*b + un1 - q1*v;
     445             : 
     446             :     q0 = un21 / vn1;
     447             :     rhat = un21 - q0*vn1;
     448             : again2:
     449             :     if (q0 >= b || q0*vn0 > b*rhat + un0) {
     450             :         q0 = q0 - 1;
     451             :         rhat = rhat + vn1;
     452             :         if (rhat < b) goto again2;
     453             :     }
     454             : 
     455             :     *q = q1*b + q0;
     456             :     *r = (un21*b + un0 - q0*v) >> s;
     457             : }
     458             : #endif /* END ANSI + LEGACY_COMPILER */
     459             : 
     460             : /* END ANSI */
     461             : #elif defined(ASM)
     462             : static inline void
     463           0 : _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
     464             : {
     465             :     mpd_uint_t h, l;
     466             : 
     467           0 :     asm ( "mull %3\n\t"
     468             :           : "=d" (h), "=a" (l)
     469             :           : "%a" (a), "rm" (b)
     470             :           : "cc"
     471             :     );
     472             : 
     473           0 :     *hi = h;
     474           0 :     *lo = l;
     475           0 : }
     476             : 
     477             : static inline void
     478           0 : _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
     479             :                mpd_uint_t d)
     480             : {
     481             :     mpd_uint_t qq, rr;
     482             : 
     483           0 :     asm ( "divl %4\n\t"
     484             :           : "=a" (qq), "=d" (rr)
     485             :           : "a" (lo), "d" (hi), "rm" (d)
     486             :           : "cc"
     487             :     );
     488             : 
     489           0 :     *q = qq;
     490           0 :     *r = rr;
     491           0 : }
     492             : /* END GCC ASM */
     493             : #elif defined(MASM)
     494             : static inline void __cdecl
     495             : _mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
     496             : {
     497             :     mpd_uint_t h, l;
     498             : 
     499             :     __asm {
     500             :         mov eax, a
     501             :         mul b
     502             :         mov h, edx
     503             :         mov l, eax
     504             :     }
     505             : 
     506             :     *hi = h;
     507             :     *lo = l;
     508             : }
     509             : 
     510             : static inline void __cdecl
     511             : _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
     512             :                mpd_uint_t d)
     513             : {
     514             :     mpd_uint_t qq, rr;
     515             : 
     516             :     __asm {
     517             :         mov eax, lo
     518             :         mov edx, hi
     519             :         div d
     520             :         mov qq, eax
     521             :         mov rr, edx
     522             :     }
     523             : 
     524             :     *q = qq;
     525             :     *r = rr;
     526             : }
     527             : /* END MASM (_MSC_VER) */
     528             : #else
     529             :   #error "need platform specific 64 bit multiplication and division"
     530             : #endif
     531             : 
     532             : #define DIVMOD(q, r, v, d) *q = v / d; *r = v - *q * d
     533             : static inline void
     534           0 : _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
     535             : {
     536             :     assert(exp <= 9);
     537             : 
     538           0 :     if (exp <= 4) {
     539           0 :         switch (exp) {
     540           0 :         case 0: *q = v; *r = 0; break;
     541           0 :         case 1: DIVMOD(q, r, v, 10UL); break;
     542           0 :         case 2: DIVMOD(q, r, v, 100UL); break;
     543           0 :         case 3: DIVMOD(q, r, v, 1000UL); break;
     544           0 :         case 4: DIVMOD(q, r, v, 10000UL); break;
     545             :         }
     546             :     }
     547             :     else {
     548           0 :         switch (exp) {
     549           0 :         case 5: DIVMOD(q, r, v, 100000UL); break;
     550           0 :         case 6: DIVMOD(q, r, v, 1000000UL); break;
     551           0 :         case 7: DIVMOD(q, r, v, 10000000UL); break;
     552           0 :         case 8: DIVMOD(q, r, v, 100000000UL); break;
     553           0 :         case 9: DIVMOD(q, r, v, 1000000000UL); break; /* GCOV_NOT_REACHED */
     554             :         }
     555             :     }
     556           0 : }
     557             : /* END CONFIG_32 */
     558             : 
     559             : /* NO CONFIG */
     560             : #else
     561             :   #error "define CONFIG_64 or CONFIG_32"
     562             : #endif /* CONFIG */
     563             : 
     564             : 
     565             : static inline void
     566           0 : _mpd_div_word(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t d)
     567             : {
     568           0 :     *q = v / d;
     569           0 :     *r = v - *q * d;
     570           0 : }
     571             : 
     572             : static inline void
     573           0 : _mpd_idiv_word(mpd_ssize_t *q, mpd_ssize_t *r, mpd_ssize_t v, mpd_ssize_t d)
     574             : {
     575           0 :     *q = v / d;
     576           0 :     *r = v - *q * d;
     577           0 : }
     578             : 
     579             : 
     580             : /** ------------------------------------------------------------
     581             :  **              Arithmetic with overflow checking
     582             :  ** ------------------------------------------------------------
     583             :  */
     584             : 
     585             : /* The following macros do call exit() in case of an overflow.
     586             :    If the library is used correctly (i.e. with valid context
     587             :    parameters), such overflows cannot occur. The macros are used
     588             :    as sanity checks in a couple of strategic places and should
     589             :    be viewed as a handwritten version of gcc's -ftrapv option. */
     590             : 
     591             : static inline mpd_size_t
     592           0 : add_size_t(mpd_size_t a, mpd_size_t b)
     593             : {
     594           0 :     if (a > MPD_SIZE_MAX - b) {
     595           0 :         mpd_err_fatal("add_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
     596             :     }
     597           0 :     return a + b;
     598             : }
     599             : 
     600             : static inline mpd_size_t
     601           0 : sub_size_t(mpd_size_t a, mpd_size_t b)
     602             : {
     603           0 :     if (b > a) {
     604           0 :         mpd_err_fatal("sub_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
     605             :     }
     606           0 :     return a - b;
     607             : }
     608             : 
     609             : #if MPD_SIZE_MAX != MPD_UINT_MAX
     610             :   #error "adapt mul_size_t() and mulmod_size_t()"
     611             : #endif
     612             : 
     613             : static inline mpd_size_t
     614           0 : mul_size_t(mpd_size_t a, mpd_size_t b)
     615             : {
     616             :     mpd_uint_t hi, lo;
     617             : 
     618           0 :     _mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
     619           0 :     if (hi) {
     620           0 :         mpd_err_fatal("mul_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
     621             :     }
     622           0 :     return lo;
     623             : }
     624             : 
     625             : static inline mpd_size_t
     626           0 : add_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow)
     627             : {
     628             :     mpd_size_t ret;
     629             : 
     630           0 :     *overflow = 0;
     631           0 :     ret = a + b;
     632           0 :     if (ret < a) *overflow = 1;
     633           0 :     return ret;
     634             : }
     635             : 
     636             : static inline mpd_size_t
     637           0 : mul_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow)
     638             : {
     639             :     mpd_uint_t lo;
     640             : 
     641           0 :     _mpd_mul_words((mpd_uint_t *)overflow, &lo, (mpd_uint_t)a,
     642             :                    (mpd_uint_t)b);
     643           0 :     return lo;
     644             : }
     645             : 
     646             : static inline mpd_ssize_t
     647           0 : mod_mpd_ssize_t(mpd_ssize_t a, mpd_ssize_t m)
     648             : {
     649           0 :     mpd_ssize_t r = a % m;
     650           0 :     return (r < 0) ? r + m : r;
     651             : }
     652             : 
     653             : static inline mpd_size_t
     654           0 : mulmod_size_t(mpd_size_t a, mpd_size_t b, mpd_size_t m)
     655             : {
     656             :     mpd_uint_t hi, lo;
     657             :     mpd_uint_t q, r;
     658             : 
     659           0 :     _mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
     660           0 :     _mpd_div_words(&q, &r, hi, lo, (mpd_uint_t)m);
     661             : 
     662           0 :     return r;
     663             : }
     664             : 
     665             : 
     666             : #endif /* TYPEARITH_H */
     667             : 
     668             : 
     669             : 

Generated by: LCOV version 1.10