GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bitblast/bitblast_utils.h Lines: 96 108 88.9 %
Date: 2021-08-01 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
80145
Node mkTrue<Node>() {
62
80145
  return NodeManager::currentNM()->mkConst<bool>(true);
63
}
64
65
template <> inline
66
293412
Node mkFalse<Node>() {
67
293412
  return NodeManager::currentNM()->mkConst<bool>(false);
68
}
69
70
template <> inline
71
331612
Node mkNot<Node>(Node a) {
72
331612
  return NodeManager::currentNM()->mkNode(kind::NOT, a);
73
}
74
75
template <> inline
76
610269
Node mkOr<Node>(Node a, Node b) {
77
610269
  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
1090650
Node mkAnd<Node>(Node a, Node b) {
91
1090650
  return NodeManager::currentNM()->mkNode(kind::AND, a, b);
92
}
93
94
template <> inline
95
44196
Node mkAnd<Node>(const std::vector<Node>& children) {
96
44196
  Assert(children.size());
97
44196
  if (children.size() == 1)
98
13228
    return children[0];
99
30968
  return NodeManager::currentNM()->mkNode(kind::AND, children);
100
}
101
102
103
template <> inline
104
903854
Node mkXor<Node>(Node a, Node b) {
105
903854
  return NodeManager::currentNM()->mkNode(kind::XOR, a, b);
106
}
107
108
template <> inline
109
642182
Node mkIff<Node>(Node a, Node b) {
110
642182
  return NodeManager::currentNM()->mkNode(kind::EQUAL, a, b);
111
}
112
113
template <> inline
114
229843
Node mkIte<Node>(Node cond, Node a, Node b) {
115
229843
  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
13774
void inline extractBits(const std::vector<T>& b, std::vector<T>& dest, unsigned lo, unsigned hi) {
124
13774
  Assert(lo < b.size() && hi < b.size() && lo <= hi);
125
134880
  for (unsigned i = lo; i <= hi; ++i) {
126
121106
    dest.push_back(b[i]);
127
  }
128
13774
}
129
130
template <class T>
131
10705
void inline negateBits(const std::vector<T>& bits, std::vector<T>& negated_bits) {
132
91379
  for(unsigned i = 0; i < bits.size(); ++i) {
133
80674
    negated_bits.push_back(mkNot(bits[i]));
134
  }
135
10705
}
136
137
template <class T>
138
4283
bool inline isZero(const std::vector<T>& bits) {
139
5379
  for(unsigned i = 0; i < bits.size(); ++i) {
140
5294
    if(bits[i] != mkFalse<T>()) {
141
4198
      return false;
142
    }
143
  }
144
85
  return true;
145
}
146
147
template <class T>
148
4198
void inline rshift(std::vector<T>& bits, unsigned amount) {
149
50639
  for (unsigned i = 0; i < bits.size() - amount; ++i) {
150
46441
    bits[i] = bits[i+amount];
151
  }
152
8396
  for(unsigned i = bits.size() - amount; i < bits.size(); ++i) {
153
4198
    bits[i] = mkFalse<T>();
154
  }
155
4198
}
156
157
template <class T>
158
8396
void inline lshift(std::vector<T>& bits, unsigned amount) {
159
101278
  for (int i = (int)bits.size() - 1; i >= (int)amount ; --i) {
160
92882
    bits[i] = bits[i-amount];
161
  }
162
16792
  for(unsigned i = 0; i < amount; ++i) {
163
8396
    bits[i] = mkFalse<T>();
164
  }
165
8396
}
166
167
template <class T>
168
7077
void inline makeZero(std::vector<T>& bits, unsigned width) {
169
7077
  Assert(bits.size() == 0);
170
79372
  for(unsigned i = 0; i < width; ++i) {
171
72295
    bits.push_back(mkFalse<T>());
172
  }
173
7077
}
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
17162
T inline rippleCarryAdder(const std::vector<T>&a, const std::vector<T>& b, std::vector<T>& res, T carry) {
188
17162
  Assert(a.size() == b.size() && res.size() == 0);
189
190
225153
  for (unsigned i = 0 ; i < a.size(); ++i) {
191
415982
    T sum = mkXor(mkXor(a[i], b[i]), carry);
192
623973
    carry = mkOr( mkAnd(a[i], b[i]),
193
415982
                  mkAnd( mkXor(a[i], b[i]),
194
                         carry));
195
207991
    res.push_back(sum);
196
  }
197
198
17162
  return carry;
199
}
200
201
template <class T>
202
1251
inline void shiftAddMultiplier(const std::vector<T>&a, const std::vector<T>&b, std::vector<T>& res) {
203
204
12447
  for (unsigned i = 0; i < a.size(); ++i) {
205
11196
    res.push_back(mkAnd(b[0], a[i]));
206
  }
207
208
11196
  for(unsigned k = 1; k < res.size(); ++k) {
209
19890
  T carry_in = mkFalse<T>();
210
19890
  T carry_out;
211
102459
    for(unsigned j = 0; j < res.size() -k; ++j) {
212
185028
      T aj = mkAnd(b[k], a[j]);
213
185028
      carry_out = mkOr(mkAnd(res[j+k], aj),
214
92514
                       mkAnd( mkXor(res[j+k], aj), carry_in));
215
92514
      res[j+k] = mkXor(mkXor(res[j+k], aj), carry_in);
216
92514
      carry_in = carry_out;
217
    }
218
  }
219
1251
}
220
221
template <class T>
222
15985
T inline uLessThanBB(const std::vector<T>&a, const std::vector<T>& b, bool orEqual) {
223
15985
  Assert(a.size() && b.size());
224
225
15985
  T res = mkAnd(mkNot(a[0]), b[0]);
226
227
15985
  if(orEqual) {
228
    res = mkOr(res, mkIff(a[0], b[0]));
229
  }
230
231
158180
  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
284390
    res = mkOr(mkAnd(mkIff(a[i], b[i]), res),
234
284390
               mkAnd(mkNot(a[i]), b[i]));
235
  }
236
15985
  return res;
237
}
238
239
template <class T>
240
7762
T inline sLessThanBB(const std::vector<T>&a, const std::vector<T>& b, bool orEqual) {
241
7762
  Assert(a.size() && b.size());
242
7762
  if (a.size() == 1) {
243
875
    if(orEqual) {
244
      return  mkOr(mkIff(a[0], b[0]),
245
                   mkAnd(a[0], mkNot(b[0])));
246
    }
247
248
875
    return mkAnd(a[0], mkNot(b[0]));
249
  }
250
6887
  unsigned n = a.size() - 1;
251
13774
  std::vector<T> a1, b1;
252
6887
  extractBits(a, a1, 0, n-1);
253
6887
  extractBits(b, b1, 0, n-1);
254
255
  // unsigned comparison of the first n-1 bits
256
13774
  T ures = uLessThanBB(a1, b1, orEqual);
257
34435
  T res = mkOr(// a b have the same sign
258
13774
               mkAnd(mkIff(a[n], b[n]),
259
                     ures),
260
               // a is negative and b positive
261
6887
               mkAnd(a[n],
262
6887
                     mkNot(b[n])));
263
6887
  return res;
264
}
265
266
}  // namespace bv
267
}  // namespace theory
268
}  // namespace cvc5
269
270
#endif  // CVC5__THEORY__BV__BITBLAST__BITBLAST_UTILS_H