GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/util/bitvector.h Lines: 70 74 94.6 %
Date: 2021-08-14 Branches: 30 41 73.2 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Aina Niemetz, Andres Noetzli, Dejan Jovanovic
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 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 fixed-size bit-vector, implemented as a wrapper around Integer.
14
 */
15
16
#include "cvc5_public.h"
17
18
#ifndef CVC5__BITVECTOR_H
19
#define CVC5__BITVECTOR_H
20
21
#include <iosfwd>
22
#include <iostream>
23
24
#include "base/exception.h"
25
#include "util/integer.h"
26
27
namespace cvc5 {
28
29
5300329
class BitVector
30
{
31
 public:
32
7061192
  BitVector(unsigned size, const Integer& val)
33
7061192
      : d_size(size), d_value(val.modByPow2(size))
34
  {
35
7061192
  }
36
37
3429217
  BitVector(unsigned size = 0) : d_size(size), d_value(0) {}
38
39
  /**
40
   * BitVector constructor using a 32-bit unsigned integer for the value.
41
   *
42
   * Note: we use an explicit bit-width here to be consistent across
43
   * platforms (long is 32-bit when compiling 64-bit binaries on
44
   * Windows but 64-bit on Linux) and to prevent ambiguous overloads.
45
   */
46
4735615
  BitVector(unsigned size, uint32_t z) : d_size(size), d_value(z)
47
  {
48
4735615
    d_value = d_value.modByPow2(size);
49
4735615
  }
50
51
  /**
52
   * BitVector constructor using a 64-bit unsigned integer for the value.
53
   *
54
   * Note: we use an explicit bit-width here to be consistent across
55
   * platforms (long is 32-bit when compiling 64-bit binaries on
56
   * Windows but 64-bit on Linux) and to prevent ambiguous overloads.
57
   */
58
101
  BitVector(unsigned size, uint64_t z) : d_size(size), d_value(z)
59
  {
60
101
    d_value = d_value.modByPow2(size);
61
101
  }
62
63
1623
  BitVector(unsigned size, const BitVector& q)
64
1623
      : d_size(size), d_value(q.d_value)
65
  {
66
1623
  }
67
68
  /**
69
   * BitVector constructor.
70
   *
71
   * The value of the bit-vector is passed in as string of base 2, 10 or 16.
72
   * The size of resulting bit-vector is
73
   * - base  2: the size of the binary string
74
   * - base 10: the min. size required to represent the decimal as a bit-vector
75
   * - base 16: the max. size required to represent the hexadecimal as a
76
   *            bit-vector (4 * size of the given value string)
77
   *
78
   * @param num The value of the bit-vector in string representation.
79
   *            This cannot be a negative value.
80
   * @param base The base of the string representation.
81
   */
82
100296
  BitVector(const std::string& num, unsigned base = 2)
83
100304
  {
84
100296
    CheckArgument(base == 2 || base == 10 || base == 16, base);
85
100294
    CheckArgument(num[0] != '-', num);
86
100290
    d_value = Integer(num, base);
87
100288
    CheckArgument(d_value == d_value.abs(), num);
88
    // Compute the length, *without* any negative sign.
89
100288
    switch (base)
90
    {
91
12
      case 10: d_size = d_value.length(); break;
92
4402
      case 16: d_size = num.size() * 4; break;
93
95874
      default: d_size = num.size();
94
    }
95
100288
  }
96
97
20628365
  ~BitVector() {}
98
99
4692401
  BitVector& operator=(const BitVector& x)
100
  {
101
4692401
    if (this == &x) return *this;
102
4691989
    d_size = x.d_size;
103
4691989
    d_value = x.d_value;
104
4691989
    return *this;
105
  }
106
107
  /* Get size (bit-width). */
108
  unsigned getSize() const;
109
  /* Get value. */
110
  const Integer& getValue() const;
111
112
  /* Return value. */
113
  Integer toInteger() const;
114
  /* Return Integer corresponding to two's complement interpretation of this. */
115
  Integer toSignedInteger() const;
116
  /* Return (binary) string representation. */
117
  std::string toString(unsigned int base = 2) const;
118
119
  /* Return hash value. */
120
  size_t hash() const;
121
122
  /**
123
   * Set bit at index 'i' to given value.
124
   * Returns a reference to this bit-vector to allow for chaining.
125
   *
126
   * value: True to set bit to 1, and false to set it to 0.
127
   *
128
   * Note: Least significant bit is at index 0.
129
   */
130
  BitVector& setBit(uint32_t i, bool value);
131
132
  /** Return true if bit at index 'i' is 1, and false otherwise. */
133
  bool isBitSet(uint32_t i) const;
134
135
  /* Return k if the value of this is equal to 2^{k-1}, and zero otherwise. */
136
  unsigned isPow2() const;
137
138
  /* -----------------------------------------------------------------------
139
   ** Operators
140
   * ----------------------------------------------------------------------- */
141
142
  /* String Operations ----------------------------------------------------- */
143
144
  /* Return the concatenation of this and bit-vector 'other'. */
145
  BitVector concat(const BitVector& other) const;
146
147
  /* Return the bit range from index 'high' to index 'low'. */
148
  BitVector extract(unsigned high, unsigned low) const;
149
150
  /* (Dis)Equality --------------------------------------------------------- */
151
152
  /* Return true if this is equal to 'y'. */
153
  bool operator==(const BitVector& y) const;
154
155
  /* Return true if this is not equal to 'y'. */
156
  bool operator!=(const BitVector& y) const;
157
158
  /* Unsigned Inequality --------------------------------------------------- */
159
160
  /* Return true if this is unsigned less than bit-vector 'y'. */
161
  bool operator<(const BitVector& y) const;
162
163
  /* Return true if this is unsigned less than or equal to bit-vector 'y'. */
164
  bool operator<=(const BitVector& y) const;
165
166
  /* Return true if this is unsigned greater than bit-vector 'y'. */
167
  bool operator>(const BitVector& y) const;
168
169
  /* Return true if this is unsigned greater than or equal to bit-vector 'y'. */
170
  bool operator>=(const BitVector& y) const;
171
172
  /* Return true if this is unsigned less than bit-vector 'y'.
173
   * This function is a synonym for operator < but performs additional
174
   * argument checks.*/
175
  bool unsignedLessThan(const BitVector& y) const;
176
177
  /* Return true if this is unsigned less than or equal to bit-vector 'y'.
178
   * This function is a synonym for operator >= but performs additional
179
   * argument checks.*/
180
  bool unsignedLessThanEq(const BitVector& y) const;
181
182
  /* Signed Inequality ----------------------------------------------------- */
183
184
  /* Return true if this is signed less than bit-vector 'y'. */
185
  bool signedLessThan(const BitVector& y) const;
186
187
  /* Return true if this is signed less than or equal to bit-vector 'y'. */
188
  bool signedLessThanEq(const BitVector& y) const;
189
190
  /* Bit-wise operations --------------------------------------------------- */
191
192
  /* Return a bit-vector representing the bit-wise xor (this ^ y). */
193
  BitVector operator^(const BitVector& y) const;
194
195
  /* Return a bit-vector representing the bit-wise or (this | y). */
196
  BitVector operator|(const BitVector& y) const;
197
198
  /* Return a bit-vector representing the bit-wise and (this & y). */
199
  BitVector operator&(const BitVector& y) const;
200
201
  /* Return a bit-vector representing the bit-wise not of this. */
202
  BitVector operator~() const;
203
204
  /* Arithmetic operations ------------------------------------------------- */
205
206
  /* Return a bit-vector representing the addition (this + y). */
207
  BitVector operator+(const BitVector& y) const;
208
209
  /* Return a bit-vector representing the subtraction (this - y). */
210
  BitVector operator-(const BitVector& y) const;
211
212
  /* Return a bit-vector representing the negation of this. */
213
  BitVector operator-() const;
214
215
  /* Return a bit-vector representing the multiplication (this * y). */
216
  BitVector operator*(const BitVector& y) const;
217
218
  /* Total division function.
219
   * Returns a bit-vector representing 2^d_size-1 (signed: -1) when the
220
   * denominator is zero, and a bit-vector representing the unsigned division
221
   * (this / y), otherwise.  */
222
  BitVector unsignedDivTotal(const BitVector& y) const;
223
224
  /* Total remainder function.
225
   * Returns this when the denominator is zero, and the unsigned remainder
226
   * (this % y), otherwise.  */
227
  BitVector unsignedRemTotal(const BitVector& y) const;
228
229
  /* Extend operations ----------------------------------------------------- */
230
231
  /* Return a bit-vector representing this extended by 'n' zero bits. */
232
  BitVector zeroExtend(unsigned n) const;
233
234
  /* Return a bit-vector representing this extended by 'n' bits of the value
235
   * of the signed bit. */
236
  BitVector signExtend(unsigned n) const;
237
238
  /* Shift operations ------------------------------------------------------ */
239
240
  /* Return a bit-vector representing a left shift of this by 'y'. */
241
  BitVector leftShift(const BitVector& y) const;
242
243
  /* Return a bit-vector representing a logical right shift of this by 'y'. */
244
  BitVector logicalRightShift(const BitVector& y) const;
245
246
  /* Return a bit-vector representing an arithmetic right shift of this
247
   * by 'y'.*/
248
  BitVector arithRightShift(const BitVector& y) const;
249
250
  /* -----------------------------------------------------------------------
251
   ** Static helpers.
252
   * ----------------------------------------------------------------------- */
253
254
  /* Create zero bit-vector of given size. */
255
  static BitVector mkZero(unsigned size);
256
257
  /* Create bit-vector representing value 1 of given size. */
258
  static BitVector mkOne(unsigned size);
259
260
  /* Create bit-vector of ones of given size. */
261
  static BitVector mkOnes(unsigned size);
262
263
  /* Create bit-vector representing the minimum signed value of given size. */
264
  static BitVector mkMinSigned(unsigned size);
265
266
  /* Create bit-vector representing the maximum signed value of given size. */
267
  static BitVector mkMaxSigned(unsigned size);
268
269
 private:
270
  /**
271
   * Class invariants:
272
   *  - no overflows: 2^d_size < d_value
273
   *  - no negative numbers: d_value >= 0
274
   */
275
276
  unsigned d_size;
277
  Integer d_value;
278
279
}; /* class BitVector */
280
281
/* -----------------------------------------------------------------------
282
 * BitVector structs
283
 * ----------------------------------------------------------------------- */
284
285
/**
286
 * The structure representing the extraction operation for bit-vectors. The
287
 * operation maps bit-vectors to bit-vector of size <code>high - low + 1</code>
288
 * by taking the bits at indices <code>high ... low</code>
289
 */
290
struct BitVectorExtract
291
{
292
  /** The high bit of the range for this extract */
293
  unsigned d_high;
294
  /** The low bit of the range for this extract */
295
  unsigned d_low;
296
297
210141
  BitVectorExtract(unsigned high, unsigned low) : d_high(high), d_low(low) {}
298
299
217170
  bool operator==(const BitVectorExtract& extract) const
300
  {
301
217170
    return d_high == extract.d_high && d_low == extract.d_low;
302
  }
303
}; /* struct BitVectorExtract */
304
305
/**
306
 * The structure representing the extraction of one Boolean bit.
307
 */
308
struct BitVectorBitOf
309
{
310
  /** The index of the bit */
311
  unsigned d_bitIndex;
312
306175
  BitVectorBitOf(unsigned i) : d_bitIndex(i) {}
313
314
339101
  bool operator==(const BitVectorBitOf& other) const
315
  {
316
339101
    return d_bitIndex == other.d_bitIndex;
317
  }
318
}; /* struct BitVectorBitOf */
319
320
struct BitVectorSize
321
{
322
  unsigned d_size;
323
507771
  BitVectorSize(unsigned size) : d_size(size) {}
324
5224840
  operator unsigned() const { return d_size; }
325
}; /* struct BitVectorSize */
326
327
struct BitVectorRepeat
328
{
329
  unsigned d_repeatAmount;
330
3046
  BitVectorRepeat(unsigned repeatAmount) : d_repeatAmount(repeatAmount) {}
331
10689
  operator unsigned() const { return d_repeatAmount; }
332
}; /* struct BitVectorRepeat */
333
334
struct BitVectorZeroExtend
335
{
336
  unsigned d_zeroExtendAmount;
337
45626
  BitVectorZeroExtend(unsigned zeroExtendAmount)
338
45626
      : d_zeroExtendAmount(zeroExtendAmount)
339
  {
340
45626
  }
341
154597
  operator unsigned() const { return d_zeroExtendAmount; }
342
}; /* struct BitVectorZeroExtend */
343
344
struct BitVectorSignExtend
345
{
346
  unsigned d_signExtendAmount;
347
27033
  BitVectorSignExtend(unsigned signExtendAmount)
348
27033
      : d_signExtendAmount(signExtendAmount)
349
  {
350
27033
  }
351
107383
  operator unsigned() const { return d_signExtendAmount; }
352
}; /* struct BitVectorSignExtend */
353
354
struct BitVectorRotateLeft
355
{
356
  unsigned d_rotateLeftAmount;
357
1390
  BitVectorRotateLeft(unsigned rotateLeftAmount)
358
1390
      : d_rotateLeftAmount(rotateLeftAmount)
359
  {
360
1390
  }
361
5094
  operator unsigned() const { return d_rotateLeftAmount; }
362
}; /* struct BitVectorRotateLeft */
363
364
struct BitVectorRotateRight
365
{
366
  unsigned d_rotateRightAmount;
367
1720
  BitVectorRotateRight(unsigned rotateRightAmount)
368
1720
      : d_rotateRightAmount(rotateRightAmount)
369
  {
370
1720
  }
371
6282
  operator unsigned() const { return d_rotateRightAmount; }
372
}; /* struct BitVectorRotateRight */
373
374
struct IntToBitVector
375
{
376
  unsigned d_size;
377
672
  IntToBitVector(unsigned size) : d_size(size) {}
378
4015
  operator unsigned() const { return d_size; }
379
}; /* struct IntToBitVector */
380
381
/* -----------------------------------------------------------------------
382
 * Hash Function structs
383
 * ----------------------------------------------------------------------- */
384
385
/*
386
 * Hash function for the BitVector constants.
387
 */
388
struct BitVectorHashFunction
389
{
390
2986519
  inline size_t operator()(const BitVector& bv) const { return bv.hash(); }
391
}; /* struct BitVectorHashFunction */
392
393
/**
394
 * Hash function for the BitVectorExtract objects.
395
 */
396
struct BitVectorExtractHashFunction
397
{
398
238125
  size_t operator()(const BitVectorExtract& extract) const
399
  {
400
238125
    size_t hash = extract.d_low;
401
238125
    hash ^= extract.d_high + 0x9e3779b9 + (hash << 6) + (hash >> 2);
402
238125
    return hash;
403
  }
404
}; /* struct BitVectorExtractHashFunction */
405
406
/**
407
 * Hash function for the BitVectorBitOf objects.
408
 */
409
struct BitVectorBitOfHashFunction
410
{
411
437879
  size_t operator()(const BitVectorBitOf& b) const { return b.d_bitIndex; }
412
}; /* struct BitVectorBitOfHashFunction */
413
414
template <typename T>
415
struct UnsignedHashFunction
416
{
417
636990
  inline size_t operator()(const T& x) const { return (size_t)x; }
418
}; /* struct UnsignedHashFunction */
419
420
/* -----------------------------------------------------------------------
421
 * Output stream
422
 * ----------------------------------------------------------------------- */
423
424
inline std::ostream& operator<<(std::ostream& os, const BitVector& bv);
425
4
inline std::ostream& operator<<(std::ostream& os, const BitVector& bv)
426
{
427
4
  return os << bv.toString();
428
}
429
430
inline std::ostream& operator<<(std::ostream& os, const BitVectorExtract& bv);
431
4
inline std::ostream& operator<<(std::ostream& os, const BitVectorExtract& bv)
432
{
433
4
  return os << "[" << bv.d_high << ":" << bv.d_low << "]";
434
}
435
436
inline std::ostream& operator<<(std::ostream& os, const BitVectorBitOf& bv);
437
inline std::ostream& operator<<(std::ostream& os, const BitVectorBitOf& bv)
438
{
439
  return os << "[" << bv.d_bitIndex << "]";
440
}
441
442
inline std::ostream& operator<<(std::ostream& os, const IntToBitVector& bv);
443
inline std::ostream& operator<<(std::ostream& os, const IntToBitVector& bv)
444
{
445
  return os << "[" << bv.d_size << "]";
446
}
447
448
}  // namespace cvc5
449
450
#endif /* CVC5__BITVECTOR_H */