CBMC
Loading...
Searching...
No Matches
bv_utils.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "bv_utils.h"
10
11#include <list>
12#include <utility>
13
14bvt bv_utilst::build_constant(const mp_integer &n, std::size_t width)
15{
16 std::string n_str=integer2binary(n, width);
17 CHECK_RETURN(n_str.size() == width);
18 bvt result;
19 result.resize(width);
20 for(std::size_t i=0; i<width; i++)
21 result[i]=const_literal(n_str[width-i-1]=='1');
22 return result;
23}
24
26{
27 PRECONDITION(!bv.empty());
28 bvt tmp;
29 tmp=bv;
30 tmp.erase(tmp.begin(), tmp.begin()+1);
31 return prop.land(is_zero(tmp), bv[0]);
32}
33
34void bv_utilst::set_equal(const bvt &a, const bvt &b)
35{
36 PRECONDITION(a.size() == b.size());
37 for(std::size_t i=0; i<a.size(); i++)
38 prop.set_equal(a[i], b[i]);
39}
40
41bvt bv_utilst::extract(const bvt &a, std::size_t first, std::size_t last)
42{
43 // preconditions
44 PRECONDITION(first < a.size());
45 PRECONDITION(last < a.size());
46 PRECONDITION(first <= last);
47
48 bvt result=a;
49 result.resize(last+1);
50 if(first!=0)
51 result.erase(result.begin(), result.begin()+first);
52
53 POSTCONDITION(result.size() == last - first + 1);
54 return result;
55}
56
57bvt bv_utilst::extract_msb(const bvt &a, std::size_t n)
58{
59 // preconditions
60 PRECONDITION(n <= a.size());
61
62 bvt result=a;
63 result.erase(result.begin(), result.begin()+(result.size()-n));
64
65 POSTCONDITION(result.size() == n);
66 return result;
67}
68
69bvt bv_utilst::extract_lsb(const bvt &a, std::size_t n)
70{
71 // preconditions
72 PRECONDITION(n <= a.size());
73
74 bvt result=a;
75 result.resize(n);
76 return result;
77}
78
80{
81 bvt result;
82
83 result.resize(a.size()+b.size());
84
85 for(std::size_t i=0; i<a.size(); i++)
86 result[i]=a[i];
87
88 for(std::size_t i=0; i<b.size(); i++)
89 result[i+a.size()]=b[i];
90
91 return result;
92}
93
96{
97 PRECONDITION(a.size() == b.size());
98
99 bvt result;
100
101 result.resize(a.size());
102 for(std::size_t i=0; i<result.size(); i++)
103 result[i]=prop.lselect(s, a[i], b[i]);
104
105 return result;
106}
107
109 const bvt &bv,
110 std::size_t new_size,
111 representationt rep)
112{
113 std::size_t old_size=bv.size();
115
116 bvt result=bv;
117 result.resize(new_size);
118
120 (rep==representationt::SIGNED && !bv.empty())?bv[old_size-1]:
121 const_literal(false);
122
123 for(std::size_t i=old_size; i<new_size; i++)
124 result[i]=extend_with;
125
126 return result;
127}
128
129
135// The optimal encoding is the default as it gives a reduction in space
136// and small performance gains
137#define OPTIMAL_FULL_ADDER
138
140 const literalt a,
141 const literalt b,
142 const literalt carry_in,
143 literalt &carry_out)
144{
145 #ifdef OPTIMAL_FULL_ADDER
147 {
148 literalt x;
149 literalt y;
150 int constantProp = -1;
151
152 if(a.is_constant())
153 {
154 x = b;
155 y = carry_in;
156 constantProp = (a.is_true()) ? 1 : 0;
157 }
158 else if(b.is_constant())
159 {
160 x = a;
161 y = carry_in;
162 constantProp = (b.is_true()) ? 1 : 0;
163 }
164 else if(carry_in.is_constant())
165 {
166 x = a;
167 y = b;
168 constantProp = (carry_in.is_true()) ? 1 : 0;
169 }
170
172
173 // Rely on prop.l* to do further constant propagation
174 if(constantProp == 1)
175 {
176 // At least one input bit is 1
177 carry_out = prop.lor(x, y);
178 sum = prop.lequal(x, y);
179 }
180 else if(constantProp == 0)
181 {
182 // At least one input bit is 0
183 carry_out = prop.land(x, y);
184 sum = prop.lxor(x, y);
185 }
186 else
187 {
190
191 // Any two inputs 1 will set the carry_out to 1
192 prop.lcnf(!a, !b, carry_out);
195
196 // Any two inputs 0 will set the carry_out to 0
197 prop.lcnf(a, b, !carry_out);
200
201 // If both carry out and sum are 1 then all inputs are 1
202 prop.lcnf(a, !sum, !carry_out);
203 prop.lcnf(b, !sum, !carry_out);
205
206 // If both carry out and sum are 0 then all inputs are 0
207 prop.lcnf(!a, sum, carry_out);
208 prop.lcnf(!b, sum, carry_out);
210
211 // If all of the inputs are 1 or all are 0 it sets the sum
212 prop.lcnf(!a, !b, !carry_in, sum);
213 prop.lcnf(a, b, carry_in, !sum);
214 }
215
216 return sum;
217 }
218 else // NOLINT(readability/braces)
219 #endif // OPTIMAL_FULL_ADDER
220 {
221 // trivial encoding
223 return prop.lxor(prop.lxor(a, b), carry_in);
224 }
225}
226
227// Daniel's carry optimisation
228#define COMPACT_CARRY
229
231{
232 #ifdef COMPACT_CARRY
234 {
235 // propagation possible?
236 const auto const_count =
237 a.is_constant() + b.is_constant() + c.is_constant();
238
239 // propagation is possible if two or three inputs are constant
240 if(const_count>=2)
241 return prop.lor(prop.lor(
242 prop.land(a, b),
243 prop.land(a, c)),
244 prop.land(b, c));
245
246 // it's also possible if two of a,b,c are the same
247 if(a==b)
248 return a;
249 else if(a==c)
250 return a;
251 else if(b==c)
252 return b;
253
254 // the below yields fewer clauses and variables,
255 // but doesn't propagate anything at all
256
257 bvt clause;
258
260
261 /*
262 carry_correct: LEMMA
263 ( a OR b OR NOT x) AND
264 ( a OR NOT b OR c OR NOT x) AND
265 ( a OR NOT b OR NOT c OR x) AND
266 (NOT a OR b OR c OR NOT x) AND
267 (NOT a OR b OR NOT c OR x) AND
268 (NOT a OR NOT b OR x)
269 IFF
270 (x=((a AND b) OR (a AND c) OR (b AND c)));
271 */
272
273 prop.lcnf(a, b, !x);
274 prop.lcnf(a, !b, c, !x);
275 prop.lcnf(a, !b, !c, x);
276 prop.lcnf(!a, b, c, !x);
277 prop.lcnf(!a, b, !c, x);
278 prop.lcnf(!a, !b, x);
279
280 return x;
281 }
282 else
283 #endif // COMPACT_CARRY
284 {
285 // trivial encoding
286 bvt tmp;
287
288 tmp.push_back(prop.land(a, b));
289 tmp.push_back(prop.land(a, c));
290 tmp.push_back(prop.land(b, c));
291
292 return prop.lor(tmp);
293 }
294}
295
296std::pair<bvt, literalt>
297bv_utilst::adder(const bvt &op0, const bvt &op1, literalt carry_in)
298{
299 PRECONDITION(op0.size() == op1.size());
300
301 std::pair<bvt, literalt> result{bvt{}, carry_in};
302 result.first.reserve(op0.size());
303 literalt &carry_out = result.second;
304
305 for(std::size_t i = 0; i < op0.size(); i++)
306 {
307 result.first.push_back(full_adder(op0[i], op1[i], carry_out, carry_out));
308 }
309
310 return result;
311}
312
314 const bvt &op0,
315 const bvt &op1,
317{
318 PRECONDITION(op0.size() == op1.size());
319
321
322 for(std::size_t i=0; i<op0.size(); i++)
323 carry_out=carry(op0[i], op1[i], carry_out);
324
325 return carry_out;
326}
327
329 const bvt &op0,
330 const bvt &op1,
331 bool subtract,
332 representationt rep)
333{
334 return adder_no_overflow(op0, op1, subtract, rep);
335}
336
337bvt bv_utilst::add_sub(const bvt &op0, const bvt &op1, bool subtract)
338{
339 PRECONDITION(op0.size() == op1.size());
340
342
343 bvt tmp_op1=subtract?inverted(op1):op1;
344
345 // we ignore the carry-out
346 return adder(op0, tmp_op1, carry_in).first;
347}
348
349bvt bv_utilst::add_sub(const bvt &op0, const bvt &op1, literalt subtract)
350{
351 const bvt op1_sign_applied=
352 select(subtract, inverted(op1), op1);
353
354 // we ignore the carry-out
355 return adder(op0, op1_sign_applied, subtract).first;
356}
357
359 const bvt &op0,
360 const bvt &op1,
361 bool subtract,
362 representationt rep)
363{
364 PRECONDITION(op0.size() == op1.size());
367
368 literalt carry_in = const_literal(subtract);
369
370 bvt tmp_op1 = subtract ? inverted(op1) : op1;
371
372 auto add_sub_result = adder(op0, tmp_op1, carry_in);
374
375 bvt result;
376 result.reserve(add_sub_result.first.size());
378 {
379 // An unsigned overflow has occurred when carry_out is not equal to
380 // subtract: addition with a carry-out means an overflow beyond the maximum
381 // representable value, subtraction without a carry-out means an underflow
382 // below zero. For saturating arithmetic the former implies that all bits
383 // should be set to 1, in the latter case all bits should be set to zero.
384 for(const auto &literal : add_sub_result.first)
385 {
386 result.push_back(
387 subtract ? prop.land(literal, carry_out)
389 }
390 }
391 else
392 {
393 // A signed overflow beyond the maximum representable value occurs when
394 // adding two positive numbers and the wrap-around result being negative, or
395 // when subtracting a negative from a positive number (and, again, the
396 // result being negative).
398 !sign_bit(op0),
399 subtract ? sign_bit(op1) : !sign_bit(op1),
400 sign_bit(add_sub_result.first)});
401 // A signed underflow below the minimum representable value occurs when
402 // adding two negative numbers and arriving at a positive result, or
403 // subtracting a positive from a negative number (and, again, obtaining a
404 // positive wrap-around result).
406 sign_bit(op0),
407 subtract ? !sign_bit(op1) : sign_bit(op1),
408 !sign_bit(add_sub_result.first)});
409
410 // set all bits except for the sign bit
411 PRECONDITION(!add_sub_result.first.empty());
412 for(std::size_t i = 0; i < add_sub_result.first.size() - 1; ++i)
413 {
414 const auto &literal = add_sub_result.first[i];
415 result.push_back(prop.land(
417 }
418 // finally add the sign bit
419 result.push_back(prop.land(
422 }
423
424 return result;
425}
426
428 const bvt &op0, const bvt &op1, representationt rep)
429{
431 {
432 // An overflow occurs if the signs of the two operands are the same
433 // and the sign of the sum is the opposite.
434
435 literalt old_sign=op0[op0.size()-1];
436 literalt sign_the_same=prop.lequal(op0[op0.size()-1], op1[op1.size()-1]);
437
438 bvt result=add(op0, op1);
439 return
440 prop.land(sign_the_same, prop.lxor(result[result.size()-1], old_sign));
441 }
442 else if(rep==representationt::UNSIGNED)
443 {
444 // overflow is simply carry-out
445 return carry_out(op0, op1, const_literal(false));
446 }
447 else
449}
450
452 const bvt &op0, const bvt &op1, representationt rep)
453{
455 {
456 // We special-case x-INT_MIN, which is >=0 if
457 // x is negative, always representable, and
458 // thus not an overflow.
460 literalt op0_is_negative=op0[op0.size()-1];
461
462 return
466 }
467 else if(rep==representationt::UNSIGNED)
468 {
469 // overflow is simply _negated_ carry-out
470 return !carry_out(op0, inverted(op1), const_literal(true));
471 }
472 else
474}
475
477 const bvt &op0,
478 const bvt &op1,
479 bool subtract,
480 representationt rep)
481{
482 const bvt tmp_op = subtract ? inverted(op1) : op1;
483
485 {
486 // an overflow occurs if the signs of the two operands are the same
487 // and the sign of the sum is the opposite
488
491
492 // we ignore the carry-out
493 bvt sum = adder(op0, tmp_op, const_literal(subtract)).first;
494
497
498 return sum;
499 }
500 else
501 {
502 INVARIANT(
504 "representation has either value signed or unsigned");
505 auto result = adder(op0, tmp_op, const_literal(subtract));
506 prop.l_set_to(result.second, subtract);
507 return std::move(result.first);
508 }
509}
510
512{
513 return adder_no_overflow(op0, op1, false, representationt::UNSIGNED);
514}
515
516bvt bv_utilst::shift(const bvt &op, const shiftt s, const bvt &dist)
517{
518 std::size_t d=1, width=op.size();
519 bvt result=op;
520
521 for(std::size_t stage=0; stage<dist.size(); stage++)
522 {
523 if(dist[stage]!=const_literal(false))
524 {
525 bvt tmp=shift(result, s, d);
526
527 for(std::size_t i=0; i<width; i++)
528 result[i]=prop.lselect(dist[stage], tmp[i], result[i]);
529 }
530
531 d=d<<1;
532 }
533
534 return result;
535}
536
537bvt bv_utilst::shift(const bvt &src, const shiftt s, std::size_t dist)
538{
539 bvt result;
540 result.resize(src.size());
541
542 // 'dist' is user-controlled, and thus arbitary.
543 // We thus must guard against the case in which i+dist overflows.
544 // We do so by considering the case dist>=src.size().
545
546 for(std::size_t i=0; i<src.size(); i++)
547 {
548 literalt l;
549
550 switch(s)
551 {
553 // no underflow on i-dist because of condition dist<=i
554 l=(dist<=i?src[i-dist]:const_literal(false));
555 break;
556
558 // src.size()-i won't underflow as i<src.size()
559 // Then, if dist<src.size()-i, then i+dist<src.size()
560 l=(dist<src.size()-i?src[i+dist]:src[src.size()-1]); // sign bit
561 break;
562
564 // src.size()-i won't underflow as i<src.size()
565 // Then, if dist<src.size()-i, then i+dist<src.size()
566 l=(dist<src.size()-i?src[i+dist]:const_literal(false));
567 break;
568
570 // prevent overflows by using dist%src.size()
571 l=src[(src.size()+i-(dist%src.size()))%src.size()];
572 break;
573
575 // prevent overflows by using dist%src.size()
576 l=src[(i+(dist%src.size()))%src.size()];
577 break;
578
579 default:
581 }
582
583 result[i]=l;
584 }
585
586 return result;
587}
588
590{
591 bvt result=inverted(bv);
593 incrementer(result, const_literal(true), carry_out);
594 return result;
595}
596
598{
600 return negate(bv);
601}
602
604{
605 // a overflow on unary- can only happen with the smallest
606 // representable number 100....0
607
609 should_be_zeros.pop_back();
610
611 return prop.land(bv[bv.size() - 1], !prop.lor(should_be_zeros));
612}
613
615 bvt &bv,
617 literalt &carry_out)
618{
620
621 for(auto &literal : bv)
622 {
626 }
627}
628
630{
631 bvt result=bv;
634 return result;
635}
636
638{
639 bvt result=bv;
640 for(auto &literal : result)
641 literal = !literal;
642 return result;
643}
644
645bvt bv_utilst::wallace_tree(const std::vector<bvt> &pps)
646{
647 PRECONDITION(!pps.empty());
648
649 if(pps.size()==1)
650 return pps.front();
651 else if(pps.size()==2)
652 return add(pps[0], pps[1]);
653 else
654 {
655 std::vector<bvt> new_pps;
656 std::size_t no_full_adders=pps.size()/3;
657
658 // add groups of three partial products using CSA
659 for(std::size_t i=0; i<no_full_adders; i++)
660 {
661 const bvt &a=pps[i*3+0],
662 &b=pps[i*3+1],
663 &c=pps[i*3+2];
664
665 INVARIANT(a.size() == b.size(), "groups should be of equal size");
666 INVARIANT(a.size() == c.size(), "groups should be of equal size");
667
668 bvt s, t(a.size(), const_literal(false));
669 s.reserve(a.size());
670
671 for(std::size_t bit=0; bit<a.size(); bit++)
672 {
674 s.push_back(full_adder(a[bit], b[bit], c[bit], carry_out));
675 if(bit + 1 < a.size())
676 t[bit + 1] = carry_out;
677 }
678
679 new_pps.push_back(std::move(s));
680 new_pps.push_back(std::move(t));
681 }
682
683 // pass onwards up to two remaining partial products
684 for(std::size_t i=no_full_adders*3; i<pps.size(); i++)
685 new_pps.push_back(pps[i]);
686
687 POSTCONDITION(new_pps.size() < pps.size());
688 return wallace_tree(new_pps);
689 }
690}
691
692bvt bv_utilst::dadda_tree(const std::vector<bvt> &pps)
693{
694 PRECONDITION(!pps.empty());
695
696 using columnt = std::list<literalt>;
697 std::vector<columnt> columns(pps.front().size());
698 for(const auto &pp : pps)
699 {
700 PRECONDITION(pp.size() == pps.front().size());
701 for(std::size_t i = 0; i < pp.size(); ++i)
702 {
703 if(!pp[i].is_false())
704 columns[i].push_back(pp[i]);
705 }
706 }
707
708 std::list<std::size_t> dadda_sequence;
709 for(std::size_t d = 2; d < pps.front().size(); d = (d * 3) / 2)
710 dadda_sequence.push_front(d);
711
712 for(auto d : dadda_sequence)
713 {
714 for(auto col_it = columns.begin(); col_it != columns.end();) // no ++col_it
715 {
716 if(col_it->size() <= d)
717 ++col_it;
718 else if(col_it->size() == d + 1)
719 {
720 // Dadda prescribes a half adder here, but OPTIMAL_FULL_ADDER makes
721 // full_adder actually build a half adder when carry-in is false.
723 col_it->push_back(full_adder(
724 col_it->front(),
725 *std::next(col_it->begin()),
726 const_literal(false),
727 carry_out));
728 col_it->pop_front();
729 col_it->pop_front();
730 if(std::next(col_it) != columns.end())
731 std::next(col_it)->push_back(carry_out);
732 }
733 else
734 {
735 // We could also experiment with n:2 compressors (for n > 3, n=3 is the
736 // full adder as used below) that use circuits with lower gate count
737 // than just combining multiple full adders.
739 col_it->push_back(full_adder(
740 col_it->front(),
741 *std::next(col_it->begin()),
742 *std::next(std::next(col_it->begin())),
743 carry_out));
744 col_it->pop_front();
745 col_it->pop_front();
746 col_it->pop_front();
747 if(std::next(col_it) != columns.end())
748 std::next(col_it)->push_back(carry_out);
749 }
750 }
751 }
752
753 bvt a, b;
754 a.reserve(pps.front().size());
755 b.reserve(pps.front().size());
756
757 for(const auto &col : columns)
758 {
759 PRECONDITION(col.size() <= 2);
760 switch(col.size())
761 {
762 case 0:
763 a.push_back(const_literal(false));
764 b.push_back(const_literal(false));
765 break;
766 case 1:
767 a.push_back(col.front());
768 b.push_back(const_literal(false));
769 break;
770 case 2:
771 a.push_back(col.front());
772 b.push_back(col.back());
773 }
774 }
775
776 return add(a, b);
777}
778
779// Wallace tree multiplier. This is disabled, as runtimes have
780// been observed to go up by 5%-10%, and on some models even by 20%.
781// #define WALLACE_TREE
782// Dadda' reduction scheme. This yields a smaller formula size than Wallace
783// trees (and also the default addition scheme), but remains disabled as it
784// isn't consistently more performant either.
785// #define DADDA_TREE
786
787// The following examples demonstrate the performance differences (with a
788// time-out of 7200 seconds):
789//
790// #ifndef BITWIDTH
791// #define BITWIDTH 8
792// #endif
793//
794// int main()
795// {
796// __CPROVER_bitvector[BITWIDTH] a, b;
797// __CPROVER_assert(a * 3 == a + a + a, "multiplication by 3");
798// __CPROVER_assert(3 * a == a + a + a, "multiplication by 3");
799// __CPROVER_bitvector[BITWIDTH] ab = a * b;
800// __CPROVER_bitvector[BITWIDTH * 2] ab_check =
801// (__CPROVER_bitvector[BITWIDTH * 2])a *
802// (__CPROVER_bitvector[BITWIDTH * 2])b;
803// __CPROVER_assert(
804// ab == (__CPROVER_bitvector[BITWIDTH])ab_check, "should pass");
805// }
806//
807// |----|-----------------------------|-----------------------------|
808// | | CaDiCaL | MiniSat2 |
809// |----|-----------------------------|-----------------------------|
810// | n | No tree | Wallace | Dadda | No tree | Wallace | Dadda |
811// |----|---------|---------|---------|---------|---------|---------|
812// | 1 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
813// | 2 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
814// | 3 | 0.01 | 0.01 | 0.00 | 0.00 | 0.00 | 0.00 |
815// | 4 | 0.01 | 0.01 | 0.01 | 0.01 | 0.01 | 0.01 |
816// | 5 | 0.04 | 0.04 | 0.04 | 0.01 | 0.01 | 0.01 |
817// | 6 | 0.11 | 0.13 | 0.12 | 0.04 | 0.05 | 0.06 |
818// | 7 | 0.28 | 0.46 | 0.44 | 0.15 | 0.27 | 0.31 |
819// | 8 | 0.50 | 1.55 | 1.09 | 0.90 | 1.06 | 1.36 |
820// | 9 | 2.22 | 3.63 | 2.67 | 3.40 | 5.85 | 3.44 |
821// | 10 | 2.79 | 4.81 | 4.69 | 4.32 | 28.41 | 28.01 |
822// | 11 | 8.48 | 4.45 | 11.99 | 38.24 | 98.55 | 86.46 |
823// | 12 | 14.52 | 4.86 | 5.80 | 115.00 | 140.11 | 461.70 |
824// | 13 | 33.62 | 5.56 | 6.14 | 210.24 | 805.59 | 609.01 |
825// | 14 | 37.23 | 6.11 | 8.01 | 776.75 | 689.96 | 6153.82 |
826// | 15 | 108.65 | 7.86 | 14.72 | 1048.92 | 1421.74 | 6881.78 |
827// | 16 | 102.61 | 14.08 | 18.54 | 1628.01 | timeout | 1943.85 |
828// | 17 | 117.89 | 18.53 | 9.19 | 4148.73 | timeout | timeout |
829// | 18 | 209.40 | 7.97 | 7.74 | 2760.51 | timeout | timeout |
830// | 19 | 168.21 | 18.04 | 15.00 | 2514.21 | timeout | timeout |
831// | 20 | 566.76 | 12.68 | 22.47 | 2609.09 | timeout | timeout |
832// | 21 | 786.31 | 23.80 | 23.80 | 2232.77 | timeout | timeout |
833// | 22 | 817.74 | 17.64 | 22.53 | 3866.70 | timeout | timeout |
834// | 23 | 1102.76 | 24.19 | 26.37 | timeout | timeout | timeout |
835// | 24 | 1319.59 | 27.37 | 29.95 | timeout | timeout | timeout |
836// | 25 | 1786.11 | 27.10 | 29.94 | timeout | timeout | timeout |
837// | 26 | 1952.18 | 31.08 | 33.95 | timeout | timeout | timeout |
838// | 27 | 6908.48 | 27.92 | 34.94 | timeout | timeout | timeout |
839// | 28 | 6919.34 | 36.63 | 33.78 | timeout | timeout | timeout |
840// | 29 | timeout | 27.95 | 40.69 | timeout | timeout | timeout |
841// | 30 | timeout | 36.94 | 31.59 | timeout | timeout | timeout |
842// | 31 | timeout | 38.41 | 40.04 | timeout | timeout | timeout |
843// | 32 | timeout | 33.06 | 91.38 | timeout | timeout | timeout |
844// |----|---------|---------|---------|---------|---------|---------|
845//
846// In summary, both Wallace tree and Dadda reduction are substantially more
847// efficient with CaDiCaL on the above code for all bit width > 11, but somewhat
848// slower with MiniSat.
849//
850// #ifndef BITWIDTH
851// #define BITWIDTH 8
852// #endif
853//
854// int main()
855// {
856// __CPROVER_bitvector[BITWIDTH] a, b, c, ab, bc, abc;
857// ab = a * b;
858// __CPROVER_bitvector[BITWIDTH * 2] ab_check =
859// (__CPROVER_bitvector[BITWIDTH * 2])a *
860// (__CPROVER_bitvector[BITWIDTH * 2])b;
861// __CPROVER_assume(ab == ab_check);
862// bc = b * c;
863// __CPROVER_bitvector[BITWIDTH * 2] bc_check =
864// (__CPROVER_bitvector[BITWIDTH * 2])b *
865// (__CPROVER_bitvector[BITWIDTH * 2])c;
866// __CPROVER_assume(bc == bc_check);
867// abc = ab * c;
868// __CPROVER_bitvector[BITWIDTH * 2] abc_check =
869// (__CPROVER_bitvector[BITWIDTH * 2])ab *
870// (__CPROVER_bitvector[BITWIDTH * 2])c;
871// __CPROVER_assume(abc == abc_check);
872// __CPROVER_assert(abc == a * bc, "associativity");
873// }
874//
875// |----|-----------------------------|-----------------------------|
876// | | CaDiCaL | MiniSat2 |
877// |----|-----------------------------|-----------------------------|
878// | n | No tree | Wallace | Dadda | No tree | Wallace | Dadda |
879// |----|---------|---------|---------|---------|---------|---------|
880// | 1 | 0.00 | 0.00 | 0.00 | 0.01 | 0.01 | 0.01 |
881// | 2 | 0.01 | 0.01 | 0.01 | 0.01 | 0.01 | 0.01 |
882// | 3 | 0.02 | 0.03 | 0.03 | 0.01 | 0.01 | 0.01 |
883// | 4 | 0.05 | 0.07 | 0.06 | 0.02 | 0.02 | 0.02 |
884// | 5 | 0.17 | 0.18 | 0.14 | 0.04 | 0.04 | 0.04 |
885// | 6 | 0.50 | 0.63 | 0.63 | 0.13 | 0.14 | 0.13 |
886// | 7 | 1.01 | 1.15 | 0.90 | 0.43 | 0.47 | 0.47 |
887// | 8 | 1.56 | 1.76 | 1.75 | 3.35 | 2.39 | 1.75 |
888// | 9 | 2.07 | 2.48 | 1.75 | 11.20 | 12.64 | 7.94 |
889// | 10 | 3.58 | 3.88 | 3.54 | 20.23 | 23.49 | 15.66 |
890// | 11 | 5.84 | 7.46 | 5.31 | 49.32 | 39.86 | 44.15 |
891// | 12 | 11.71 | 16.85 | 13.40 | 69.32 | 156.57 | 46.50 |
892// | 13 | 33.22 | 41.95 | 34.43 | 250.91 | 294.73 | 79.47 |
893// | 14 | 76.27 | 109.59 | 84.49 | 226.98 | 259.84 | 258.08 |
894// | 15 | 220.01 | 330.10 | 267.11 | 783.73 | 1160.47 | 1262.91 |
895// | 16 | 591.91 | 981.16 | 808.33 | 2712.20 | 4286.60 | timeout |
896// | 17 | 1634.97 | 2574.81 | 2006.27 | timeout | timeout | timeout |
897// | 18 | 4680.16 | timeout | 6704.35 | timeout | timeout | timeout |
898// | 19 | timeout | timeout | timeout | timeout | timeout | timeout |
899// | 20 | timeout | timeout | timeout | timeout | timeout | timeout |
900// | 21 | timeout | timeout | timeout | timeout | timeout | timeout |
901// | 22 | timeout | timeout | timeout | timeout | timeout | timeout |
902// | 23 | timeout | timeout | timeout | timeout | timeout | timeout |
903// | 24 | timeout | timeout | timeout | timeout | timeout | timeout |
904// | 25 | timeout | timeout | timeout | timeout | timeout | timeout |
905// | 26 | timeout | timeout | timeout | timeout | timeout | timeout |
906// | 27 | timeout | timeout | timeout | timeout | timeout | timeout |
907// | 28 | timeout | timeout | timeout | timeout | timeout | timeout |
908// | 29 | timeout | timeout | timeout | timeout | timeout | timeout |
909// | 30 | timeout | timeout | timeout | timeout | timeout | timeout |
910// | 31 | timeout | timeout | timeout | timeout | timeout | timeout |
911// | 32 | timeout | timeout | timeout | timeout | timeout | timeout |
912// |----|---------|---------|---------|---------|---------|---------|
913//
914// In summary, Wallace tree reduction is slower for both solvers and all bit
915// widths (except BITWIDTH==8 with MiniSat2). Dadda multipliers get closer to
916// our multiplier that's not using a tree reduction scheme, but aren't uniformly
917// better either.
918
920{
921 bvt op0=_op0, op1=_op1;
922
923 if(is_constant(op1))
924 std::swap(op0, op1);
925
926 // build the usual quadratic number of partial products
927 std::vector<bvt> pps;
928 pps.reserve(op0.size());
929
930 for(std::size_t bit=0; bit<op0.size(); bit++)
931 {
932 if(op0[bit] == const_literal(false))
933 continue;
934
935 // zeros according to weight
936 bvt pp = zeros(bit);
937 pp.reserve(op0.size());
938
939 for(std::size_t idx = bit; idx < op0.size(); idx++)
940 pp.push_back(prop.land(op1[idx - bit], op0[bit]));
941
942 pps.push_back(pp);
943 }
944
945 if(pps.empty())
946 return zeros(op0.size());
947 else
948 {
949#ifdef WALLACE_TREE
950 return wallace_tree(pps);
951#elif defined(DADDA_TREE)
952 return dadda_tree(pps);
953#else
954 bvt product = pps.front();
955
956 for(auto it = std::next(pps.begin()); it != pps.end(); ++it)
957 product = add(product, *it);
958
959 return product;
960#endif
961 }
962}
963
965 const bvt &op0,
966 const bvt &op1)
967{
968 bvt _op0=op0, _op1=op1;
969
970 PRECONDITION(_op0.size() == _op1.size());
971
972 if(is_constant(_op1))
973 _op0.swap(_op1);
974
975 bvt product;
976 product.resize(_op0.size());
977
978 for(std::size_t i=0; i<product.size(); i++)
979 product[i]=const_literal(false);
980
981 for(std::size_t sum=0; sum<op0.size(); sum++)
982 if(op0[sum]!=const_literal(false))
983 {
984 bvt tmpop;
985
986 tmpop.reserve(product.size());
987
988 for(std::size_t idx=0; idx<sum; idx++)
989 tmpop.push_back(const_literal(false));
990
991 for(std::size_t idx=sum; idx<product.size(); idx++)
992 tmpop.push_back(prop.land(op1[idx-sum], op0[sum]));
993
995
996 for(std::size_t idx=op1.size()-sum; idx<op1.size(); idx++)
997 prop.l_set_to_false(prop.land(op1[idx], op0[sum]));
998 }
999
1000 return product;
1001}
1002
1004{
1005 if(op0.empty() || op1.empty())
1006 return bvt();
1007
1008 literalt sign0=op0[op0.size()-1];
1009 literalt sign1=op1[op1.size()-1];
1010
1011 bvt neg0=cond_negate(op0, sign0);
1012 bvt neg1=cond_negate(op1, sign1);
1013
1015
1017
1018 return cond_negate(result, result_sign);
1019}
1020
1022{
1023 bvt neg_bv=negate(bv);
1024
1025 bvt result;
1026 result.resize(bv.size());
1027
1028 for(std::size_t i=0; i<bv.size(); i++)
1029 result[i]=prop.lselect(cond, neg_bv[i], bv[i]);
1030
1031 return result;
1032}
1033
1035{
1036 PRECONDITION(!bv.empty());
1037 return cond_negate(bv, bv[bv.size()-1]);
1038}
1039
1041{
1043
1044 return cond_negate(bv, cond);
1045}
1046
1048 const bvt &op0,
1049 const bvt &op1)
1050{
1051 if(op0.empty() || op1.empty())
1052 return bvt();
1053
1054 literalt sign0=op0[op0.size()-1];
1055 literalt sign1=op1[op1.size()-1];
1056
1059
1061
1062 prop.l_set_to_false(result[result.size() - 1]);
1063
1065
1066 return cond_negate_no_overflow(result, result_sign);
1067}
1068
1070 const bvt &op0,
1071 const bvt &op1,
1072 representationt rep)
1073{
1074 // We determine the result size from the operand size, and the implementation
1075 // liberally swaps the operands, so we need to arrive at the same size
1076 // whatever the order of the operands.
1077 PRECONDITION(op0.size() == op1.size());
1078
1079 switch(rep)
1080 {
1081 case representationt::SIGNED: return signed_multiplier(op0, op1);
1082 case representationt::UNSIGNED: return unsigned_multiplier(op0, op1);
1083 }
1084
1086}
1087
1089 const bvt &op0,
1090 const bvt &op1,
1091 representationt rep)
1092{
1093 switch(rep)
1094 {
1096 return signed_multiplier_no_overflow(op0, op1);
1098 return unsigned_multiplier_no_overflow(op0, op1);
1099 }
1100
1102}
1103
1105 const bvt &op0,
1106 const bvt &op1,
1107 bvt &res,
1108 bvt &rem)
1109{
1110 if(op0.empty() || op1.empty())
1111 return;
1112
1113 bvt _op0(op0), _op1(op1);
1114
1115 literalt sign_0=_op0[_op0.size()-1];
1116 literalt sign_1=_op1[_op1.size()-1];
1117
1119
1120 for(std::size_t i=0; i<_op0.size(); i++)
1121 _op0[i]=(prop.lselect(sign_0, neg_0[i], _op0[i]));
1122
1123 for(std::size_t i=0; i<_op1.size(); i++)
1124 _op1[i]=(prop.lselect(sign_1, neg_1[i], _op1[i]));
1125
1126 unsigned_divider(_op0, _op1, res, rem);
1127
1129
1131
1132 for(std::size_t i=0; i<res.size(); i++)
1133 res[i]=prop.lselect(result_sign, neg_res[i], res[i]);
1134
1135 for(std::size_t i=0; i<res.size(); i++)
1136 rem[i]=prop.lselect(sign_0, neg_rem[i], rem[i]);
1137}
1138
1140 const bvt &op0,
1141 const bvt &op1,
1142 bvt &result,
1143 bvt &remainer,
1144 representationt rep)
1145{
1147
1148 switch(rep)
1149 {
1151 signed_divider(op0, op1, result, remainer); break;
1153 unsigned_divider(op0, op1, result, remainer); break;
1154 }
1155}
1156
1158 const bvt &op0,
1159 const bvt &op1,
1160 bvt &res,
1161 bvt &rem)
1162{
1163 std::size_t width=op0.size();
1164
1165 // check if we divide by a power of two
1166 #if 0
1167 {
1168 std::size_t one_count=0, non_const_count=0, one_pos=0;
1169
1170 for(std::size_t i=0; i<op1.size(); i++)
1171 {
1172 literalt l=op1[i];
1173 if(l.is_true())
1174 {
1175 one_count++;
1176 one_pos=i;
1177 }
1178 else if(!l.is_false())
1180 }
1181
1182 if(non_const_count==0 && one_count==1 && one_pos!=0)
1183 {
1184 // it is a power of two!
1185 res=shift(op0, LRIGHT, one_pos);
1186
1187 // remainder is just a mask
1188 rem=op0;
1189 for(std::size_t i=one_pos; i<rem.size(); i++)
1190 rem[i]=const_literal(false);
1191 return;
1192 }
1193 }
1194 #endif
1195
1196 // Division by zero test.
1197 // Note that we produce a non-deterministic result in
1198 // case of division by zero. SMT-LIB now says the following:
1199 // bvudiv returns a vector of all 1s if the second operand is 0
1200 // bvurem returns its first operand if the second operand is 0
1201
1203
1204 // free variables for result of division
1205 res = prop.new_variables(width);
1206 rem = prop.new_variables(width);
1207
1208 // add implications
1209
1210 bvt product=
1212
1213 // res*op1 + rem = op0
1214
1216
1217 literalt is_equal=equal(sum, op0);
1218
1220
1221 // op1!=0 => rem < op1
1222
1224 prop.limplies(
1225 is_not_zero, lt_or_le(false, rem, op1, representationt::UNSIGNED)));
1226
1227 // op1!=0 => res <= op0
1228
1230 prop.limplies(
1232}
1233
1234
1235#ifdef COMPACT_EQUAL_CONST
1236// TODO : use for lt_or_le as well
1237
1241void bv_utilst::equal_const_register(const bvt &var)
1242{
1244 equal_const_registered.insert(var);
1245 return;
1246}
1247
1254literalt bv_utilst::equal_const_rec(bvt &var, bvt &constant)
1255{
1256 std::size_t size = var.size();
1257
1258 PRECONDITION(size != 0);
1259 PRECONDITION(size == constant.size());
1260 PRECONDITION(is_constant(constant));
1261
1262 if(size == 1)
1263 {
1264 literalt comp = prop.lequal(var[size - 1], constant[size - 1]);
1265 var.pop_back();
1266 constant.pop_back();
1267 return comp;
1268 }
1269 else
1270 {
1271 var_constant_pairt index(var, constant);
1272
1273 equal_const_cachet::iterator entry = equal_const_cache.find(index);
1274
1275 if(entry != equal_const_cache.end())
1276 {
1277 return entry->second;
1278 }
1279 else
1280 {
1281 literalt comp = prop.lequal(var[size - 1], constant[size - 1]);
1282 var.pop_back();
1283 constant.pop_back();
1284
1285 literalt rec = equal_const_rec(var, constant);
1286 literalt compare = prop.land(rec, comp);
1287
1288 equal_const_cache.insert(
1289 std::pair<var_constant_pairt, literalt>(index, compare));
1290
1291 return compare;
1292 }
1293 }
1294}
1295
1304literalt bv_utilst::equal_const(const bvt &var, const bvt &constant)
1305{
1306 std::size_t size = constant.size();
1307
1308 PRECONDITION(var.size() == size);
1310 PRECONDITION(is_constant(constant));
1311 PRECONDITION(size >= 2);
1312
1313 // These get modified : be careful!
1314 bvt var_upper;
1315 bvt var_lower;
1318
1319 /* Split the constant based on a change in parity
1320 * This is based on the observation that most constants are small,
1321 * so combinations of the lower bits are heavily used but the upper
1322 * bits are almost always either all 0 or all 1.
1323 */
1324 literalt top_bit = constant[size - 1];
1325
1326 std::size_t split = size - 1;
1327 var_upper.push_back(var[size - 1]);
1328 constant_upper.push_back(constant[size - 1]);
1329
1330 for(split = size - 2; split != 0; --split)
1331 {
1332 if(constant[split] != top_bit)
1333 {
1334 break;
1335 }
1336 else
1337 {
1338 var_upper.push_back(var[split]);
1339 constant_upper.push_back(constant[split]);
1340 }
1341 }
1342
1343 for(std::size_t i = 0; i <= split; ++i)
1344 {
1345 var_lower.push_back(var[i]);
1346 constant_lower.push_back(constant[i]);
1347 }
1348
1349 // Check we have split the array correctly
1350 INVARIANT(
1351 var_upper.size() + var_lower.size() == size,
1352 "lower size plus upper size should equal the total size");
1353 INVARIANT(
1354 constant_upper.size() + constant_lower.size() == size,
1355 "lower size plus upper size should equal the total size");
1356
1359
1361}
1362
1363#endif
1364
1369literalt bv_utilst::equal(const bvt &op0, const bvt &op1)
1370{
1371 PRECONDITION(op0.size() == op1.size());
1372
1373 #ifdef COMPACT_EQUAL_CONST
1374 // simplify_expr should put the constant on the right
1375 // but bit-level simplification may result in the other cases
1376 if(is_constant(op0) && !is_constant(op1) && op0.size() > 2 &&
1378 return equal_const(op1, op0);
1379 else if(!is_constant(op0) && is_constant(op1) && op0.size() > 2 &&
1381 return equal_const(op0, op1);
1382 #endif
1383
1384 bvt equal_bv;
1385 equal_bv.resize(op0.size());
1386
1387 for(std::size_t i=0; i<op0.size(); i++)
1388 equal_bv[i]=prop.lequal(op0[i], op1[i]);
1389
1390 return prop.land(equal_bv);
1391}
1392
1397
1398#define COMPACT_LT_OR_LE
1399/* Some clauses are not needed for correctness but they remove
1400 models (effectively setting "don't care" bits) and so may be worth
1401 including.*/
1402// #define INCLUDE_REDUNDANT_CLAUSES
1403
1405 bool or_equal,
1406 const bvt &bv0,
1407 const bvt &bv1,
1408 representationt rep)
1409{
1410 PRECONDITION(bv0.size() == bv1.size());
1411
1412 literalt top0=bv0[bv0.size()-1],
1413 top1=bv1[bv1.size()-1];
1414
1415#ifdef COMPACT_LT_OR_LE
1417 {
1418 bvt compareBelow; // 1 if a compare is needed below this bit
1419 literalt result;
1420 size_t start;
1421 size_t i;
1422
1423 if(rep == representationt::SIGNED)
1424 {
1425 if(top0.is_false() && top1.is_true())
1426 return const_literal(false);
1427 else if(top0.is_true() && top1.is_false())
1428 return const_literal(true);
1429
1430 INVARIANT(
1431 bv0.size() >= 2, "signed bitvectors should have at least two bits");
1432 compareBelow = prop.new_variables(bv0.size() - 1);
1433 start = compareBelow.size() - 1;
1434
1436 if(top0.is_false())
1437 firstComp = !top1;
1438 else if(top0.is_true())
1439 firstComp = top1;
1440 else if(top1.is_false())
1441 firstComp = !top0;
1442 else if(top1.is_true())
1443 firstComp = top0;
1444
1445 result = prop.new_variable();
1446
1447 // When comparing signs we are comparing the top bit
1448 // Four cases...
1449 prop.lcnf(top0, top1, firstComp); // + + compare needed
1450 prop.lcnf(top0, !top1, !result); // + - result false and no compare needed
1451 prop.lcnf(!top0, top1, result); // - + result true and no compare needed
1452 prop.lcnf(!top0, !top1, firstComp); // - - negated compare needed
1453
1454#ifdef INCLUDE_REDUNDANT_CLAUSES
1457#endif
1458 }
1459 else
1460 {
1461 // Unsigned is much easier
1462 compareBelow = prop.new_variables(bv0.size() - 1);
1463 compareBelow.push_back(const_literal(true));
1464 start = compareBelow.size() - 1;
1465 result = prop.new_variable();
1466 }
1467
1468 // Determine the output
1469 // \forall i . cb[i] & -a[i] & b[i] => result
1470 // \forall i . cb[i] & a[i] & -b[i] => -result
1471 i = start;
1472 do
1473 {
1474 if(compareBelow[i].is_false())
1475 continue;
1476 else if(compareBelow[i].is_true())
1477 {
1478 if(bv0[i].is_false() && bv1[i].is_true())
1479 return const_literal(true);
1480 else if(bv0[i].is_true() && bv1[i].is_false())
1481 return const_literal(false);
1482 }
1483
1484 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], result);
1485 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !result);
1486 }
1487 while(i-- != 0);
1488
1489 // Chain the comparison bit
1490 // \forall i != 0 . cb[i] & a[i] & b[i] => cb[i-1]
1491 // \forall i != 0 . cb[i] & -a[i] & -b[i] => cb[i-1]
1492 for(i = start; i > 0; i--)
1493 {
1494 prop.lcnf(!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i-1]);
1495 prop.lcnf(!compareBelow[i], bv0[i], bv1[i], compareBelow[i-1]);
1496 }
1497
1498
1499#ifdef INCLUDE_REDUNDANT_CLAUSES
1500 // Optional zeroing of the comparison bit when not needed
1501 // \forall i != 0 . -c[i] => -c[i-1]
1502 // \forall i != 0 . c[i] & -a[i] & b[i] => -c[i-1]
1503 // \forall i != 0 . c[i] & a[i] & -b[i] => -c[i-1]
1504 for(i = start; i > 0; i--)
1505 {
1507 prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i-1]);
1508 prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i-1]);
1509 }
1510#endif
1511
1512 // The 'base case' of the induction is the case when they are equal
1513 prop.lcnf(!compareBelow[0], !bv0[0], !bv1[0], (or_equal)?result:!result);
1514 prop.lcnf(!compareBelow[0], bv0[0], bv1[0], (or_equal)?result:!result);
1515
1516 return result;
1517 }
1518 else
1519#endif
1520 {
1523
1524 literalt result;
1525
1527 result=prop.lxor(prop.lequal(top0, top1), carry);
1528 else
1529 {
1530 INVARIANT(
1532 "representation has either value signed or unsigned");
1533 result = !carry;
1534 }
1535
1536 if(or_equal)
1537 result=prop.lor(result, equal(bv0, bv1));
1538
1539 return result;
1540 }
1541}
1542
1544 const bvt &op0,
1545 const bvt &op1)
1546{
1547#ifdef COMPACT_LT_OR_LE
1548 return lt_or_le(false, op0, op1, representationt::UNSIGNED);
1549#else
1550 // A <= B iff there is an overflow on A-B
1551 return !carry_out(op0, inverted(op1), const_literal(true));
1552#endif
1553}
1554
1556 const bvt &bv0,
1557 const bvt &bv1)
1558{
1559 return lt_or_le(false, bv0, bv1, representationt::SIGNED);
1560}
1561
1563 const bvt &bv0,
1564 irep_idt id,
1565 const bvt &bv1,
1566 representationt rep)
1567{
1568 if(id==ID_equal)
1569 return equal(bv0, bv1);
1570 else if(id==ID_notequal)
1571 return !equal(bv0, bv1);
1572 else if(id==ID_le)
1573 return lt_or_le(true, bv0, bv1, rep);
1574 else if(id==ID_lt)
1575 return lt_or_le(false, bv0, bv1, rep);
1576 else if(id==ID_ge)
1577 return lt_or_le(true, bv1, bv0, rep); // swapped
1578 else if(id==ID_gt)
1579 return lt_or_le(false, bv1, bv0, rep); // swapped
1580 else
1582}
1583
1585{
1586 for(const auto &literal : bv)
1587 {
1588 if(!literal.is_constant())
1589 return false;
1590 }
1591
1592 return true;
1593}
1594
1596 literalt cond,
1597 const bvt &a,
1598 const bvt &b)
1599{
1600 PRECONDITION(a.size() == b.size());
1601
1603 {
1604 for(std::size_t i=0; i<a.size(); i++)
1605 {
1606 prop.lcnf(!cond, a[i], !b[i]);
1607 prop.lcnf(!cond, !a[i], b[i]);
1608 }
1609 }
1610 else
1611 {
1612 prop.limplies(cond, equal(a, b));
1613 }
1614
1615 return;
1616}
1617
1619{
1620 bvt odd_bits;
1621 odd_bits.reserve(src.size()/2);
1622
1623 // check every odd bit
1624 for(std::size_t i=0; i<src.size(); i++)
1625 {
1626 if(i%2!=0)
1627 odd_bits.push_back(src[i]);
1628 }
1629
1630 return prop.lor(odd_bits);
1631}
1632
1634{
1635 bvt even_bits;
1636 even_bits.reserve(src.size()/2);
1637
1638 // get every even bit
1639 for(std::size_t i=0; i<src.size(); i++)
1640 {
1641 if(i%2==0)
1642 even_bits.push_back(src[i]);
1643 }
1644
1645 return even_bits;
1646}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
static bvt inverted(const bvt &op)
Definition bv_utils.cpp:637
literalt signed_less_than(const bvt &bv0, const bvt &bv1)
static bool is_constant(const bvt &bv)
std::pair< bvt, literalt > adder(const bvt &op0, const bvt &op1, literalt carry_in)
Return the sum and carry-out when adding op0 and op1 under initial carry carry_in.
Definition bv_utils.cpp:297
bvt wallace_tree(const std::vector< bvt > &pps)
Definition bv_utils.cpp:645
literalt is_not_zero(const bvt &op)
Definition bv_utils.h:146
static bvt verilog_bv_normal_bits(const bvt &)
literalt is_int_min(const bvt &op)
Definition bv_utils.h:149
static bvt extract_msb(const bvt &a, std::size_t n)
Definition bv_utils.cpp:57
void set_equal(const bvt &a, const bvt &b)
Definition bv_utils.cpp:34
static literalt sign_bit(const bvt &op)
Definition bv_utils.h:138
bvt multiplier_no_overflow(const bvt &op0, const bvt &op1, representationt rep)
bvt add_sub_no_overflow(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
Definition bv_utils.cpp:328
bvt add(const bvt &op0, const bvt &op1)
Definition bv_utils.h:66
bvt absolute_value(const bvt &op)
bvt select(literalt s, const bvt &a, const bvt &b)
If s is true, selects a otherwise selects b.
Definition bv_utils.cpp:95
static bvt build_constant(const mp_integer &i, std::size_t width)
Definition bv_utils.cpp:14
void signed_divider(const bvt &op0, const bvt &op1, bvt &res, bvt &rem)
literalt is_zero(const bvt &op)
Definition bv_utils.h:143
literalt equal(const bvt &op0, const bvt &op1)
Bit-blasting ID_equal and use in other encodings.
bvt signed_multiplier(const bvt &op0, const bvt &op1)
literalt overflow_add(const bvt &op0, const bvt &op1, representationt rep)
Definition bv_utils.cpp:427
literalt is_one(const bvt &op)
Definition bv_utils.cpp:25
bvt cond_negate_no_overflow(const bvt &bv, const literalt cond)
literalt overflow_sub(const bvt &op0, const bvt &op1, representationt rep)
Definition bv_utils.cpp:451
void cond_implies_equal(literalt cond, const bvt &a, const bvt &b)
literalt unsigned_less_than(const bvt &bv0, const bvt &bv1)
bvt signed_multiplier_no_overflow(const bvt &op0, const bvt &op1)
bvt incrementer(const bvt &op, literalt carry_in)
Definition bv_utils.cpp:629
bvt add_sub(const bvt &op0, const bvt &op1, bool subtract)
Definition bv_utils.cpp:337
static bvt shift(const bvt &op, const shiftt shift, std::size_t distance)
Definition bv_utils.cpp:537
literalt lt_or_le(bool or_equal, const bvt &bv0, const bvt &bv1, representationt rep)
literalt overflow_negate(const bvt &op)
Definition bv_utils.cpp:603
static bvt concatenate(const bvt &a, const bvt &b)
Definition bv_utils.cpp:79
representationt
Definition bv_utils.h:28
literalt full_adder(const literalt a, const literalt b, const literalt carry_in, literalt &carry_out)
Definition bv_utils.cpp:139
bvt negate_no_overflow(const bvt &op)
Definition bv_utils.cpp:597
static bvt extract(const bvt &a, std::size_t first, std::size_t last)
Definition bv_utils.cpp:41
bvt unsigned_multiplier(const bvt &op0, const bvt &op1)
Definition bv_utils.cpp:919
bvt divider(const bvt &op0, const bvt &op1, representationt rep)
Definition bv_utils.h:89
void unsigned_divider(const bvt &op0, const bvt &op1, bvt &res, bvt &rem)
bvt multiplier(const bvt &op0, const bvt &op1, representationt rep)
bvt cond_negate(const bvt &bv, const literalt cond)
bvt dadda_tree(const std::vector< bvt > &pps)
Definition bv_utils.cpp:692
literalt carry_out(const bvt &op0, const bvt &op1, literalt carry_in)
Definition bv_utils.cpp:313
bvt negate(const bvt &op)
Definition bv_utils.cpp:589
static bvt extension(const bvt &bv, std::size_t new_size, representationt rep)
Definition bv_utils.cpp:108
static bvt extract_lsb(const bvt &a, std::size_t n)
Definition bv_utils.cpp:69
literalt verilog_bv_has_x_or_z(const bvt &)
literalt carry(literalt a, literalt b, literalt c)
Definition bv_utils.cpp:230
bvt unsigned_multiplier_no_overflow(const bvt &op0, const bvt &op1)
Definition bv_utils.cpp:964
static bvt zeros(std::size_t new_size)
Definition bv_utils.h:192
literalt rel(const bvt &bv0, irep_idt id, const bvt &bv1, representationt rep)
propt & prop
Definition bv_utils.h:222
bvt adder_no_overflow(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
Definition bv_utils.cpp:476
bvt saturating_add_sub(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
Definition bv_utils.cpp:358
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
bool is_true() const
Definition literal.h:156
bool is_false() const
Definition literal.h:161
void l_set_to_true(literalt a)
Definition prop.h:52
virtual literalt land(literalt a, literalt b)=0
virtual literalt limplies(literalt a, literalt b)=0
virtual literalt lselect(literalt a, literalt b, literalt c)=0
virtual bool cnf_handled_well() const
Definition prop.h:85
virtual void l_set_to(literalt a, bool value)
Definition prop.h:47
virtual literalt lxor(literalt a, literalt b)=0
void lcnf(literalt l0, literalt l1)
Definition prop.h:58
virtual void set_equal(literalt a, literalt b)
asserts a==b in the propositional formula
Definition prop.cpp:12
virtual bvt new_variables(std::size_t width)
generates a bitvector of given width with new variables
Definition prop.cpp:30
virtual literalt new_variable()=0
virtual literalt lequal(literalt a, literalt b)=0
virtual literalt lor(literalt a, literalt b)=0
void l_set_to_false(literalt a)
Definition prop.h:54
virtual bool has_set_to() const
Definition prop.h:81
bool is_false(const literalt &l)
Definition literal.h:197
bool is_true(const literalt &l)
Definition literal.h:198
std::vector< literalt > bvt
Definition literal.h:201
literalt const_literal(bool value)
Definition literal.h:188
const std::string integer2binary(const mp_integer &n, std::size_t width)
Definition mp_arith.cpp:64
BigInt mp_integer
Definition smt_terms.h:17
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
#define POSTCONDITION(CONDITION)
Definition invariant.h:479