1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Liana Hadarean, Aina Niemetz, Tim King |
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 |
|
* Implementation of bitblasting functions for various operators. |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "cvc5_private.h" |
17 |
|
|
18 |
|
#ifndef CVC5__THEORY__BV__BITBLAST__BITBLAST_STRATEGIES_TEMPLATE_H |
19 |
|
#define CVC5__THEORY__BV__BITBLAST__BITBLAST_STRATEGIES_TEMPLATE_H |
20 |
|
|
21 |
|
#include <cmath> |
22 |
|
#include <ostream> |
23 |
|
|
24 |
|
#include "expr/node.h" |
25 |
|
#include "theory/bv/bitblast/bitblast_utils.h" |
26 |
|
#include "theory/bv/theory_bv_utils.h" |
27 |
|
#include "theory/rewriter.h" |
28 |
|
#include "util/bitvector.h" |
29 |
|
|
30 |
|
namespace cvc5 { |
31 |
|
|
32 |
|
namespace theory { |
33 |
|
namespace bv { |
34 |
|
|
35 |
|
/** |
36 |
|
* Default Atom Bitblasting strategies: |
37 |
|
* |
38 |
|
* @param node the atom to be bitblasted |
39 |
|
* @param bb the bitblaster |
40 |
|
*/ |
41 |
|
|
42 |
|
template <class T> |
43 |
|
T UndefinedAtomBBStrategy(TNode node, TBitblaster<T>* bb) { |
44 |
|
Debug("bitvector") << "TheoryBV::Bitblaster Undefined bitblasting strategy for kind: " |
45 |
|
<< node.getKind() << "\n"; |
46 |
|
Unreachable(); |
47 |
|
} |
48 |
|
|
49 |
|
|
50 |
|
template <class T> |
51 |
38263 |
T DefaultEqBB(TNode node, TBitblaster<T>* bb) { |
52 |
38263 |
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
53 |
|
|
54 |
38263 |
Assert(node.getKind() == kind::EQUAL); |
55 |
76526 |
std::vector<T> lhs, rhs; |
56 |
38263 |
bb->bbTerm(node[0], lhs); |
57 |
38263 |
bb->bbTerm(node[1], rhs); |
58 |
|
|
59 |
38263 |
Assert(lhs.size() == rhs.size()); |
60 |
|
|
61 |
76526 |
std::vector<T> bits_eq; |
62 |
455067 |
for (unsigned i = 0; i < lhs.size(); i++) { |
63 |
833608 |
T bit_eq = mkIff(lhs[i], rhs[i]); |
64 |
416804 |
bits_eq.push_back(bit_eq); |
65 |
|
} |
66 |
38263 |
T bv_eq = mkAnd(bits_eq); |
67 |
76526 |
return bv_eq; |
68 |
|
} |
69 |
|
|
70 |
|
template <class T> |
71 |
|
T AdderUltBB(TNode node, TBitblaster<T>* bb) { |
72 |
|
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
73 |
|
Assert(node.getKind() == kind::BITVECTOR_ULT); |
74 |
|
std::vector<T> a, b; |
75 |
|
bb->bbTerm(node[0], a); |
76 |
|
bb->bbTerm(node[1], b); |
77 |
|
Assert(a.size() == b.size()); |
78 |
|
|
79 |
|
// a < b <=> ~ (add(a, ~b, 1).carry_out) |
80 |
|
std::vector<T> not_b; |
81 |
|
negateBits(b, not_b); |
82 |
|
T carry = mkTrue<T>(); |
83 |
|
|
84 |
|
for (unsigned i = 0 ; i < a.size(); ++i) { |
85 |
|
carry = mkOr( mkAnd(a[i], not_b[i]), |
86 |
|
mkAnd( mkXor(a[i], not_b[i]), |
87 |
|
carry)); |
88 |
|
} |
89 |
|
return mkNot(carry); |
90 |
|
} |
91 |
|
|
92 |
|
|
93 |
|
template <class T> |
94 |
6308 |
T DefaultUltBB(TNode node, TBitblaster<T>* bb) { |
95 |
6308 |
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
96 |
6308 |
Assert(node.getKind() == kind::BITVECTOR_ULT); |
97 |
12616 |
std::vector<T> a, b; |
98 |
6308 |
bb->bbTerm(node[0], a); |
99 |
6308 |
bb->bbTerm(node[1], b); |
100 |
6308 |
Assert(a.size() == b.size()); |
101 |
|
|
102 |
|
// construct bitwise comparison |
103 |
6308 |
T res = uLessThanBB(a, b, false); |
104 |
12616 |
return res; |
105 |
|
} |
106 |
|
|
107 |
|
template <class T> |
108 |
|
T DefaultUleBB(TNode node, TBitblaster<T>* bb){ |
109 |
|
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
110 |
|
Assert(node.getKind() == kind::BITVECTOR_ULE); |
111 |
|
std::vector<T> a, b; |
112 |
|
|
113 |
|
bb->bbTerm(node[0], a); |
114 |
|
bb->bbTerm(node[1], b); |
115 |
|
Assert(a.size() == b.size()); |
116 |
|
// construct bitwise comparison |
117 |
|
T res = uLessThanBB(a, b, true); |
118 |
|
return res; |
119 |
|
} |
120 |
|
|
121 |
|
template <class T> |
122 |
|
T DefaultUgtBB(TNode node, TBitblaster<T>* bb){ |
123 |
|
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
124 |
|
// should be rewritten |
125 |
|
Unimplemented(); |
126 |
|
} |
127 |
|
template <class T> |
128 |
|
T DefaultUgeBB(TNode node, TBitblaster<T>* bb){ |
129 |
|
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
130 |
|
// should be rewritten |
131 |
|
Unimplemented(); |
132 |
|
} |
133 |
|
|
134 |
|
template <class T> |
135 |
6504 |
T DefaultSltBB(TNode node, TBitblaster<T>* bb){ |
136 |
6504 |
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
137 |
|
|
138 |
13008 |
std::vector<T> a, b; |
139 |
6504 |
bb->bbTerm(node[0], a); |
140 |
6504 |
bb->bbTerm(node[1], b); |
141 |
6504 |
Assert(a.size() == b.size()); |
142 |
|
|
143 |
6504 |
T res = sLessThanBB(a, b, false); |
144 |
13008 |
return res; |
145 |
|
} |
146 |
|
|
147 |
|
template <class T> |
148 |
|
T DefaultSleBB(TNode node, TBitblaster<T>* bb){ |
149 |
|
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
150 |
|
|
151 |
|
std::vector<T> a, b; |
152 |
|
bb->bbTerm(node[0], a); |
153 |
|
bb->bbTerm(node[1], b); |
154 |
|
Assert(a.size() == b.size()); |
155 |
|
|
156 |
|
T res = sLessThanBB(a, b, true); |
157 |
|
return res; |
158 |
|
} |
159 |
|
|
160 |
|
template <class T> |
161 |
|
T DefaultSgtBB(TNode node, TBitblaster<T>* bb){ |
162 |
|
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
163 |
|
// should be rewritten |
164 |
|
Unimplemented(); |
165 |
|
} |
166 |
|
|
167 |
|
template <class T> |
168 |
|
T DefaultSgeBB(TNode node, TBitblaster<T>* bb){ |
169 |
|
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
170 |
|
// should be rewritten |
171 |
|
Unimplemented(); |
172 |
|
} |
173 |
|
|
174 |
|
|
175 |
|
/// Term bitblasting strategies |
176 |
|
|
177 |
|
/** |
178 |
|
* Default Term Bitblasting strategies |
179 |
|
* |
180 |
|
* @param node the term to be bitblasted |
181 |
|
* @param bits [output parameter] bits representing the new term |
182 |
|
* @param bb the bitblaster in which the clauses are added |
183 |
|
*/ |
184 |
|
template <class T> |
185 |
|
void UndefinedTermBBStrategy(TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
186 |
|
Debug("bitvector") << "theory::bv:: Undefined bitblasting strategy for kind: " |
187 |
|
<< node.getKind() << "\n"; |
188 |
|
Unreachable(); |
189 |
|
} |
190 |
|
|
191 |
|
template <class T> |
192 |
19536 |
void DefaultVarBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
193 |
19536 |
Assert(bits.size() == 0); |
194 |
19536 |
bb->makeVariable(node, bits); |
195 |
|
|
196 |
19536 |
if(Debug.isOn("bitvector-bb")) { |
197 |
|
Debug("bitvector-bb") << "theory::bv::DefaultVarBB bitblasting " << node << "\n"; |
198 |
|
Debug("bitvector-bb") << " with bits " << toString(bits); |
199 |
|
} |
200 |
19536 |
} |
201 |
|
|
202 |
|
template <class T> |
203 |
14736 |
void DefaultConstBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
204 |
14736 |
Debug("bitvector-bb") << "theory::bv::DefaultConstBB bitblasting " << node << "\n"; |
205 |
14736 |
Assert(node.getKind() == kind::CONST_BITVECTOR); |
206 |
14736 |
Assert(bits.size() == 0); |
207 |
|
|
208 |
178677 |
for (unsigned i = 0; i < utils::getSize(node); ++i) { |
209 |
327882 |
Integer bit = node.getConst<BitVector>().extract(i, i).getValue(); |
210 |
163941 |
if(bit == Integer(0)){ |
211 |
110579 |
bits.push_back(mkFalse<T>()); |
212 |
|
} else { |
213 |
53362 |
Assert(bit == Integer(1)); |
214 |
53362 |
bits.push_back(mkTrue<T>()); |
215 |
|
} |
216 |
|
} |
217 |
14736 |
if(Debug.isOn("bitvector-bb")) { |
218 |
|
Debug("bitvector-bb") << "with bits: " << toString(bits) << "\n"; |
219 |
|
} |
220 |
14736 |
} |
221 |
|
|
222 |
|
|
223 |
|
template <class T> |
224 |
5116 |
void DefaultNotBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
225 |
5116 |
Debug("bitvector-bb") << "theory::bv::DefaultNotBB bitblasting " << node << "\n"; |
226 |
5116 |
Assert(node.getKind() == kind::BITVECTOR_NOT); |
227 |
5116 |
Assert(bits.size() == 0); |
228 |
10232 |
std::vector<T> bv; |
229 |
5116 |
bb->bbTerm(node[0], bv); |
230 |
5116 |
negateBits(bv, bits); |
231 |
5116 |
} |
232 |
|
|
233 |
|
template <class T> |
234 |
9087 |
void DefaultConcatBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
235 |
9087 |
Debug("bitvector-bb") << "theory::bv::DefaultConcatBB bitblasting " << node << "\n"; |
236 |
9087 |
Assert(bits.size() == 0); |
237 |
|
|
238 |
9087 |
Assert(node.getKind() == kind::BITVECTOR_CONCAT); |
239 |
33207 |
for (int i = node.getNumChildren() -1 ; i >= 0; --i ) { |
240 |
48240 |
TNode current = node[i]; |
241 |
48240 |
std::vector<T> current_bits; |
242 |
24120 |
bb->bbTerm(current, current_bits); |
243 |
|
|
244 |
148812 |
for(unsigned j = 0; j < utils::getSize(current); ++j) { |
245 |
124692 |
bits.push_back(current_bits[j]); |
246 |
|
} |
247 |
|
} |
248 |
9087 |
Assert(bits.size() == utils::getSize(node)); |
249 |
9087 |
if(Debug.isOn("bitvector-bb")) { |
250 |
|
Debug("bitvector-bb") << "with bits: " << toString(bits) << "\n"; |
251 |
|
} |
252 |
9087 |
} |
253 |
|
|
254 |
|
template <class T> |
255 |
4340 |
void DefaultAndBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
256 |
4340 |
Debug("bitvector-bb") << "theory::bv::DefaultAndBB bitblasting " << node << "\n"; |
257 |
|
|
258 |
4340 |
Assert(node.getKind() == kind::BITVECTOR_AND && bits.size() == 0); |
259 |
|
|
260 |
4340 |
bb->bbTerm(node[0], bits); |
261 |
8680 |
std::vector<T> current; |
262 |
11792 |
for(unsigned j = 1; j < node.getNumChildren(); ++j) { |
263 |
7452 |
bb->bbTerm(node[j], current); |
264 |
24565 |
for (unsigned i = 0; i < utils::getSize(node); ++i) { |
265 |
17113 |
bits[i] = mkAnd(bits[i], current[i]); |
266 |
|
} |
267 |
7452 |
current.clear(); |
268 |
|
} |
269 |
4340 |
Assert(bits.size() == utils::getSize(node)); |
270 |
4340 |
} |
271 |
|
|
272 |
|
template <class T> |
273 |
5702 |
void DefaultOrBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
274 |
5702 |
Debug("bitvector-bb") << "theory::bv::DefaultOrBB bitblasting " << node << "\n"; |
275 |
|
|
276 |
5702 |
Assert(node.getKind() == kind::BITVECTOR_OR && bits.size() == 0); |
277 |
|
|
278 |
5702 |
bb->bbTerm(node[0], bits); |
279 |
11404 |
std::vector<T> current; |
280 |
52702 |
for(unsigned j = 1; j < node.getNumChildren(); ++j) { |
281 |
47000 |
bb->bbTerm(node[j], current); |
282 |
97613 |
for (unsigned i = 0; i < utils::getSize(node); ++i) { |
283 |
50613 |
bits[i] = mkOr(bits[i], current[i]); |
284 |
|
} |
285 |
47000 |
current.clear(); |
286 |
|
} |
287 |
5702 |
Assert(bits.size() == utils::getSize(node)); |
288 |
5702 |
} |
289 |
|
|
290 |
|
template <class T> |
291 |
516 |
void DefaultXorBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
292 |
516 |
Debug("bitvector-bb") << "theory::bv::DefaultXorBB bitblasting " << node << "\n"; |
293 |
|
|
294 |
516 |
Assert(node.getKind() == kind::BITVECTOR_XOR && bits.size() == 0); |
295 |
|
|
296 |
516 |
bb->bbTerm(node[0], bits); |
297 |
1032 |
std::vector<T> current; |
298 |
1039 |
for(unsigned j = 1; j < node.getNumChildren(); ++j) { |
299 |
523 |
bb->bbTerm(node[j], current); |
300 |
2856 |
for (unsigned i = 0; i < utils::getSize(node); ++i) { |
301 |
2333 |
bits[i] = mkXor(bits[i], current[i]); |
302 |
|
} |
303 |
523 |
current.clear(); |
304 |
|
} |
305 |
516 |
Assert(bits.size() == utils::getSize(node)); |
306 |
516 |
} |
307 |
|
|
308 |
|
template <class T> |
309 |
|
void DefaultXnorBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
310 |
|
Debug("bitvector-bb") << "theory::bv::DefaultXnorBB bitblasting " << node << "\n"; |
311 |
|
|
312 |
|
Assert(node.getNumChildren() == 2 && node.getKind() == kind::BITVECTOR_XNOR |
313 |
|
&& bits.size() == 0); |
314 |
|
std::vector<T> lhs, rhs; |
315 |
|
bb->bbTerm(node[0], lhs); |
316 |
|
bb->bbTerm(node[1], rhs); |
317 |
|
Assert(lhs.size() == rhs.size()); |
318 |
|
|
319 |
|
for (unsigned i = 0; i < lhs.size(); ++i) { |
320 |
|
bits.push_back(mkIff(lhs[i], rhs[i])); |
321 |
|
} |
322 |
|
} |
323 |
|
|
324 |
|
|
325 |
|
template <class T> |
326 |
|
void DefaultNandBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
327 |
|
Debug("bitvector") << "theory::bv:: Unimplemented kind " |
328 |
|
<< node.getKind() << "\n"; |
329 |
|
Unimplemented(); |
330 |
|
} |
331 |
|
template <class T> |
332 |
|
void DefaultNorBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
333 |
|
Debug("bitvector") << "theory::bv:: Unimplemented kind " |
334 |
|
<< node.getKind() << "\n"; |
335 |
|
Unimplemented(); |
336 |
|
} |
337 |
|
template <class T> |
338 |
6779 |
void DefaultCompBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
339 |
6779 |
Debug("bitvector") << "theory::bv:: DefaultCompBB bitblasting "<< node << "\n"; |
340 |
|
|
341 |
6779 |
Assert(utils::getSize(node) == 1 && bits.size() == 0 |
342 |
|
&& node.getKind() == kind::BITVECTOR_COMP); |
343 |
13558 |
std::vector<T> a, b; |
344 |
6779 |
bb->bbTerm(node[0], a); |
345 |
6779 |
bb->bbTerm(node[1], b); |
346 |
|
|
347 |
13558 |
std::vector<T> bit_eqs; |
348 |
74801 |
for (unsigned i = 0; i < a.size(); ++i) { |
349 |
136044 |
T eq = mkIff(a[i], b[i]); |
350 |
68022 |
bit_eqs.push_back(eq); |
351 |
|
} |
352 |
13558 |
T a_eq_b = mkAnd(bit_eqs); |
353 |
6779 |
bits.push_back(a_eq_b); |
354 |
6779 |
} |
355 |
|
|
356 |
|
template <class T> |
357 |
1191 |
void DefaultMultBB (TNode node, std::vector<T>& res, TBitblaster<T>* bb) { |
358 |
1191 |
Debug("bitvector") << "theory::bv:: DefaultMultBB bitblasting "<< node << "\n"; |
359 |
1191 |
Assert(res.size() == 0 && node.getKind() == kind::BITVECTOR_MULT); |
360 |
|
|
361 |
|
// if (node.getNumChildren() == 2) { |
362 |
|
// std::vector<T> a; |
363 |
|
// std::vector<T> b; |
364 |
|
// bb->bbTerm(node[0], a); |
365 |
|
// bb->bbTerm(node[1], b); |
366 |
|
// unsigned bw = utils::getSize(node); |
367 |
|
// unsigned thresh = bw % 2 ? bw/2 : bw/2 - 1; |
368 |
|
// bool no_overflow = true; |
369 |
|
// for (unsigned i = thresh; i < bw; ++i) { |
370 |
|
// if (a[i] != mkFalse<T> || b[i] != mkFalse<T> ) { |
371 |
|
// no_overflow = false; |
372 |
|
// } |
373 |
|
// } |
374 |
|
// if (no_overflow) { |
375 |
|
// shiftAddMultiplier(); |
376 |
|
// return; |
377 |
|
// } |
378 |
|
|
379 |
|
// } |
380 |
|
|
381 |
2382 |
std::vector<T> newres; |
382 |
1191 |
bb->bbTerm(node[0], res); |
383 |
2418 |
for(unsigned i = 1; i < node.getNumChildren(); ++i) { |
384 |
2454 |
std::vector<T> current; |
385 |
1227 |
bb->bbTerm(node[i], current); |
386 |
1227 |
newres.clear(); |
387 |
|
// constructs a simple shift and add multiplier building the result |
388 |
|
// in res |
389 |
1227 |
shiftAddMultiplier(res, current, newres); |
390 |
1227 |
res = newres; |
391 |
|
} |
392 |
1191 |
if(Debug.isOn("bitvector-bb")) { |
393 |
|
Debug("bitvector-bb") << "with bits: " << toString(res) << "\n"; |
394 |
|
} |
395 |
1191 |
} |
396 |
|
|
397 |
|
template <class T> |
398 |
2881 |
void DefaultAddBB(TNode node, std::vector<T>& res, TBitblaster<T>* bb) |
399 |
|
{ |
400 |
2881 |
Debug("bitvector-bb") << "theory::bv::DefaultAddBB bitblasting " << node |
401 |
|
<< "\n"; |
402 |
2881 |
Assert(node.getKind() == kind::BITVECTOR_ADD && res.size() == 0); |
403 |
|
|
404 |
2881 |
bb->bbTerm(node[0], res); |
405 |
|
|
406 |
5762 |
std::vector<T> newres; |
407 |
|
|
408 |
5917 |
for(unsigned i = 1; i < node.getNumChildren(); ++i) { |
409 |
6072 |
std::vector<T> current; |
410 |
3036 |
bb->bbTerm(node[i], current); |
411 |
3036 |
newres.clear(); |
412 |
3036 |
rippleCarryAdder(res, current, newres, mkFalse<T>()); |
413 |
3036 |
res = newres; |
414 |
|
} |
415 |
|
|
416 |
2881 |
Assert(res.size() == utils::getSize(node)); |
417 |
2881 |
} |
418 |
|
|
419 |
|
template <class T> |
420 |
|
void DefaultSubBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
421 |
|
Debug("bitvector-bb") << "theory::bv::DefaultSubBB bitblasting " << node << "\n"; |
422 |
|
Assert(node.getKind() == kind::BITVECTOR_SUB && node.getNumChildren() == 2 |
423 |
|
&& bits.size() == 0); |
424 |
|
|
425 |
|
std::vector<T> a, b; |
426 |
|
bb->bbTerm(node[0], a); |
427 |
|
bb->bbTerm(node[1], b); |
428 |
|
Assert(a.size() == b.size() && utils::getSize(node) == a.size()); |
429 |
|
|
430 |
|
// bvsub a b = adder(a, ~b, 1) |
431 |
|
std::vector<T> not_b; |
432 |
|
negateBits(b, not_b); |
433 |
|
rippleCarryAdder(a, not_b, bits, mkTrue<T>()); |
434 |
|
} |
435 |
|
|
436 |
|
template <class T> |
437 |
1487 |
void DefaultNegBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
438 |
1487 |
Debug("bitvector-bb") << "theory::bv::DefaultNegBB bitblasting " << node << "\n"; |
439 |
1487 |
Assert(node.getKind() == kind::BITVECTOR_NEG); |
440 |
|
|
441 |
2974 |
std::vector<T> a; |
442 |
1487 |
bb->bbTerm(node[0], a); |
443 |
1487 |
Assert(utils::getSize(node) == a.size()); |
444 |
|
|
445 |
|
// -a = add(~a, 0, 1). |
446 |
2974 |
std::vector<T> not_a; |
447 |
1487 |
negateBits(a, not_a); |
448 |
2974 |
std::vector<T> zero; |
449 |
1487 |
makeZero(zero, utils::getSize(node)); |
450 |
|
|
451 |
1487 |
rippleCarryAdder(not_a, zero, bits, mkTrue<T>()); |
452 |
1487 |
} |
453 |
|
|
454 |
|
template <class T> |
455 |
4867 |
void uDivModRec(const std::vector<T>& a, const std::vector<T>& b, std::vector<T>& q, std::vector<T>& r, unsigned rec_width) { |
456 |
4867 |
Assert(q.size() == 0 && r.size() == 0); |
457 |
|
|
458 |
4867 |
if(rec_width == 0 || isZero(a)) { |
459 |
683 |
makeZero(q, a.size()); |
460 |
683 |
makeZero(r, a.size()); |
461 |
683 |
return; |
462 |
|
} |
463 |
|
|
464 |
8368 |
std::vector<T> q1, r1; |
465 |
8368 |
std::vector<T> a1 = a; |
466 |
4184 |
rshift(a1, 1); |
467 |
|
|
468 |
4184 |
uDivModRec(a1, b, q1, r1, rec_width - 1); |
469 |
|
// shift the quotient and remainder (i.e. multiply by two) and add 1 to remainder if a is odd |
470 |
4184 |
lshift(q1, 1); |
471 |
4184 |
lshift(r1, 1); |
472 |
|
|
473 |
|
|
474 |
8368 |
T is_odd = mkIff(a[0], mkTrue<T>()); |
475 |
8368 |
T one_if_odd = mkIte(is_odd, mkTrue<T>(), mkFalse<T>()); |
476 |
|
|
477 |
8368 |
std::vector<T> zero; |
478 |
4184 |
makeZero(zero, b.size()); |
479 |
|
|
480 |
8368 |
std::vector<T> r1_shift_add; |
481 |
|
// account for a being odd |
482 |
4184 |
rippleCarryAdder(r1, zero, r1_shift_add, one_if_odd); |
483 |
|
// now check if the remainder is greater than b |
484 |
8368 |
std::vector<T> not_b; |
485 |
4184 |
negateBits(b, not_b); |
486 |
8368 |
std::vector<T> r_minus_b; |
487 |
8368 |
T co1; |
488 |
|
// use adder because we need r_minus_b anyway |
489 |
4184 |
co1 = rippleCarryAdder(r1_shift_add, not_b, r_minus_b, mkTrue<T>()); |
490 |
|
// sign is true if r1 < b |
491 |
8368 |
T sign = mkNot(co1); |
492 |
|
|
493 |
4184 |
q1[0] = mkIte(sign, q1[0], mkTrue<T>()); |
494 |
|
|
495 |
|
// would be nice to have a high level ITE instead of bitwise |
496 |
54755 |
for(unsigned i = 0; i < a.size(); ++i) { |
497 |
50571 |
r1_shift_add[i] = mkIte(sign, r1_shift_add[i], r_minus_b[i]); |
498 |
|
} |
499 |
|
|
500 |
|
// check if a < b |
501 |
|
|
502 |
8368 |
std::vector<T> a_minus_b; |
503 |
8368 |
T co2 = rippleCarryAdder(a, not_b, a_minus_b, mkTrue<T>()); |
504 |
|
// Node a_lt_b = a_minus_b.back(); |
505 |
8368 |
T a_lt_b = mkNot(co2); |
506 |
|
|
507 |
54755 |
for(unsigned i = 0; i < a.size(); ++i) { |
508 |
101142 |
T qval = mkIte(a_lt_b, mkFalse<T>(), q1[i]); |
509 |
101142 |
T rval = mkIte(a_lt_b, a[i], r1_shift_add[i]); |
510 |
50571 |
q.push_back(qval); |
511 |
50571 |
r.push_back(rval); |
512 |
|
} |
513 |
|
|
514 |
|
} |
515 |
|
|
516 |
|
template <class T> |
517 |
381 |
void DefaultUdivBB(TNode node, std::vector<T>& q, TBitblaster<T>* bb) |
518 |
|
{ |
519 |
381 |
Debug("bitvector-bb") << "theory::bv::DefaultUdivBB bitblasting " << node |
520 |
|
<< "\n"; |
521 |
381 |
Assert(node.getKind() == kind::BITVECTOR_UDIV && q.size() == 0); |
522 |
|
|
523 |
762 |
std::vector<T> a, b; |
524 |
381 |
bb->bbTerm(node[0], a); |
525 |
381 |
bb->bbTerm(node[1], b); |
526 |
|
|
527 |
762 |
std::vector<T> r; |
528 |
381 |
uDivModRec(a, b, q, r, utils::getSize(node)); |
529 |
|
// adding a special case for division by 0 |
530 |
762 |
std::vector<T> iszero; |
531 |
3058 |
for (unsigned i = 0; i < b.size(); ++i) |
532 |
|
{ |
533 |
2677 |
iszero.push_back(mkIff(b[i], mkFalse<T>())); |
534 |
|
} |
535 |
762 |
T b_is_0 = mkAnd(iszero); |
536 |
|
|
537 |
3058 |
for (unsigned i = 0; i < q.size(); ++i) |
538 |
|
{ |
539 |
2677 |
q[i] = mkIte(b_is_0, mkTrue<T>(), q[i]); // a udiv 0 is 11..11 |
540 |
2677 |
r[i] = mkIte(b_is_0, a[i], r[i]); // a urem 0 is a |
541 |
|
} |
542 |
|
|
543 |
|
// cache the remainder in case we need it later |
544 |
762 |
Node remainder = Rewriter::rewrite( |
545 |
|
NodeManager::currentNM()->mkNode(kind::BITVECTOR_UREM, node[0], node[1])); |
546 |
381 |
bb->storeBBTerm(remainder, r); |
547 |
381 |
} |
548 |
|
|
549 |
|
template <class T> |
550 |
302 |
void DefaultUremBB(TNode node, std::vector<T>& rem, TBitblaster<T>* bb) |
551 |
|
{ |
552 |
302 |
Debug("bitvector-bb") << "theory::bv::DefaultUremBB bitblasting " << node |
553 |
|
<< "\n"; |
554 |
302 |
Assert(node.getKind() == kind::BITVECTOR_UREM && rem.size() == 0); |
555 |
|
|
556 |
604 |
std::vector<T> a, b; |
557 |
302 |
bb->bbTerm(node[0], a); |
558 |
302 |
bb->bbTerm(node[1], b); |
559 |
|
|
560 |
604 |
std::vector<T> q; |
561 |
302 |
uDivModRec(a, b, q, rem, utils::getSize(node)); |
562 |
|
// adding a special case for division by 0 |
563 |
604 |
std::vector<T> iszero; |
564 |
2432 |
for (unsigned i = 0; i < b.size(); ++i) |
565 |
|
{ |
566 |
2130 |
iszero.push_back(mkIff(b[i], mkFalse<T>())); |
567 |
|
} |
568 |
604 |
T b_is_0 = mkAnd(iszero); |
569 |
|
|
570 |
2432 |
for (unsigned i = 0; i < q.size(); ++i) |
571 |
|
{ |
572 |
2130 |
q[i] = mkIte(b_is_0, mkTrue<T>(), q[i]); // a udiv 0 is 11..11 |
573 |
2130 |
rem[i] = mkIte(b_is_0, a[i], rem[i]); // a urem 0 is a |
574 |
|
} |
575 |
|
|
576 |
|
// cache the quotient in case we need it later |
577 |
604 |
Node quotient = Rewriter::rewrite( |
578 |
|
NodeManager::currentNM()->mkNode(kind::BITVECTOR_UDIV, node[0], node[1])); |
579 |
302 |
bb->storeBBTerm(quotient, q); |
580 |
302 |
} |
581 |
|
|
582 |
|
template <class T> |
583 |
|
void DefaultSdivBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
584 |
|
Debug("bitvector") << "theory::bv:: Unimplemented kind " |
585 |
|
<< node.getKind() << "\n"; |
586 |
|
Unimplemented(); |
587 |
|
} |
588 |
|
template <class T> |
589 |
|
void DefaultSremBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
590 |
|
Debug("bitvector") << "theory::bv:: Unimplemented kind " |
591 |
|
<< node.getKind() << "\n"; |
592 |
|
Unimplemented(); |
593 |
|
} |
594 |
|
template <class T> |
595 |
|
void DefaultSmodBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
596 |
|
Debug("bitvector") << "theory::bv:: Unimplemented kind " |
597 |
|
<< node.getKind() << "\n"; |
598 |
|
Unimplemented(); |
599 |
|
} |
600 |
|
|
601 |
|
template <class T> |
602 |
691 |
void DefaultShlBB(TNode node, std::vector<T>& res, TBitblaster<T>* bb) |
603 |
|
{ |
604 |
691 |
Debug("bitvector-bb") << "theory::bv::DefaultShlBB bitblasting " << node |
605 |
|
<< "\n"; |
606 |
691 |
Assert(node.getKind() == kind::BITVECTOR_SHL && res.size() == 0); |
607 |
1382 |
std::vector<T> a, b; |
608 |
691 |
bb->bbTerm(node[0], a); |
609 |
691 |
bb->bbTerm(node[1], b); |
610 |
|
|
611 |
|
// check for b < log2(n) |
612 |
691 |
unsigned size = utils::getSize(node); |
613 |
691 |
unsigned log2_size = std::ceil(log2((double)size)); |
614 |
1382 |
Node a_size = utils::mkConst(size, size); |
615 |
|
|
616 |
1382 |
std::vector<T> a_size_bits; |
617 |
691 |
DefaultConstBB(a_size, a_size_bits, bb); |
618 |
1382 |
T b_ult_a_size = uLessThanBB(b, a_size_bits, false); |
619 |
|
|
620 |
1382 |
std::vector<T> prev_res; |
621 |
691 |
res = a; |
622 |
|
// we only need to look at the bits bellow log2_a_size |
623 |
2321 |
for (unsigned s = 0; s < log2_size; ++s) |
624 |
|
{ |
625 |
|
// barrel shift stage: at each stage you can either shift by 2^s bits |
626 |
|
// or leave the previous stage untouched |
627 |
1630 |
prev_res = res; |
628 |
1630 |
unsigned threshold = pow(2, s); |
629 |
17800 |
for (unsigned i = 0; i < a.size(); ++i) |
630 |
|
{ |
631 |
16170 |
if (i < threshold) |
632 |
|
{ |
633 |
|
// if b[s] is true then we must have shifted by at least 2^b bits so |
634 |
|
// all bits bellow 2^s will be 0, otherwise just use previous shift |
635 |
|
// value |
636 |
4672 |
res[i] = mkIte(b[s], mkFalse<T>(), prev_res[i]); |
637 |
|
} |
638 |
|
else |
639 |
|
{ |
640 |
|
// if b[s]= 0, use previous value, otherwise shift by threshold bits |
641 |
11498 |
Assert(i >= threshold); |
642 |
11498 |
res[i] = mkIte(b[s], prev_res[i - threshold], prev_res[i]); |
643 |
|
} |
644 |
|
} |
645 |
|
} |
646 |
691 |
prev_res = res; |
647 |
5340 |
for (unsigned i = 0; i < b.size(); ++i) |
648 |
|
{ |
649 |
|
// this is fine because b_ult_a_size has been bit-blasted |
650 |
4649 |
res[i] = mkIte(b_ult_a_size, prev_res[i], mkFalse<T>()); |
651 |
|
} |
652 |
|
|
653 |
691 |
if (Debug.isOn("bitvector-bb")) |
654 |
|
{ |
655 |
|
Debug("bitvector-bb") << "with bits: " << toString(res) << "\n"; |
656 |
|
} |
657 |
691 |
} |
658 |
|
|
659 |
|
template <class T> |
660 |
805 |
void DefaultLshrBB(TNode node, std::vector<T>& res, TBitblaster<T>* bb) |
661 |
|
{ |
662 |
805 |
Debug("bitvector-bb") << "theory::bv::DefaultLshrBB bitblasting " << node |
663 |
|
<< "\n"; |
664 |
805 |
Assert(node.getKind() == kind::BITVECTOR_LSHR && res.size() == 0); |
665 |
1610 |
std::vector<T> a, b; |
666 |
805 |
bb->bbTerm(node[0], a); |
667 |
805 |
bb->bbTerm(node[1], b); |
668 |
|
|
669 |
|
// check for b < log2(n) |
670 |
805 |
unsigned size = utils::getSize(node); |
671 |
805 |
unsigned log2_size = std::ceil(log2((double)size)); |
672 |
1610 |
Node a_size = utils::mkConst(size, size); |
673 |
|
|
674 |
1610 |
std::vector<T> a_size_bits; |
675 |
805 |
DefaultConstBB(a_size, a_size_bits, bb); |
676 |
1610 |
T b_ult_a_size = uLessThanBB(b, a_size_bits, false); |
677 |
|
|
678 |
805 |
res = a; |
679 |
1610 |
std::vector<T> prev_res; |
680 |
|
|
681 |
2752 |
for (unsigned s = 0; s < log2_size; ++s) |
682 |
|
{ |
683 |
|
// barrel shift stage: at each stage you can either shift by 2^s bits |
684 |
|
// or leave the previous stage untouched |
685 |
1947 |
prev_res = res; |
686 |
1947 |
int threshold = pow(2, s); |
687 |
22435 |
for (unsigned i = 0; i < a.size(); ++i) |
688 |
|
{ |
689 |
20488 |
if (i + threshold >= a.size()) |
690 |
|
{ |
691 |
|
// if b[s] is true then we must have shifted by at least 2^b bits so |
692 |
|
// all bits above 2^s will be 0, otherwise just use previous shift value |
693 |
5344 |
res[i] = mkIte(b[s], mkFalse<T>(), prev_res[i]); |
694 |
|
} |
695 |
|
else |
696 |
|
{ |
697 |
|
// if b[s]= 0, use previous value, otherwise shift by threshold bits |
698 |
15144 |
Assert(i + threshold < a.size()); |
699 |
15144 |
res[i] = mkIte(mkNot(b[s]), prev_res[i], prev_res[i + threshold]); |
700 |
|
} |
701 |
|
} |
702 |
|
} |
703 |
|
|
704 |
805 |
prev_res = res; |
705 |
6735 |
for (unsigned i = 0; i < b.size(); ++i) |
706 |
|
{ |
707 |
|
// this is fine because b_ult_a_size has been bit-blasted |
708 |
5930 |
res[i] = mkIte(b_ult_a_size, prev_res[i], mkFalse<T>()); |
709 |
|
} |
710 |
|
|
711 |
805 |
if (Debug.isOn("bitvector-bb")) |
712 |
|
{ |
713 |
|
Debug("bitvector-bb") << "with bits: " << toString(res) << "\n"; |
714 |
|
} |
715 |
805 |
} |
716 |
|
|
717 |
|
template <class T> |
718 |
623 |
void DefaultAshrBB(TNode node, std::vector<T>& res, TBitblaster<T>* bb) |
719 |
|
{ |
720 |
623 |
Debug("bitvector-bb") << "theory::bv::DefaultAshrBB bitblasting " << node |
721 |
|
<< "\n"; |
722 |
623 |
Assert(node.getKind() == kind::BITVECTOR_ASHR && res.size() == 0); |
723 |
1246 |
std::vector<T> a, b; |
724 |
623 |
bb->bbTerm(node[0], a); |
725 |
623 |
bb->bbTerm(node[1], b); |
726 |
|
|
727 |
|
// check for b < n |
728 |
623 |
unsigned size = utils::getSize(node); |
729 |
623 |
unsigned log2_size = std::ceil(log2((double)size)); |
730 |
1246 |
Node a_size = utils::mkConst(size, size); |
731 |
|
|
732 |
1246 |
std::vector<T> a_size_bits; |
733 |
623 |
DefaultConstBB(a_size, a_size_bits, bb); |
734 |
1246 |
T b_ult_a_size = uLessThanBB(b, a_size_bits, false); |
735 |
|
|
736 |
623 |
res = a; |
737 |
1246 |
T sign_bit = a.back(); |
738 |
1246 |
std::vector<T> prev_res; |
739 |
|
|
740 |
1911 |
for (unsigned s = 0; s < log2_size; ++s) |
741 |
|
{ |
742 |
|
// barrel shift stage: at each stage you can either shift by 2^s bits |
743 |
|
// or leave the previous stage untouched |
744 |
1288 |
prev_res = res; |
745 |
1288 |
int threshold = pow(2, s); |
746 |
10603 |
for (unsigned i = 0; i < a.size(); ++i) |
747 |
|
{ |
748 |
9315 |
if (i + threshold >= a.size()) |
749 |
|
{ |
750 |
|
// if b[s] is true then we must have shifted by at least 2^b bits so |
751 |
|
// all bits above 2^s will be the sign bit, otherwise just use previous |
752 |
|
// shift value |
753 |
2890 |
res[i] = mkIte(b[s], sign_bit, prev_res[i]); |
754 |
|
} |
755 |
|
else |
756 |
|
{ |
757 |
|
// if b[s]= 0, use previous value, otherwise shift by threshold bits |
758 |
6425 |
Assert(i + threshold < a.size()); |
759 |
6425 |
res[i] = mkIte(mkNot(b[s]), prev_res[i], prev_res[i + threshold]); |
760 |
|
} |
761 |
|
} |
762 |
|
} |
763 |
|
|
764 |
623 |
prev_res = res; |
765 |
3864 |
for (unsigned i = 0; i < b.size(); ++i) |
766 |
|
{ |
767 |
|
// this is fine because b_ult_a_size has been bit-blasted |
768 |
3241 |
res[i] = mkIte(b_ult_a_size, prev_res[i], sign_bit); |
769 |
|
} |
770 |
|
|
771 |
623 |
if (Debug.isOn("bitvector-bb")) |
772 |
|
{ |
773 |
|
Debug("bitvector-bb") << "with bits: " << toString(res) << "\n"; |
774 |
|
} |
775 |
623 |
} |
776 |
|
|
777 |
|
template <class T> |
778 |
581 |
void DefaultUltbvBB (TNode node, std::vector<T>& res, TBitblaster<T>* bb) { |
779 |
581 |
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
780 |
581 |
Assert(node.getKind() == kind::BITVECTOR_ULTBV); |
781 |
1162 |
std::vector<T> a, b; |
782 |
581 |
bb->bbTerm(node[0], a); |
783 |
581 |
bb->bbTerm(node[1], b); |
784 |
581 |
Assert(a.size() == b.size()); |
785 |
|
|
786 |
|
// construct bitwise comparison |
787 |
581 |
res.push_back(uLessThanBB(a, b, false)); |
788 |
581 |
} |
789 |
|
|
790 |
|
template <class T> |
791 |
1175 |
void DefaultSltbvBB (TNode node, std::vector<T>& res, TBitblaster<T>* bb) { |
792 |
1175 |
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
793 |
1175 |
Assert(node.getKind() == kind::BITVECTOR_SLTBV); |
794 |
2350 |
std::vector<T> a, b; |
795 |
1175 |
bb->bbTerm(node[0], a); |
796 |
1175 |
bb->bbTerm(node[1], b); |
797 |
1175 |
Assert(a.size() == b.size()); |
798 |
|
|
799 |
|
// construct bitwise comparison |
800 |
1175 |
res.push_back(sLessThanBB(a, b, false)); |
801 |
1175 |
} |
802 |
|
|
803 |
|
template <class T> |
804 |
3523 |
void DefaultIteBB (TNode node, std::vector<T>& res, TBitblaster<T>* bb) { |
805 |
3523 |
Debug("bitvector-bb") << "Bitblasting node " << node << "\n"; |
806 |
3523 |
Assert(node.getKind() == kind::BITVECTOR_ITE); |
807 |
7046 |
std::vector<T> cond, thenpart, elsepart; |
808 |
3523 |
bb->bbTerm(node[0], cond); |
809 |
3523 |
bb->bbTerm(node[1], thenpart); |
810 |
3523 |
bb->bbTerm(node[2], elsepart); |
811 |
|
|
812 |
3523 |
Assert(cond.size() == 1); |
813 |
3523 |
Assert(thenpart.size() == elsepart.size()); |
814 |
|
|
815 |
58574 |
for (unsigned i = 0; i < thenpart.size(); ++i) { |
816 |
|
// (~cond OR thenpart) AND (cond OR elsepart) |
817 |
55051 |
res.push_back(mkAnd(mkOr(mkNot(cond[0]),thenpart[i]),mkOr(cond[0],elsepart[i]))); |
818 |
|
} |
819 |
3523 |
} |
820 |
|
|
821 |
|
template <class T> |
822 |
8996 |
void DefaultExtractBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
823 |
8996 |
Assert(node.getKind() == kind::BITVECTOR_EXTRACT); |
824 |
8996 |
Assert(bits.size() == 0); |
825 |
|
|
826 |
17992 |
std::vector<T> base_bits; |
827 |
8996 |
bb->bbTerm(node[0], base_bits); |
828 |
8996 |
unsigned high = utils::getExtractHigh(node); |
829 |
8996 |
unsigned low = utils::getExtractLow(node); |
830 |
|
|
831 |
70422 |
for (unsigned i = low; i <= high; ++i) { |
832 |
61426 |
bits.push_back(base_bits[i]); |
833 |
|
} |
834 |
8996 |
Assert(bits.size() == high - low + 1); |
835 |
|
|
836 |
8996 |
if(Debug.isOn("bitvector-bb")) { |
837 |
|
Debug("bitvector-bb") << "theory::bv::DefaultExtractBB bitblasting " << node << "\n"; |
838 |
|
Debug("bitvector-bb") << " with bits " << toString(bits); |
839 |
|
} |
840 |
8996 |
} |
841 |
|
|
842 |
|
|
843 |
|
template <class T> |
844 |
|
void DefaultRepeatBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
845 |
|
Debug("bitvector") << "theory::bv:: Unimplemented kind " |
846 |
|
<< node.getKind() << "\n"; |
847 |
|
// this should be rewritten |
848 |
|
Unimplemented(); |
849 |
|
} |
850 |
|
|
851 |
|
template <class T> |
852 |
|
void DefaultZeroExtendBB (TNode node, std::vector<T>& res_bits, TBitblaster<T>* bb) { |
853 |
|
|
854 |
|
Debug("bitvector-bb") << "theory::bv::DefaultZeroExtendBB bitblasting " << node << "\n"; |
855 |
|
|
856 |
|
// this should be rewritten |
857 |
|
Unimplemented(); |
858 |
|
|
859 |
|
} |
860 |
|
|
861 |
|
template <class T> |
862 |
4080 |
void DefaultSignExtendBB (TNode node, std::vector<T>& res_bits, TBitblaster<T>* bb) { |
863 |
4080 |
Debug("bitvector-bb") << "theory::bv::DefaultSignExtendBB bitblasting " << node << "\n"; |
864 |
|
|
865 |
4080 |
Assert(node.getKind() == kind::BITVECTOR_SIGN_EXTEND && res_bits.size() == 0); |
866 |
|
|
867 |
8160 |
std::vector<T> bits; |
868 |
4080 |
bb->bbTerm(node[0], bits); |
869 |
|
|
870 |
8160 |
T sign_bit = bits.back(); |
871 |
4080 |
unsigned amount = |
872 |
8160 |
node.getOperator().getConst<BitVectorSignExtend>().d_signExtendAmount; |
873 |
|
|
874 |
15534 |
for (unsigned i = 0; i < bits.size(); ++i ) { |
875 |
11454 |
res_bits.push_back(bits[i]); |
876 |
|
} |
877 |
|
|
878 |
23240 |
for (unsigned i = 0 ; i < amount ; ++i ) { |
879 |
19160 |
res_bits.push_back(sign_bit); |
880 |
|
} |
881 |
|
|
882 |
4080 |
Assert(res_bits.size() == amount + bits.size()); |
883 |
4080 |
} |
884 |
|
|
885 |
|
template <class T> |
886 |
|
void DefaultRotateRightBB (TNode node, std::vector<T>& res, TBitblaster<T>* bb) { |
887 |
|
Debug("bitvector") << "theory::bv:: Unimplemented kind " |
888 |
|
<< node.getKind() << "\n"; |
889 |
|
|
890 |
|
Unimplemented(); |
891 |
|
} |
892 |
|
|
893 |
|
template <class T> |
894 |
|
void DefaultRotateLeftBB (TNode node, std::vector<T>& bits, TBitblaster<T>* bb) { |
895 |
|
Debug("bitvector") << "theory::bv:: Unimplemented kind " |
896 |
|
<< node.getKind() << "\n"; |
897 |
|
Unimplemented(); |
898 |
|
} |
899 |
|
|
900 |
|
|
901 |
|
} |
902 |
|
} |
903 |
|
} // namespace cvc5 |
904 |
|
|
905 |
|
#endif |