1 /********************* */
2 /*! \file bitvector.cpp
4 ** Top contributors (to current version):
5 ** Aina Niemetz, Liana Hadarean, Morgan Deters
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 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.\endverbatim
12 ** \brief A fixed-size bit-vector.
14 ** A fixed-size bit-vector, implemented as a wrapper around Integer.
16 ** \todo document this file
19 #include "util/bitvector.h"
23 unsigned BitVector::getSize() const { return d_size
; }
25 const Integer
& BitVector::getValue() const { return d_value
; }
27 Integer
BitVector::toInteger() const { return d_value
; }
29 Integer
BitVector::toSignedInteger() const
31 unsigned size
= d_size
;
32 Integer sign_bit
= d_value
.extractBitRange(1, size
- 1);
33 Integer val
= d_value
.extractBitRange(size
- 1, 0);
34 Integer res
= Integer(-1) * sign_bit
.multiplyByPow2(size
- 1) + val
;
38 std::string
BitVector::toString(unsigned int base
) const
40 std::string str
= d_value
.toString(base
);
41 if (base
== 2 && d_size
> str
.size())
44 for (unsigned int i
= 0; i
< d_size
- str
.size(); ++i
)
56 size_t BitVector::hash() const
58 return d_value
.hash() + d_size
;
61 BitVector
BitVector::setBit(uint32_t i
) const
63 CheckArgument(i
< d_size
, i
);
64 Integer res
= d_value
.setBit(i
);
65 return BitVector(d_size
, res
);
68 bool BitVector::isBitSet(uint32_t i
) const
70 CheckArgument(i
< d_size
, i
);
71 return d_value
.isBitSet(i
);
74 unsigned BitVector::isPow2() const
76 return d_value
.isPow2();
79 /* -----------------------------------------------------------------------
81 * ----------------------------------------------------------------------- */
83 /* String Operations ----------------------------------------------------- */
85 BitVector
BitVector::concat(const BitVector
& other
) const
87 return BitVector(d_size
+ other
.d_size
,
88 (d_value
.multiplyByPow2(other
.d_size
)) + other
.d_value
);
91 BitVector
BitVector::extract(unsigned high
, unsigned low
) const
93 CheckArgument(high
< d_size
, high
);
94 CheckArgument(low
<= high
, low
);
95 return BitVector(high
- low
+ 1,
96 d_value
.extractBitRange(high
- low
+ 1, low
));
99 /* (Dis)Equality --------------------------------------------------------- */
101 bool BitVector::operator==(const BitVector
& y
) const
103 if (d_size
!= y
.d_size
) return false;
104 return d_value
== y
.d_value
;
107 bool BitVector::operator!=(const BitVector
& y
) const
109 if (d_size
!= y
.d_size
) return true;
110 return d_value
!= y
.d_value
;
113 /* Unsigned Inequality --------------------------------------------------- */
115 bool BitVector::operator<(const BitVector
& y
) const
117 return d_value
< y
.d_value
;
120 bool BitVector::operator<=(const BitVector
& y
) const
122 return d_value
<= y
.d_value
;
125 bool BitVector::operator>(const BitVector
& y
) const
127 return d_value
> y
.d_value
;
130 bool BitVector::operator>=(const BitVector
& y
) const
132 return d_value
>= y
.d_value
;
135 bool BitVector::unsignedLessThan(const BitVector
& y
) const
137 CheckArgument(d_size
== y
.d_size
, y
);
138 CheckArgument(d_value
>= 0, this);
139 CheckArgument(y
.d_value
>= 0, y
);
140 return d_value
< y
.d_value
;
143 bool BitVector::unsignedLessThanEq(const BitVector
& y
) const
145 CheckArgument(d_size
== y
.d_size
, this);
146 CheckArgument(d_value
>= 0, this);
147 CheckArgument(y
.d_value
>= 0, y
);
148 return d_value
<= y
.d_value
;
151 /* Signed Inequality ----------------------------------------------------- */
153 bool BitVector::signedLessThan(const BitVector
& y
) const
155 CheckArgument(d_size
== y
.d_size
, y
);
156 CheckArgument(d_value
>= 0, this);
157 CheckArgument(y
.d_value
>= 0, y
);
158 Integer a
= (*this).toSignedInteger();
159 Integer b
= y
.toSignedInteger();
164 bool BitVector::signedLessThanEq(const BitVector
& y
) const
166 CheckArgument(d_size
== y
.d_size
, y
);
167 CheckArgument(d_value
>= 0, this);
168 CheckArgument(y
.d_value
>= 0, y
);
169 Integer a
= (*this).toSignedInteger();
170 Integer b
= y
.toSignedInteger();
175 /* Bit-wise operations --------------------------------------------------- */
177 BitVector
BitVector::operator^(const BitVector
& y
) const
179 CheckArgument(d_size
== y
.d_size
, y
);
180 return BitVector(d_size
, d_value
.bitwiseXor(y
.d_value
));
183 BitVector
BitVector::operator|(const BitVector
& y
) const
185 CheckArgument(d_size
== y
.d_size
, y
);
186 return BitVector(d_size
, d_value
.bitwiseOr(y
.d_value
));
189 BitVector
BitVector::operator&(const BitVector
& y
) const
191 CheckArgument(d_size
== y
.d_size
, y
);
192 return BitVector(d_size
, d_value
.bitwiseAnd(y
.d_value
));
195 BitVector
BitVector::operator~() const
197 return BitVector(d_size
, d_value
.bitwiseNot());
200 /* Arithmetic operations ------------------------------------------------- */
202 BitVector
BitVector::operator+(const BitVector
& y
) const
204 CheckArgument(d_size
== y
.d_size
, y
);
205 Integer sum
= d_value
+ y
.d_value
;
206 return BitVector(d_size
, sum
);
209 BitVector
BitVector::operator-(const BitVector
& y
) const
211 CheckArgument(d_size
== y
.d_size
, y
);
212 // to maintain the invariant that we are only adding BitVectors of the
214 BitVector
one(d_size
, Integer(1));
215 return *this + ~y
+ one
;
218 BitVector
BitVector::operator-() const
220 BitVector
one(d_size
, Integer(1));
221 return ~(*this) + one
;
224 BitVector
BitVector::operator*(const BitVector
& y
) const
226 CheckArgument(d_size
== y
.d_size
, y
);
227 Integer prod
= d_value
* y
.d_value
;
228 return BitVector(d_size
, prod
);
231 BitVector
BitVector::unsignedDivTotal(const BitVector
& y
) const
233 CheckArgument(d_size
== y
.d_size
, y
);
234 /* d_value / 0 = -1 = 2^d_size - 1 */
237 return BitVector(d_size
, Integer(1).oneExtend(1, d_size
- 1));
239 CheckArgument(d_value
>= 0, this);
240 CheckArgument(y
.d_value
> 0, y
);
241 return BitVector(d_size
, d_value
.floorDivideQuotient(y
.d_value
));
244 BitVector
BitVector::unsignedRemTotal(const BitVector
& y
) const
246 CheckArgument(d_size
== y
.d_size
, y
);
249 return BitVector(d_size
, d_value
);
251 CheckArgument(d_value
>= 0, this);
252 CheckArgument(y
.d_value
> 0, y
);
253 return BitVector(d_size
, d_value
.floorDivideRemainder(y
.d_value
));
256 /* Extend operations ----------------------------------------------------- */
258 BitVector
BitVector::zeroExtend(unsigned n
) const
260 return BitVector(d_size
+ n
, d_value
);
263 BitVector
BitVector::signExtend(unsigned n
) const
265 Integer sign_bit
= d_value
.extractBitRange(1, d_size
- 1);
266 if (sign_bit
== Integer(0))
268 return BitVector(d_size
+ n
, d_value
);
270 Integer val
= d_value
.oneExtend(d_size
, n
);
271 return BitVector(d_size
+ n
, val
);
274 /* Shift operations ------------------------------------------------------ */
276 BitVector
BitVector::leftShift(const BitVector
& y
) const
278 if (y
.d_value
> Integer(d_size
))
280 return BitVector(d_size
, Integer(0));
286 // making sure we don't lose information casting
287 CheckArgument(y
.d_value
< Integer(1).multiplyByPow2(32), y
);
288 uint32_t amount
= y
.d_value
.toUnsignedInt();
289 Integer res
= d_value
.multiplyByPow2(amount
);
290 return BitVector(d_size
, res
);
293 BitVector
BitVector::logicalRightShift(const BitVector
& y
) const
295 if (y
.d_value
> Integer(d_size
))
297 return BitVector(d_size
, Integer(0));
299 // making sure we don't lose information casting
300 CheckArgument(y
.d_value
< Integer(1).multiplyByPow2(32), y
);
301 uint32_t amount
= y
.d_value
.toUnsignedInt();
302 Integer res
= d_value
.divByPow2(amount
);
303 return BitVector(d_size
, res
);
306 BitVector
BitVector::arithRightShift(const BitVector
& y
) const
308 Integer sign_bit
= d_value
.extractBitRange(1, d_size
- 1);
309 if (y
.d_value
> Integer(d_size
))
311 if (sign_bit
== Integer(0))
313 return BitVector(d_size
, Integer(0));
317 return BitVector(d_size
, Integer(d_size
).multiplyByPow2(d_size
) - 1);
326 // making sure we don't lose information casting
327 CheckArgument(y
.d_value
< Integer(1).multiplyByPow2(32), y
);
329 uint32_t amount
= y
.d_value
.toUnsignedInt();
330 Integer rest
= d_value
.divByPow2(amount
);
332 if (sign_bit
== Integer(0))
334 return BitVector(d_size
, rest
);
336 Integer res
= rest
.oneExtend(d_size
- amount
, amount
);
337 return BitVector(d_size
, res
);
340 /* -----------------------------------------------------------------------
342 * ----------------------------------------------------------------------- */
344 BitVector
BitVector::mkZero(unsigned size
)
346 CheckArgument(size
> 0, size
);
347 return BitVector(size
);
350 BitVector
BitVector::mkOne(unsigned size
)
352 CheckArgument(size
> 0, size
);
353 return BitVector(size
, 1u);
356 BitVector
BitVector::mkOnes(unsigned size
)
358 CheckArgument(size
> 0, size
);
359 return BitVector(1, Integer(1)).signExtend(size
- 1);
362 BitVector
BitVector::mkMinSigned(unsigned size
)
364 CheckArgument(size
> 0, size
);
365 return BitVector(size
).setBit(size
- 1);
368 BitVector
BitVector::mkMaxSigned(unsigned size
)
370 CheckArgument(size
> 0, size
);
371 return ~BitVector::mkMinSigned(size
);