5#ifndef OASIS_BOUNDEDBINARYEXPRESSION_HPP
6#define OASIS_BOUNDEDBINARYEXPRESSION_HPP
24template <
template <IExpression, IExpression, IExpression, IExpression>
class DerivedT, IExpression MostSigOpT = Expression, IExpression LeastSigOpT = MostSigOpT, IExpression LowerBoundT = Expression, IExpression UpperBoundT = LowerBoundT>
27 using DerivedSpecialized = DerivedT<MostSigOpT, LeastSigOpT, LowerBoundT, UpperBoundT>;
28 using DerivedGeneralized = DerivedT<Expression, Expression, Expression, Expression>;
56 DerivedSpecialized copy;
58 if (this->mostSigOp) {
59 subflow.emplace([
this, ©](tf::Subflow& sbf) {
60 copy.SetMostSigOp(mostSigOp->Copy(sbf), sbf);
64 if (this->leastSigOp) {
65 subflow.emplace([
this, ©](tf::Subflow& sbf) {
66 copy.SetLeastSigOp(leastSigOp->Copy(sbf), sbf);
77 if (this->
GetType() != other.GetType()) {
81 const auto otherGeneralized = other.Generalize();
82 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
84 bool mostSigOpMismatch =
false, leastSigOpMismatch =
false;
86 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
87 if (mostSigOp && otherBinaryGeneralized.HasMostSigOp()) {
88 mostSigOpMismatch = !mostSigOp->Equals(otherBinaryGeneralized.GetMostSigOp());
91 mostSigOpMismatch =
true;
94 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
95 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
96 leastSigOpMismatch = !leastSigOp->Equals(otherBinaryGeneralized.GetLeastSigOp());
99 mostSigOpMismatch =
true;
102 if (!mostSigOpMismatch && !leastSigOpMismatch) {
114 otherBinaryGeneralized.Flatten(otherFlattened);
116 for (
const auto& thisOperand : thisFlattened) {
117 if (
std::find_if(otherFlattened.begin(), otherFlattened.end(), [&thisOperand](
const auto& otherOperand) {
118 return thisOperand->Equals(*otherOperand);
120 == otherFlattened.end()) {
130 DerivedGeneralized generalized;
132 if (this->mostSigOp) {
133 generalized.SetMostSigOp(*this->mostSigOp->Copy());
136 if (this->leastSigOp) {
137 generalized.SetLeastSigOp(*this->leastSigOp->Copy());
145 DerivedGeneralized generalized;
147 if (this->mostSigOp) {
148 subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
149 generalized.SetMostSigOp(*this->mostSigOp->Copy(sbf));
153 if (this->leastSigOp) {
154 subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
155 generalized.SetLeastSigOp(*this->leastSigOp->Copy(sbf));
168 tf::Task generalizeTask = subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
172 tf::Task simplifyTask = subflow.emplace([&generalized, &simplified](tf::Subflow& sbf) {
173 simplified = generalized->Simplify(sbf);
176 simplifyTask.succeed(generalizeTask);
184 if (this->
GetType() != other.GetType()) {
189 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
191 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
192 if (this->
HasMostSigOp() && otherBinaryGeneralized.HasMostSigOp()) {
193 if (!mostSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetMostSigOp())) {
199 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
200 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
201 if (!leastSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetLeastSigOp())) {
212 if (this->
GetType() != other.GetType()) {
218 tf::Task generalizeTask = subflow.emplace([&](tf::Subflow& sbf) {
219 otherGeneralized = other.Generalize(sbf);
222 bool mostSigOpEquivalent =
false, leastSigOpEquivalent =
false;
224 if (this->mostSigOp) {
225 tf::Task compMostSigOp = subflow.emplace([
this, &otherGeneralized, &mostSigOpEquivalent](tf::Subflow& sbf) {
226 if (
const auto& otherBinary =
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasMostSigOp()) {
227 mostSigOpEquivalent = mostSigOp->StructurallyEquivalent(otherBinary.GetMostSigOp(), sbf);
231 compMostSigOp.succeed(generalizeTask);
234 if (this->leastSigOp) {
235 tf::Task compLeastSigOp = subflow.emplace([
this, &otherGeneralized, &leastSigOpEquivalent](tf::Subflow& sbf) {
236 if (
const auto& otherBinary =
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasLeastSigOp()) {
237 leastSigOpEquivalent = leastSigOp->StructurallyEquivalent(otherBinary.GetLeastSigOp(), sbf);
241 compLeastSigOp.succeed(generalizeTask);
246 return mostSigOpEquivalent && leastSigOpEquivalent;
262 if (this->mostSigOp->template Is<DerivedT>()) {
263 auto generalizedMostSigOp = this->mostSigOp->Generalize();
264 const auto& mostSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedMostSigOp);
265 mostSigOp.Flatten(out);
267 out.push_back(this->mostSigOp->Copy());
270 if (this->leastSigOp->template Is<DerivedT>()) {
271 auto generalizedLeastSigOp = this->leastSigOp->Generalize();
272 const auto& leastSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedLeastSigOp);
273 leastSigOp.Flatten(out);
275 out.push_back(this->leastSigOp->Copy());
285 assert(mostSigOp !=
nullptr);
295 assert(leastSigOp !=
nullptr);
305 return mostSigOp !=
nullptr;
314 return leastSigOp !=
nullptr;
321 template <
typename T>
326 this->mostSigOp = op.Copy();
335 if (
auto castedOp = Oasis::RecursiveCast<MostSigOpT>(op); castedOp) {
336 mostSigOp = std::move(castedOp);
347 template <
typename T>
352 this->leastSigOp = op.Copy();
361 if (
auto castedOp = Oasis::RecursiveCast<LeastSigOpT>(op); castedOp) {
362 leastSigOp = std::move(castedOp);
373 DerivedGeneralized comb { *left, *right };
384 return DerivedT { *this->leastSigOp, *this->mostSigOp };
389 void Serialize(SerializationVisitor& visitor)
const override
392 const auto& derivedGeneralized =
dynamic_cast<const DerivedGeneralized&
>(*generalized);
393 visitor.Serialize(derivedGeneralized);
A concept for an operand of a binary expression with bounds.
Definition BoundedBinaryExpression.hpp:25
auto SwapOperands() const -> DerivedSpecialized
Swaps the operands of this expression.
Definition BoundedBinaryExpression.hpp:382
auto GetMostSigOp() const -> const MostSigOpT &
Gets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:283
auto Flatten(std::vector< std::unique_ptr< Expression > > &out) const -> void
Flattens this expression.
Definition BoundedBinaryExpression.hpp:260
auto Simplify(tf::Subflow &subflow) const -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:164
BoundedBinaryExpression(const MostSigOpT &mostSigOp, const LeastSigOpT &leastSigOp)
Definition BoundedBinaryExpression.hpp:43
auto Substitute(const Expression &var, const Expression &val) -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:369
auto Equals(const Expression &other) const -> bool final
Compares this expression to another expression for equality.
Definition BoundedBinaryExpression.hpp:75
auto SetMostSigOp(const T &op) -> bool
Sets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:323
auto Generalize() const -> std::unique_ptr< Expression > final
Converts this expression to a more general expression.
Definition BoundedBinaryExpression.hpp:128
auto HasMostSigOp() const -> bool
Gets whether this expression has a most significant operand.
Definition BoundedBinaryExpression.hpp:303
void Serialize(SerializationVisitor &visitor) const override
Definition BoundedBinaryExpression.hpp:389
auto GetLeastSigOp() const -> const LeastSigOpT &
Gets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:293
auto HasLeastSigOp() const -> bool
Gets whether this expression has a least significant operand.
Definition BoundedBinaryExpression.hpp:312
auto SetLeastSigOp(const T &op) -> bool
Sets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:349
auto Generalize(tf::Subflow &subflow) const -> std::unique_ptr< Expression > final
Definition BoundedBinaryExpression.hpp:143
auto Copy(tf::Subflow &subflow) const -> std::unique_ptr< Expression > final
Definition BoundedBinaryExpression.hpp:54
auto Copy() const -> std::unique_ptr< Expression > final
Copies this expression.
Definition BoundedBinaryExpression.hpp:49
auto StructurallyEquivalent(const Expression &other) const -> bool final
Checks whether this expression is structurally equivalent to another expression.
Definition BoundedBinaryExpression.hpp:182
auto operator=(const BoundedBinaryExpression &other) -> BoundedBinaryExpression &=default
auto StructurallyEquivalent(const Expression &other, tf::Subflow &subflow) const -> bool final
Definition BoundedBinaryExpression.hpp:210
BoundedBinaryExpression()=default
BoundedBinaryExpression(const BoundedBinaryExpression &other)
Definition BoundedBinaryExpression.hpp:32
A concept base class for both Unary and BoundedBinary expressions.
Definition BoundedExpression.hpp:23
An expression.
Definition Expression.hpp:63
virtual auto GetCategory() const -> uint32_t
Gets the category of this expression.
Definition Expression.cpp:221
virtual auto GetType() const -> ExpressionType
Gets the type of this expression.
Definition Expression.cpp:236
Checks if type T is same as any of the provided types in U.
Definition Concepts.hpp:53
@ Associative
Definition Expression.hpp:50