LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/util - bitvector.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 196 197 99.5 %
Date: 2026-04-25 10:46:27 Functions: 44 44 100.0 %
Branches: 120 283 42.4 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * A fixed-size bit-vector, implemented as a wrapper around Integer.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "util/bitvector.h"
      14                 :            : 
      15                 :            : #include "base/check.h"
      16                 :            : #include "util/hash.h"
      17                 :            : 
      18                 :            : namespace cvc5::internal {
      19                 :            : 
      20                 :     129798 : BitVector::BitVector(const std::string& num, uint32_t base)
      21                 :            : {
      22 [ +  + ][ +  + ]:     129798 :   Assert(base == 2 || base == 10 || base == 16);
         [ +  + ][ +  - ]
         [ -  + ][ -  + ]
                 [ -  - ]
      23 [ -  + ][ -  + ]:     129798 :   Assert(num[0] != '-');
                 [ -  - ]
      24                 :     129798 :   d_value = Integer(num, base);
      25 [ -  + ][ -  + ]:     129798 :   Assert(d_value == d_value.abs());
                 [ -  - ]
      26                 :            :   // Compute the length, *without* any negative sign.
      27    [ +  + ][ + ]:     129798 :   switch (base)
      28                 :            :   {
      29                 :          1 :     case 10: d_size = d_value.length(); break;
      30                 :          2 :     case 16: d_size = num.size() * 4; break;
      31                 :     129795 :     default: d_size = num.size();
      32                 :            :   }
      33                 :     129798 : }
      34                 :            : 
      35                 :   87667789 : unsigned BitVector::getSize() const { return d_size; }
      36                 :            : 
      37                 :   63481078 : const Integer& BitVector::getValue() const { return d_value; }
      38                 :            : 
      39                 :      31750 : Integer BitVector::toInteger() const { return d_value; }
      40                 :            : 
      41                 :    3522848 : Integer BitVector::toSignedInteger() const
      42                 :            : {
      43                 :    3522848 :   unsigned size = d_size;
      44                 :    3522848 :   Integer sign_bit = d_value.extractBitRange(1, size - 1);
      45                 :    3522848 :   Integer val = d_value.extractBitRange(size - 1, 0);
      46                 :    7045696 :   Integer res = Integer(-1) * sign_bit.multiplyByPow2(size - 1) + val;
      47                 :    7045696 :   return res;
      48                 :    3522848 : }
      49                 :            : 
      50                 :     174309 : std::string BitVector::toString(unsigned int base) const
      51                 :            : {
      52                 :     174309 :   std::string str = d_value.toString(base);
      53 [ +  + ][ +  + ]:     174309 :   if (base == 2 && d_size > str.size())
                 [ +  + ]
      54                 :            :   {
      55                 :     125400 :     std::string zeroes;
      56         [ +  + ]:    1308502 :     for (unsigned int i = 0; i < d_size - str.size(); ++i)
      57                 :            :     {
      58                 :    1183102 :       zeroes.append("0");
      59                 :            :     }
      60                 :     125400 :     return zeroes + str;
      61                 :     125400 :   }
      62                 :            :   else
      63                 :            :   {
      64                 :      48909 :     return str;
      65                 :            :   }
      66                 :     174309 : }
      67                 :            : 
      68                 :    4530383 : size_t BitVector::hash() const
      69                 :            : {
      70                 :            :   PairHashFunction<size_t, size_t> h;
      71                 :    4530383 :   return h(std::make_pair(d_value.hash(), d_size));
      72                 :            : }
      73                 :            : 
      74                 :       2269 : BitVector& BitVector::setBit(uint32_t i, bool value)
      75                 :            : {
      76 [ -  + ][ -  + ]:       2269 :   Assert(i < d_size);
                 [ -  - ]
      77                 :       2269 :   d_value.setBit(i, value);
      78                 :       2269 :   return *this;
      79                 :            : }
      80                 :            : 
      81                 :     140634 : bool BitVector::isBitSet(uint32_t i) const
      82                 :            : {
      83 [ -  + ][ -  + ]:     140634 :   Assert(i < d_size);
                 [ -  - ]
      84                 :     140634 :   return d_value.isBitSet(i);
      85                 :            : }
      86                 :            : 
      87                 :     194988 : unsigned BitVector::isPow2() const { return d_value.isPow2(); }
      88                 :            : 
      89                 :          2 : bool BitVector::is_one() const { return d_value == Integer(1); }
      90                 :            : 
      91                 :            : /* -----------------------------------------------------------------------
      92                 :            :  * Operators
      93                 :            :  * ----------------------------------------------------------------------- */
      94                 :            : 
      95                 :            : /* String Operations ----------------------------------------------------- */
      96                 :            : 
      97                 :     307565 : BitVector BitVector::concat(const BitVector& other) const
      98                 :            : {
      99                 :     307565 :   return BitVector(d_size + other.d_size,
     100                 :     615130 :                    (d_value.multiplyByPow2(other.d_size)) + other.d_value);
     101                 :            : }
     102                 :            : 
     103                 :     898272 : BitVector BitVector::extract(unsigned high, unsigned low) const
     104                 :            : {
     105 [ -  + ][ -  + ]:     898272 :   Assert(high < d_size);
                 [ -  - ]
     106 [ -  + ][ -  + ]:     898272 :   Assert(low <= high);
                 [ -  - ]
     107                 :     898272 :   return BitVector(high - low + 1,
     108                 :    1796544 :                    d_value.extractBitRange(high - low + 1, low));
     109                 :            : }
     110                 :            : 
     111                 :            : /* (Dis)Equality --------------------------------------------------------- */
     112                 :            : 
     113                 :   19028572 : bool operator==(const BitVector& a, const BitVector& b)
     114                 :            : {
     115         [ -  + ]:   19028572 :   if (a.getSize() != b.getSize()) return false;
     116                 :   19028572 :   return a.getValue() == b.getValue();
     117                 :            : }
     118                 :            : 
     119                 :    1162768 : bool operator!=(const BitVector& a, const BitVector& b)
     120                 :            : {
     121         [ -  + ]:    1162768 :   if (a.getSize() != b.getSize()) return true;
     122                 :    1162768 :   return a.getValue() != b.getValue();
     123                 :            : }
     124                 :            : 
     125                 :            : /* Unsigned Inequality --------------------------------------------------- */
     126                 :            : 
     127                 :       1273 : bool operator<(const BitVector& a, const BitVector& b)
     128                 :            : {
     129                 :       1273 :   return a.getValue() < b.getValue();
     130                 :            : }
     131                 :            : 
     132                 :       2560 : bool operator<=(const BitVector& a, const BitVector& b)
     133                 :            : {
     134                 :       2560 :   return a.getValue() <= b.getValue();
     135                 :            : }
     136                 :            : 
     137                 :        474 : bool operator>(const BitVector& a, const BitVector& b)
     138                 :            : {
     139                 :        474 :   return a.getValue() > b.getValue();
     140                 :            : }
     141                 :            : 
     142                 :        986 : bool operator>=(const BitVector& a, const BitVector& b)
     143                 :            : {
     144                 :        986 :   return a.getValue() >= b.getValue();
     145                 :            : }
     146                 :            : 
     147                 :      58117 : bool BitVector::unsignedLessThan(const BitVector& y) const
     148                 :            : {
     149 [ -  + ][ -  + ]:      58117 :   Assert(d_size == y.d_size);
                 [ -  - ]
     150 [ -  + ][ -  + ]:      58117 :   Assert(d_value >= 0);
                 [ -  - ]
     151 [ -  + ][ -  + ]:      58117 :   Assert(y.d_value >= 0);
                 [ -  - ]
     152                 :      58117 :   return d_value < y.d_value;
     153                 :            : }
     154                 :            : 
     155                 :      13604 : bool BitVector::unsignedLessThanEq(const BitVector& y) const
     156                 :            : {
     157 [ -  + ][ -  + ]:      13604 :   Assert(d_size == y.d_size);
                 [ -  - ]
     158 [ -  + ][ -  + ]:      13604 :   Assert(d_value >= 0);
                 [ -  - ]
     159 [ -  + ][ -  + ]:      13604 :   Assert(y.d_value >= 0);
                 [ -  - ]
     160                 :      13604 :   return d_value <= y.d_value;
     161                 :            : }
     162                 :            : 
     163                 :            : /* Signed Inequality ----------------------------------------------------- */
     164                 :            : 
     165                 :      75292 : bool BitVector::signedLessThan(const BitVector& y) const
     166                 :            : {
     167 [ -  + ][ -  + ]:      75292 :   Assert(d_size == y.d_size);
                 [ -  - ]
     168 [ -  + ][ -  + ]:      75292 :   Assert(d_value >= 0);
                 [ -  - ]
     169 [ -  + ][ -  + ]:      75292 :   Assert(y.d_value >= 0);
                 [ -  - ]
     170                 :      75292 :   Integer a = (*this).toSignedInteger();
     171                 :      75292 :   Integer b = y.toSignedInteger();
     172                 :            : 
     173                 :     150584 :   return a < b;
     174                 :      75292 : }
     175                 :            : 
     176                 :    1686102 : bool BitVector::signedLessThanEq(const BitVector& y) const
     177                 :            : {
     178 [ -  + ][ -  + ]:    1686102 :   Assert(d_size == y.d_size);
                 [ -  - ]
     179 [ -  + ][ -  + ]:    1686102 :   Assert(d_value >= 0);
                 [ -  - ]
     180 [ -  + ][ -  + ]:    1686102 :   Assert(y.d_value >= 0);
                 [ -  - ]
     181                 :    1686102 :   Integer a = (*this).toSignedInteger();
     182                 :    1686102 :   Integer b = y.toSignedInteger();
     183                 :            : 
     184                 :    3372204 :   return a <= b;
     185                 :    1686102 : }
     186                 :            : 
     187                 :            : /* Bit-wise operations --------------------------------------------------- */
     188                 :            : 
     189                 :       3211 : BitVector operator^(const BitVector& a, const BitVector& b)
     190                 :            : {
     191 [ -  + ][ -  + ]:       3211 :   Assert(a.getSize() == b.getSize());
                 [ -  - ]
     192                 :       6422 :   return BitVector(a.getSize(), a.getValue().bitwiseXor(b.getValue()));
     193                 :            : }
     194                 :            : 
     195                 :     327557 : BitVector operator|(const BitVector& a, const BitVector& b)
     196                 :            : {
     197 [ -  + ][ -  + ]:     327557 :   Assert(a.getSize() == b.getSize());
                 [ -  - ]
     198                 :     655114 :   return BitVector(a.getSize(), a.getValue().bitwiseOr(b.getValue()));
     199                 :            : }
     200                 :            : 
     201                 :     660812 : BitVector operator&(const BitVector& a, const BitVector& b)
     202                 :            : {
     203 [ -  + ][ -  + ]:     660812 :   Assert(a.getSize() == b.getSize());
                 [ -  - ]
     204                 :    1321624 :   return BitVector(a.getSize(), a.getValue().bitwiseAnd(b.getValue()));
     205                 :            : }
     206                 :            : 
     207                 :    4790630 : BitVector operator~(const BitVector& a)
     208                 :            : {
     209                 :    9581260 :   return BitVector(a.getSize(), a.getValue().bitwiseNot());
     210                 :            : }
     211                 :            : 
     212                 :            : /* Arithmetic operations ------------------------------------------------- */
     213                 :            : 
     214                 :    7537960 : BitVector operator+(const BitVector& a, const BitVector& b)
     215                 :            : {
     216 [ -  + ][ -  + ]:    7537960 :   Assert(a.getSize() == b.getSize());
                 [ -  - ]
     217                 :    7537960 :   Integer sum = a.getValue() + b.getValue();
     218                 :   15075920 :   return BitVector(a.getSize(), sum);
     219                 :    7537960 : }
     220                 :            : 
     221                 :    2835841 : BitVector operator-(const BitVector& a, const BitVector& b)
     222                 :            : {
     223 [ -  + ][ -  + ]:    2835841 :   Assert(a.getSize() == b.getSize());
                 [ -  - ]
     224                 :            :   // to maintain the invariant that we are only adding BitVectors of the
     225                 :            :   // same size
     226                 :    2835841 :   BitVector one(a.getSize(), Integer(1));
     227                 :    8507523 :   return a + ~b + one;
     228                 :    2835841 : }
     229                 :            : 
     230                 :    1600126 : BitVector operator-(const BitVector& a)
     231                 :            : {
     232                 :    1600126 :   BitVector one(a.getSize(), Integer(1));
     233                 :    4800378 :   return ~a + one;
     234                 :    1600126 : }
     235                 :            : 
     236                 :     475649 : BitVector operator*(const BitVector& a, const BitVector& b)
     237                 :            : {
     238 [ -  + ][ -  + ]:     475649 :   Assert(a.getSize() == b.getSize());
                 [ -  - ]
     239                 :     475649 :   Integer prod = a.getValue() * b.getValue();
     240                 :     951298 :   return BitVector(a.getSize(), prod);
     241                 :     475649 : }
     242                 :            : 
     243                 :      62472 : BitVector BitVector::unsignedDivTotal(const BitVector& y) const
     244                 :            : {
     245 [ -  + ][ -  + ]:      62472 :   Assert(d_size == y.d_size);
                 [ -  - ]
     246                 :            :   /* d_value / 0 = -1 = 2^d_size - 1 */
     247         [ +  + ]:      62472 :   if (y.d_value == 0)
     248                 :            :   {
     249                 :      16308 :     return BitVector(d_size, Integer(1).oneExtend(1, d_size - 1));
     250                 :            :   }
     251 [ -  + ][ -  + ]:      54318 :   Assert(d_value >= 0);
                 [ -  - ]
     252 [ -  + ][ -  + ]:      54318 :   Assert(y.d_value > 0);
                 [ -  - ]
     253                 :     108636 :   return BitVector(d_size, d_value.floorDivideQuotient(y.d_value));
     254                 :            : }
     255                 :            : 
     256                 :      67332 : BitVector BitVector::unsignedRemTotal(const BitVector& y) const
     257                 :            : {
     258 [ -  + ][ -  + ]:      67332 :   Assert(d_size == y.d_size);
                 [ -  - ]
     259         [ +  + ]:      67332 :   if (y.d_value == 0)
     260                 :            :   {
     261                 :       8113 :     return BitVector(d_size, d_value);
     262                 :            :   }
     263 [ -  + ][ -  + ]:      59219 :   Assert(d_value >= 0);
                 [ -  - ]
     264 [ -  + ][ -  + ]:      59219 :   Assert(y.d_value > 0);
                 [ -  - ]
     265                 :     118438 :   return BitVector(d_size, d_value.floorDivideRemainder(y.d_value));
     266                 :            : }
     267                 :            : 
     268                 :            : /* Extend operations ----------------------------------------------------- */
     269                 :            : 
     270                 :     588835 : BitVector BitVector::zeroExtend(unsigned n) const
     271                 :            : {
     272                 :     588835 :   return BitVector(d_size + n, d_value);
     273                 :            : }
     274                 :            : 
     275                 :    1529468 : BitVector BitVector::signExtend(unsigned n) const
     276                 :            : {
     277                 :    1529468 :   Integer sign_bit = d_value.extractBitRange(1, d_size - 1);
     278         [ +  + ]:    1529468 :   if (sign_bit == Integer(0))
     279                 :            :   {
     280                 :      89975 :     return BitVector(d_size + n, d_value);
     281                 :            :   }
     282                 :    1439493 :   Integer val = d_value.oneExtend(d_size, n);
     283                 :    1439493 :   return BitVector(d_size + n, val);
     284                 :    1529468 : }
     285                 :            : 
     286                 :            : /* Shift operations ------------------------------------------------------ */
     287                 :            : 
     288                 :    2340578 : BitVector BitVector::leftShift(const BitVector& y) const
     289                 :            : {
     290         [ +  + ]:    2340578 :   if (y.d_value > Integer(d_size))
     291                 :            :   {
     292                 :      22218 :     return BitVector(d_size, Integer(0));
     293                 :            :   }
     294         [ +  + ]:    2329469 :   if (y.d_value == 0)
     295                 :            :   {
     296                 :     182274 :     return *this;
     297                 :            :   }
     298                 :            :   // making sure we don't lose information casting
     299 [ -  + ][ -  + ]:    2147195 :   Assert(y.d_value < Integer(1).multiplyByPow2(32));
                 [ -  - ]
     300                 :    2147195 :   uint32_t amount = y.d_value.toUnsignedInt();
     301                 :    2147195 :   Integer res = d_value.multiplyByPow2(amount);
     302                 :    2147195 :   return BitVector(d_size, res);
     303                 :    2147195 : }
     304                 :            : 
     305                 :      57892 : BitVector BitVector::logicalRightShift(const BitVector& y) const
     306                 :            : {
     307         [ +  + ]:      57892 :   if (y.d_value > Integer(d_size))
     308                 :            :   {
     309                 :          2 :     return BitVector(d_size, Integer(0));
     310                 :            :   }
     311                 :            :   // making sure we don't lose information casting
     312 [ -  + ][ -  + ]:      57891 :   Assert(y.d_value < Integer(1).multiplyByPow2(32));
                 [ -  - ]
     313                 :      57891 :   uint32_t amount = y.d_value.toUnsignedInt();
     314                 :      57891 :   Integer res = d_value.divByPow2(amount);
     315                 :      57891 :   return BitVector(d_size, res);
     316                 :      57891 : }
     317                 :            : 
     318                 :      20623 : BitVector BitVector::arithRightShift(const BitVector& y) const
     319                 :            : {
     320                 :      20623 :   Integer sign_bit = d_value.extractBitRange(1, d_size - 1);
     321         [ +  + ]:      20623 :   if (y.d_value > Integer(d_size))
     322                 :            :   {
     323         [ +  + ]:        852 :     if (sign_bit == Integer(0))
     324                 :            :     {
     325                 :       1074 :       return BitVector(d_size, Integer(0));
     326                 :            :     }
     327                 :            :     else
     328                 :            :     {
     329                 :        630 :       return BitVector(d_size, Integer(d_size).multiplyByPow2(d_size) - 1);
     330                 :            :     }
     331                 :            :   }
     332                 :            : 
     333         [ +  + ]:      19771 :   if (y.d_value == 0)
     334                 :            :   {
     335                 :        754 :     return *this;
     336                 :            :   }
     337                 :            : 
     338                 :            :   // making sure we don't lose information casting
     339 [ -  + ][ -  + ]:      19017 :   Assert(y.d_value < Integer(1).multiplyByPow2(32));
                 [ -  - ]
     340                 :            : 
     341                 :      19017 :   uint32_t amount = y.d_value.toUnsignedInt();
     342                 :      19017 :   Integer rest = d_value.divByPow2(amount);
     343                 :            : 
     344         [ +  + ]:      19017 :   if (sign_bit == Integer(0))
     345                 :            :   {
     346                 :      12862 :     return BitVector(d_size, rest);
     347                 :            :   }
     348                 :       6155 :   Integer res = rest.oneExtend(d_size - amount, amount);
     349                 :       6155 :   return BitVector(d_size, res);
     350                 :      20623 : }
     351                 :            : 
     352                 :            : /* -----------------------------------------------------------------------
     353                 :            :  * Static helpers.
     354                 :            :  * ----------------------------------------------------------------------- */
     355                 :            : 
     356                 :         41 : BitVector BitVector::mkZero(unsigned size)
     357                 :            : {
     358 [ -  + ][ -  + ]:         41 :   Assert(size > 0);
                 [ -  - ]
     359                 :         41 :   return BitVector(size);
     360                 :            : }
     361                 :            : 
     362                 :         45 : BitVector BitVector::mkOne(unsigned size)
     363                 :            : {
     364 [ -  + ][ -  + ]:         45 :   Assert(size > 0);
                 [ -  - ]
     365                 :         45 :   return BitVector(size, 1u);
     366                 :            : }
     367                 :            : 
     368                 :    1331928 : BitVector BitVector::mkOnes(unsigned size)
     369                 :            : {
     370 [ -  + ][ -  + ]:    1331928 :   Assert(size > 0);
                 [ -  - ]
     371                 :    2663856 :   return BitVector(1, Integer(1)).signExtend(size - 1);
     372                 :            : }
     373                 :            : 
     374                 :        127 : BitVector BitVector::mkMinSigned(unsigned size)
     375                 :            : {
     376 [ -  + ][ -  + ]:        127 :   Assert(size > 0);
                 [ -  - ]
     377                 :        127 :   BitVector res(size);
     378                 :        127 :   res.setBit(size - 1, true);
     379                 :        127 :   return res;
     380                 :          0 : }
     381                 :            : 
     382                 :         39 : BitVector BitVector::mkMaxSigned(unsigned size)
     383                 :            : {
     384 [ -  + ][ -  + ]:         39 :   Assert(size > 0);
                 [ -  - ]
     385                 :         78 :   return ~BitVector::mkMinSigned(size);
     386                 :            : }
     387                 :            : 
     388                 :          2 : BitVector BitVector::mkRandom(uint32_t size)
     389                 :            : {
     390 [ -  + ][ -  + ]:          2 :   Assert(size > 0);
                 [ -  - ]
     391                 :          4 :   return BitVector(size, Integer::mkRandom(size));
     392                 :            : }
     393                 :            : 
     394                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14