CBMC
bv_utils.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "bv_utils.h"
10 
11 #include <list>
12 #include <utility>
13 
14 bvt 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 
34 void 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 
41 bvt 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 
57 bvt 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 
69 bvt 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 
79 bvt bv_utilst::concatenate(const bvt &a, const bvt &b)
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 
95 bvt bv_utilst::select(literalt s, const bvt &a, const bvt &b)
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();
114  PRECONDITION(old_size != 0);
115 
116  bvt result=bv;
117  result.resize(new_size);
118 
119  literalt extend_with=
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 
171  literalt sum;
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  {
189  sum = prop.new_variable();
190 
191  // Any two inputs 1 will set the carry_out to 1
192  prop.lcnf(!a, !b, carry_out);
193  prop.lcnf(!a, !carry_in, carry_out);
194  prop.lcnf(!b, !carry_in, carry_out);
195 
196  // Any two inputs 0 will set the carry_out to 0
197  prop.lcnf(a, b, !carry_out);
198  prop.lcnf(a, carry_in, !carry_out);
199  prop.lcnf(b, carry_in, !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);
204  prop.lcnf(carry_in, !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);
209  prop.lcnf(!carry_in, 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
222  carry_out=carry(a, b, carry_in);
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 
296 std::pair<bvt, literalt>
297 bv_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,
316  literalt carry_in)
317 {
318  PRECONDITION(op0.size() == op1.size());
319 
320  literalt carry_out=carry_in;
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 
337 bvt bv_utilst::add_sub(const bvt &op0, const bvt &op1, bool subtract)
338 {
339  PRECONDITION(op0.size() == op1.size());
340 
341  literalt carry_in=const_literal(subtract);
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 
349 bvt 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());
365  PRECONDITION(
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);
373  literalt carry_out = add_sub_result.second;
374 
375  bvt result;
376  result.reserve(add_sub_result.first.size());
377  if(rep == representationt::UNSIGNED)
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)
388  : prop.lor(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).
397  literalt overflow_to_max_int = prop.land(bvt{
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).
405  literalt overflow_to_min_int = prop.land(bvt{
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(
416  prop.lor(overflow_to_max_int, literal), !overflow_to_min_int));
417  }
418  // finally add the sign bit
419  result.push_back(prop.land(
420  prop.lor(overflow_to_min_int, sign_bit(add_sub_result.first)),
421  !overflow_to_max_int));
422  }
423 
424  return result;
425 }
426 
428  const bvt &op0, const bvt &op1, representationt rep)
429 {
430  if(rep==representationt::SIGNED)
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
448  UNREACHABLE;
449 }
450 
452  const bvt &op0, const bvt &op1, representationt rep)
453 {
454  if(rep==representationt::SIGNED)
455  {
456  // We special-case x-INT_MIN, which is >=0 if
457  // x is negative, always representable, and
458  // thus not an overflow.
459  literalt op1_is_int_min=is_int_min(op1);
460  literalt op0_is_negative=op0[op0.size()-1];
461 
462  return
463  prop.lselect(op1_is_int_min,
464  !op0_is_negative,
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
473  UNREACHABLE;
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 
484  if(rep==representationt::SIGNED)
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 
489  literalt old_sign = sign_bit(op0);
490  literalt sign_the_same = prop.lequal(sign_bit(op0), sign_bit(tmp_op));
491 
492  // we ignore the carry-out
493  bvt sum = adder(op0, tmp_op, const_literal(subtract)).first;
494 
496  prop.land(sign_the_same, prop.lxor(sign_bit(sum), old_sign)));
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 
511 bvt bv_utilst::adder_no_overflow(const bvt &op0, const bvt &op1)
512 {
513  return adder_no_overflow(op0, op1, false, representationt::UNSIGNED);
514 }
515 
516 bvt 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 
537 bvt 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  {
552  case shiftt::SHIFT_LEFT:
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 
569  case shiftt::ROTATE_LEFT:
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:
580  UNREACHABLE;
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 
608  bvt should_be_zeros(bv);
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,
616  literalt carry_in,
617  literalt &carry_out)
618 {
619  carry_out=carry_in;
620 
621  for(auto &literal : bv)
622  {
623  literalt new_carry = prop.land(carry_out, literal);
624  literal = prop.lxor(literal, carry_out);
625  carry_out=new_carry;
626  }
627 }
628 
630 {
631  bvt result=bv;
633  incrementer(result, carry_in, carry_out);
634  return result;
635 }
636 
638 {
639  bvt result=bv;
640  for(auto &literal : result)
641  literal = !literal;
642  return result;
643 }
644 
645 bvt 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 
692 bvt 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 
919 bvt bv_utilst::unsigned_multiplier(const bvt &_op0, const bvt &_op1)
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 
994  product = adder_no_overflow(product, tmpop);
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 
1003 bvt bv_utilst::signed_multiplier(const bvt &op0, const bvt &op1)
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 
1014  bvt result=unsigned_multiplier(neg0, neg1);
1015 
1016  literalt result_sign=prop.lxor(sign0, sign1);
1017 
1018  return cond_negate(result, result_sign);
1019 }
1020 
1021 bvt bv_utilst::cond_negate(const bvt &bv, const literalt cond)
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 
1057  bvt neg0=cond_negate_no_overflow(op0, sign0);
1058  bvt neg1=cond_negate_no_overflow(op1, sign1);
1059 
1060  bvt result=unsigned_multiplier_no_overflow(neg0, neg1);
1061 
1062  prop.l_set_to_false(result[result.size() - 1]);
1063 
1064  literalt result_sign=prop.lxor(sign0, sign1);
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 
1085  UNREACHABLE;
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 
1101  UNREACHABLE;
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 
1118  bvt neg_0=negate(_op0), neg_1=negate(_op1);
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 
1128  bvt neg_res=negate(res), neg_rem=negate(rem);
1129 
1130  literalt result_sign=prop.lxor(sign_0, sign_1);
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())
1179  non_const_count++;
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 
1215  bvt sum = adder_no_overflow(product, rem);
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(
1231  is_not_zero, lt_or_le(true, res, op0, representationt::UNSIGNED)));
1232 }
1233 
1234 
1235 #ifdef COMPACT_EQUAL_CONST
1236 // TODO : use for lt_or_le as well
1237 
1241 void bv_utilst::equal_const_register(const bvt &var)
1242 {
1243  PRECONDITION(!is_constant(var));
1244  equal_const_registered.insert(var);
1245  return;
1246 }
1247 
1254 literalt 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 
1304 literalt bv_utilst::equal_const(const bvt &var, const bvt &constant)
1305 {
1306  std::size_t size = constant.size();
1307 
1308  PRECONDITION(var.size() == size);
1309  PRECONDITION(!is_constant(var));
1310  PRECONDITION(is_constant(constant));
1311  PRECONDITION(size >= 2);
1312 
1313  // These get modified : be careful!
1314  bvt var_upper;
1315  bvt var_lower;
1316  bvt constant_upper;
1317  bvt constant_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 
1357  literalt top_comparison = equal_const_rec(var_upper, constant_upper);
1358  literalt bottom_comparison = equal_const_rec(var_lower, constant_lower);
1359 
1360  return prop.land(top_comparison, bottom_comparison);
1361 }
1362 
1363 #endif
1364 
1369 literalt 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 &&
1377  equal_const_registered.find(op1) != equal_const_registered.end())
1378  return equal_const(op1, op0);
1379  else if(!is_constant(op0) && is_constant(op1) && op0.size() > 2 &&
1380  equal_const_registered.find(op0) != equal_const_registered.end())
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 
1435  literalt &firstComp = compareBelow[start];
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
1455  prop.lcnf(top0, !top1, !firstComp);
1456  prop.lcnf(!top0, top1, !firstComp);
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  {
1506  prop.lcnf(compareBelow[i], !compareBelow[i-1]);
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  {
1521  literalt carry=
1522  carry_out(bv0, inverted(bv1), const_literal(true));
1523 
1524  literalt result;
1525 
1526  if(rep==representationt::SIGNED)
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
1581  UNREACHABLE;
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 
1602  if(prop.cnf_handled_well())
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 }
static bvt inverted(const bvt &op)
Definition: bv_utils.cpp:637
literalt signed_less_than(const bvt &bv0, const bvt &bv1)
Definition: bv_utils.cpp:1555
static bool is_constant(const bvt &bv)
Definition: bv_utils.cpp:1584
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 &)
Definition: bv_utils.cpp:1633
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)
Definition: bv_utils.cpp:1088
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)
Definition: bv_utils.cpp:1034
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)
Definition: bv_utils.cpp:1104
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.
Definition: bv_utils.cpp:1369
bvt signed_multiplier(const bvt &op0, const bvt &op1)
Definition: bv_utils.cpp:1003
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)
Definition: bv_utils.cpp:1040
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)
Definition: bv_utils.cpp:1595
literalt unsigned_less_than(const bvt &bv0, const bvt &bv1)
Definition: bv_utils.cpp:1543
bvt signed_multiplier_no_overflow(const bvt &op0, const bvt &op1)
Definition: bv_utils.cpp:1047
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)
Definition: bv_utils.cpp:1404
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)
Definition: bv_utils.cpp:1157
bvt multiplier(const bvt &op0, const bvt &op1, representationt rep)
Definition: bv_utils.cpp:1069
bvt cond_negate(const bvt &bv, const literalt cond)
Definition: bv_utils.cpp:1021
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 &)
Definition: bv_utils.cpp:1618
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)
Definition: bv_utils.cpp:1562
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_constant() const
Definition: literal.h:166
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 POSTCONDITION(CONDITION)
Definition: invariant.h:479