GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bitblast/bitblast_utils.h Lines: 96 108 88.9 %
Date: 2021-05-22 Branches: 144 382 37.7 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Liana Hadarean, Dejan Jovanovic, Mathias Preiner
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
 * Various utility functions for bit-blasting.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__BV__BITBLAST__BITBLAST_UTILS_H
19
#define CVC5__THEORY__BV__BITBLAST__BITBLAST_UTILS_H
20
21
#include <ostream>
22
#include "expr/node.h"
23
24
namespace cvc5 {
25
namespace theory {
26
namespace bv {
27
28
template <class T> class TBitblaster;
29
30
template <class T>
31
std::string toString (const std::vector<T>& bits);
32
33
template <> inline
34
std::string toString<Node> (const std::vector<Node>& bits) {
35
  std::ostringstream os;
36
  for (int i = bits.size() - 1; i >= 0; --i) {
37
    TNode bit = bits[i];
38
    if (bit.getKind() == kind::CONST_BOOLEAN) {
39
      os << (bit.getConst<bool>() ? "1" : "0");
40
    } else {
41
      os << bit<< " ";
42
    }
43
  }
44
  os <<"\n";
45
  return os.str();
46
}
47
48
template <class T> T mkTrue();
49
template <class T> T mkFalse();
50
template <class T> T mkNot(T a);
51
template <class T> T mkOr(T a, T b);
52
template <class T> T mkOr(const std::vector<T>& a);
53
template <class T> T mkAnd(T a, T b);
54
template <class T> T mkAnd(const std::vector<T>& a);
55
template <class T> T mkXor(T a, T b);
56
template <class T> T mkIff(T a, T b);
57
template <class T> T mkIte(T cond, T a, T b);
58
59
60
template <> inline
61
65005
Node mkTrue<Node>() {
62
65005
  return NodeManager::currentNM()->mkConst<bool>(true);
63
}
64
65
template <> inline
66
257316
Node mkFalse<Node>() {
67
257316
  return NodeManager::currentNM()->mkConst<bool>(false);
68
}
69
70
template <> inline
71
373602
Node mkNot<Node>(Node a) {
72
373602
  return NodeManager::currentNM()->mkNode(kind::NOT, a);
73
}
74
75
template <> inline
76
639546
Node mkOr<Node>(Node a, Node b) {
77
639546
  return NodeManager::currentNM()->mkNode(kind::OR, a, b);
78
}
79
80
template <> inline
81
Node mkOr<Node>(const std::vector<Node>& children) {
82
  Assert(children.size());
83
  if (children.size() == 1)
84
    return children[0];
85
  return NodeManager::currentNM()->mkNode(kind::OR, children);
86
}
87
88
89
template <> inline
90
1197863
Node mkAnd<Node>(Node a, Node b) {
91
1197863
  return NodeManager::currentNM()->mkNode(kind::AND, a, b);
92
}
93
94
template <> inline
95
55555
Node mkAnd<Node>(const std::vector<Node>& children) {
96
55555
  Assert(children.size());
97
55555
  if (children.size() == 1)
98
17279
    return children[0];
99
38276
  return NodeManager::currentNM()->mkNode(kind::AND, children);
100
}
101
102
103
template <> inline
104
940821
Node mkXor<Node>(Node a, Node b) {
105
940821
  return NodeManager::currentNM()->mkNode(kind::XOR, a, b);
106
}
107
108
template <> inline
109
740237
Node mkIff<Node>(Node a, Node b) {
110
740237
  return NodeManager::currentNM()->mkNode(kind::EQUAL, a, b);
111
}
112
113
template <> inline
114
219220
Node mkIte<Node>(Node cond, Node a, Node b) {
115
219220
  return NodeManager::currentNM()->mkNode(kind::ITE, cond, a, b);
116
}
117
118
/*
119
 Various helper functions that get called by the bitblasting procedures
120
 */
121
122
template <class T>
123
24540
void inline extractBits(const std::vector<T>& b, std::vector<T>& dest, unsigned lo, unsigned hi) {
124
24540
  Assert(lo < b.size() && hi < b.size() && lo <= hi);
125
191828
  for (unsigned i = lo; i <= hi; ++i) {
126
167288
    dest.push_back(b[i]);
127
  }
128
24540
}
129
130
template <class T>
131
11195
void inline negateBits(const std::vector<T>& bits, std::vector<T>& negated_bits) {
132
91855
  for(unsigned i = 0; i < bits.size(); ++i) {
133
80660
    negated_bits.push_back(mkNot(bits[i]));
134
  }
135
11195
}
136
137
template <class T>
138
4230
bool inline isZero(const std::vector<T>& bits) {
139
5748
  for(unsigned i = 0; i < bits.size(); ++i) {
140
5633
    if(bits[i] != mkFalse<T>()) {
141
4115
      return false;
142
    }
143
  }
144
115
  return true;
145
}
146
147
template <class T>
148
4115
void inline rshift(std::vector<T>& bits, unsigned amount) {
149
44596
  for (unsigned i = 0; i < bits.size() - amount; ++i) {
150
40481
    bits[i] = bits[i+amount];
151
  }
152
8230
  for(unsigned i = bits.size() - amount; i < bits.size(); ++i) {
153
4115
    bits[i] = mkFalse<T>();
154
  }
155
4115
}
156
157
template <class T>
158
8230
void inline lshift(std::vector<T>& bits, unsigned amount) {
159
89192
  for (int i = (int)bits.size() - 1; i >= (int)amount ; --i) {
160
80962
    bits[i] = bits[i-amount];
161
  }
162
16460
  for(unsigned i = 0; i < amount; ++i) {
163
8230
    bits[i] = mkFalse<T>();
164
  }
165
8230
}
166
167
template <class T>
168
7166
void inline makeZero(std::vector<T>& bits, unsigned width) {
169
7166
  Assert(bits.size() == 0);
170
74417
  for(unsigned i = 0; i < width; ++i) {
171
67251
    bits.push_back(mkFalse<T>());
172
  }
173
7166
}
174
175
176
/**
177
 * Constructs a simple ripple carry adder
178
 *
179
 * @param a first term to be added
180
 * @param b second term to be added
181
 * @param res the result
182
 * @param carry the carry-in bit
183
 *
184
 * @return the carry-out
185
 */
186
template <class T>
187
17785
T inline rippleCarryAdder(const std::vector<T>&a, const std::vector<T>& b, std::vector<T>& res, T carry) {
188
17785
  Assert(a.size() == b.size() && res.size() == 0);
189
190
219330
  for (unsigned i = 0 ; i < a.size(); ++i) {
191
403090
    T sum = mkXor(mkXor(a[i], b[i]), carry);
192
604635
    carry = mkOr( mkAnd(a[i], b[i]),
193
403090
                  mkAnd( mkXor(a[i], b[i]),
194
                         carry));
195
201545
    res.push_back(sum);
196
  }
197
198
17785
  return carry;
199
}
200
201
template <class T>
202
1111
inline void shiftAddMultiplier(const std::vector<T>&a, const std::vector<T>&b, std::vector<T>& res) {
203
204
12311
  for (unsigned i = 0; i < a.size(); ++i) {
205
11200
    res.push_back(mkAnd(b[0], a[i]));
206
  }
207
208
11200
  for(unsigned k = 1; k < res.size(); ++k) {
209
20178
  T carry_in = mkFalse<T>();
210
20178
  T carry_out;
211
120959
    for(unsigned j = 0; j < res.size() -k; ++j) {
212
221740
      T aj = mkAnd(b[k], a[j]);
213
221740
      carry_out = mkOr(mkAnd(res[j+k], aj),
214
110870
                       mkAnd( mkXor(res[j+k], aj), carry_in));
215
110870
      res[j+k] = mkXor(mkXor(res[j+k], aj), carry_in);
216
110870
      carry_in = carry_out;
217
    }
218
  }
219
1111
}
220
221
template <class T>
222
27526
T inline uLessThanBB(const std::vector<T>&a, const std::vector<T>& b, bool orEqual) {
223
27526
  Assert(a.size() && b.size());
224
225
27526
  T res = mkAnd(mkNot(a[0]), b[0]);
226
227
27526
  if(orEqual) {
228
    res = mkOr(res, mkIff(a[0], b[0]));
229
  }
230
231
191055
  for (unsigned i = 1; i < a.size(); ++i) {
232
    // a < b iff ( a[i] <-> b[i] AND a[i-1:0] < b[i-1:0]) OR (~a[i] AND b[i])
233
327058
    res = mkOr(mkAnd(mkIff(a[i], b[i]), res),
234
327058
               mkAnd(mkNot(a[i]), b[i]));
235
  }
236
27526
  return res;
237
}
238
239
template <class T>
240
14897
T inline sLessThanBB(const std::vector<T>&a, const std::vector<T>& b, bool orEqual) {
241
14897
  Assert(a.size() && b.size());
242
14897
  if (a.size() == 1) {
243
2627
    if(orEqual) {
244
      return  mkOr(mkIff(a[0], b[0]),
245
                   mkAnd(a[0], mkNot(b[0])));
246
    }
247
248
2627
    return mkAnd(a[0], mkNot(b[0]));
249
  }
250
12270
  unsigned n = a.size() - 1;
251
24540
  std::vector<T> a1, b1;
252
12270
  extractBits(a, a1, 0, n-1);
253
12270
  extractBits(b, b1, 0, n-1);
254
255
  // unsigned comparison of the first n-1 bits
256
24540
  T ures = uLessThanBB(a1, b1, orEqual);
257
61350
  T res = mkOr(// a b have the same sign
258
24540
               mkAnd(mkIff(a[n], b[n]),
259
                     ures),
260
               // a is negative and b positive
261
12270
               mkAnd(a[n],
262
12270
                     mkNot(b[n])));
263
12270
  return res;
264
}
265
266
}  // namespace bv
267
}  // namespace theory
268
}  // namespace cvc5
269
270
#endif  // CVC5__THEORY__BV__BITBLAST__BITBLAST_UTILS_H