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