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