LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/util - integer_cln_imp.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 222 242 91.7 %
Date: 2026-01-20 13:04:20 Functions: 63 69 91.3 %
Branches: 77 143 53.8 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Aina Niemetz, Tim King, Gereon Kremer
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * A multiprecision integer constant; wraps a CLN multiprecision integer.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <cln/input.h>
      17                 :            : #include <cln/integer_io.h>
      18                 :            : #include <cln/modinteger.h>
      19                 :            : #include <cln/numtheory.h>
      20                 :            : 
      21                 :            : #include <iostream>
      22                 :            : #include <sstream>
      23                 :            : #include <string>
      24                 :            : 
      25                 :            : #include "base/cvc5config.h"
      26                 :            : #include "util/integer.h"
      27                 :            : 
      28                 :            : #ifndef CVC5_CLN_IMP
      29                 :            : #error "This source should only ever be built if CVC5_CLN_IMP is on !"
      30                 :            : #endif /* CVC5_CLN_IMP */
      31                 :            : 
      32                 :            : #include "base/check.h"
      33                 :            : 
      34                 :            : using namespace std;
      35                 :            : 
      36                 :            : namespace cvc5::internal {
      37                 :            : 
      38                 :            : signed int Integer::s_fastSignedIntMin = -(1 << 29);
      39                 :            : signed int Integer::s_fastSignedIntMax = (1 << 29) - 1;
      40                 :            : signed long Integer::s_slowSignedIntMin =
      41                 :            :     (signed long)std::numeric_limits<signed int>::min();
      42                 :            : signed long Integer::s_slowSignedIntMax =
      43                 :            :     (signed long)std::numeric_limits<signed int>::max();
      44                 :            : 
      45                 :            : unsigned int Integer::s_fastUnsignedIntMax = (1 << 29) - 1;
      46                 :            : unsigned long Integer::s_slowUnsignedIntMax =
      47                 :            :     (unsigned long)std::numeric_limits<unsigned int>::max();
      48                 :            : 
      49                 :            : unsigned long Integer::s_signedLongMin =
      50                 :            :     std::numeric_limits<signed long>::min();
      51                 :            : unsigned long Integer::s_signedLongMax =
      52                 :            :     std::numeric_limits<signed long>::max();
      53                 :            : unsigned long Integer::s_unsignedLongMax =
      54                 :            :     std::numeric_limits<unsigned long>::max();
      55                 :            : 
      56                 :   57064200 : Integer& Integer::operator=(const Integer& x)
      57                 :            : {
      58         [ -  + ]:   57064200 :   if (this == &x) return *this;
      59                 :   57064200 :   d_value = x.d_value;
      60                 :   57064200 :   return *this;
      61                 :            : }
      62                 :            : 
      63                 :   32286800 : bool Integer::operator==(const Integer& y) const
      64                 :            : {
      65                 :   32286800 :   return d_value == y.d_value;
      66                 :            : }
      67                 :            : 
      68                 :    5551380 : Integer Integer::operator-() const { return Integer(-(d_value)); }
      69                 :            : 
      70                 :    1103360 : bool Integer::operator!=(const Integer& y) const
      71                 :            : {
      72                 :    1103360 :   return d_value != y.d_value;
      73                 :            : }
      74                 :            : 
      75                 :    9017720 : bool Integer::operator<(const Integer& y) const { return d_value < y.d_value; }
      76                 :            : 
      77                 :    5537960 : bool Integer::operator<=(const Integer& y) const
      78                 :            : {
      79                 :    5537960 :   return d_value <= y.d_value;
      80                 :            : }
      81                 :            : 
      82                 :    7951440 : bool Integer::operator>(const Integer& y) const { return d_value > y.d_value; }
      83                 :            : 
      84                 :   12360100 : bool Integer::operator>=(const Integer& y) const
      85                 :            : {
      86                 :   12360100 :   return d_value >= y.d_value;
      87                 :            : }
      88                 :            : 
      89                 :   36062000 : Integer Integer::operator+(const Integer& y) const
      90                 :            : {
      91                 :   72124100 :   return Integer(d_value + y.d_value);
      92                 :            : }
      93                 :            : 
      94                 :     112194 : Integer& Integer::operator+=(const Integer& y)
      95                 :            : {
      96                 :     112194 :   d_value += y.d_value;
      97                 :     112194 :   return *this;
      98                 :            : }
      99                 :            : 
     100                 :    2675910 : Integer Integer::operator-(const Integer& y) const
     101                 :            : {
     102                 :    5351820 :   return Integer(d_value - y.d_value);
     103                 :            : }
     104                 :            : 
     105                 :       3126 : Integer& Integer::operator-=(const Integer& y)
     106                 :            : {
     107                 :       3126 :   d_value -= y.d_value;
     108                 :       3126 :   return *this;
     109                 :            : }
     110                 :            : 
     111                 :   12535700 : Integer Integer::operator*(const Integer& y) const
     112                 :            : {
     113                 :   25071500 :   return Integer(d_value * y.d_value);
     114                 :            : }
     115                 :            : 
     116                 :       5214 : Integer& Integer::operator*=(const Integer& y)
     117                 :            : {
     118                 :       5214 :   d_value *= y.d_value;
     119                 :       5214 :   return *this;
     120                 :            : }
     121                 :            : 
     122                 :     520030 : Integer Integer::bitwiseOr(const Integer& y) const
     123                 :            : {
     124                 :    1040060 :   return Integer(cln::logior(d_value, y.d_value));
     125                 :            : }
     126                 :            : 
     127                 :    1727000 : Integer Integer::bitwiseAnd(const Integer& y) const
     128                 :            : {
     129                 :    3454000 :   return Integer(cln::logand(d_value, y.d_value));
     130                 :            : }
     131                 :            : 
     132                 :       2965 : Integer Integer::bitwiseXor(const Integer& y) const
     133                 :            : {
     134                 :       5930 :   return Integer(cln::logxor(d_value, y.d_value));
     135                 :            : }
     136                 :            : 
     137                 :   28679900 : Integer Integer::bitwiseNot() const { return Integer(cln::lognot(d_value)); }
     138                 :            : 
     139                 :   27529000 : Integer Integer::multiplyByPow2(uint32_t pow) const
     140                 :            : {
     141                 :   27529000 :   cln::cl_I ipow(pow);
     142                 :   82587100 :   return Integer(d_value << ipow);
     143                 :            : }
     144                 :            : 
     145                 :     136943 : bool Integer::isBitSet(uint32_t i) const
     146                 :            : {
     147                 :     136943 :   return !extractBitRange(1, i).isZero();
     148                 :            : }
     149                 :            : 
     150                 :       2269 : void Integer::setBit(uint32_t i, bool value)
     151                 :            : {
     152                 :       4538 :   cln::cl_I mask(1);
     153                 :       2269 :   mask = mask << i;
     154         [ +  + ]:       2269 :   if (value)
     155                 :            :   {
     156                 :       2255 :     d_value = cln::logior(d_value, mask);
     157                 :            :   }
     158                 :            :   else
     159                 :            :   {
     160                 :         14 :     mask = cln::lognot(mask);
     161                 :         14 :     d_value = cln::logand(d_value, mask);
     162                 :            :   }
     163                 :       2269 : }
     164                 :            : 
     165                 :    1498680 : Integer Integer::oneExtend(uint32_t size, uint32_t amount) const
     166                 :            : {
     167 [ -  + ][ -  + ]:    1498680 :   Assert((*this) < Integer(1).multiplyByPow2(size));
                 [ -  - ]
     168                 :    1498680 :   cln::cl_byte range(amount, size);
     169                 :    4496040 :   cln::cl_I allones = (cln::cl_I(1) << (size + amount)) - 1;  // 2^size - 1
     170                 :    1498680 :   Integer temp(allones);
     171                 :            : 
     172                 :    4496040 :   return Integer(cln::deposit_field(allones, d_value, range));
     173                 :            : }
     174                 :            : 
     175                 :   26250000 : uint32_t Integer::toUnsignedInt() const { return cln::cl_I_to_uint(d_value); }
     176                 :            : 
     177                 :   26791200 : Integer Integer::extractBitRange(uint32_t bitCount, uint32_t low) const
     178                 :            : {
     179                 :   26791200 :   cln::cl_byte range(bitCount, low);
     180                 :   53582300 :   return Integer(cln::ldb(d_value, range));
     181                 :            : }
     182                 :            : 
     183                 :      60935 : Integer Integer::floorDivideQuotient(const Integer& y) const
     184                 :            : {
     185                 :     121870 :   return Integer(cln::floor1(d_value, y.d_value));
     186                 :            : }
     187                 :            : 
     188                 :     158648 : Integer Integer::floorDivideRemainder(const Integer& y) const
     189                 :            : {
     190                 :     317296 :   return Integer(cln::floor2(d_value, y.d_value).remainder);
     191                 :            : }
     192                 :            : 
     193                 :     164299 : void Integer::floorQR(Integer& q,
     194                 :            :                       Integer& r,
     195                 :            :                       const Integer& x,
     196                 :            :                       const Integer& y)
     197                 :            : {
     198                 :     328598 :   cln::cl_I_div_t res = cln::floor2(x.d_value, y.d_value);
     199                 :     164299 :   q.d_value = res.quotient;
     200                 :     164299 :   r.d_value = res.remainder;
     201                 :     164299 : }
     202                 :            : 
     203                 :          0 : Integer Integer::ceilingDivideQuotient(const Integer& y) const
     204                 :            : {
     205                 :          0 :   return Integer(cln::ceiling1(d_value, y.d_value));
     206                 :            : }
     207                 :            : 
     208                 :          0 : Integer Integer::ceilingDivideRemainder(const Integer& y) const
     209                 :            : {
     210                 :          0 :   return Integer(cln::ceiling2(d_value, y.d_value).remainder);
     211                 :            : }
     212                 :            : 
     213                 :     162823 : void Integer::euclidianQR(Integer& q,
     214                 :            :                           Integer& r,
     215                 :            :                           const Integer& x,
     216                 :            :                           const Integer& y)
     217                 :            : {
     218                 :            :   // compute the floor and then fix the value up if needed.
     219                 :     162823 :   floorQR(q, r, x, y);
     220                 :            : 
     221         [ +  + ]:     162823 :   if (r.strictlyNegative())
     222                 :            :   {
     223                 :            :     // if r < 0
     224                 :            :     // abs(r) < abs(y)
     225                 :            :     // - abs(y) < r < 0, then 0 < r + abs(y) < abs(y)
     226                 :            :     // n = y * q + r
     227                 :            :     // n = y * q - abs(y) + r + abs(y)
     228         [ -  + ]:         30 :     if (r.sgn() >= 0)
     229                 :            :     {
     230                 :            :       // y = abs(y)
     231                 :            :       // n = y * q - y + r + y
     232                 :            :       // n = y * (q-1) + (r+y)
     233                 :          0 :       q -= 1;
     234                 :          0 :       r += y;
     235                 :            :     }
     236                 :            :     else
     237                 :            :     {
     238                 :            :       // y = -abs(y)
     239                 :            :       // n = y * q + y + r - y
     240                 :            :       // n = y * (q+1) + (r-y)
     241                 :         30 :       q += 1;
     242                 :         30 :       r -= y;
     243                 :            :     }
     244                 :            :   }
     245                 :     162823 : }
     246                 :            : 
     247                 :       1783 : Integer Integer::euclidianDivideQuotient(const Integer& y) const
     248                 :            : {
     249                 :       3566 :   Integer q, r;
     250                 :       1783 :   euclidianQR(q, r, *this, y);
     251                 :       3566 :   return q;
     252                 :            : }
     253                 :            : 
     254                 :     161032 : Integer Integer::euclidianDivideRemainder(const Integer& y) const
     255                 :            : {
     256                 :     322064 :   Integer q, r;
     257                 :     161032 :   euclidianQR(q, r, *this, y);
     258                 :     322064 :   return r;
     259                 :            : }
     260                 :            : 
     261                 :          0 : Integer Integer::exactQuotient(const Integer& y) const
     262                 :            : {
     263                 :          0 :   Assert(y.divides(*this));
     264                 :          0 :   return Integer(cln::exquo(d_value, y.d_value));
     265                 :            : }
     266                 :            : 
     267                 :   98529300 : Integer Integer::modByPow2(uint32_t exp) const
     268                 :            : {
     269                 :   98529300 :   cln::cl_byte range(exp, 0);
     270                 :  197059000 :   return Integer(cln::ldb(d_value, range));
     271                 :            : }
     272                 :            : 
     273                 :     453350 : Integer Integer::divByPow2(uint32_t exp) const { return d_value >> exp; }
     274                 :            : 
     275                 :     153214 : Integer Integer::pow(uint32_t exp) const
     276                 :            : {
     277         [ +  + ]:     153214 :   if (exp == 0)
     278                 :            :   {
     279                 :        452 :     return Integer(1);
     280                 :            :   }
     281                 :            :   else
     282                 :            :   {
     283 [ -  + ][ -  + ]:     152762 :     Assert(exp > 0);
                 [ -  - ]
     284                 :     305524 :     cln::cl_I result = cln::expt_pos(d_value, exp);
     285                 :     152762 :     return Integer(result);
     286                 :            :   }
     287                 :            : }
     288                 :            : 
     289                 :    5219230 : Integer Integer::gcd(const Integer& y) const
     290                 :            : {
     291                 :   10438500 :   cln::cl_I result = cln::gcd(d_value, y.d_value);
     292                 :   10438500 :   return Integer(result);
     293                 :            : }
     294                 :            : 
     295                 :   17722000 : Integer Integer::lcm(const Integer& y) const
     296                 :            : {
     297                 :   35444100 :   cln::cl_I result = cln::lcm(d_value, y.d_value);
     298                 :   35444100 :   return Integer(result);
     299                 :            : }
     300                 :            : 
     301                 :       7815 : Integer Integer::modAdd(const Integer& y, const Integer& m) const
     302                 :            : {
     303                 :      15630 :   cln::cl_modint_ring ry = cln::find_modint_ring(m.d_value);
     304                 :      15630 :   cln::cl_MI xm = ry->canonhom(d_value);
     305                 :      15630 :   cln::cl_MI ym = ry->canonhom(y.d_value);
     306                 :       7815 :   cln::cl_MI res = xm + ym;
     307                 :      23445 :   return Integer(ry->retract(res));
     308                 :            : }
     309                 :            : 
     310                 :       8791 : Integer Integer::modMultiply(const Integer& y, const Integer& m) const
     311                 :            : {
     312                 :      17582 :   cln::cl_modint_ring ry = cln::find_modint_ring(m.d_value);
     313                 :      17582 :   cln::cl_MI xm = ry->canonhom(d_value);
     314                 :      17582 :   cln::cl_MI ym = ry->canonhom(y.d_value);
     315                 :       8791 :   cln::cl_MI res = xm * ym;
     316                 :      26373 :   return Integer(ry->retract(res));
     317                 :            : }
     318                 :            : 
     319                 :        429 : Integer Integer::modInverse(const Integer& m) const
     320                 :            : {
     321 [ -  + ][ -  + ]:        429 :   Assert(m > 0) << "m must be greater than zero";
                 [ -  - ]
     322                 :        858 :   cln::cl_modint_ring ry = cln::find_modint_ring(m.d_value);
     323                 :        858 :   cln::cl_MI xm = ry->canonhom(d_value);
     324                 :            :   /* normalize to modulo m for coprime check */
     325                 :        858 :   cln::cl_I x = ry->retract(xm);
     326                 :        429 :   if (x == 0 || cln::gcd(x, m.d_value) != 1)
     327                 :            :   {
     328                 :         13 :     return Integer(-1);
     329                 :            :   }
     330                 :        416 :   cln::cl_MI res = cln::recip(xm);
     331                 :        832 :   return Integer(ry->retract(res));
     332                 :            : }
     333                 :            : 
     334                 :      56893 : bool Integer::divides(const Integer& y) const
     335                 :            : {
     336                 :     113786 :   cln::cl_I result = cln::rem(y.d_value, d_value);
     337                 :     113786 :   return cln::zerop(result);
     338                 :            : }
     339                 :            : 
     340         [ +  + ]:   27984400 : Integer Integer::abs() const { return d_value >= 0 ? *this : -*this; }
     341                 :            : 
     342                 :     309748 : std::string Integer::toString(int base) const
     343                 :            : {
     344                 :     619496 :   std::stringstream ss;
     345 [ +  - ][ +  + ]:     309748 :   switch (base)
                    [ - ]
     346                 :            :   {
     347                 :     173816 :     case 2: fprintbinary(ss, d_value); break;
     348                 :          0 :     case 8: fprintoctal(ss, d_value); break;
     349                 :     135466 :     case 10: fprintdecimal(ss, d_value); break;
     350                 :        466 :     case 16: fprinthexadecimal(ss, d_value); break;
     351                 :          0 :     default: throw Exception("Unhandled base in Integer::toString()");
     352                 :            :   }
     353                 :     309748 :   std::string output = ss.str();
     354         [ +  + ]:    2271160 :   for (unsigned i = 0; i <= output.length(); ++i)
     355                 :            :   {
     356         [ +  + ]:    1961420 :     if (isalpha(output[i]))
     357                 :            :     {
     358                 :        464 :       output.replace(i, 1, 1, tolower(output[i]));
     359                 :            :     }
     360                 :            :   }
     361                 :            : 
     362                 :     619496 :   return output;
     363                 :            : }
     364                 :            : 
     365                 :   19460700 : int Integer::sgn() const
     366                 :            : {
     367                 :   38921400 :   cln::cl_I sgn = cln::signum(d_value);
     368                 :   38921400 :   return cln::cl_I_to_int(sgn);
     369                 :            : }
     370                 :            : 
     371                 :         61 : bool Integer::strictlyPositive() const { return cln::plusp(d_value); }
     372                 :            : 
     373                 :     382754 : bool Integer::strictlyNegative() const { return cln::minusp(d_value); }
     374                 :            : 
     375                 :    7169810 : bool Integer::isZero() const { return cln::zerop(d_value); }
     376                 :            : 
     377                 :   24116800 : bool Integer::isOne() const { return d_value == 1; }
     378                 :            : 
     379                 :          0 : bool Integer::isNegativeOne() const { return d_value == -1; }
     380                 :            : 
     381                 :     587993 : void Integer::parseInt(const std::string& s, unsigned base)
     382                 :            : {
     383                 :            :   cln::cl_read_flags flags;
     384                 :     587993 :   flags.syntax = cln::syntax_integer;
     385                 :     587993 :   flags.lsyntax = cln::lsyntax_standard;
     386                 :     587993 :   flags.rational_base = base;
     387         [ +  + ]:     587993 :   if (base == 0)
     388                 :            :   {
     389                 :            :     // infer base in a manner consistent with GMP
     390         [ +  + ]:          8 :     if (s[0] == '0')
     391                 :            :     {
     392                 :          5 :       flags.lsyntax = cln::lsyntax_commonlisp;
     393                 :          6 :       std::string st = s;
     394 [ +  - ][ +  + ]:          5 :       if (s[1] == 'X' || s[1] == 'x')
                 [ +  + ]
     395                 :            :       {
     396                 :          2 :         st.replace(0, 2, "#x");
     397                 :            :       }
     398 [ +  - ][ +  + ]:          3 :       else if (s[1] == 'B' || s[1] == 'b')
                 [ +  + ]
     399                 :            :       {
     400                 :          2 :         st.replace(0, 2, "#b");
     401                 :            :       }
     402                 :            :       else
     403                 :            :       {
     404                 :          1 :         st.replace(0, 1, "#o");
     405                 :            :       }
     406                 :          5 :       readInt(flags, st, base);
     407                 :          4 :       return;
     408                 :            :     }
     409                 :            :     else
     410                 :            :     {
     411                 :          3 :       flags.rational_base = 10;
     412                 :            :     }
     413                 :            :   }
     414                 :     587988 :   readInt(flags, s, base);
     415                 :            : }
     416                 :            : 
     417                 :     587993 : void Integer::readInt(const cln::cl_read_flags& flags,
     418                 :            :                       const std::string& s,
     419                 :            :                       unsigned base)
     420                 :            : {
     421                 :            :   try
     422                 :            :   {
     423                 :            :     // Removing leading zeroes, CLN has a bug for these inputs up to and
     424                 :            :     // including CLN v1.3.2.
     425                 :            :     // See
     426                 :            :     // http://www.ginac.de/CLN/cln.git/?a=commit;h=4a477b0cc3dd7fbfb23b25090ff8c8869c8fa21a
     427                 :            :     // for details.
     428                 :     587993 :     size_t pos = s.find_first_not_of('0');
     429         [ +  + ]:     587993 :     if (pos == std::string::npos)
     430                 :            :     {
     431                 :     119802 :       d_value = cln::read_integer(flags, "0", NULL, NULL);
     432                 :            :     }
     433                 :            :     else
     434                 :            :     {
     435                 :     468191 :       const char* cstr = s.c_str();
     436                 :     468191 :       const char* start = cstr + pos;
     437                 :     468191 :       const char* end = cstr + s.length();
     438                 :     468191 :       d_value = cln::read_integer(flags, start, end, NULL);
     439                 :            :     }
     440                 :            :   }
     441                 :        798 :   catch (...)
     442                 :            :   {
     443                 :        798 :     std::stringstream ss;
     444                 :        399 :     ss << "Integer() failed to parse value \"" << s << "\" in base " << base;
     445                 :        399 :     throw std::invalid_argument(ss.str());
     446                 :            :   }
     447                 :     587594 : }
     448                 :            : 
     449                 :        782 : bool Integer::fitsSignedInt() const
     450                 :            : {
     451                 :            :   // http://www.ginac.de/CLN/cln.html#Conversions
     452                 :            :   // TODO improve performance
     453 [ -  + ][ -  + ]:        782 :   Assert(s_slowSignedIntMin <= s_fastSignedIntMin);
                 [ -  - ]
     454 [ -  + ][ -  + ]:        782 :   Assert(s_fastSignedIntMin <= s_fastSignedIntMax);
                 [ -  - ]
     455 [ -  + ][ -  + ]:        782 :   Assert(s_fastSignedIntMax <= s_slowSignedIntMax);
                 [ -  - ]
     456                 :            : 
     457                 :        782 :   return (d_value <= s_fastSignedIntMax || d_value <= s_slowSignedIntMax)
     458                 :       1564 :          && (d_value >= s_fastSignedIntMin || d_value >= s_slowSignedIntMax);
     459                 :            : }
     460                 :            : 
     461                 :   19124400 : bool Integer::fitsUnsignedInt() const
     462                 :            : {
     463                 :            :   // TODO improve performance
     464 [ -  + ][ -  + ]:   19124400 :   Assert(s_fastUnsignedIntMax <= s_slowUnsignedIntMax);
                 [ -  - ]
     465                 :   38248700 :   return sgn() >= 0
     466 [ +  + ][ +  + ]:   38249500 :          && (d_value <= s_fastUnsignedIntMax
                 [ -  - ]
     467 [ +  + ][ +  + ]:   38249500 :              || d_value <= s_slowUnsignedIntMax);
         [ +  + ][ -  - ]
     468                 :            : }
     469                 :            : 
     470                 :        782 : signed int Integer::getSignedInt() const
     471                 :            : {
     472                 :            :   // ensure there isn't overflow
     473 [ -  + ][ -  + ]:        782 :   Assert(fitsSignedInt()) << "Overflow detected in Integer::getSignedInt()";
                 [ -  - ]
     474                 :        782 :   return cln::cl_I_to_int(d_value);
     475                 :            : }
     476                 :            : 
     477                 :      20517 : unsigned int Integer::getUnsignedInt() const
     478                 :            : {
     479                 :            :   // ensure there isn't overflow
     480 [ -  + ][ -  + ]:      20517 :   Assert(fitsUnsignedInt()) << "Overflow detected in Integer::getUnsignedInt()";
                 [ -  - ]
     481                 :      20517 :   return cln::cl_I_to_uint(d_value);
     482                 :            : }
     483                 :            : 
     484                 :       3509 : long Integer::getLong() const
     485                 :            : {
     486                 :            :   // ensure there isn't overflow
     487 [ -  + ][ -  + ]:       3509 :   Assert(d_value <= std::numeric_limits<long>::max())
                 [ -  - ]
     488                 :          0 :       << "Overflow detected in Integer::getLong()";
     489 [ -  + ][ -  + ]:       3509 :   Assert(d_value >= std::numeric_limits<long>::min())
                 [ -  - ]
     490                 :          0 :       << "Overflow detected in Integer::getLong()";
     491                 :       3509 :   return cln::cl_I_to_long(d_value);
     492                 :            : }
     493                 :            : 
     494                 :       1099 : unsigned long Integer::getUnsignedLong() const
     495                 :            : {
     496                 :            :   // ensure there isn't overflow
     497 [ -  + ][ -  + ]:       1099 :   Assert(d_value <= std::numeric_limits<unsigned long>::max())
                 [ -  - ]
     498                 :          0 :       << "Overflow detected in Integer::getUnsignedLong()";
     499 [ -  + ][ -  + ]:       1099 :   Assert(d_value >= std::numeric_limits<unsigned long>::min())
                 [ -  - ]
     500                 :          0 :       << "Overflow detected in Integer::getUnsignedLong()";
     501                 :       1099 :   return cln::cl_I_to_ulong(d_value);
     502                 :            : }
     503                 :            : 
     504                 :       1293 : int64_t Integer::getSigned64() const
     505                 :            : {
     506                 :            :   if constexpr (sizeof(int64_t) == sizeof(signed long int))
     507                 :            :   {
     508                 :       1293 :     return getLong();
     509                 :            :   }
     510                 :            :   else
     511                 :            :   {
     512                 :            :     if (std::numeric_limits<long>::min() <= d_value
     513                 :            :         && d_value <= std::numeric_limits<long>::max())
     514                 :            :     {
     515                 :            :       return getLong();
     516                 :            :     }
     517                 :            :     // ensure there isn't overflow
     518                 :            :     Assert(d_value <= std::numeric_limits<int64_t>::max())
     519                 :            :         << "Overflow detected in Integer::getSigned64()";
     520                 :            :     Assert(d_value >= std::numeric_limits<int64_t>::min())
     521                 :            :         << "Overflow detected in Integer::getSigned64()";
     522                 :            :     return std::stoll(toString());
     523                 :            :   }
     524                 :            : }
     525                 :       1067 : uint64_t Integer::getUnsigned64() const
     526                 :            : {
     527                 :            :   if constexpr (sizeof(uint64_t) == sizeof(unsigned long int))
     528                 :            :   {
     529                 :       1067 :     return getUnsignedLong();
     530                 :            :   }
     531                 :            :   else
     532                 :            :   {
     533                 :            :     if (std::numeric_limits<unsigned long>::min() <= d_value
     534                 :            :         && d_value <= std::numeric_limits<unsigned long>::max())
     535                 :            :     {
     536                 :            :       return getUnsignedLong();
     537                 :            :     }
     538                 :            :     // ensure there isn't overflow
     539                 :            :     Assert(d_value <= std::numeric_limits<uint64_t>::max())
     540                 :            :         << "Overflow detected in Integer::getSigned64()";
     541                 :            :     Assert(d_value >= std::numeric_limits<uint64_t>::min())
     542                 :            :         << "Overflow detected in Integer::getSigned64()";
     543                 :            :     return std::stoull(toString());
     544                 :            :   }
     545                 :            : }
     546                 :            : 
     547                 :    5089860 : size_t Integer::hash() const { return equal_hashcode(d_value); }
     548                 :            : 
     549                 :      10397 : bool Integer::testBit(unsigned n) const { return cln::logbitp(n, d_value); }
     550                 :            : 
     551                 :     194342 : unsigned Integer::isPow2() const
     552                 :            : {
     553         [ +  + ]:     194342 :   if (d_value <= 0) return 0;
     554                 :            :   // power2p returns n such that d_value = 2^(n-1)
     555                 :     178397 :   return cln::power2p(d_value);
     556                 :            : }
     557                 :            : 
     558                 :     286594 : size_t Integer::length() const
     559                 :            : {
     560                 :     286594 :   int s = sgn();
     561         [ +  + ]:     286594 :   if (s == 0)
     562                 :            :   {
     563                 :      51205 :     return 1;
     564                 :            :   }
     565         [ +  + ]:     235389 :   else if (s < 0)
     566                 :            :   {
     567                 :      96293 :     size_t len = cln::integer_length(d_value);
     568                 :            :     /*If this is -2^n, return len+1 not len to stay consistent with the
     569                 :            :      * definition above! From CLN's documentation of integer_length: This is
     570                 :            :      * the smallest n >= 0 such that -2^n <= x < 2^n. If x > 0, this is the
     571                 :            :      * unique n > 0 such that 2^(n-1) <= x < 2^n.
     572                 :            :      */
     573                 :      96293 :     size_t ord2 = cln::ord2(d_value);
     574         [ +  + ]:      96293 :     return (len == ord2) ? (len + 1) : len;
     575                 :            :   }
     576                 :            :   else
     577                 :            :   {
     578                 :     139096 :     return cln::integer_length(d_value);
     579                 :            :   }
     580                 :            : }
     581                 :            : 
     582                 :      75209 : bool Integer::isProbablePrime() const { return cln::isprobprime(d_value); }
     583                 :            : 
     584                 :         72 : void Integer::extendedGcd(
     585                 :            :     Integer& g, Integer& s, Integer& t, const Integer& a, const Integer& b)
     586                 :            : {
     587                 :         72 :   g.d_value = cln::xgcd(a.d_value, b.d_value, &s.d_value, &t.d_value);
     588                 :         72 : }
     589                 :            : 
     590                 :          0 : const Integer& Integer::min(const Integer& a, const Integer& b)
     591                 :            : {
     592         [ -  - ]:          0 :   return (a <= b) ? a : b;
     593                 :            : }
     594                 :            : 
     595                 :          0 : const Integer& Integer::max(const Integer& a, const Integer& b)
     596                 :            : {
     597         [ -  - ]:          0 :   return (a >= b) ? a : b;
     598                 :            : }
     599                 :            : 
     600                 :     122901 : std::ostream& operator<<(std::ostream& os, const Integer& n)
     601                 :            : {
     602                 :     122901 :   return os << n.toString();
     603                 :            : }
     604                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14