LCOV - code coverage report
Current view: top level - libgnucash/engine - gnc-int128.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 68.5 % 600 411
Test Date: 2025-02-07 16:25:45 Functions: 78.3 % 60 47
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /********************************************************************
       2                 :             :  * qofmath128.c -- an 128-bit integer library                       *
       3                 :             :  * Copyright (C) 2004 Linas Vepstas <linas@linas.org>               *
       4                 :             :  * Copyright (C) 2014 John Ralls <jralls@ceridwen.us>               *
       5                 :             :  *                                                                  *
       6                 :             :  * This program is free software; you can redistribute it and/or    *
       7                 :             :  * modify it under the terms of the GNU General Public License as   *
       8                 :             :  * published by the Free Software Foundation; either version 2 of   *
       9                 :             :  * the License, or (at your option) any later version.              *
      10                 :             :  *                                                                  *
      11                 :             :  * This program is distributed in the hope that it will be useful,  *
      12                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      13                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      14                 :             :  * GNU General Public License for more details.                     *
      15                 :             :  *                                                                  *
      16                 :             :  * You should have received a copy of the GNU General Public License*
      17                 :             :  * along with this program; if not, contact:                        *
      18                 :             :  *                                                                  *
      19                 :             :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      20                 :             :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      21                 :             :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      22                 :             :  *                                                                  *
      23                 :             :  *******************************************************************/
      24                 :             : #include <config.h>
      25                 :             : 
      26                 :             : #include "gnc-int128.hpp"
      27                 :             : 
      28                 :             : #include <iomanip>
      29                 :             : #include <utility>
      30                 :             : #include <cassert>
      31                 :             : #include <cstdio>
      32                 :             : #include <sstream>
      33                 :             : 
      34                 :             : /* All algorithms from Donald E. Knuth, "The Art of Computer
      35                 :             :  * Programming, Volume 2: Seminumerical Algorithms", 3rd Ed.,
      36                 :             :  * Addison-Wesley, 1998.
      37                 :             :  */
      38                 :             : 
      39                 :             : namespace {
      40                 :             :     static const unsigned int upper_num_bits = 61;
      41                 :             :     static const unsigned int sublegs = GncInt128::numlegs * 2;
      42                 :             :     static const unsigned int sublegbits = GncInt128::legbits / 2;
      43                 :             :     static const uint64_t sublegmask = (UINT64_C(1) << sublegbits) - 1;
      44                 :             :     static const uint64_t flagmask = UINT64_C(0xe000000000000000);
      45                 :             :     static const uint64_t nummask = UINT64_C(0x1fffffffffffffff);
      46                 :             : /* Assumes that the high bits represent old flags to be replaced.
      47                 :             :  * Any overflow must be detected first!
      48                 :             :  */
      49                 :    24419525 :     static inline uint64_t set_flags(uint64_t leg, uint8_t flags)
      50                 :             :     {
      51                 :    24419525 :         auto flag_part = static_cast<uint64_t>(flags) << upper_num_bits;
      52                 :    24419525 :         return flag_part + (leg & nummask);
      53                 :             :     }
      54                 :    76319081 :     static inline uint8_t get_flags(uint64_t leg)
      55                 :             :     {
      56                 :    76319081 :         return (leg & flagmask) >> upper_num_bits;
      57                 :             :     }
      58                 :    33720461 :     static inline uint64_t get_num(uint64_t leg)
      59                 :             :     {
      60                 :    33720461 :         return leg & nummask;
      61                 :             :     }
      62                 :             : }
      63                 :             : 
      64                 :     2484462 : GncInt128::GncInt128 () : m_hi {0}, m_lo {0}{}
      65                 :             : 
      66                 :     3991610 : GncInt128::GncInt128 (int64_t upper, int64_t lower, uint8_t flags) :
      67                 :     3991610 :     m_hi {static_cast<uint64_t>(upper < 0 ? -upper : upper)},
      68                 :     3991610 :     m_lo {static_cast<uint64_t>(lower < 0 ? -lower : lower)}
      69                 :             : {
      70                 :     3991610 :     if ((upper < 0 && lower > 0) || (upper > 0 && lower < 0))
      71                 :           0 :         m_lo = (m_hi << 63) - m_lo;
      72                 :             :     else
      73                 :     3991610 :         m_lo += (m_hi << 63);
      74                 :             : 
      75                 :     3991610 :     m_hi >>= 1;
      76                 :     3991610 :     if (m_hi & flagmask)
      77                 :             :     {
      78                 :           0 :         std::ostringstream ss;
      79                 :           0 :         ss << "Constructing GncInt128 with int64_t " << upper
      80                 :           0 :            << " which is too big.";
      81                 :           0 :         throw std::overflow_error(ss.str());
      82                 :           0 :     }
      83                 :     3991610 :     flags ^= (upper < 0 ? neg : upper == 0 && lower < 0 ? neg : pos);
      84                 :     3991610 :     m_hi = set_flags(m_hi, flags);
      85                 :     3991610 : }
      86                 :             : 
      87                 :           0 : GncInt128::GncInt128 (int64_t upper, uint64_t lower, uint8_t flags) :
      88                 :           0 :     m_hi {static_cast<uint64_t>(upper < 0 ? -upper : upper)}, m_lo {lower}
      89                 :             : {
      90                 :           0 :     if (m_hi & flagmask)
      91                 :             :     {
      92                 :           0 :         std::ostringstream ss;
      93                 :           0 :         ss << "Constructing GncInt128 with int64_t " << upper
      94                 :           0 :            << " which is too big when lower is unsigned.";
      95                 :           0 :         throw std::overflow_error(ss.str());
      96                 :           0 :     }
      97                 :           0 :     flags ^= (upper < 0 ? neg : pos);
      98                 :           0 :     m_hi = set_flags(m_hi, flags);
      99                 :           0 : }
     100                 :             : 
     101                 :     3969017 : GncInt128::GncInt128 (uint64_t upper, uint64_t lower, uint8_t flags) :
     102                 :     3969017 :     m_hi {upper}, m_lo {lower}
     103                 :             :  {
     104                 :             :      /* somewhere in the bowels of gnc_module.scm compilation this gets called
     105                 :             :       * with upper=INT64_MAX, which would otherwise throw. Make it our max value
     106                 :             :       * instead.
     107                 :             :       */
     108                 :     3969017 :     if (m_hi == UINT64_MAX)
     109                 :        1338 :          m_hi = nummask;
     110                 :     3969017 :      if (m_hi & flagmask)
     111                 :             :     {
     112                 :           0 :         std::ostringstream ss;
     113                 :           0 :         ss << "Constructing GncInt128 with uint64_t " << upper
     114                 :           0 :            << " which is too big.";
     115                 :           0 :         throw std::overflow_error(ss.str());
     116                 :           0 :     }
     117                 :             : 
     118                 :     3969017 :      m_hi = set_flags(m_hi, flags);
     119                 :     3969017 : }
     120                 :             : 
     121                 :             : GncInt128&
     122                 :     2484462 : GncInt128::zero () noexcept
     123                 :             : {
     124                 :     2484462 :     m_lo = m_hi = UINT64_C(0);
     125                 :     2484462 :     return *this;
     126                 :             : }
     127                 :             : 
     128                 :      814878 : GncInt128::operator int64_t() const
     129                 :             : {
     130                 :      814878 :     auto flags = get_flags(m_hi);
     131                 :      814878 :     if ((flags & neg) && isBig())
     132                 :           0 :         throw std::underflow_error ("Negative value too large to represent as int64_t");
     133                 :      814878 :     if ((flags & (overflow | NaN)) || isBig())
     134                 :          15 :         throw std::overflow_error ("Value too large to represent as int64_t");
     135                 :      814863 :     int64_t retval = static_cast<int64_t>(m_lo);
     136                 :      814863 :     return flags & neg ? -retval : retval;
     137                 :             : }
     138                 :             : 
     139                 :           0 : GncInt128::operator uint64_t() const
     140                 :             : {
     141                 :           0 :     auto flags = get_flags(m_hi);
     142                 :           0 :     if ((flags & neg) && !isZero()) // exclude negative zero
     143                 :           0 :         throw std::underflow_error ("Can't represent negative value as uint64_t");
     144                 :           0 :     if ((flags & (overflow | NaN)) || (m_hi || m_lo > UINT64_MAX))
     145                 :           0 :         throw std::overflow_error ("Value to large to represent as uint64_t");
     146                 :           0 :     return m_lo;
     147                 :             : }
     148                 :             : 
     149                 :             : 
     150                 :             : int
     151                 :     2578048 : GncInt128::cmp (const GncInt128& b) const noexcept
     152                 :             : {
     153                 :     2578048 :     auto flags = get_flags(m_hi);
     154                 :     2578048 :     if (flags & (overflow | NaN))
     155                 :           0 :         return -1;
     156                 :     2578048 :     if (b.isOverflow () || b.isNan ())
     157                 :           0 :         return 1;
     158                 :     2578048 :     auto hi = get_num(m_hi);
     159                 :     2578048 :     auto bhi = get_num(b.m_hi);
     160                 :     2578048 :     if (isZero() && b.isZero()) return 0;
     161                 :     2556197 :     if (flags & neg)
     162                 :             :     {
     163                 :         864 :         if (!b.isNeg()) return -1;
     164                 :         212 :         if (hi > bhi) return -1;
     165                 :         212 :         if (hi < bhi) return 1;
     166                 :         212 :         if (m_lo > b.m_lo) return -1;
     167                 :          80 :         if (m_lo < b.m_lo) return 1;
     168                 :          10 :         return 0;
     169                 :             :     }
     170                 :     2555333 :     if (b.isNeg()) return 1;
     171                 :     2555320 :     if (hi < bhi) return -1;
     172                 :     2554008 :     if (hi > bhi) return 1;
     173                 :     2543708 :     if (m_lo < b.m_lo) return -1;
     174                 :     1856410 :     if (m_lo > b.m_lo) return 1;
     175                 :      866424 :     return 0;
     176                 :             : }
     177                 :             : 
     178                 :             : /* Knuth 4.5.3 Algo B, recommended by GMP as much faster than Algo A (Euclidean
     179                 :             :  * method).
     180                 :             :  */
     181                 :             : GncInt128
     182                 :      362122 : GncInt128::gcd(GncInt128 b) const noexcept
     183                 :             : {
     184                 :      362122 :     if (b.isZero())
     185                 :         252 :         return *this;
     186                 :      361870 :     if (isZero())
     187                 :           0 :         return b;
     188                 :             : 
     189                 :      361870 :     if (b.isOverflow() || b.isNan())
     190                 :           0 :         return b;
     191                 :      361870 :     if (isOverflow() || isNan())
     192                 :           0 :         return *this;
     193                 :             : 
     194                 :      361870 :     GncInt128 a (isNeg() ? -(*this) : *this);
     195                 :      361870 :     if (b.isNeg()) b = -b;
     196                 :             : 
     197                 :      361870 :     unsigned int k {};
     198                 :      361870 :     const uint64_t one {1};
     199                 :      753773 :     while (!((a & one) || (b & one))) //B1
     200                 :             :     {
     201                 :      391903 :         a >>= 1;
     202                 :      391903 :         b >>= 1;
     203                 :      391903 :         ++k;
     204                 :             :     }
     205                 :      361870 :     GncInt128 t {a & one ? -b : a}; //B2
     206                 :      761645 :     while (a != b)
     207                 :             :     {
     208                 :     1213552 :         while (t && ((t & one) ^ one)) t >>= 1;  //B3 & B4
     209                 :      399775 :         if (t.isNeg())  //B5
     210                 :      320932 :             b = -t;
     211                 :             :         else
     212                 :       78843 :             a = t;
     213                 :      399775 :         t = a - b;  //B6
     214                 :             :     }
     215                 :      361870 :     return a << k;
     216                 :             : }
     217                 :             : 
     218                 :             : /* Since u * v = gcd(u, v) * lcm(u, v), we find lcm by u / gcd * v. */
     219                 :             : 
     220                 :             : GncInt128
     221                 :      257841 : GncInt128::lcm(const GncInt128& b) const noexcept
     222                 :             : {
     223                 :      257841 :     auto common = gcd(b);
     224                 :      257841 :     return *this / common * b.abs(); //Preserve our sign, discard the other's.
     225                 :             : }
     226                 :             : 
     227                 :             : /* Knuth section 4.6.3 */
     228                 :             : GncInt128
     229                 :           0 : GncInt128::pow(unsigned int b) const noexcept
     230                 :             : {
     231                 :           0 :     if (isZero() || (m_lo == 1 && m_hi == 0) || isNan() || isOverflow())
     232                 :           0 :         return *this;
     233                 :           0 :     if (b == 0)
     234                 :           0 :         return GncInt128 (1);
     235                 :           0 :     GncInt128 retval (1), squares = *this;
     236                 :           0 :     while (b && !retval.isOverflow())
     237                 :             :     {
     238                 :           0 :         if (b & 1)
     239                 :           0 :             retval *= squares;
     240                 :           0 :         squares *= squares;
     241                 :           0 :         b >>= 1;
     242                 :             :     }
     243                 :           0 :     return retval;
     244                 :             : }
     245                 :             : 
     246                 :             : bool
     247                 :    13804756 : GncInt128::isNeg () const noexcept
     248                 :             : {
     249                 :    13804756 :     return (get_flags(m_hi) & neg);
     250                 :             : }
     251                 :             : 
     252                 :             : bool
     253                 :     1599249 : GncInt128::isBig () const noexcept
     254                 :             : {
     255                 :     1599249 :     return (get_num(m_hi) || m_lo > INT64_MAX);
     256                 :             : }
     257                 :             : 
     258                 :             : bool
     259                 :    17456522 : GncInt128::isOverflow () const noexcept
     260                 :             : {
     261                 :    17456522 :     return (get_flags(m_hi) & overflow);
     262                 :             : }
     263                 :             : 
     264                 :             : bool
     265                 :    17583454 : GncInt128::isNan () const noexcept
     266                 :             : {
     267                 :    17583454 :     return (get_flags(m_hi) & NaN);
     268                 :             : }
     269                 :             : 
     270                 :             : bool
     271                 :     1615030 : GncInt128::valid() const noexcept
     272                 :             : {
     273                 :     1615030 :     return !(get_flags(m_hi) & (overflow | NaN));
     274                 :             : }
     275                 :             : 
     276                 :             : bool
     277                 :    10387796 : GncInt128::isZero() const noexcept
     278                 :             : {
     279                 :    20775592 :     return ((get_flags(m_hi) & (overflow | NaN)) == 0 &&
     280                 :    20775592 :             get_num(m_hi) == 0 && m_lo == 0);
     281                 :             : }
     282                 :             : 
     283                 :             : GncInt128
     284                 :     3718565 : GncInt128::abs() const noexcept
     285                 :             : {
     286                 :     3718565 :     if (isNeg())
     287                 :      411536 :         return operator-();
     288                 :             : 
     289                 :     3307029 :     return *this;
     290                 :             : }
     291                 :             : 
     292                 :             : unsigned int
     293                 :     1656116 : GncInt128::bits() const noexcept
     294                 :             : {
     295                 :     1656116 :     auto hi = get_num(m_hi);
     296                 :     1656116 :     unsigned int bits {static_cast<unsigned int>(hi == 0 ? 0 : 64)};
     297                 :     1656116 :     uint64_t temp {(hi == 0 ? m_lo : hi)};
     298                 :    14306078 :     for (;temp > 0; temp >>= 1)
     299                 :    12649962 :         ++bits;
     300                 :     1656116 :     return bits;
     301                 :             : }
     302                 :             : 
     303                 :             : 
     304                 :             : GncInt128
     305                 :     1165593 : GncInt128::operator-() const noexcept
     306                 :             : {
     307                 :     1165593 :     auto retval = *this;
     308                 :     1165593 :     auto flags = get_flags(retval.m_hi);
     309                 :     1165593 :     if (isNeg())
     310                 :      784468 :         flags ^= neg;
     311                 :             :     else
     312                 :      381125 :         flags |= neg;
     313                 :     1165593 :     retval.m_hi = set_flags(retval.m_hi, flags);
     314                 :     1165593 :     return retval;
     315                 :             : }
     316                 :             : 
     317                 :     3970139 : GncInt128::operator bool() const noexcept
     318                 :             : {
     319                 :     3970139 :     return ! isZero ();
     320                 :             : }
     321                 :             : 
     322                 :             : GncInt128&
     323                 :           0 : GncInt128::operator++ () noexcept
     324                 :             : {
     325                 :           0 :     return operator+=(UINT64_C(1));
     326                 :             : }
     327                 :             : 
     328                 :             : GncInt128&
     329                 :           0 : GncInt128::operator++ (int) noexcept
     330                 :             : {
     331                 :           0 :     return operator+=(UINT64_C(1));
     332                 :             : }
     333                 :             : 
     334                 :             : GncInt128&
     335                 :           0 : GncInt128::operator-- () noexcept
     336                 :             : {
     337                 :           0 :     return operator-=(UINT64_C(1));
     338                 :             : }
     339                 :             : 
     340                 :             : GncInt128&
     341                 :           0 : GncInt128::operator-- (int) noexcept
     342                 :             : {
     343                 :           0 :     return operator-=(UINT64_C(1));
     344                 :             : }
     345                 :             : 
     346                 :             : GncInt128&
     347                 :      257581 : GncInt128::operator+= (const GncInt128& b) noexcept
     348                 :             : {
     349                 :      257581 :     auto flags = get_flags(m_hi);
     350                 :      257581 :     if (b.isOverflow())
     351                 :           0 :         flags |= overflow;
     352                 :      257581 :     if (b.isNan())
     353                 :           0 :         flags |= NaN;
     354                 :      257581 :     m_hi = set_flags(m_hi, flags);
     355                 :      257581 :     if (isOverflow() || isNan())
     356                 :           0 :         return *this;
     357                 :      257581 :     if ((isNeg () && !b.isNeg ()) || (!isNeg () && b.isNeg ()))
     358                 :       87673 :         return this->operator-= (-b);
     359                 :      169908 :     uint64_t result = m_lo + b.m_lo;
     360                 :      169908 :     uint64_t carry = static_cast<int64_t>(result < m_lo);  //Wrapping
     361                 :      169908 :     m_lo = result;
     362                 :      169908 :     auto hi = get_num(m_hi);
     363                 :      169908 :     auto bhi = get_num(b.m_hi);
     364                 :      169908 :     result = hi + bhi + carry;
     365                 :      169908 :     if (result < hi || result & flagmask)
     366                 :           0 :         flags |= overflow;
     367                 :      169908 :     m_hi = set_flags(result, flags);
     368                 :      169908 :     return *this;
     369                 :             : }
     370                 :             : 
     371                 :             : GncInt128&
     372                 :      361870 : GncInt128::operator<<= (unsigned int i) noexcept
     373                 :             : {
     374                 :      361870 :     auto flags = get_flags(m_hi);
     375                 :      361870 :     if (i == 0)
     376                 :      170452 :         return *this;
     377                 :      191418 :     if (i > maxbits)
     378                 :             :     {
     379                 :           0 :         flags &= 0xfe;
     380                 :           0 :         m_hi = set_flags(0, flags);
     381                 :           0 :         m_lo = 0;
     382                 :           0 :         return *this;
     383                 :             :     }
     384                 :      191418 :     auto hi = get_num(m_hi);
     385                 :      191418 :     if (i < legbits)
     386                 :             :     {
     387                 :      191418 :         uint64_t carry {(m_lo & (((UINT64_C(1) << i) - 1) << (legbits - i))) >> (legbits - i)};
     388                 :      191418 :         m_lo <<= i;
     389                 :      191418 :         hi <<= i;
     390                 :      191418 :         hi += carry;
     391                 :      191418 :         m_hi = set_flags(hi, flags);
     392                 :      191418 :         return *this;
     393                 :             :     }
     394                 :           0 :     hi = m_lo << (i - legbits);
     395                 :           0 :     m_hi = set_flags(hi, flags);
     396                 :           0 :     m_lo = 0;
     397                 :           0 :     return *this;
     398                 :             : }
     399                 :             : 
     400                 :             : GncInt128&
     401                 :     1597650 : GncInt128::operator>>= (unsigned int i) noexcept
     402                 :             : {
     403                 :     1597650 :     auto flags = get_flags(m_hi);
     404                 :     1597650 :     if (i > maxbits)
     405                 :             :     {
     406                 :           0 :         flags &= 0xfe;
     407                 :           0 :         m_hi = set_flags(0, flags);
     408                 :           0 :         m_lo = 0;
     409                 :           0 :         return *this;
     410                 :             :     }
     411                 :     1597650 :     auto hi = get_num(m_hi);
     412                 :     1597650 :     if (i < legbits)
     413                 :             :     {
     414                 :     1597622 :         uint64_t carry {(hi & ((UINT64_C(1) << i) - 1))};
     415                 :     1597622 :         m_lo >>= i;
     416                 :     1597622 :         hi >>= i;
     417                 :     1597622 :         m_lo += (carry << (legbits - i));
     418                 :     1597622 :         m_hi = set_flags(hi, flags);
     419                 :     1597622 :         return *this;
     420                 :             :     }
     421                 :          28 :     m_lo = hi >> (i - legbits);
     422                 :          28 :     m_hi = set_flags(0, flags);
     423                 :          28 :     return *this;
     424                 :             : }
     425                 :             : 
     426                 :             : GncInt128&
     427                 :      487448 : GncInt128::operator-= (const GncInt128& b) noexcept
     428                 :             : {
     429                 :      487448 :     auto flags = get_flags(m_hi);
     430                 :      487448 :     if (b.isOverflow())
     431                 :           0 :         flags |= overflow;
     432                 :      487448 :     if (b.isNan())
     433                 :           0 :         flags |= NaN;
     434                 :      487448 :     m_hi = set_flags(m_hi, flags);
     435                 :             : 
     436                 :      487448 :     if (isOverflow() || isNan())
     437                 :           0 :         return *this;
     438                 :             : 
     439                 :      487448 :     if ((!isNeg() && b.isNeg()) || (isNeg() && !b.isNeg()))
     440                 :           0 :         return this->operator+= (-b);
     441                 :      487448 :     bool operand_bigger {abs().cmp (b.abs()) < 0};
     442                 :      487448 :     auto hi = get_num(m_hi);
     443                 :      487448 :     auto far_hi = get_num(b.m_hi);
     444                 :      487448 :     if (operand_bigger)
     445                 :             :     {
     446                 :      248814 :         flags ^= neg; // ^= flips the bit
     447                 :      248814 :         if (m_lo > b.m_lo)
     448                 :             :         {
     449                 :             :             /* The + 1 on the end is because we really want to use 2^64, or
     450                 :             :              * UINT64_MAX + 1, but that can't be represented in a uint64_t.
     451                 :             :              */
     452                 :           0 :             m_lo = UINT64_MAX - m_lo + b.m_lo + 1;
     453                 :           0 :             --far_hi; //borrow
     454                 :             :         }
     455                 :             :         else
     456                 :      248814 :             m_lo = b.m_lo - m_lo;
     457                 :      248814 :         hi = far_hi - hi;
     458                 :      248814 :         m_hi = set_flags(hi, flags);
     459                 :      248814 :         return *this;
     460                 :             :     }
     461                 :      238634 :     if (m_lo < b.m_lo)
     462                 :             :     {
     463                 :           0 :         m_lo = UINT64_MAX - b.m_lo + m_lo + 1; //See UINT64_MAX comment above
     464                 :           0 :         --hi; //borrow
     465                 :             :     }
     466                 :             :     else
     467                 :      238634 :         m_lo -= b.m_lo;
     468                 :             : 
     469                 :      238634 :     hi -= far_hi;
     470                 :      238634 :     m_hi = set_flags(hi, flags);
     471                 :      238634 :     return *this;
     472                 :             : }
     473                 :             : 
     474                 :             : GncInt128&
     475                 :      886218 : GncInt128::operator*= (const GncInt128& b) noexcept
     476                 :             : {
     477                 :             :     /* Test for 0 first */
     478                 :      886218 :     auto flags = get_flags(m_hi);
     479                 :             :     /* Handle the sign; ^ flips if b is negative */
     480                 :      886218 :     flags ^= (get_flags(b.m_hi) & neg);
     481                 :      886218 :     if (isZero() || b.isZero())
     482                 :             :     {
     483                 :       58160 :         m_lo = 0;
     484                 :       58160 :         m_hi = set_flags(0, flags);
     485                 :       58160 :         return *this;
     486                 :             :     }
     487                 :      828058 :     if (b.isOverflow())
     488                 :           0 :         flags |= overflow;
     489                 :      828058 :     if (b.isNan())
     490                 :           0 :         flags |= NaN;
     491                 :      828058 :     m_hi = set_flags(m_hi, flags);
     492                 :      828058 :     if (isOverflow() || isNan())
     493                 :           0 :         return *this;
     494                 :             : 
     495                 :             :     /* Test for overflow before spending time on the calculation */
     496                 :      828058 :     auto hi = get_num(m_hi);
     497                 :      828058 :     auto bhi = get_num(b.m_hi);
     498                 :      828058 :     if (hi && bhi)
     499                 :             :     {
     500                 :           0 :         flags |= overflow;
     501                 :           0 :         m_hi = set_flags(hi, flags);
     502                 :           0 :         return *this;
     503                 :             :     }
     504                 :             : 
     505                 :      828058 :     unsigned int abits {bits()}, bbits {b.bits()};
     506                 :             :     /* If the product of the high bytes < 7fff then the result will have abits +
     507                 :             :      * bbits -1 bits and won't actually overflow. It's not worth the effort to
     508                 :             :      * work that out for this corner-case, so we'll take the risk and calculate
     509                 :             :      * the product and catch the overflow later.
     510                 :             :      */
     511                 :      828058 :     if (abits + bbits - 1 > maxbits)
     512                 :             :     {
     513                 :           0 :         flags |= overflow;
     514                 :           0 :         m_hi = set_flags(m_hi, flags);
     515                 :           0 :         return *this;
     516                 :             :     }
     517                 :             : 
     518                 :             :     /* The trivial case */
     519                 :      828058 :     if (abits + bbits <= legbits)
     520                 :             :     {
     521                 :      825399 :         m_lo *= b.m_lo;
     522                 :      825399 :         m_hi = set_flags(m_hi, flags);
     523                 :      825399 :         return *this;
     524                 :             :     }
     525                 :             : 
     526                 :             : /* This is Knuth's "classical" multi-precision multiplication algorithm
     527                 :             :  * truncated to a GncInt128 result with the loop unrolled for clarity and with
     528                 :             :  * overflow and zero checks beforehand to save time. See Donald Knuth, "The Art
     529                 :             :  * of Computer Programming Volume 2: Seminumerical Algorithms", Addison-Wesley,
     530                 :             :  * 1998, p 268.
     531                 :             :  *
     532                 :             :  * There are potentially faster algorithms (O(n^1.6) instead of O(n^2) for the
     533                 :             :  * full precision), but this is already close to that fast because of truncation
     534                 :             :  * and it's not clear that the truncation is applicable to the faster
     535                 :             :  * algorithms.
     536                 :             :  */
     537                 :             : 
     538                 :        2659 :     uint64_t av[sublegs] {(m_lo & sublegmask), (m_lo >> sublegbits),
     539                 :        2659 :             (hi & sublegmask), (hi >> sublegbits)};
     540                 :        2659 :     uint64_t bv[sublegs] {(b.m_lo & sublegmask), (b.m_lo >> sublegbits),
     541                 :        2659 :             (bhi & sublegmask), (bhi >> sublegbits)};
     542                 :        2659 :     uint64_t rv[sublegs] {};
     543                 :        2659 :     uint64_t carry {}, scratch {};
     544                 :             : 
     545                 :        2659 :     rv[0] = av[0] * bv[0];
     546                 :             : 
     547                 :        2659 :     rv[1] = av[1] * bv [0];
     548                 :        2659 :     scratch = rv[1] + av[0] * bv[1];
     549                 :        2659 :     carry = rv[1] > scratch ? 1 : 0;
     550                 :        2659 :     rv[1] = scratch;
     551                 :             : 
     552                 :        2659 :     rv[2] = av[2] * bv[0] + carry; //0xffff^2 + 1 < 0xffffffff, can't overflow
     553                 :        2659 :     scratch = rv[2] + av[1] * bv[1];
     554                 :        2659 :     carry = rv[2] > scratch ? 1 : 0;
     555                 :        2659 :     rv[2] = scratch + av[0] * bv[2];
     556                 :        2659 :     carry += scratch > rv[2] ? 1 : 0;
     557                 :             : 
     558                 :        2659 :     rv[3] = av[3] * bv[0] + carry;
     559                 :        2659 :     scratch = rv[3] + av[2] * bv[1];
     560                 :        2659 :     carry = rv[3] > scratch ? 1 : 0;
     561                 :        2659 :     rv[3] = scratch + av[1] * bv[2];
     562                 :        2659 :     carry += scratch > rv[3] ? 1 : 0;
     563                 :        2659 :     scratch = rv[3] + av[0] * bv[3];
     564                 :        2659 :     carry += rv[3] > scratch ? 1 : 0;
     565                 :        2659 :     rv[3] = scratch;
     566                 :             : 
     567                 :        2659 :     if (carry) //Shouldn't happen because of the checks above
     568                 :             :     {
     569                 :           0 :         flags |= overflow;
     570                 :           0 :         m_hi = set_flags(m_hi, flags);
     571                 :           0 :         return *this;
     572                 :             :     }
     573                 :             : 
     574                 :        2659 :     m_lo = rv[0] + (rv[1] << sublegbits);
     575                 :        2659 :     carry = rv[1] >> sublegbits;
     576                 :        2659 :     carry += (rv[1] << sublegbits) > m_lo || rv[0] > m_lo ? 1 : 0;
     577                 :        2659 :     hi = rv[2] + (rv[3] << sublegbits) + carry;
     578                 :        2659 :     if ((rv[3] << sublegbits) > hi || rv[2] > hi || (rv[3] >> sublegbits) ||
     579                 :             :         hi & flagmask)
     580                 :             :     {
     581                 :           0 :         flags |= overflow;
     582                 :           0 :         m_hi = set_flags(hi, flags);
     583                 :           0 :         return *this;
     584                 :             :     }
     585                 :        2659 :     m_hi = set_flags(hi, flags);
     586                 :        2659 :     return *this;
     587                 :             : }
     588                 :             : 
     589                 :             : namespace {
     590                 :             : /* Algorithm from Knuth (full citation at operator*=) p272ff.  Again, there
     591                 :             :  * are faster algorithms out there, but they require much larger numbers to
     592                 :             :  * be of benefit.
     593                 :             :  */
     594                 :             : /* We're using arrays here instead of vectors to avoid an alloc. */
     595                 :             : void
     596                 :          82 : div_multi_leg (uint64_t* u, size_t m, uint64_t* v, size_t n,
     597                 :             :                GncInt128& q, GncInt128& r) noexcept
     598                 :             : {
     599                 :             : /* D1, Normalization */
     600                 :          82 :     uint64_t qv[sublegs] {};
     601                 :          82 :     uint64_t d {(UINT64_C(1) << sublegbits)/(v[n - 1] + UINT64_C(1))};
     602                 :          82 :     uint64_t carry {UINT64_C(0)};
     603                 :          82 :     bool negative {q.isNeg()};
     604                 :          82 :     bool rnegative {r.isNeg()};
     605                 :         359 :     for (size_t i = 0; i < m; ++i)
     606                 :             :     {
     607                 :         277 :         u[i] = u[i] * d + carry;
     608                 :         277 :         if (u[i] > sublegmask)
     609                 :             :         {
     610                 :         226 :             carry = u[i] >> sublegbits;
     611                 :         226 :             u[i] &= sublegmask;
     612                 :             :         }
     613                 :             :         else
     614                 :          51 :             carry = UINT64_C(0);
     615                 :         277 :         assert (u[i] <= sublegmask);
     616                 :             :     }
     617                 :          82 :     if (carry)
     618                 :             :     {
     619                 :          39 :         u[m++] = carry;
     620                 :          39 :         carry = UINT64_C(0);
     621                 :             :     }
     622                 :         250 :     for (size_t i = 0; i < n; ++i)
     623                 :             :     {
     624                 :         168 :         v[i] = v[i] * d + carry;
     625                 :         168 :         if (v[i] > sublegmask)
     626                 :             :         {
     627                 :          82 :             carry = v[i] >> sublegbits;
     628                 :          82 :             v[i] &= sublegmask;
     629                 :             :         }
     630                 :             :         else
     631                 :          86 :             carry = UINT64_C(0);
     632                 :         168 :         assert (v[i] < sublegmask);
     633                 :             :     }
     634                 :          82 :     assert (carry == UINT64_C(0));
     635                 :         312 :     for (int j = m - n; j >= 0; j--) //D3
     636                 :             :     {
     637                 :             :         uint64_t qhat, rhat;
     638                 :         230 :         qhat = ((u[j + n] << sublegbits) + u[j + n - 1]) / v[n - 1];
     639                 :         230 :         rhat = ((u[j + n] << sublegbits) + u[j + n - 1]) % v[n - 1];
     640                 :             : 
     641                 :         257 :         while (qhat > sublegmask ||
     642                 :         236 :                (rhat <= sublegmask &&
     643                 :         236 :                 ((qhat * v[n - 2]) > ((rhat << sublegbits) + u[j + n - 2]))))
     644                 :             :         {
     645                 :          27 :             --qhat;
     646                 :          27 :             rhat += v[n - 1];
     647                 :             :         }
     648                 :         230 :         carry = UINT64_C(0);
     649                 :         230 :         uint64_t borrow {};
     650                 :         697 :         for (size_t k = 0; k < n; ++k) //D4
     651                 :             :         {
     652                 :         467 :             auto subend = qhat * v[k] + carry;
     653                 :         467 :             carry = subend >> sublegbits;
     654                 :         467 :             subend &= sublegmask;
     655                 :         467 :             if (u[j + k] >= subend)
     656                 :             :             {
     657                 :         345 :                 u[j + k] = u[j + k] - subend;
     658                 :         345 :                 borrow = UINT64_C(0);
     659                 :             :             }
     660                 :             :             else
     661                 :             :             {
     662                 :         122 :                 if (u[j + k + 1] > 0)
     663                 :         122 :                     --u[j + k + 1];
     664                 :             :                 else
     665                 :           0 :                     ++borrow;
     666                 :         122 :                 u[j + k] = u[j + k] + sublegmask + 1 - subend;
     667                 :         122 :                 u[j + k] &= sublegmask;
     668                 :             :             }
     669                 :             :         }
     670                 :         230 :         u[j + n] -= carry;
     671                 :         230 :         qv[j] = qhat;
     672                 :         230 :         if (borrow) //D5
     673                 :             :         { //D6
     674                 :           0 :             --qv[j];
     675                 :           0 :             carry = UINT64_C(0);
     676                 :           0 :             for (size_t k = 0; k < n; ++k)
     677                 :             :             {
     678                 :           0 :                 u[j + k] += v[k] + carry;
     679                 :           0 :                 if (u[j + k] > sublegmask)
     680                 :             :                 {
     681                 :           0 :                     carry = u[j + k] >> sublegbits;
     682                 :           0 :                     u[j + k] &= sublegmask;
     683                 :             :                 }
     684                 :             :             }
     685                 :           0 :             u[j + n] += carry;
     686                 :             :         }
     687                 :             :     }//D7
     688                 :          82 :     q = GncInt128 ((qv[3] << sublegbits) + qv[2], (qv[1] << sublegbits) + qv[0]);
     689                 :          82 :     r = GncInt128 ((u[3] << sublegbits) + u[2], (u[1] << sublegbits) + u[0]);
     690                 :          82 :     r /= d;
     691                 :          82 :     if (negative) q = -q;
     692                 :          82 :     if (rnegative) r = -r;
     693                 :          82 : }
     694                 :             : 
     695                 :             : void
     696                 :        7938 : div_single_leg (uint64_t* u, size_t m, uint64_t v,
     697                 :             :                 GncInt128& q, GncInt128& r) noexcept
     698                 :             : {
     699                 :        7938 :     uint64_t qv[sublegs] {};
     700                 :        7938 :     bool negative {q.isNeg()};
     701                 :        7938 :     bool rnegative {r.isNeg()};
     702                 :       31766 :     for (int i = m - 1; i >= 0; --i)
     703                 :             :     {
     704                 :       23828 :         qv[i] = u[i] / v;
     705                 :       23828 :         if (i > 0)
     706                 :             :         {
     707                 :       15890 :             u[i - 1] += ((u[i] % v) << sublegbits);
     708                 :       15890 :             u[i] = UINT64_C(0);
     709                 :             :         }
     710                 :             :         else
     711                 :        7938 :             u[i] %= v;
     712                 :             :     }
     713                 :             : 
     714                 :        7938 :     q = GncInt128 ((qv[3] << sublegbits) + qv[2], (qv[1] << sublegbits) + qv[0]);
     715                 :        7938 :     r = GncInt128 ((u[3] << sublegbits) + u[2], (u[1] << sublegbits) + u[0]);
     716                 :        7938 :     if (negative) q = -q;
     717                 :        7938 :     if (rnegative) r = -r;
     718                 :        7938 : }
     719                 :             : 
     720                 :             : }// namespace
     721                 :             : 
     722                 :             : void
     723                 :     1242231 : GncInt128::div (const GncInt128& b, GncInt128& q, GncInt128& r) const noexcept
     724                 :             : {
     725                 :             :     // clear remainder and quotient
     726                 :     1242231 :     r = GncInt128(0);
     727                 :     1242231 :     q = GncInt128(0);
     728                 :             : 
     729                 :     1242231 :     auto qflags = get_flags(q.m_hi);
     730                 :     1242231 :     auto rflags = get_flags(r.m_hi);
     731                 :     1242231 :     if (isOverflow() || b.isOverflow())
     732                 :             :     {
     733                 :           0 :         qflags |= overflow;
     734                 :           0 :         rflags |= overflow;
     735                 :           0 :         q.m_hi = set_flags(q.m_hi, qflags);
     736                 :           0 :         r.m_hi = set_flags(r.m_hi, rflags);
     737                 :           0 :         return;
     738                 :             :     }
     739                 :             : 
     740                 :     1242231 :     if (isNan() || b.isNan())
     741                 :             :     {
     742                 :           0 :         qflags |= NaN;
     743                 :           0 :         rflags |= NaN;
     744                 :           0 :         q.m_hi = set_flags(q.m_hi, qflags);
     745                 :           0 :         r.m_hi = set_flags(r.m_hi, rflags);
     746                 :           0 :         return;
     747                 :             :     }
     748                 :     1242231 :     assert (&q != this);
     749                 :     1242231 :     assert (&r != this);
     750                 :     1242231 :     assert (&q != &b);
     751                 :     1242231 :     assert (&r != &b);
     752                 :             : 
     753                 :     1242231 :     q.zero(), r.zero();
     754                 :     1242231 :     qflags = rflags = 0;
     755                 :     1242231 :     if (b.isZero())
     756                 :             :     {
     757                 :           0 :         qflags |= NaN;
     758                 :           0 :         rflags |= NaN;
     759                 :           0 :         q.m_hi = set_flags(q.m_hi, qflags);
     760                 :           0 :         r.m_hi = set_flags(r.m_hi, rflags);
     761                 :           0 :         return;
     762                 :             :     }
     763                 :             : 
     764                 :     1242231 :     if (isNeg())
     765                 :             :     {
     766                 :      339235 :         qflags |= neg;
     767                 :      339235 :         rflags |= neg;          // the remainder inherits the dividend's sign
     768                 :             :     }
     769                 :             : 
     770                 :     1242231 :     if (b.isNeg())
     771                 :           0 :         qflags ^= neg;
     772                 :             : 
     773                 :     1242231 :     q.m_hi = set_flags(q.m_hi, qflags);
     774                 :     1242231 :     r.m_hi = set_flags(r.m_hi, rflags);
     775                 :             : 
     776                 :     1242231 :     if (abs() < b.abs())
     777                 :             :     {
     778                 :      113134 :         r = *this;
     779                 :      113134 :         return;
     780                 :             :     }
     781                 :     1129097 :     auto hi = get_num(m_hi);
     782                 :     1129097 :     auto bhi = get_num(b.m_hi);
     783                 :             : 
     784                 :     1129097 :     if (hi == 0 && bhi == 0) //let the hardware do it
     785                 :             :     {
     786                 :     1121077 :         assert (b.m_lo != 0); // b.m_hi is 0 but b isn't or we didn't get here.
     787                 :     1121077 :         q.m_lo = m_lo / b.m_lo;
     788                 :     1121077 :         r.m_lo = m_lo % b.m_lo;
     789                 :     1121077 :         return;
     790                 :             :     }
     791                 :             : 
     792                 :        8020 :     uint64_t u[sublegs + 2] {(m_lo & sublegmask), (m_lo >> sublegbits),
     793                 :        8020 :             (hi & sublegmask), (hi >> sublegbits), 0, 0};
     794                 :        8020 :     uint64_t v[sublegs] {(b.m_lo & sublegmask), (b.m_lo >> sublegbits),
     795                 :        8020 :             (bhi & sublegmask), (bhi >> sublegbits)};
     796                 :        8020 :     auto m = u[3] ? 4 : u[2] ? 3 : u[1] ? 2 : u[0] ? 1 : 0;
     797                 :        8020 :     auto n = v[3] ? 4 : v[2] ? 3 : v[1] ? 2 : v[0] ? 1 : 0;
     798                 :        8020 :     if (m == 0 || n == 0) //Shouldn't happen
     799                 :           0 :         return;
     800                 :        8020 :     if (n == 1)
     801                 :        7938 :         return div_single_leg (u, m, v[0], q, r);
     802                 :             : 
     803                 :          82 :     return div_multi_leg (u, m, v, n, q, r);
     804                 :             : }
     805                 :             : 
     806                 :             : GncInt128&
     807                 :     1109667 : GncInt128::operator/= (const GncInt128& b) noexcept
     808                 :             : {
     809                 :     1109667 :     GncInt128 q {}, r {};
     810                 :     1109667 :     div(b, q, r);
     811                 :     1109667 :     std::swap (*this, q);
     812                 :     1109667 :     return *this;
     813                 :             : }
     814                 :             : 
     815                 :             : GncInt128&
     816                 :      132555 : GncInt128::operator%= (const GncInt128& b) noexcept
     817                 :             : {
     818                 :      132555 :     GncInt128 q {}, r {};
     819                 :      132555 :     div(b, q, r);
     820                 :      132555 :     std::swap (*this, r);
     821                 :      132555 :     if (q.isNan())
     822                 :           0 :         m_hi = set_flags(m_hi, (get_flags(m_hi) | NaN));
     823                 :      132555 :     return *this;
     824                 :             : }
     825                 :             : 
     826                 :             : GncInt128&
     827                 :     2738005 : GncInt128::operator&= (const GncInt128& b) noexcept
     828                 :             : {
     829                 :     2738005 :     auto flags = get_flags(m_hi);
     830                 :     2738005 :     if (b.isOverflow())
     831                 :           0 :         flags |= overflow;
     832                 :     2738005 :     if (b.isNan())
     833                 :           0 :         flags |= NaN;
     834                 :     2738005 :     m_hi = set_flags(m_hi, flags);
     835                 :     2738005 :     if (isOverflow() || isNan())
     836                 :           0 :         return *this;
     837                 :     2738005 :     auto hi = get_num(m_hi);
     838                 :     2738005 :     hi &= get_num(b.m_hi);
     839                 :     2738005 :     m_lo &= b.m_lo;
     840                 :     2738005 :     m_hi = set_flags(hi, flags);
     841                 :     2738005 :     return *this;
     842                 :             : }
     843                 :             : 
     844                 :             : GncInt128&
     845                 :           0 : GncInt128::operator|= (const GncInt128& b) noexcept
     846                 :             : {
     847                 :           0 :     auto flags = get_flags(m_hi);
     848                 :           0 :     auto hi = get_num(m_hi);
     849                 :           0 :     hi  ^= get_num(b.m_hi);
     850                 :           0 :     m_hi = set_flags(hi, flags);
     851                 :           0 :     m_lo ^= b.m_lo;
     852                 :           0 :     return *this;
     853                 :             : }
     854                 :             : 
     855                 :             : GncInt128&
     856                 :     1213552 : GncInt128::operator^= (const GncInt128& b) noexcept
     857                 :             : {
     858                 :     1213552 :     auto flags = get_flags(m_hi);
     859                 :     1213552 :     if (b.isOverflow())
     860                 :           0 :         flags |= overflow;
     861                 :     1213552 :     if (b.isNan())
     862                 :           0 :         flags |= NaN;
     863                 :     1213552 :     m_hi = set_flags(m_hi, flags);
     864                 :     1213552 :     if (isOverflow() || isNan())
     865                 :           0 :         return *this;
     866                 :     1213552 :     auto hi = get_num(m_hi);
     867                 :     1213552 :     hi ^= get_num(b.m_hi);
     868                 :     1213552 :     m_hi = set_flags(hi, flags);
     869                 :     1213552 :     m_lo ^= b.m_lo;
     870                 :     1213552 :     return *this;
     871                 :             : }
     872                 :             : 
     873                 :             : static const uint8_t dec_array_size {5};
     874                 :             : /* Convert a uint128 represented as a binary number into 4 10-digit decimal
     875                 :             :  * equivalents. Adapted from Douglas W. Jones, "Binary to Decimal Conversion in
     876                 :             :  * Limited Precision", http://homepage.cs.uiowa.edu/~jones/bcd/decimal.html,
     877                 :             :  * accessed 28 Oct 2014. */
     878                 :             : static void
     879                 :           0 : decimal_from_binary (uint64_t d[dec_array_size], uint64_t hi, uint64_t lo)
     880                 :             : {
     881                 :             :     /* Coefficients are the values of 2^96, 2^64, and 2^32 divided into 8-digit
     882                 :             :      * segments:
     883                 :             :      * 2^96 =               79228,16251426,43375935,43950336
     884                 :             :      * 2^64 =                         1844,67440737,09551616
     885                 :             :      * 2^32 =                                    42,94967296
     886                 :             :      */
     887                 :           0 :     const uint8_t coeff_array_size = dec_array_size - 1;
     888                 :           0 :     const uint32_t coeff_3 [coeff_array_size] {79228, 16251426, 43375935, 43950336};
     889                 :           0 :     const uint32_t coeff_2 [coeff_array_size] {0, 1844, 67440737, 9551616};
     890                 :           0 :     const uint32_t coeff_1 [coeff_array_size] {0, 0, 42, 94967296};
     891                 :           0 :     const uint32_t bin_mask {0xffffffff};
     892                 :           0 :     const uint32_t dec_div {UINT32_C(100000000)};
     893                 :           0 :     const uint8_t last {dec_array_size - 1};
     894                 :             : 
     895                 :           0 :     d[0] = lo & bin_mask;
     896                 :           0 :     d[1] = (lo >> 32) & bin_mask;
     897                 :           0 :     d[2] = hi & bin_mask;
     898                 :           0 :     d[3] = (hi >> 32) & bin_mask;
     899                 :             : 
     900                 :           0 :     d[0] += coeff_3[3] * d[3] + coeff_2[3] * d[2] + coeff_1[3] * d[1];
     901                 :           0 :     uint64_t q {d[0] / dec_div};
     902                 :           0 :     d[0] %= dec_div;
     903                 :             : 
     904                 :           0 :     for (int i {1}; i < coeff_array_size; ++i)
     905                 :             :     {
     906                 :           0 :         int j = coeff_array_size - i - 1;
     907                 :           0 :         d[i] = q + coeff_3[j] * d[3] + coeff_2[j] * d[2] + coeff_1[j] * d[1];
     908                 :           0 :         q = d[i] / dec_div;
     909                 :           0 :         d[i] %= dec_div;
     910                 :             :     }
     911                 :           0 :     d[last] = q;
     912                 :           0 :     return;
     913                 :             : }
     914                 :             : 
     915                 :             : static const uint8_t char_buf_size {41}; //39 digits plus sign and trailing null
     916                 :             : 
     917                 :             : char*
     918                 :           0 : GncInt128::asCharBufR(char* buf, uint32_t size) const noexcept
     919                 :             : {
     920                 :           0 :     if (isOverflow())
     921                 :             :     {
     922                 :           0 :         snprintf (buf, size, "%s", "Overflow");
     923                 :           0 :         return buf;
     924                 :             :     }
     925                 :           0 :     if (isNan())
     926                 :             :     {
     927                 :           0 :         snprintf (buf, size, "%s", "NaN");
     928                 :           0 :         return buf;
     929                 :             :     }
     930                 :           0 :     if (isZero())
     931                 :             :     {
     932                 :           0 :         snprintf (buf, size, "%d", 0);
     933                 :           0 :         return buf;
     934                 :             :     }
     935                 :           0 :     uint64_t d[dec_array_size] {};
     936                 :           0 :     decimal_from_binary(d, get_num(m_hi), m_lo);
     937                 :           0 :     char* next = buf;
     938                 :           0 :     char neg {'-'};
     939                 :             : 
     940                 :           0 :     if (isNeg()) *(next++) = neg;
     941                 :           0 :     bool trailing {false};
     942                 :           0 :     for (unsigned int i {dec_array_size}; i; --i)
     943                 :           0 :         if (d[i - 1] || trailing)
     944                 :             :         {
     945                 :           0 :             uint32_t new_size = size - (next - buf);
     946                 :           0 :             if (trailing)
     947                 :           0 :                 next += snprintf (next, new_size, "%8.8" PRIu64, d[i - 1]);
     948                 :             :             else
     949                 :           0 :                 next += snprintf (next, new_size, "%" PRIu64, d[i - 1]);
     950                 :             : 
     951                 :           0 :             trailing = true;
     952                 :             :         }
     953                 :             : 
     954                 :           0 :     return buf;
     955                 :             : }
     956                 :             : 
     957                 :             : std::ostream&
     958                 :           0 : operator<< (std::ostream& stream, const GncInt128& a) noexcept
     959                 :             : {
     960                 :           0 :     char buf[char_buf_size] {};
     961                 :           0 :     stream << a.asCharBufR (buf, char_buf_size - 1);
     962                 :           0 :     return stream;
     963                 :             : }
     964                 :             : 
     965                 :             : bool
     966                 :       48223 : operator== (const GncInt128& a, const GncInt128& b) noexcept
     967                 :             : {
     968                 :       48223 :     return a.cmp(b) == 0;
     969                 :             : }
     970                 :             : 
     971                 :             : bool
     972                 :      761645 : operator!= (const GncInt128& a, const GncInt128& b) noexcept
     973                 :             : {
     974                 :      761645 :     return a.cmp(b) != 0;
     975                 :             : }
     976                 :             : 
     977                 :             : bool
     978                 :     1246457 : operator< (const GncInt128& a, const GncInt128& b) noexcept
     979                 :             : {
     980                 :     1246457 :     return a.cmp(b) < 0;
     981                 :             : }
     982                 :             : 
     983                 :             : bool
     984                 :       34213 : operator> (const GncInt128& a, const GncInt128& b) noexcept
     985                 :             : {
     986                 :       34213 :     return a.cmp(b) > 0;
     987                 :             : }
     988                 :             : 
     989                 :             : bool
     990                 :           0 : operator<= (const GncInt128& a, const GncInt128& b) noexcept
     991                 :             : {
     992                 :           0 :     return a.cmp(b) <= 0;
     993                 :             : }
     994                 :             : 
     995                 :             : bool
     996                 :          62 : operator>= (const GncInt128& a, const GncInt128& b) noexcept
     997                 :             : {
     998                 :          62 :     return a.cmp(b) >= 0;
     999                 :             : }
    1000                 :             : 
    1001                 :             : GncInt128
    1002                 :      257572 : operator+ (GncInt128 a, const GncInt128& b) noexcept
    1003                 :             : {
    1004                 :      257572 :     a += b;
    1005                 :      257572 :     return a;
    1006                 :             : }
    1007                 :             : 
    1008                 :             : GncInt128
    1009                 :      399775 : operator- (GncInt128 a, const GncInt128& b) noexcept
    1010                 :             : {
    1011                 :      399775 :     a -= b;
    1012                 :      399775 :     return a;
    1013                 :             : }
    1014                 :             : GncInt128
    1015                 :      886218 : operator* (GncInt128 a, const GncInt128& b) noexcept
    1016                 :             : {
    1017                 :      886218 :     a *= b;
    1018                 :      886218 :     return a;
    1019                 :             : }
    1020                 :             : 
    1021                 :             : GncInt128
    1022                 :      980740 : operator/ (GncInt128 a, const GncInt128& b) noexcept
    1023                 :             : {
    1024                 :      980740 :     a /= b;
    1025                 :      980740 :     return a;
    1026                 :             : }
    1027                 :             : 
    1028                 :             : GncInt128
    1029                 :      132555 : operator% (GncInt128 a, const GncInt128& b) noexcept
    1030                 :             : {
    1031                 :      132555 :     a %= b;
    1032                 :      132555 :     return a;
    1033                 :             : }
    1034                 :             : 
    1035                 :             : GncInt128
    1036                 :     2738005 : operator& (GncInt128 a, const GncInt128& b) noexcept
    1037                 :             : {
    1038                 :     2738005 :     a &= b;
    1039                 :     2738005 :     return a;
    1040                 :             : }
    1041                 :             : 
    1042                 :             : GncInt128
    1043                 :           0 : operator| (GncInt128 a, const GncInt128& b) noexcept
    1044                 :             : {
    1045                 :           0 :     a |= b;
    1046                 :           0 :     return a;
    1047                 :             : }
    1048                 :             : 
    1049                 :             : GncInt128
    1050                 :     1213552 : operator^ (GncInt128 a, const GncInt128& b) noexcept
    1051                 :             : {
    1052                 :     1213552 :     a ^= b;
    1053                 :     1213552 :     return a;
    1054                 :             : }
    1055                 :             : 
    1056                 :             : GncInt128
    1057                 :      361870 : operator<< (GncInt128 a, unsigned int b) noexcept
    1058                 :             : {
    1059                 :      361870 :     a <<= b;
    1060                 :      361870 :     return a;
    1061                 :             : }
    1062                 :             : 
    1063                 :             : GncInt128
    1064                 :          67 : operator>> (GncInt128 a, unsigned int b) noexcept
    1065                 :             : {
    1066                 :          67 :     a >>= b;
    1067                 :          67 :     return a;
    1068                 :             : }
        

Generated by: LCOV version 2.0-1