GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/bv/bitblast/bitblast_utils.h Lines: 96 108 88.9 %
Date: 2021-08-06 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
80484
Node mkTrue<Node>() {
62
80484
  return NodeManager::currentNM()->mkConst<bool>(true);
63
}
64
65
template <> inline
66
293467
Node mkFalse<Node>() {
67
293467
  return NodeManager::currentNM()->mkConst<bool>(false);
68
}
69
70
template <> inline
71
331600
Node mkNot<Node>(Node a) {
72
331600
  return NodeManager::currentNM()->mkNode(kind::NOT, a);
73
}
74
75
template <> inline
76
609374
Node mkOr<Node>(Node a, Node b) {
77
609374
  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
1089630
Node mkAnd<Node>(Node a, Node b) {
91
1089630
  return NodeManager::currentNM()->mkNode(kind::AND, a, b);
92
}
93
94
template <> inline
95
45680
Node mkAnd<Node>(const std::vector<Node>& children) {
96
45680
  Assert(children.size());
97
45680
  if (children.size() == 1)
98
13441
    return children[0];
99
32239
  return NodeManager::currentNM()->mkNode(kind::AND, children);
100
}
101
102
103
template <> inline
104
903096
Node mkXor<Node>(Node a, Node b) {
105
903096
  return NodeManager::currentNM()->mkNode(kind::XOR, a, b);
106
}
107
108
template <> inline
109
642149
Node mkIff<Node>(Node a, Node b) {
110
642149
  return NodeManager::currentNM()->mkNode(kind::EQUAL, a, b);
111
}
112
113
template <> inline
114
229452
Node mkIte<Node>(Node cond, Node a, Node b) {
115
229452
  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
13602
void inline extractBits(const std::vector<T>& b, std::vector<T>& dest, unsigned lo, unsigned hi) {
124
13602
  Assert(lo < b.size() && hi < b.size() && lo <= hi);
125
134010
  for (unsigned i = lo; i <= hi; ++i) {
126
120408
    dest.push_back(b[i]);
127
  }
128
13602
}
129
130
template <class T>
131
10792
void inline negateBits(const std::vector<T>& bits, std::vector<T>& negated_bits) {
132
92335
  for(unsigned i = 0; i < bits.size(); ++i) {
133
81543
    negated_bits.push_back(mkNot(bits[i]));
134
  }
135
10792
}
136
137
template <class T>
138
4269
bool inline isZero(const std::vector<T>& bits) {
139
5365
  for(unsigned i = 0; i < bits.size(); ++i) {
140
5280
    if(bits[i] != mkFalse<T>()) {
141
4184
      return false;
142
    }
143
  }
144
85
  return true;
145
}
146
147
template <class T>
148
4184
void inline rshift(std::vector<T>& bits, unsigned amount) {
149
50571
  for (unsigned i = 0; i < bits.size() - amount; ++i) {
150
46387
    bits[i] = bits[i+amount];
151
  }
152
8368
  for(unsigned i = bits.size() - amount; i < bits.size(); ++i) {
153
4184
    bits[i] = mkFalse<T>();
154
  }
155
4184
}
156
157
template <class T>
158
8368
void inline lshift(std::vector<T>& bits, unsigned amount) {
159
101142
  for (int i = (int)bits.size() - 1; i >= (int)amount ; --i) {
160
92774
    bits[i] = bits[i-amount];
161
  }
162
16736
  for(unsigned i = 0; i < amount; ++i) {
163
8368
    bits[i] = mkFalse<T>();
164
  }
165
8368
}
166
167
template <class T>
168
7032
void inline makeZero(std::vector<T>& bits, unsigned width) {
169
7032
  Assert(bits.size() == 0);
170
79147
  for(unsigned i = 0; i < width; ++i) {
171
72115
    bits.push_back(mkFalse<T>());
172
  }
173
7032
}
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
17082
T inline rippleCarryAdder(const std::vector<T>&a, const std::vector<T>& b, std::vector<T>& res, T carry) {
188
17082
  Assert(a.size() == b.size() && res.size() == 0);
189
190
224978
  for (unsigned i = 0 ; i < a.size(); ++i) {
191
415792
    T sum = mkXor(mkXor(a[i], b[i]), carry);
192
623688
    carry = mkOr( mkAnd(a[i], b[i]),
193
415792
                  mkAnd( mkXor(a[i], b[i]),
194
                         carry));
195
207896
    res.push_back(sum);
196
  }
197
198
17082
  return carry;
199
}
200
201
template <class T>
202
1228
inline void shiftAddMultiplier(const std::vector<T>&a, const std::vector<T>&b, std::vector<T>& res) {
203
204
12323
  for (unsigned i = 0; i < a.size(); ++i) {
205
11095
    res.push_back(mkAnd(b[0], a[i]));
206
  }
207
208
11095
  for(unsigned k = 1; k < res.size(); ++k) {
209
19734
  T carry_in = mkFalse<T>();
210
19734
  T carry_out;
211
102225
    for(unsigned j = 0; j < res.size() -k; ++j) {
212
184716
      T aj = mkAnd(b[k], a[j]);
213
184716
      carry_out = mkOr(mkAnd(res[j+k], aj),
214
92358
                       mkAnd( mkXor(res[j+k], aj), carry_in));
215
92358
      res[j+k] = mkXor(mkXor(res[j+k], aj), carry_in);
216
92358
      carry_in = carry_out;
217
    }
218
  }
219
1228
}
220
221
template <class T>
222
15809
T inline uLessThanBB(const std::vector<T>&a, const std::vector<T>& b, bool orEqual) {
223
15809
  Assert(a.size() && b.size());
224
225
15809
  T res = mkAnd(mkNot(a[0]), b[0]);
226
227
15809
  if(orEqual) {
228
    res = mkOr(res, mkIff(a[0], b[0]));
229
  }
230
231
157447
  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
283276
    res = mkOr(mkAnd(mkIff(a[i], b[i]), res),
234
283276
               mkAnd(mkNot(a[i]), b[i]));
235
  }
236
15809
  return res;
237
}
238
239
template <class T>
240
7663
T inline sLessThanBB(const std::vector<T>&a, const std::vector<T>& b, bool orEqual) {
241
7663
  Assert(a.size() && b.size());
242
7663
  if (a.size() == 1) {
243
862
    if(orEqual) {
244
      return  mkOr(mkIff(a[0], b[0]),
245
                   mkAnd(a[0], mkNot(b[0])));
246
    }
247
248
862
    return mkAnd(a[0], mkNot(b[0]));
249
  }
250
6801
  unsigned n = a.size() - 1;
251
13602
  std::vector<T> a1, b1;
252
6801
  extractBits(a, a1, 0, n-1);
253
6801
  extractBits(b, b1, 0, n-1);
254
255
  // unsigned comparison of the first n-1 bits
256
13602
  T ures = uLessThanBB(a1, b1, orEqual);
257
34005
  T res = mkOr(// a b have the same sign
258
13602
               mkAnd(mkIff(a[n], b[n]),
259
                     ures),
260
               // a is negative and b positive
261
6801
               mkAnd(a[n],
262
6801
                     mkNot(b[n])));
263
6801
  return res;
264
}
265
266
}  // namespace bv
267
}  // namespace theory
268
}  // namespace cvc5
269
270
#endif  // CVC5__THEORY__BV__BITBLAST__BITBLAST_UTILS_H