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 bvt bv_utilst::build_constant(const mp_integer &n, std::size_t width)
12 {
13  std::string n_str=integer2binary(n, width);
14  CHECK_RETURN(n_str.size() == width);
15  bvt result;
16  result.resize(width);
17  for(std::size_t i=0; i<width; i++)
18  result[i]=const_literal(n_str[width-i-1]=='1');
19  return result;
20 }
21 
23 {
24  PRECONDITION(!bv.empty());
25  bvt tmp;
26  tmp=bv;
27  tmp.erase(tmp.begin(), tmp.begin()+1);
28  return prop.land(is_zero(tmp), bv[0]);
29 }
30 
31 void bv_utilst::set_equal(const bvt &a, const bvt &b)
32 {
33  PRECONDITION(a.size() == b.size());
34  for(std::size_t i=0; i<a.size(); i++)
35  prop.set_equal(a[i], b[i]);
36 }
37 
38 bvt bv_utilst::extract(const bvt &a, std::size_t first, std::size_t last)
39 {
40  // preconditions
41  PRECONDITION(first < a.size());
42  PRECONDITION(last < a.size());
43  PRECONDITION(first <= last);
44 
45  bvt result=a;
46  result.resize(last+1);
47  if(first!=0)
48  result.erase(result.begin(), result.begin()+first);
49 
50  POSTCONDITION(result.size() == last - first + 1);
51  return result;
52 }
53 
54 bvt bv_utilst::extract_msb(const bvt &a, std::size_t n)
55 {
56  // preconditions
57  PRECONDITION(n <= a.size());
58 
59  bvt result=a;
60  result.erase(result.begin(), result.begin()+(result.size()-n));
61 
62  POSTCONDITION(result.size() == n);
63  return result;
64 }
65 
66 bvt bv_utilst::extract_lsb(const bvt &a, std::size_t n)
67 {
68  // preconditions
69  PRECONDITION(n <= a.size());
70 
71  bvt result=a;
72  result.resize(n);
73  return result;
74 }
75 
76 bvt bv_utilst::concatenate(const bvt &a, const bvt &b)
77 {
78  bvt result;
79 
80  result.resize(a.size()+b.size());
81 
82  for(std::size_t i=0; i<a.size(); i++)
83  result[i]=a[i];
84 
85  for(std::size_t i=0; i<b.size(); i++)
86  result[i+a.size()]=b[i];
87 
88  return result;
89 }
90 
92 bvt bv_utilst::select(literalt s, const bvt &a, const bvt &b)
93 {
94  PRECONDITION(a.size() == b.size());
95 
96  bvt result;
97 
98  result.resize(a.size());
99  for(std::size_t i=0; i<result.size(); i++)
100  result[i]=prop.lselect(s, a[i], b[i]);
101 
102  return result;
103 }
104 
106  const bvt &bv,
107  std::size_t new_size,
108  representationt rep)
109 {
110  std::size_t old_size=bv.size();
111  PRECONDITION(old_size != 0);
112 
113  bvt result=bv;
114  result.resize(new_size);
115 
116  literalt extend_with=
117  (rep==representationt::SIGNED && !bv.empty())?bv[old_size-1]:
118  const_literal(false);
119 
120  for(std::size_t i=old_size; i<new_size; i++)
121  result[i]=extend_with;
122 
123  return result;
124 }
125 
126 
132 // The optimal encoding is the default as it gives a reduction in space
133 // and small performance gains
134 #define OPTIMAL_FULL_ADDER
135 
137  const literalt a,
138  const literalt b,
139  const literalt carry_in,
140  literalt &carry_out)
141 {
142  #ifdef OPTIMAL_FULL_ADDER
144  {
145  literalt x;
146  literalt y;
147  int constantProp = -1;
148 
149  if(a.is_constant())
150  {
151  x = b;
152  y = carry_in;
153  constantProp = (a.is_true()) ? 1 : 0;
154  }
155  else if(b.is_constant())
156  {
157  x = a;
158  y = carry_in;
159  constantProp = (b.is_true()) ? 1 : 0;
160  }
161  else if(carry_in.is_constant())
162  {
163  x = a;
164  y = b;
165  constantProp = (carry_in.is_true()) ? 1 : 0;
166  }
167 
168  literalt sum;
169 
170  // Rely on prop.l* to do further constant propagation
171  if(constantProp == 1)
172  {
173  // At least one input bit is 1
174  carry_out = prop.lor(x, y);
175  sum = prop.lequal(x, y);
176  }
177  else if(constantProp == 0)
178  {
179  // At least one input bit is 0
180  carry_out = prop.land(x, y);
181  sum = prop.lxor(x, y);
182  }
183  else
184  {
186  sum = prop.new_variable();
187 
188  // Any two inputs 1 will set the carry_out to 1
189  prop.lcnf(!a, !b, carry_out);
190  prop.lcnf(!a, !carry_in, carry_out);
191  prop.lcnf(!b, !carry_in, carry_out);
192 
193  // Any two inputs 0 will set the carry_out to 0
194  prop.lcnf(a, b, !carry_out);
195  prop.lcnf(a, carry_in, !carry_out);
196  prop.lcnf(b, carry_in, !carry_out);
197 
198  // If both carry out and sum are 1 then all inputs are 1
199  prop.lcnf(a, !sum, !carry_out);
200  prop.lcnf(b, !sum, !carry_out);
201  prop.lcnf(carry_in, !sum, !carry_out);
202 
203  // If both carry out and sum are 0 then all inputs are 0
204  prop.lcnf(!a, sum, carry_out);
205  prop.lcnf(!b, sum, carry_out);
206  prop.lcnf(!carry_in, sum, carry_out);
207 
208  // If all of the inputs are 1 or all are 0 it sets the sum
209  prop.lcnf(!a, !b, !carry_in, sum);
210  prop.lcnf(a, b, carry_in, !sum);
211  }
212 
213  return sum;
214  }
215  else // NOLINT(readability/braces)
216  #endif // OPTIMAL_FULL_ADDER
217  {
218  // trivial encoding
219  carry_out=carry(a, b, carry_in);
220  return prop.lxor(prop.lxor(a, b), carry_in);
221  }
222 }
223 
224 // Daniel's carry optimisation
225 #define COMPACT_CARRY
226 
228 {
229  #ifdef COMPACT_CARRY
231  {
232  // propagation possible?
233  const auto const_count =
234  a.is_constant() + b.is_constant() + c.is_constant();
235 
236  // propagation is possible if two or three inputs are constant
237  if(const_count>=2)
238  return prop.lor(prop.lor(
239  prop.land(a, b),
240  prop.land(a, c)),
241  prop.land(b, c));
242 
243  // it's also possible if two of a,b,c are the same
244  if(a==b)
245  return a;
246  else if(a==c)
247  return a;
248  else if(b==c)
249  return b;
250 
251  // the below yields fewer clauses and variables,
252  // but doesn't propagate anything at all
253 
254  bvt clause;
255 
257 
258  /*
259  carry_correct: LEMMA
260  ( a OR b OR NOT x) AND
261  ( a OR NOT b OR c OR NOT x) AND
262  ( a OR NOT b OR NOT c OR x) AND
263  (NOT a OR b OR c OR NOT x) AND
264  (NOT a OR b OR NOT c OR x) AND
265  (NOT a OR NOT b OR x)
266  IFF
267  (x=((a AND b) OR (a AND c) OR (b AND c)));
268  */
269 
270  prop.lcnf(a, b, !x);
271  prop.lcnf(a, !b, c, !x);
272  prop.lcnf(a, !b, !c, x);
273  prop.lcnf(!a, b, c, !x);
274  prop.lcnf(!a, b, !c, x);
275  prop.lcnf(!a, !b, x);
276 
277  return x;
278  }
279  else
280  #endif // COMPACT_CARRY
281  {
282  // trivial encoding
283  bvt tmp;
284 
285  tmp.push_back(prop.land(a, b));
286  tmp.push_back(prop.land(a, c));
287  tmp.push_back(prop.land(b, c));
288 
289  return prop.lor(tmp);
290  }
291 }
292 
294  bvt &sum,
295  const bvt &op,
296  literalt carry_in,
297  literalt &carry_out)
298 {
299  PRECONDITION(sum.size() == op.size());
300 
301  carry_out=carry_in;
302 
303  for(std::size_t i=0; i<sum.size(); i++)
304  {
305  sum[i] = full_adder(sum[i], op[i], carry_out, carry_out);
306  }
307 }
308 
310  const bvt &op0,
311  const bvt &op1,
312  literalt carry_in)
313 {
314  PRECONDITION(op0.size() == op1.size());
315 
316  literalt carry_out=carry_in;
317 
318  for(std::size_t i=0; i<op0.size(); i++)
319  carry_out=carry(op0[i], op1[i], carry_out);
320 
321  return carry_out;
322 }
323 
325  const bvt &op0,
326  const bvt &op1,
327  bool subtract,
328  representationt rep)
329 {
330  bvt sum=op0;
331  adder_no_overflow(sum, op1, subtract, rep);
332  return sum;
333 }
334 
335 bvt bv_utilst::add_sub(const bvt &op0, const bvt &op1, bool subtract)
336 {
337  PRECONDITION(op0.size() == op1.size());
338 
339  literalt carry_in=const_literal(subtract);
341 
342  bvt result=op0;
343  bvt tmp_op1=subtract?inverted(op1):op1;
344 
345  adder(result, tmp_op1, carry_in, carry_out);
346 
347  return result;
348 }
349 
350 bvt bv_utilst::add_sub(const bvt &op0, const bvt &op1, literalt subtract)
351 {
352  const bvt op1_sign_applied=
353  select(subtract, inverted(op1), op1);
354 
355  bvt result=op0;
357 
358  adder(result, op1_sign_applied, subtract, carry_out);
359 
360  return result;
361 }
362 
364  const bvt &op0,
365  const bvt &op1,
366  bool subtract,
367  representationt rep)
368 {
369  PRECONDITION(op0.size() == op1.size());
370  PRECONDITION(
372 
373  literalt carry_in = const_literal(subtract);
375 
376  bvt add_sub_result = op0;
377  bvt tmp_op1 = subtract ? inverted(op1) : op1;
378 
379  adder(add_sub_result, tmp_op1, carry_in, carry_out);
380 
381  bvt result;
382  result.reserve(add_sub_result.size());
383  if(rep == representationt::UNSIGNED)
384  {
385  // An unsigned overflow has occurred when carry_out is not equal to
386  // subtract: addition with a carry-out means an overflow beyond the maximum
387  // representable value, subtraction without a carry-out means an underflow
388  // below zero. For saturating arithmetic the former implies that all bits
389  // should be set to 1, in the latter case all bits should be set to zero.
390  for(const auto &literal : add_sub_result)
391  {
392  result.push_back(
393  subtract ? prop.land(literal, carry_out)
394  : prop.lor(literal, carry_out));
395  }
396  }
397  else
398  {
399  // A signed overflow beyond the maximum representable value occurs when
400  // adding two positive numbers and the wrap-around result being negative, or
401  // when subtracting a negative from a positive number (and, again, the
402  // result being negative).
403  literalt overflow_to_max_int = prop.land(bvt{
404  !sign_bit(op0),
405  subtract ? sign_bit(op1) : !sign_bit(op1),
406  sign_bit(add_sub_result)});
407  // A signed underflow below the minimum representable value occurs when
408  // adding two negative numbers and arriving at a positive result, or
409  // subtracting a positive from a negative number (and, again, obtaining a
410  // positive wrap-around result).
411  literalt overflow_to_min_int = prop.land(bvt{
412  sign_bit(op0),
413  subtract ? !sign_bit(op1) : sign_bit(op1),
414  !sign_bit(add_sub_result)});
415 
416  // set all bits except for the sign bit
417  PRECONDITION(!add_sub_result.empty());
418  for(std::size_t i = 0; i < add_sub_result.size() - 1; ++i)
419  {
420  const auto &literal = add_sub_result[i];
421  result.push_back(prop.land(
422  prop.lor(overflow_to_max_int, literal), !overflow_to_min_int));
423  }
424  // finally add the sign bit
425  result.push_back(prop.land(
426  prop.lor(overflow_to_min_int, add_sub_result.back()),
427  !overflow_to_max_int));
428  }
429 
430  return result;
431 }
432 
434  const bvt &op0, const bvt &op1, representationt rep)
435 {
436  if(rep==representationt::SIGNED)
437  {
438  // An overflow occurs if the signs of the two operands are the same
439  // and the sign of the sum is the opposite.
440 
441  literalt old_sign=op0[op0.size()-1];
442  literalt sign_the_same=prop.lequal(op0[op0.size()-1], op1[op1.size()-1]);
443 
444  bvt result=add(op0, op1);
445  return
446  prop.land(sign_the_same, prop.lxor(result[result.size()-1], old_sign));
447  }
448  else if(rep==representationt::UNSIGNED)
449  {
450  // overflow is simply carry-out
451  return carry_out(op0, op1, const_literal(false));
452  }
453  else
454  UNREACHABLE;
455 }
456 
458  const bvt &op0, const bvt &op1, representationt rep)
459 {
460  if(rep==representationt::SIGNED)
461  {
462  // We special-case x-INT_MIN, which is >=0 if
463  // x is negative, always representable, and
464  // thus not an overflow.
465  literalt op1_is_int_min=is_int_min(op1);
466  literalt op0_is_negative=op0[op0.size()-1];
467 
468  return
469  prop.lselect(op1_is_int_min,
470  !op0_is_negative,
472  }
473  else if(rep==representationt::UNSIGNED)
474  {
475  // overflow is simply _negated_ carry-out
476  return !carry_out(op0, inverted(op1), const_literal(true));
477  }
478  else
479  UNREACHABLE;
480 }
481 
483  bvt &sum,
484  const bvt &op,
485  bool subtract,
486  representationt rep)
487 {
488  const bvt tmp_op=subtract?inverted(op):op;
489 
490  if(rep==representationt::SIGNED)
491  {
492  // an overflow occurs if the signs of the two operands are the same
493  // and the sign of the sum is the opposite
494 
495  literalt old_sign=sum[sum.size()-1];
496  literalt sign_the_same=
497  prop.lequal(sum[sum.size()-1], tmp_op[tmp_op.size()-1]);
498 
499  literalt carry;
500  adder(sum, tmp_op, const_literal(subtract), carry);
501 
502  // result of addition in sum
504  prop.land(sign_the_same, prop.lxor(sum[sum.size()-1], old_sign)));
505  }
506  else
507  {
508  INVARIANT(
510  "representation has either value signed or unsigned");
512  adder(sum, tmp_op, const_literal(subtract), carry_out);
513  prop.l_set_to(carry_out, subtract);
514  }
515 }
516 
517 void bv_utilst::adder_no_overflow(bvt &sum, const bvt &op)
518 {
520 
521  adder(sum, op, carry_out, carry_out);
522 
523  prop.l_set_to_false(carry_out); // enforce no overflow
524 }
525 
526 bvt bv_utilst::shift(const bvt &op, const shiftt s, const bvt &dist)
527 {
528  std::size_t d=1, width=op.size();
529  bvt result=op;
530 
531  for(std::size_t stage=0; stage<dist.size(); stage++)
532  {
533  if(dist[stage]!=const_literal(false))
534  {
535  bvt tmp=shift(result, s, d);
536 
537  for(std::size_t i=0; i<width; i++)
538  result[i]=prop.lselect(dist[stage], tmp[i], result[i]);
539  }
540 
541  d=d<<1;
542  }
543 
544  return result;
545 }
546 
547 bvt bv_utilst::shift(const bvt &src, const shiftt s, std::size_t dist)
548 {
549  bvt result;
550  result.resize(src.size());
551 
552  // 'dist' is user-controlled, and thus arbitary.
553  // We thus must guard against the case in which i+dist overflows.
554  // We do so by considering the case dist>=src.size().
555 
556  for(std::size_t i=0; i<src.size(); i++)
557  {
558  literalt l;
559 
560  switch(s)
561  {
562  case shiftt::SHIFT_LEFT:
563  // no underflow on i-dist because of condition dist<=i
564  l=(dist<=i?src[i-dist]:const_literal(false));
565  break;
566 
568  // src.size()-i won't underflow as i<src.size()
569  // Then, if dist<src.size()-i, then i+dist<src.size()
570  l=(dist<src.size()-i?src[i+dist]:src[src.size()-1]); // sign bit
571  break;
572 
574  // src.size()-i won't underflow as i<src.size()
575  // Then, if dist<src.size()-i, then i+dist<src.size()
576  l=(dist<src.size()-i?src[i+dist]:const_literal(false));
577  break;
578 
579  case shiftt::ROTATE_LEFT:
580  // prevent overflows by using dist%src.size()
581  l=src[(src.size()+i-(dist%src.size()))%src.size()];
582  break;
583 
585  // prevent overflows by using dist%src.size()
586  l=src[(i+(dist%src.size()))%src.size()];
587  break;
588 
589  default:
590  UNREACHABLE;
591  }
592 
593  result[i]=l;
594  }
595 
596  return result;
597 }
598 
600 {
601  bvt result=inverted(bv);
603  incrementer(result, const_literal(true), carry_out);
604  return result;
605 }
606 
608 {
610  return negate(bv);
611 }
612 
614 {
615  // a overflow on unary- can only happen with the smallest
616  // representable number 100....0
617 
618  bvt should_be_zeros(bv);
619  should_be_zeros.pop_back();
620 
621  return prop.land(bv[bv.size() - 1], !prop.lor(should_be_zeros));
622 }
623 
625  bvt &bv,
626  literalt carry_in,
627  literalt &carry_out)
628 {
629  carry_out=carry_in;
630 
631  for(auto &literal : bv)
632  {
633  literalt new_carry = prop.land(carry_out, literal);
634  literal = prop.lxor(literal, carry_out);
635  carry_out=new_carry;
636  }
637 }
638 
640 {
641  bvt result=bv;
643  incrementer(result, carry_in, carry_out);
644  return result;
645 }
646 
648 {
649  bvt result=bv;
650  for(auto &literal : result)
651  literal = !literal;
652  return result;
653 }
654 
655 bvt bv_utilst::wallace_tree(const std::vector<bvt> &pps)
656 {
657  PRECONDITION(!pps.empty());
658 
659  if(pps.size()==1)
660  return pps.front();
661  else if(pps.size()==2)
662  return add(pps[0], pps[1]);
663  else
664  {
665  std::vector<bvt> new_pps;
666  std::size_t no_full_adders=pps.size()/3;
667 
668  // add groups of three partial products using CSA
669  for(std::size_t i=0; i<no_full_adders; i++)
670  {
671  const bvt &a=pps[i*3+0],
672  &b=pps[i*3+1],
673  &c=pps[i*3+2];
674 
675  INVARIANT(a.size() == b.size(), "groups should be of equal size");
676  INVARIANT(a.size() == c.size(), "groups should be of equal size");
677 
678  bvt s(a.size()), t(a.size());
679 
680  for(std::size_t bit=0; bit<a.size(); bit++)
681  {
682  // \todo reformulate using full_adder
683  s[bit]=prop.lxor(a[bit], prop.lxor(b[bit], c[bit]));
684  t[bit]=(bit==0)?const_literal(false):
685  carry(a[bit-1], b[bit-1], c[bit-1]);
686  }
687 
688  new_pps.push_back(s);
689  new_pps.push_back(t);
690  }
691 
692  // pass onwards up to two remaining partial products
693  for(std::size_t i=no_full_adders*3; i<pps.size(); i++)
694  new_pps.push_back(pps[i]);
695 
696  POSTCONDITION(new_pps.size() < pps.size());
697  return wallace_tree(new_pps);
698  }
699 }
700 
701 bvt bv_utilst::unsigned_multiplier(const bvt &_op0, const bvt &_op1)
702 {
703  #if 1
704  bvt op0=_op0, op1=_op1;
705 
706  if(is_constant(op1))
707  std::swap(op0, op1);
708 
709  bvt product;
710  product.resize(op0.size());
711 
712  for(std::size_t i=0; i<product.size(); i++)
713  product[i]=const_literal(false);
714 
715  for(std::size_t sum=0; sum<op0.size(); sum++)
716  if(op0[sum]!=const_literal(false))
717  {
718  bvt tmpop = zeros(sum);
719  tmpop.reserve(op0.size());
720 
721  for(std::size_t idx=sum; idx<op0.size(); idx++)
722  tmpop.push_back(prop.land(op1[idx-sum], op0[sum]));
723 
724  product=add(product, tmpop);
725  }
726 
727  return product;
728  #else
729  // Wallace tree multiplier. This is disabled, as runtimes have
730  // been observed to go up by 5%-10%, and on some models even by 20%.
731 
732  // build the usual quadratic number of partial products
733 
734  bvt op0=_op0, op1=_op1;
735 
736  if(is_constant(op1))
737  std::swap(op0, op1);
738 
739  std::vector<bvt> pps;
740  pps.reserve(op0.size());
741 
742  for(std::size_t bit=0; bit<op0.size(); bit++)
743  if(op0[bit]!=const_literal(false))
744  {
745  // zeros according to weight
746  bvt pp = zeros(bit);
747  pp.reserve(op0.size());
748 
749  for(std::size_t idx=bit; idx<op0.size(); idx++)
750  pp.push_back(prop.land(op1[idx-bit], op0[bit]));
751 
752  pps.push_back(pp);
753  }
754 
755  if(pps.empty())
756  return zeros(op0.size());
757  else
758  return wallace_tree(pps);
759 
760  #endif
761 }
762 
764  const bvt &op0,
765  const bvt &op1)
766 {
767  bvt _op0=op0, _op1=op1;
768 
769  PRECONDITION(_op0.size() == _op1.size());
770 
771  if(is_constant(_op1))
772  _op0.swap(_op1);
773 
774  bvt product;
775  product.resize(_op0.size());
776 
777  for(std::size_t i=0; i<product.size(); i++)
778  product[i]=const_literal(false);
779 
780  for(std::size_t sum=0; sum<op0.size(); sum++)
781  if(op0[sum]!=const_literal(false))
782  {
783  bvt tmpop;
784 
785  tmpop.reserve(product.size());
786 
787  for(std::size_t idx=0; idx<sum; idx++)
788  tmpop.push_back(const_literal(false));
789 
790  for(std::size_t idx=sum; idx<product.size(); idx++)
791  tmpop.push_back(prop.land(op1[idx-sum], op0[sum]));
792 
793  adder_no_overflow(product, tmpop);
794 
795  for(std::size_t idx=op1.size()-sum; idx<op1.size(); idx++)
796  prop.l_set_to_false(prop.land(op1[idx], op0[sum]));
797  }
798 
799  return product;
800 }
801 
802 bvt bv_utilst::signed_multiplier(const bvt &op0, const bvt &op1)
803 {
804  if(op0.empty() || op1.empty())
805  return bvt();
806 
807  literalt sign0=op0[op0.size()-1];
808  literalt sign1=op1[op1.size()-1];
809 
810  bvt neg0=cond_negate(op0, sign0);
811  bvt neg1=cond_negate(op1, sign1);
812 
813  bvt result=unsigned_multiplier(neg0, neg1);
814 
815  literalt result_sign=prop.lxor(sign0, sign1);
816 
817  return cond_negate(result, result_sign);
818 }
819 
820 bvt bv_utilst::cond_negate(const bvt &bv, const literalt cond)
821 {
822  bvt neg_bv=negate(bv);
823 
824  bvt result;
825  result.resize(bv.size());
826 
827  for(std::size_t i=0; i<bv.size(); i++)
828  result[i]=prop.lselect(cond, neg_bv[i], bv[i]);
829 
830  return result;
831 }
832 
834 {
835  PRECONDITION(!bv.empty());
836  return cond_negate(bv, bv[bv.size()-1]);
837 }
838 
840 {
842 
843  return cond_negate(bv, cond);
844 }
845 
847  const bvt &op0,
848  const bvt &op1)
849 {
850  if(op0.empty() || op1.empty())
851  return bvt();
852 
853  literalt sign0=op0[op0.size()-1];
854  literalt sign1=op1[op1.size()-1];
855 
856  bvt neg0=cond_negate_no_overflow(op0, sign0);
857  bvt neg1=cond_negate_no_overflow(op1, sign1);
858 
859  bvt result=unsigned_multiplier_no_overflow(neg0, neg1);
860 
861  prop.l_set_to_false(result[result.size() - 1]);
862 
863  literalt result_sign=prop.lxor(sign0, sign1);
864 
865  return cond_negate_no_overflow(result, result_sign);
866 }
867 
869  const bvt &op0,
870  const bvt &op1,
871  representationt rep)
872 {
873  switch(rep)
874  {
875  case representationt::SIGNED: return signed_multiplier(op0, op1);
876  case representationt::UNSIGNED: return unsigned_multiplier(op0, op1);
877  }
878 
879  UNREACHABLE;
880 }
881 
883  const bvt &op0,
884  const bvt &op1,
885  representationt rep)
886 {
887  switch(rep)
888  {
890  return signed_multiplier_no_overflow(op0, op1);
892  return unsigned_multiplier_no_overflow(op0, op1);
893  }
894 
895  UNREACHABLE;
896 }
897 
899  const bvt &op0,
900  const bvt &op1,
901  bvt &res,
902  bvt &rem)
903 {
904  if(op0.empty() || op1.empty())
905  return;
906 
907  bvt _op0(op0), _op1(op1);
908 
909  literalt sign_0=_op0[_op0.size()-1];
910  literalt sign_1=_op1[_op1.size()-1];
911 
912  bvt neg_0=negate(_op0), neg_1=negate(_op1);
913 
914  for(std::size_t i=0; i<_op0.size(); i++)
915  _op0[i]=(prop.lselect(sign_0, neg_0[i], _op0[i]));
916 
917  for(std::size_t i=0; i<_op1.size(); i++)
918  _op1[i]=(prop.lselect(sign_1, neg_1[i], _op1[i]));
919 
920  unsigned_divider(_op0, _op1, res, rem);
921 
922  bvt neg_res=negate(res), neg_rem=negate(rem);
923 
924  literalt result_sign=prop.lxor(sign_0, sign_1);
925 
926  for(std::size_t i=0; i<res.size(); i++)
927  res[i]=prop.lselect(result_sign, neg_res[i], res[i]);
928 
929  for(std::size_t i=0; i<res.size(); i++)
930  rem[i]=prop.lselect(sign_0, neg_rem[i], rem[i]);
931 }
932 
934  const bvt &op0,
935  const bvt &op1,
936  bvt &result,
937  bvt &remainer,
938  representationt rep)
939 {
941 
942  switch(rep)
943  {
945  signed_divider(op0, op1, result, remainer); break;
947  unsigned_divider(op0, op1, result, remainer); break;
948  }
949 }
950 
952  const bvt &op0,
953  const bvt &op1,
954  bvt &res,
955  bvt &rem)
956 {
957  std::size_t width=op0.size();
958 
959  // check if we divide by a power of two
960  #if 0
961  {
962  std::size_t one_count=0, non_const_count=0, one_pos=0;
963 
964  for(std::size_t i=0; i<op1.size(); i++)
965  {
966  literalt l=op1[i];
967  if(l.is_true())
968  {
969  one_count++;
970  one_pos=i;
971  }
972  else if(!l.is_false())
973  non_const_count++;
974  }
975 
976  if(non_const_count==0 && one_count==1 && one_pos!=0)
977  {
978  // it is a power of two!
979  res=shift(op0, LRIGHT, one_pos);
980 
981  // remainder is just a mask
982  rem=op0;
983  for(std::size_t i=one_pos; i<rem.size(); i++)
984  rem[i]=const_literal(false);
985  return;
986  }
987  }
988  #endif
989 
990  // Division by zero test.
991  // Note that we produce a non-deterministic result in
992  // case of division by zero. SMT-LIB now says the following:
993  // bvudiv returns a vector of all 1s if the second operand is 0
994  // bvurem returns its first operand if the second operand is 0
995 
997 
998  // free variables for result of division
999  res = prop.new_variables(width);
1000  rem = prop.new_variables(width);
1001 
1002  // add implications
1003 
1004  bvt product=
1006 
1007  // res*op1 + rem = op0
1008 
1009  bvt sum=product;
1010 
1011  adder_no_overflow(sum, rem);
1012 
1013  literalt is_equal=equal(sum, op0);
1014 
1016 
1017  // op1!=0 => rem < op1
1018 
1020  prop.limplies(
1021  is_not_zero, lt_or_le(false, rem, op1, representationt::UNSIGNED)));
1022 
1023  // op1!=0 => res <= op0
1024 
1026  prop.limplies(
1027  is_not_zero, lt_or_le(true, res, op0, representationt::UNSIGNED)));
1028 }
1029 
1030 
1031 #ifdef COMPACT_EQUAL_CONST
1032 // TODO : use for lt_or_le as well
1033 
1037 void bv_utilst::equal_const_register(const bvt &var)
1038 {
1039  PRECONDITION(!is_constant(var));
1040  equal_const_registered.insert(var);
1041  return;
1042 }
1043 
1050 literalt bv_utilst::equal_const_rec(bvt &var, bvt &constant)
1051 {
1052  std::size_t size = var.size();
1053 
1054  PRECONDITION(size != 0);
1055  PRECONDITION(size == constant.size());
1056  PRECONDITION(is_constant(constant));
1057 
1058  if(size == 1)
1059  {
1060  literalt comp = prop.lequal(var[size - 1], constant[size - 1]);
1061  var.pop_back();
1062  constant.pop_back();
1063  return comp;
1064  }
1065  else
1066  {
1067  var_constant_pairt index(var, constant);
1068 
1069  equal_const_cachet::iterator entry = equal_const_cache.find(index);
1070 
1071  if(entry != equal_const_cache.end())
1072  {
1073  return entry->second;
1074  }
1075  else
1076  {
1077  literalt comp = prop.lequal(var[size - 1], constant[size - 1]);
1078  var.pop_back();
1079  constant.pop_back();
1080 
1081  literalt rec = equal_const_rec(var, constant);
1082  literalt compare = prop.land(rec, comp);
1083 
1084  equal_const_cache.insert(
1085  std::pair<var_constant_pairt, literalt>(index, compare));
1086 
1087  return compare;
1088  }
1089  }
1090 }
1091 
1100 literalt bv_utilst::equal_const(const bvt &var, const bvt &constant)
1101 {
1102  std::size_t size = constant.size();
1103 
1104  PRECONDITION(var.size() == size);
1105  PRECONDITION(!is_constant(var));
1106  PRECONDITION(is_constant(constant));
1107  PRECONDITION(size >= 2);
1108 
1109  // These get modified : be careful!
1110  bvt var_upper;
1111  bvt var_lower;
1112  bvt constant_upper;
1113  bvt constant_lower;
1114 
1115  /* Split the constant based on a change in parity
1116  * This is based on the observation that most constants are small,
1117  * so combinations of the lower bits are heavily used but the upper
1118  * bits are almost always either all 0 or all 1.
1119  */
1120  literalt top_bit = constant[size - 1];
1121 
1122  std::size_t split = size - 1;
1123  var_upper.push_back(var[size - 1]);
1124  constant_upper.push_back(constant[size - 1]);
1125 
1126  for(split = size - 2; split != 0; --split)
1127  {
1128  if(constant[split] != top_bit)
1129  {
1130  break;
1131  }
1132  else
1133  {
1134  var_upper.push_back(var[split]);
1135  constant_upper.push_back(constant[split]);
1136  }
1137  }
1138 
1139  for(std::size_t i = 0; i <= split; ++i)
1140  {
1141  var_lower.push_back(var[i]);
1142  constant_lower.push_back(constant[i]);
1143  }
1144 
1145  // Check we have split the array correctly
1146  INVARIANT(
1147  var_upper.size() + var_lower.size() == size,
1148  "lower size plus upper size should equal the total size");
1149  INVARIANT(
1150  constant_upper.size() + constant_lower.size() == size,
1151  "lower size plus upper size should equal the total size");
1152 
1153  literalt top_comparison = equal_const_rec(var_upper, constant_upper);
1154  literalt bottom_comparison = equal_const_rec(var_lower, constant_lower);
1155 
1156  return prop.land(top_comparison, bottom_comparison);
1157 }
1158 
1159 #endif
1160 
1165 literalt bv_utilst::equal(const bvt &op0, const bvt &op1)
1166 {
1167  PRECONDITION(op0.size() == op1.size());
1168 
1169  #ifdef COMPACT_EQUAL_CONST
1170  // simplify_expr should put the constant on the right
1171  // but bit-level simplification may result in the other cases
1172  if(is_constant(op0) && !is_constant(op1) && op0.size() > 2 &&
1173  equal_const_registered.find(op1) != equal_const_registered.end())
1174  return equal_const(op1, op0);
1175  else if(!is_constant(op0) && is_constant(op1) && op0.size() > 2 &&
1176  equal_const_registered.find(op0) != equal_const_registered.end())
1177  return equal_const(op0, op1);
1178  #endif
1179 
1180  bvt equal_bv;
1181  equal_bv.resize(op0.size());
1182 
1183  for(std::size_t i=0; i<op0.size(); i++)
1184  equal_bv[i]=prop.lequal(op0[i], op1[i]);
1185 
1186  return prop.land(equal_bv);
1187 }
1188 
1193 
1194 #define COMPACT_LT_OR_LE
1195 /* Some clauses are not needed for correctness but they remove
1196  models (effectively setting "don't care" bits) and so may be worth
1197  including.*/
1198 // #define INCLUDE_REDUNDANT_CLAUSES
1199 
1201  bool or_equal,
1202  const bvt &bv0,
1203  const bvt &bv1,
1204  representationt rep)
1205 {
1206  PRECONDITION(bv0.size() == bv1.size());
1207 
1208  literalt top0=bv0[bv0.size()-1],
1209  top1=bv1[bv1.size()-1];
1210 
1211 #ifdef COMPACT_LT_OR_LE
1213  {
1214  bvt compareBelow; // 1 if a compare is needed below this bit
1215  literalt result;
1216  size_t start;
1217  size_t i;
1218 
1219  compareBelow = prop.new_variables(bv0.size());
1220  result = prop.new_variable();
1221 
1222  if(rep == representationt::SIGNED)
1223  {
1224  INVARIANT(
1225  bv0.size() >= 2, "signed bitvectors should have at least two bits");
1226  start = compareBelow.size() - 2;
1227 
1228  literalt firstComp=compareBelow[start];
1229 
1230  // When comparing signs we are comparing the top bit
1231 #ifdef INCLUDE_REDUNDANT_CLAUSES
1232  prop.l_set_to_true(compareBelow[start + 1])
1233 #endif
1234 
1235  // Four cases...
1236  prop.lcnf(top0, top1, firstComp); // + + compare needed
1237  prop.lcnf(top0, !top1, !result); // + - result false and no compare needed
1238  prop.lcnf(!top0, top1, result); // - + result true and no compare needed
1239  prop.lcnf(!top0, !top1, firstComp); // - - negated compare needed
1240 
1241 #ifdef INCLUDE_REDUNDANT_CLAUSES
1242  prop.lcnf(top0, !top1, !firstComp);
1243  prop.lcnf(!top0, top1, !firstComp);
1244 #endif
1245  }
1246  else
1247  {
1248  // Unsigned is much easier
1249  start = compareBelow.size() - 1;
1250  prop.l_set_to_true(compareBelow[start]);
1251  }
1252 
1253  // Determine the output
1254  // \forall i . cb[i] & -a[i] & b[i] => result
1255  // \forall i . cb[i] & a[i] & -b[i] => -result
1256  i = start;
1257  do
1258  {
1259  prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], result);
1260  prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !result);
1261  }
1262  while(i-- != 0);
1263 
1264  // Chain the comparison bit
1265  // \forall i != 0 . cb[i] & a[i] & b[i] => cb[i-1]
1266  // \forall i != 0 . cb[i] & -a[i] & -b[i] => cb[i-1]
1267  for(i = start; i > 0; i--)
1268  {
1269  prop.lcnf(!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i-1]);
1270  prop.lcnf(!compareBelow[i], bv0[i], bv1[i], compareBelow[i-1]);
1271  }
1272 
1273 
1274 #ifdef INCLUDE_REDUNDANT_CLAUSES
1275  // Optional zeroing of the comparison bit when not needed
1276  // \forall i != 0 . -c[i] => -c[i-1]
1277  // \forall i != 0 . c[i] & -a[i] & b[i] => -c[i-1]
1278  // \forall i != 0 . c[i] & a[i] & -b[i] => -c[i-1]
1279  for(i = start; i > 0; i--)
1280  {
1281  prop.lcnf(compareBelow[i], !compareBelow[i-1]);
1282  prop.lcnf(!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i-1]);
1283  prop.lcnf(!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i-1]);
1284  }
1285 #endif
1286 
1287  // The 'base case' of the induction is the case when they are equal
1288  prop.lcnf(!compareBelow[0], !bv0[0], !bv1[0], (or_equal)?result:!result);
1289  prop.lcnf(!compareBelow[0], bv0[0], bv1[0], (or_equal)?result:!result);
1290 
1291  return result;
1292  }
1293  else
1294 #endif
1295  {
1296  literalt carry=
1297  carry_out(bv0, inverted(bv1), const_literal(true));
1298 
1299  literalt result;
1300 
1301  if(rep==representationt::SIGNED)
1302  result=prop.lxor(prop.lequal(top0, top1), carry);
1303  else
1304  {
1305  INVARIANT(
1307  "representation has either value signed or unsigned");
1308  result = !carry;
1309  }
1310 
1311  if(or_equal)
1312  result=prop.lor(result, equal(bv0, bv1));
1313 
1314  return result;
1315  }
1316 }
1317 
1319  const bvt &op0,
1320  const bvt &op1)
1321 {
1322 #ifdef COMPACT_LT_OR_LE
1323  return lt_or_le(false, op0, op1, representationt::UNSIGNED);
1324 #else
1325  // A <= B iff there is an overflow on A-B
1326  return !carry_out(op0, inverted(op1), const_literal(true));
1327 #endif
1328 }
1329 
1331  const bvt &bv0,
1332  const bvt &bv1)
1333 {
1334  return lt_or_le(false, bv0, bv1, representationt::SIGNED);
1335 }
1336 
1338  const bvt &bv0,
1339  irep_idt id,
1340  const bvt &bv1,
1341  representationt rep)
1342 {
1343  if(id==ID_equal)
1344  return equal(bv0, bv1);
1345  else if(id==ID_notequal)
1346  return !equal(bv0, bv1);
1347  else if(id==ID_le)
1348  return lt_or_le(true, bv0, bv1, rep);
1349  else if(id==ID_lt)
1350  return lt_or_le(false, bv0, bv1, rep);
1351  else if(id==ID_ge)
1352  return lt_or_le(true, bv1, bv0, rep); // swapped
1353  else if(id==ID_gt)
1354  return lt_or_le(false, bv1, bv0, rep); // swapped
1355  else
1356  UNREACHABLE;
1357 }
1358 
1360 {
1361  for(const auto &literal : bv)
1362  {
1363  if(!literal.is_constant())
1364  return false;
1365  }
1366 
1367  return true;
1368 }
1369 
1371  literalt cond,
1372  const bvt &a,
1373  const bvt &b)
1374 {
1375  PRECONDITION(a.size() == b.size());
1376 
1377  if(prop.cnf_handled_well())
1378  {
1379  for(std::size_t i=0; i<a.size(); i++)
1380  {
1381  prop.lcnf(!cond, a[i], !b[i]);
1382  prop.lcnf(!cond, !a[i], b[i]);
1383  }
1384  }
1385  else
1386  {
1387  prop.limplies(cond, equal(a, b));
1388  }
1389 
1390  return;
1391 }
1392 
1394 {
1395  bvt odd_bits;
1396  odd_bits.reserve(src.size()/2);
1397 
1398  // check every odd bit
1399  for(std::size_t i=0; i<src.size(); i++)
1400  {
1401  if(i%2!=0)
1402  odd_bits.push_back(src[i]);
1403  }
1404 
1405  return prop.lor(odd_bits);
1406 }
1407 
1409 {
1410  bvt even_bits;
1411  even_bits.reserve(src.size()/2);
1412 
1413  // get every even bit
1414  for(std::size_t i=0; i<src.size(); i++)
1415  {
1416  if(i%2==0)
1417  even_bits.push_back(src[i]);
1418  }
1419 
1420  return even_bits;
1421 }
bv_utilst::shiftt::SHIFT_LEFT
@ SHIFT_LEFT
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
bv_utilst::cond_negate_no_overflow
bvt cond_negate_no_overflow(const bvt &bv, const literalt cond)
Definition: bv_utils.cpp:839
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
bv_utilst::extract_lsb
static bvt extract_lsb(const bvt &a, std::size_t n)
Definition: bv_utils.cpp:66
bv_utilst::cond_implies_equal
void cond_implies_equal(literalt cond, const bvt &a, const bvt &b)
Definition: bv_utils.cpp:1370
propt::new_variables
virtual bvt new_variables(std::size_t width)
generates a bitvector of given width with new variables
Definition: prop.cpp:20
bv_utilst::carry
literalt carry(literalt a, literalt b, literalt c)
Definition: bv_utils.cpp:227
bv_utilst::full_adder
literalt full_adder(const literalt a, const literalt b, const literalt carry_in, literalt &carry_out)
Definition: bv_utils.cpp:136
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
bv_utilst::is_not_zero
literalt is_not_zero(const bvt &op)
Definition: bv_utils.h:146
bv_utilst::carry_out
literalt carry_out(const bvt &op0, const bvt &op1, literalt carry_in)
Definition: bv_utils.cpp:309
bvt
std::vector< literalt > bvt
Definition: literal.h:201
bv_utilst::negate_no_overflow
bvt negate_no_overflow(const bvt &op)
Definition: bv_utils.cpp:607
bv_utilst::adder_no_overflow
void adder_no_overflow(bvt &sum, const bvt &op, bool subtract, representationt rep)
Definition: bv_utils.cpp:482
bv_utilst::signed_multiplier
bvt signed_multiplier(const bvt &op0, const bvt &op1)
Definition: bv_utils.cpp:802
bv_utilst::shiftt::SHIFT_ARIGHT
@ SHIFT_ARIGHT
bv_utilst::zeros
static bvt zeros(std::size_t new_size)
Definition: bv_utils.h:192
propt::set_equal
virtual void set_equal(literalt a, literalt b)
asserts a==b in the propositional formula
Definition: prop.cpp:12
bv_utilst::representationt::UNSIGNED
@ UNSIGNED
bv_utilst::set_equal
void set_equal(const bvt &a, const bvt &b)
Definition: bv_utils.cpp:31
bv_utils.h
bv_utilst::signed_divider
void signed_divider(const bvt &op0, const bvt &op1, bvt &res, bvt &rem)
Definition: bv_utils.cpp:898
propt::new_variable
virtual literalt new_variable()=0
propt::lor
virtual literalt lor(literalt a, literalt b)=0
propt::l_set_to_true
void l_set_to_true(literalt a)
Definition: prop.h:50
propt::l_set_to
virtual void l_set_to(literalt a, bool value)
Definition: prop.h:45
bv_utilst::prop
propt & prop
Definition: bv_utils.h:222
bv_utilst::incrementer
bvt incrementer(const bvt &op, literalt carry_in)
Definition: bv_utils.cpp:639
bv_utilst::inverted
static bvt inverted(const bvt &op)
Definition: bv_utils.cpp:647
bv_utilst::absolute_value
bvt absolute_value(const bvt &op)
Definition: bv_utils.cpp:833
bv_utilst::unsigned_multiplier
bvt unsigned_multiplier(const bvt &op0, const bvt &op1)
Definition: bv_utils.cpp:701
propt::land
virtual literalt land(literalt a, literalt b)=0
bv_utilst::select
bvt select(literalt s, const bvt &a, const bvt &b)
If s is true, selects a otherwise selects b.
Definition: bv_utils.cpp:92
bv_utilst::shift
static bvt shift(const bvt &op, const shiftt shift, std::size_t distance)
Definition: bv_utils.cpp:547
bv_utilst::unsigned_less_than
literalt unsigned_less_than(const bvt &bv0, const bvt &bv1)
Definition: bv_utils.cpp:1318
bv_utilst::unsigned_divider
void unsigned_divider(const bvt &op0, const bvt &op1, bvt &res, bvt &rem)
Definition: bv_utils.cpp:951
literalt::is_true
bool is_true() const
Definition: literal.h:156
propt::lxor
virtual literalt lxor(literalt a, literalt b)=0
bv_utilst::is_int_min
literalt is_int_min(const bvt &op)
Definition: bv_utils.h:149
bv_utilst::add
bvt add(const bvt &op0, const bvt &op1)
Definition: bv_utils.h:66
propt::limplies
virtual literalt limplies(literalt a, literalt b)=0
bv_utilst::representationt::SIGNED
@ SIGNED
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
propt::cnf_handled_well
virtual bool cnf_handled_well() const
Definition: prop.h:83
bv_utilst::representationt
representationt
Definition: bv_utils.h:28
bv_utilst::cond_negate
bvt cond_negate(const bvt &bv, const literalt cond)
Definition: bv_utils.cpp:820
bv_utilst::overflow_sub
literalt overflow_sub(const bvt &op0, const bvt &op1, representationt rep)
Definition: bv_utils.cpp:457
literalt::is_false
bool is_false() const
Definition: literal.h:161
const_literal
literalt const_literal(bool value)
Definition: literal.h:188
bv_utilst::overflow_add
literalt overflow_add(const bvt &op0, const bvt &op1, representationt rep)
Definition: bv_utils.cpp:433
bv_utilst::signed_multiplier_no_overflow
bvt signed_multiplier_no_overflow(const bvt &op0, const bvt &op1)
Definition: bv_utils.cpp:846
bv_utilst::unsigned_multiplier_no_overflow
bvt unsigned_multiplier_no_overflow(const bvt &op0, const bvt &op1)
Definition: bv_utils.cpp:763
bv_utilst::concatenate
static bvt concatenate(const bvt &a, const bvt &b)
Definition: bv_utils.cpp:76
bv_utilst::lt_or_le
literalt lt_or_le(bool or_equal, const bvt &bv0, const bvt &bv1, representationt rep)
Definition: bv_utils.cpp:1200
bv_utilst::add_sub
bvt add_sub(const bvt &op0, const bvt &op1, bool subtract)
Definition: bv_utils.cpp:335
bv_utilst::wallace_tree
bvt wallace_tree(const std::vector< bvt > &pps)
Definition: bv_utils.cpp:655
propt::l_set_to_false
void l_set_to_false(literalt a)
Definition: prop.h:52
bv_utilst::multiplier_no_overflow
bvt multiplier_no_overflow(const bvt &op0, const bvt &op1, representationt rep)
Definition: bv_utils.cpp:882
bv_utilst::build_constant
static bvt build_constant(const mp_integer &i, std::size_t width)
Definition: bv_utils.cpp:11
propt::lequal
virtual literalt lequal(literalt a, literalt b)=0
bv_utilst::rel
literalt rel(const bvt &bv0, irep_idt id, const bvt &bv1, representationt rep)
Definition: bv_utils.cpp:1337
POSTCONDITION
#define POSTCONDITION(CONDITION)
Definition: invariant.h:479
bv_utilst::shiftt
shiftt
Definition: bv_utils.h:73
bv_utilst::negate
bvt negate(const bvt &op)
Definition: bv_utils.cpp:599
bv_utilst::overflow_negate
literalt overflow_negate(const bvt &op)
Definition: bv_utils.cpp:613
bv_utilst::shiftt::ROTATE_RIGHT
@ ROTATE_RIGHT
bv_utilst::sign_bit
static literalt sign_bit(const bvt &op)
Definition: bv_utils.h:138
bv_utilst::extension
static bvt extension(const bvt &bv, std::size_t new_size, representationt rep)
Definition: bv_utils.cpp:105
literalt
Definition: literal.h:25
bv_utilst::divider
bvt divider(const bvt &op0, const bvt &op1, representationt rep)
Definition: bv_utils.h:89
bv_utilst::extract
static bvt extract(const bvt &a, std::size_t first, std::size_t last)
Definition: bv_utils.cpp:38
propt::has_set_to
virtual bool has_set_to() const
Definition: prop.h:79
bv_utilst::signed_less_than
literalt signed_less_than(const bvt &bv0, const bvt &bv1)
Definition: bv_utils.cpp:1330
bv_utilst::shiftt::SHIFT_LRIGHT
@ SHIFT_LRIGHT
bv_utilst::multiplier
bvt multiplier(const bvt &op0, const bvt &op1, representationt rep)
Definition: bv_utils.cpp:868
bv_utilst::extract_msb
static bvt extract_msb(const bvt &a, std::size_t n)
Definition: bv_utils.cpp:54
literalt::is_constant
bool is_constant() const
Definition: literal.h:166
bv_utilst::verilog_bv_normal_bits
static bvt verilog_bv_normal_bits(const bvt &)
Definition: bv_utils.cpp:1408
bv_utilst::adder
void adder(bvt &sum, const bvt &op, literalt carry_in, literalt &carry_out)
Definition: bv_utils.cpp:293
integer2binary
const std::string integer2binary(const mp_integer &n, std::size_t width)
Definition: mp_arith.cpp:64
bv_utilst::add_sub_no_overflow
bvt add_sub_no_overflow(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
Definition: bv_utils.cpp:324
bv_utilst::equal
literalt equal(const bvt &op0, const bvt &op1)
Bit-blasting ID_equal and use in other encodings.
Definition: bv_utils.cpp:1165
bv_utilst::is_zero
literalt is_zero(const bvt &op)
Definition: bv_utils.h:143
bv_utilst::shiftt::ROTATE_LEFT
@ ROTATE_LEFT
bv_utilst::saturating_add_sub
bvt saturating_add_sub(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
Definition: bv_utils.cpp:363
propt::lselect
virtual literalt lselect(literalt a, literalt b, literalt c)=0
bv_utilst::verilog_bv_has_x_or_z
literalt verilog_bv_has_x_or_z(const bvt &)
Definition: bv_utils.cpp:1393
bv_utilst::is_one
literalt is_one(const bvt &op)
Definition: bv_utils.cpp:22
propt::lcnf
void lcnf(literalt l0, literalt l1)
Definition: prop.h:56
validation_modet::INVARIANT
@ INVARIANT
bv_utilst::is_constant
static bool is_constant(const bvt &bv)
Definition: bv_utils.cpp:1359