carl  24.04
Computer ARithmetic Library
BVTermContent.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "BVTerm.h"
4 #include "BVTermType.h"
5 #include "BVValue.h"
6 #include "BVVariable.h"
7 
8 #include <tuple>
9 #include <variant>
10 
11 namespace carl {
12 
15  std::size_t mIndex;
16 
17  explicit BVUnaryContent(BVTerm operand, std::size_t index = 0)
18  : mOperand(operand), mIndex(index) {}
19 
20  bool operator==(const BVUnaryContent& rhs) const {
21  return std::tie(mIndex, mOperand) == std::tie(rhs.mIndex, rhs.mOperand);
22  }
23  bool operator<(const BVUnaryContent& rhs) const {
24  return std::tie(mOperand, mIndex) < std::tie(rhs.mOperand, rhs.mIndex);
25  }
26 };
27 
31 
32  BVBinaryContent(BVTerm first, BVTerm second)
33  : mFirst(first), mSecond(second) {}
34  bool operator==(const BVBinaryContent& rhs) const {
35  return std::tie(mFirst, mSecond) == std::tie(rhs.mFirst, rhs.mSecond);
36  }
37  bool operator<(const BVBinaryContent& rhs) const {
38  return std::tie(mFirst, mSecond) < std::tie(rhs.mFirst, rhs.mSecond);
39  }
40 };
41 
44  std::size_t mHighest;
45  std::size_t mLowest;
46 
47  BVExtractContent(BVTerm _operand, std::size_t _highest, std::size_t _lowest)
48  : mOperand(_operand), mHighest(_highest), mLowest(_lowest) {}
49  bool operator==(const BVExtractContent& rhs) const {
50  return std::tie(mOperand, mHighest, mLowest) == std::tie(rhs.mOperand, rhs.mHighest, rhs.mLowest);
51  }
52  bool operator<(const BVExtractContent& rhs) const {
53  return std::tie(mOperand, mHighest, mLowest) < std::tie(rhs.mOperand, rhs.mHighest, rhs.mLowest);
54  }
55 };
56 } // namespace carl
57 
58 namespace std {
59 template<>
60 struct hash<carl::BVUnaryContent> {
61  std::size_t operator()(const carl::BVUnaryContent& uc) const {
62  return carl::hash_all(uc.mOperand, uc.mIndex);
63  }
64 };
65 template<>
66 struct hash<carl::BVBinaryContent> {
67  std::size_t operator()(const carl::BVBinaryContent& bc) const {
68  return carl::hash_all(bc.mFirst, bc.mSecond);
69  }
70 };
71 template<>
72 struct hash<carl::BVExtractContent> {
73  std::size_t operator()(const carl::BVExtractContent& ec) const {
74  return carl::hash_all(ec.mOperand, ec.mHighest, ec.mLowest);
75  }
76 };
77 } // namespace std
78 
79 namespace carl {
80 
81 struct BVTermContent {
82  using ContentType = std::variant<BVVariable, BVValue, BVUnaryContent, BVBinaryContent, BVExtractContent>;
83 
86  std::size_t mWidth = 0;
87  std::size_t mId = 0;
88  std::size_t mHash = 0;
89 
90  std::size_t computeHash() const {
91  return std::hash<ContentType>()(mContent);
92  }
93 
94  template<typename T>
95  const T& as() const {
96  assert(std::holds_alternative<T>(mContent));
97  return std::get<T>(mContent);
98  }
99 
101  : mHash(computeHash()) {}
102 
104  : mType(type), mContent(std::move(value)),
105  mWidth(as<BVValue>().width()), mHash(computeHash()) {
106  assert(type == BVTermType::CONSTANT);
107  }
108 
110  : mType(type), mContent(variable), mWidth(variable.width()),
111  mHash(computeHash()) {
112  assert(type == BVTermType::VARIABLE);
113  }
114 
115  BVTermContent(BVTermType type, const BVTerm& _operand, std::size_t _index = 0)
116  : mType(type), mContent(BVUnaryContent(_operand, _index)),
117  mHash(computeHash()) {
118  assert(typeIsUnary(type));
119  if (type == BVTermType::NOT || type == BVTermType::NEG) {
120  assert(_index == 0);
121  mWidth = _operand.width();
122  } else if (type == BVTermType::LROTATE || type == BVTermType::RROTATE) {
123  mWidth = _operand.width();
124  } else if (type == BVTermType::REPEAT) {
125  assert(_index > 0);
126  mWidth = _operand.width() * _index;
127  } else if (type == BVTermType::EXT_U || type == BVTermType::EXT_S) {
128  mWidth = _operand.width() + _index;
129  } else {
130  assert(false);
131  }
132  }
133 
134  BVTermContent(BVTermType type, const BVTerm& _first, const BVTerm& _second)
135  : mType(type), mContent(BVBinaryContent(_first, _second)),
136  mHash(computeHash()) {
137  assert(typeIsBinary(type));
138 
139  if (type == BVTermType::CONCAT) {
140  mWidth = _first.width() + _second.width();
141  } else if (type == BVTermType::EQ) {
142  mWidth = 1;
143  } else {
144  mWidth = _first.width();
145  }
146  }
147 
148  BVTermContent(BVTermType type, const BVTerm& _operand, std::size_t _highest, std::size_t _lowest)
149  : mType(type), mContent(BVExtractContent(_operand, _highest, _lowest)), mWidth(_highest - _lowest + 1),
150  mHash(computeHash()) {
151  assert(type == BVTermType::EXTRACT);
152  assert(_highest < _operand.width() && _highest >= _lowest);
153  }
154 
155  std::size_t id() const {
156  return mId;
157  }
158 
159  std::size_t width() const {
160  return mWidth;
161  }
162 
163  BVTermType type() const {
164  return mType;
165  }
166 
167  const auto& content() const {
168  return mContent;
169  }
170 
171  bool isInvalid() const {
172  return (mType == BVTermType::CONSTANT && mWidth == 0);
173  }
174 
175  void gatherBVVariables(std::set<BVVariable>& vars) const {
177  [&vars](const BVVariable& v){ vars.insert(v); },
178  [&vars](const BVExtractContent& c){ c.mOperand.gatherBVVariables(vars); },
179  [&vars](const BVUnaryContent& c){ c.mOperand.gatherBVVariables(vars); },
180  [&vars](const BVBinaryContent& c){
181  c.mFirst.gatherBVVariables(vars);
182  c.mSecond.gatherBVVariables(vars);
183  },
184  [](const auto&){}
185  }, mContent);
186  }
187 
188  std::size_t complexity() const {
189  if (type() == BVTermType::CONSTANT) {
190  return 1;
191  } else if (type() == BVTermType::VARIABLE) {
192  return width();
193  } else if (type() == BVTermType::EXTRACT) {
194  return as<BVExtractContent>().mHighest - as<BVExtractContent>().mLowest + as<BVExtractContent>().mOperand.complexity();
195  } else if (typeIsUnary(type())) {
196  return width() + as<BVUnaryContent>().mOperand.complexity();
197  } else if (typeIsBinary(type())) {
198  return width() + as<BVBinaryContent>().mFirst.complexity() + as<BVBinaryContent>().mSecond.complexity();
199  }
200  assert(false);
201  return 0;
202  }
203 
204  std::size_t hash() const {
205  return mHash;
206  }
207 };
208 
209 inline bool operator==(const BVTermContent& lhs, const BVTermContent& rhs) {
210  if (lhs.id() != 0 && rhs.id() != 0) return lhs.id() == rhs.id();
211  return std::forward_as_tuple(lhs.type(), lhs.hash(), lhs.width(), lhs.content()) == std::forward_as_tuple(rhs.type(), rhs.hash(), rhs.width(), rhs.content());
212 }
213 inline bool operator<(const BVTermContent& lhs, const BVTermContent& rhs) {
214  if (lhs.id() != 0 && rhs.id() != 0) return lhs.id() < rhs.id();
215  return std::forward_as_tuple(lhs.type(), lhs.hash(), lhs.width(), lhs.content()) < std::forward_as_tuple(rhs.type(), rhs.hash(), rhs.width(), rhs.content());
216 }
217 
218 /**
219  * The output operator of a term.
220  * @param os Output stream.
221  * @param term Content of a bitvector term.
222  */
223 inline std::ostream& operator<<(std::ostream& os, const BVTermContent& term) {
224  if (term.isInvalid()) {
225  return os << "%invalid%";
226  }
227  switch (term.type()) {
229  return os << term.as<BVValue>();
231  return os << term.as<BVVariable>();
232  case BVTermType::EXTRACT: {
233  const auto& ex = term.as<BVExtractContent>();
234  return os << term.type() << "_{" << ex.mHighest << "," << ex.mLowest << "}(" << ex.mOperand << ")";
235  }
236  case BVTermType::LROTATE:
237  case BVTermType::RROTATE:
238  case BVTermType::EXT_U:
239  case BVTermType::EXT_S:
240  case BVTermType::REPEAT: {
241  const auto& un = term.as<BVUnaryContent>();
242  return os << term.type() << "_" << un.mIndex << "(" << un.mOperand << ")";
243  }
244  default:
245  if (typeIsUnary(term.type())) {
246  return os << term.type() << "(" << term.as<BVUnaryContent>().mOperand << ")";
247  } else {
248  const auto& bi = term.as<BVBinaryContent>();
249  return os << term.type() << "(" << bi.mFirst << ", " << bi.mSecond << ")";
250  }
251  }
252 }
253 } // namespace carl
254 
255 namespace std {
256 
257 /**
258  * Implements std::hash for bit vector term contents.
259  */
260 template<>
261 struct hash<carl::BVTermContent> {
262  /**
263  * @param tc The bit vector term content to get the hash for.
264  * @return The hash of the given bit vector term content.
265  */
266  std::size_t operator()(const carl::BVTermContent& tc) const {
267  return tc.hash();
268  }
269 };
270 } // namespace std
carl is the main namespace for the library.
bool typeIsUnary(BVTermType type)
Definition: BVTermType.h:66
bool operator<(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
BVTermType
Definition: BVTermType.h:10
bool typeIsBinary(BVTermType type)
Definition: BVTermType.h:74
std::ostream & operator<<(std::ostream &os, const BasicConstraint< Poly > &c)
Prints the given constraint on the given stream.
void visit(const Formula< Pol > &formula, Visitor func)
Recursively calls func on every subformula.
Definition: Visit.h:12
bool operator==(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
std::size_t hash_all(Args &&... args)
Hashes an arbitrary number of values.
Definition: hash.h:71
std::size_t width() const
Definition: BVTerm.cpp:43
bool operator<(const BVUnaryContent &rhs) const
Definition: BVTermContent.h:23
bool operator==(const BVUnaryContent &rhs) const
Definition: BVTermContent.h:20
BVUnaryContent(BVTerm operand, std::size_t index=0)
Definition: BVTermContent.h:17
BVBinaryContent(BVTerm first, BVTerm second)
Definition: BVTermContent.h:32
bool operator==(const BVBinaryContent &rhs) const
Definition: BVTermContent.h:34
bool operator<(const BVBinaryContent &rhs) const
Definition: BVTermContent.h:37
bool operator<(const BVExtractContent &rhs) const
Definition: BVTermContent.h:52
BVExtractContent(BVTerm _operand, std::size_t _highest, std::size_t _lowest)
Definition: BVTermContent.h:47
bool operator==(const BVExtractContent &rhs) const
Definition: BVTermContent.h:49
std::size_t operator()(const carl::BVUnaryContent &uc) const
Definition: BVTermContent.h:61
std::size_t operator()(const carl::BVBinaryContent &bc) const
Definition: BVTermContent.h:67
std::size_t operator()(const carl::BVExtractContent &ec) const
Definition: BVTermContent.h:73
std::size_t width() const
std::size_t computeHash() const
Definition: BVTermContent.h:90
BVTermType type() const
BVTermContent(BVTermType type, BVValue &&value)
std::size_t id() const
const T & as() const
Definition: BVTermContent.h:95
bool isInvalid() const
const auto & content() const
void gatherBVVariables(std::set< BVVariable > &vars) const
BVTermContent(BVTermType type, const BVTerm &_first, const BVTerm &_second)
BVTermContent(BVTermType type, const BVTerm &_operand, std::size_t _highest, std::size_t _lowest)
BVTermContent(BVTermType type, const BVTerm &_operand, std::size_t _index=0)
std::size_t hash() const
std::variant< BVVariable, BVValue, BVUnaryContent, BVBinaryContent, BVExtractContent > ContentType
Definition: BVTermContent.h:82
ContentType mContent
Definition: BVTermContent.h:85
std::size_t mWidth
Definition: BVTermContent.h:86
std::size_t complexity() const
BVTermContent(BVTermType type, const BVVariable &variable)
std::size_t operator()(const carl::BVTermContent &tc) const
Represent a BitVector-Variable.
Definition: BVVariable.h:13