CBMC
boolbv_add_sub.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 "boolbv.h"
10 
11 #include <util/bitvector_types.h>
12 #include <util/invariant.h>
13 
15 
17 {
19  expr.id() == ID_plus || expr.id() == ID_minus ||
20  expr.id() == "no-overflow-plus" || expr.id() == "no-overflow-minus");
21 
22  const typet &type = expr.type();
23 
24  if(type.id()!=ID_unsignedbv &&
25  type.id()!=ID_signedbv &&
26  type.id()!=ID_fixedbv &&
27  type.id()!=ID_floatbv &&
28  type.id()!=ID_range &&
29  type.id()!=ID_complex &&
30  type.id()!=ID_vector)
31  return conversion_failed(expr);
32 
33  std::size_t width=boolbv_width(type);
34 
35  const exprt::operandst &operands=expr.operands();
36 
38  !operands.empty(),
39  "operator " + expr.id_string() + " takes at least one operand");
40 
41  const exprt &op0 = to_multi_ary_expr(expr).op0();
43  op0.type() == type, "add/sub with mixed types:\n" + expr.pretty());
44 
45  bvt bv = convert_bv(op0, width);
46 
47  bool subtract=(expr.id()==ID_minus ||
48  expr.id()=="no-overflow-minus");
49 
50  bool no_overflow=(expr.id()=="no-overflow-plus" ||
51  expr.id()=="no-overflow-minus");
52 
53  typet arithmetic_type = (type.id() == ID_vector || type.id() == ID_complex)
55  : type;
56 
58  (arithmetic_type.id()==ID_signedbv ||
59  arithmetic_type.id()==ID_fixedbv)?bv_utilst::representationt::SIGNED:
61 
62  for(exprt::operandst::const_iterator
63  it=operands.begin()+1;
64  it!=operands.end(); it++)
65  {
67  it->type() == type, "add/sub with mixed types:\n" + expr.pretty());
68 
69  const bvt &op = convert_bv(*it, width);
70 
71  if(type.id()==ID_vector || type.id()==ID_complex)
72  {
73  std::size_t sub_width =
74  boolbv_width(to_type_with_subtype(type).subtype());
75 
76  INVARIANT(sub_width != 0, "vector elements shall have nonzero bit width");
77  INVARIANT(
78  width % sub_width == 0,
79  "total vector bit width shall be a multiple of the element bit width");
80 
81  std::size_t size=width/sub_width;
82  bv.resize(width);
83 
84  for(std::size_t i=0; i<size; i++)
85  {
86  bvt tmp_op;
87  tmp_op.resize(sub_width);
88 
89  for(std::size_t j=0; j<tmp_op.size(); j++)
90  {
91  const std::size_t index = i * sub_width + j;
92  INVARIANT(index < op.size(), "bit index shall be within bounds");
93  tmp_op[j] = op[index];
94  }
95 
96  bvt tmp_result;
97  tmp_result.resize(sub_width);
98 
99  for(std::size_t j=0; j<tmp_result.size(); j++)
100  {
101  const std::size_t index = i * sub_width + j;
102  INVARIANT(index < bv.size(), "bit index shall be within bounds");
103  tmp_result[j] = bv[index];
104  }
105 
106  if(to_type_with_subtype(type).subtype().id() == ID_floatbv)
107  {
108  // needs to change due to rounding mode
109  float_utilst float_utils(
110  prop, to_floatbv_type(to_type_with_subtype(type).subtype()));
111  tmp_result=float_utils.add_sub(tmp_result, tmp_op, subtract);
112  }
113  else
114  tmp_result=bv_utils.add_sub(tmp_result, tmp_op, subtract);
115 
116  INVARIANT(
117  tmp_result.size() == sub_width,
118  "applying the add/sub operation shall not change the bitwidth");
119 
120  for(std::size_t j=0; j<tmp_result.size(); j++)
121  {
122  const std::size_t index = i * sub_width + j;
123  INVARIANT(index < bv.size(), "bit index shall be within bounds");
124  bv[index] = tmp_result[j];
125  }
126  }
127  }
128  else if(type.id()==ID_floatbv)
129  {
130  // needs to change due to rounding mode
131  float_utilst float_utils(prop, to_floatbv_type(arithmetic_type));
132  bv=float_utils.add_sub(bv, op, subtract);
133  }
134  else if(no_overflow)
135  bv=bv_utils.add_sub_no_overflow(bv, op, subtract, rep);
136  else
137  bv=bv_utils.add_sub(bv, op, subtract);
138  }
139 
140  return bv;
141 }
142 
144 {
145  PRECONDITION(
146  expr.id() == ID_saturating_minus || expr.id() == ID_saturating_plus);
147 
148  const typet &type = expr.type();
149 
150  if(
151  type.id() != ID_unsignedbv && type.id() != ID_signedbv &&
152  type.id() != ID_fixedbv && type.id() != ID_complex &&
153  type.id() != ID_vector)
154  {
155  return conversion_failed(expr);
156  }
157 
158  std::size_t width = boolbv_width(type);
159 
161  expr.lhs().type() == type && expr.rhs().type() == type,
162  "saturating add/sub with mixed types:\n" + expr.pretty());
163 
164  const bool subtract = expr.id() == ID_saturating_minus;
165 
166  typet arithmetic_type = (type.id() == ID_vector || type.id() == ID_complex)
167  ? to_type_with_subtype(type).subtype()
168  : type;
169 
171  (arithmetic_type.id() == ID_signedbv || arithmetic_type.id() == ID_fixedbv)
174 
175  bvt bv = convert_bv(expr.lhs(), width);
176  const bvt &op = convert_bv(expr.rhs(), width);
177 
178  if(type.id() != ID_vector && type.id() != ID_complex)
179  return bv_utils.saturating_add_sub(bv, op, subtract, rep);
180 
181  std::size_t sub_width = boolbv_width(to_type_with_subtype(type).subtype());
182 
183  INVARIANT(sub_width != 0, "vector elements shall have nonzero bit width");
184  INVARIANT(
185  width % sub_width == 0,
186  "total vector bit width shall be a multiple of the element bit width");
187 
188  std::size_t size = width / sub_width;
189 
190  for(std::size_t i = 0; i < size; i++)
191  {
192  bvt tmp_op;
193  tmp_op.resize(sub_width);
194 
195  for(std::size_t j = 0; j < tmp_op.size(); j++)
196  {
197  const std::size_t index = i * sub_width + j;
198  INVARIANT(index < op.size(), "bit index shall be within bounds");
199  tmp_op[j] = op[index];
200  }
201 
202  bvt tmp_result;
203  tmp_result.resize(sub_width);
204 
205  for(std::size_t j = 0; j < tmp_result.size(); j++)
206  {
207  const std::size_t index = i * sub_width + j;
208  INVARIANT(index < bv.size(), "bit index shall be within bounds");
209  tmp_result[j] = bv[index];
210  }
211 
212  tmp_result = bv_utils.saturating_add_sub(tmp_result, tmp_op, subtract, rep);
213 
214  INVARIANT(
215  tmp_result.size() == sub_width,
216  "applying the add/sub operation shall not change the bitwidth");
217 
218  for(std::size_t j = 0; j < tmp_result.size(); j++)
219  {
220  const std::size_t index = i * sub_width + j;
221  INVARIANT(index < bv.size(), "bit index shall be within bounds");
222  bv[index] = tmp_result[j];
223  }
224  }
225 
226  return bv;
227 }
binary_exprt::rhs
exprt & rhs()
Definition: std_expr.h:623
float_utilst::add_sub
virtual bvt add_sub(const bvt &src1, const bvt &src2, bool subtract)
Definition: float_utils.cpp:243
float_utilst
Definition: float_utils.h:17
typet
The type of an expression, extends irept.
Definition: type.h:28
float_utils.h
bvt
std::vector< literalt > bvt
Definition: literal.h:201
irept::pretty
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:495
to_floatbv_type
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
Definition: bitvector_types.h:367
bv_utilst::representationt::UNSIGNED
@ UNSIGNED
invariant.h
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
exprt
Base class for all expressions.
Definition: expr.h:55
binary_exprt::lhs
exprt & lhs()
Definition: std_expr.h:613
binary_exprt
A base class for binary expressions.
Definition: std_expr.h:582
boolbvt::convert_add_sub
virtual bvt convert_add_sub(const exprt &expr)
Definition: boolbv_add_sub.cpp:16
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:510
boolbvt::boolbv_width
virtual std::size_t boolbv_width(const typet &type) const
Definition: boolbv.h:102
boolbvt::convert_bv
virtual const bvt & convert_bv(const exprt &expr, const optionalt< std::size_t > expected_width={})
Convert expression to vector of literalts, using an internal cache to speed up conversion if availabl...
Definition: boolbv.cpp:39
bv_utilst::representationt::SIGNED
@ SIGNED
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
bv_utilst::representationt
representationt
Definition: bv_utils.h:28
bitvector_types.h
irept::id_string
const std::string & id_string() const
Definition: irep.h:399
boolbvt::convert_saturating_add_sub
virtual bvt convert_saturating_add_sub(const binary_exprt &expr)
Definition: boolbv_add_sub.cpp:143
irept::id
const irep_idt & id() const
Definition: irep.h:396
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
bv_utilst::add_sub
bvt add_sub(const bvt &op0, const bvt &op1, bool subtract)
Definition: bv_utils.cpp:335
boolbvt::bv_utils
bv_utilst bv_utils
Definition: boolbv.h:117
type_with_subtypet::subtype
const typet & subtype() const
Definition: type.h:172
boolbvt::conversion_failed
bvt conversion_failed(const exprt &expr)
Print that the expression of x has failed conversion, then return a vector of x's width.
Definition: boolbv.cpp:83
boolbv.h
exprt::operands
operandst & operands()
Definition: expr.h:94
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
multi_ary_exprt::op0
exprt & op0()
Definition: std_expr.h:877
bv_utilst::saturating_add_sub
bvt saturating_add_sub(const bvt &op0, const bvt &op1, bool subtract, representationt rep)
Definition: bv_utils.cpp:363
to_multi_ary_expr
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:932
validation_modet::INVARIANT
@ INVARIANT
prop_conv_solvert::prop
propt & prop
Definition: prop_conv_solver.h:130