5#ifndef OASIS_BOUNDEDBINARYEXPRESSION_HPP 
    6#define OASIS_BOUNDEDBINARYEXPRESSION_HPP 
   14template <
template <IExpression, IExpression, IExpression, IExpression> 
class DerivedT, IExpression MostSigOpT = Expression, IExpression LeastSigOpT = MostSigOpT, IExpression LowerBoundT = Expression, IExpression UpperBoundT = LowerBoundT>
 
   17    using DerivedSpecialized = DerivedT<MostSigOpT, LeastSigOpT, LowerBoundT, UpperBoundT>;
 
   18    using DerivedGeneralized = DerivedT<Expression, Expression, Expression, Expression>;
 
   46        DerivedSpecialized copy;
 
   48        if (this->mostSigOp) {
 
   49            subflow.emplace([
this, ©](tf::Subflow& sbf) {
 
   50                copy.SetMostSigOp(mostSigOp->Copy(sbf), sbf);
 
   54        if (this->leastSigOp) {
 
   55            subflow.emplace([
this, ©](tf::Subflow& sbf) {
 
   56                copy.SetLeastSigOp(leastSigOp->Copy(sbf), sbf);
 
 
   66        return Generalize()->Differentiate(differentiationVariable);
 
 
   70        if (this->
GetType() != other.GetType()) {
 
   74        const auto otherGeneralized = other.Generalize();
 
   75        const auto& otherBinaryGeneralized = 
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
 
   77        bool mostSigOpMismatch = 
false, leastSigOpMismatch = 
false;
 
   79        if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
 
   80            if (mostSigOp && otherBinaryGeneralized.HasMostSigOp()) {
 
   81                mostSigOpMismatch = !mostSigOp->Equals(otherBinaryGeneralized.GetMostSigOp());
 
   84            mostSigOpMismatch = 
true;
 
   87        if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
 
   88            if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
 
   89                leastSigOpMismatch = !leastSigOp->Equals(otherBinaryGeneralized.GetLeastSigOp());
 
   92            mostSigOpMismatch = 
true;
 
   95        if (!mostSigOpMismatch && !leastSigOpMismatch) {
 
  107        otherBinaryGeneralized.Flatten(otherFlattened);
 
  109        for (
const auto& thisOperand : thisFlattened) {
 
  110            if (
std::find_if(otherFlattened.begin(), otherFlattened.end(), [&thisOperand](
const auto& otherOperand) {
 
  111                    return thisOperand->Equals(*otherOperand);
 
  113                == otherFlattened.end()) {
 
 
  123        DerivedGeneralized generalized;
 
  125        if (this->mostSigOp) {
 
  126            generalized.SetMostSigOp(*this->mostSigOp->Copy());
 
  129        if (this->leastSigOp) {
 
  130            generalized.SetLeastSigOp(*this->leastSigOp->Copy());
 
 
  138        DerivedGeneralized generalized;
 
  140        if (this->mostSigOp) {
 
  141            subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
 
  142                generalized.SetMostSigOp(*this->mostSigOp->Copy(sbf));
 
  146        if (this->leastSigOp) {
 
  147            subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
 
  148                generalized.SetLeastSigOp(*this->leastSigOp->Copy(sbf));
 
 
  166        tf::Task generalizeTask = subflow.emplace([
this, &generalized](tf::Subflow& sbf) {
 
  170        tf::Task simplifyTask = subflow.emplace([&generalized, &simplified](tf::Subflow& sbf) {
 
  171            simplified = generalized->Simplify(sbf);
 
  174        simplifyTask.succeed(generalizeTask);
 
 
  182        if (this->
GetType() != other.GetType()) {
 
  187        const auto& otherBinaryGeneralized = 
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
 
  189        if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
 
  190            if (this->
HasMostSigOp() && otherBinaryGeneralized.HasMostSigOp()) {
 
  191                if (!mostSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetMostSigOp())) {
 
  197        if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
 
  198            if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
 
  199                if (!leastSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetLeastSigOp())) {
 
 
  210        if (this->
GetType() != other.GetType()) {
 
  216        tf::Task generalizeTask = subflow.emplace([&](tf::Subflow& sbf) {
 
  217            otherGeneralized = other.Generalize(sbf);
 
  220        bool mostSigOpEquivalent = 
false, leastSigOpEquivalent = 
false;
 
  222        if (this->mostSigOp) {
 
  223            tf::Task compMostSigOp = subflow.emplace([
this, &otherGeneralized, &mostSigOpEquivalent](tf::Subflow& sbf) {
 
  224                if (
const auto& otherBinary = 
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasMostSigOp()) {
 
  225                    mostSigOpEquivalent = mostSigOp->StructurallyEquivalent(otherBinary.GetMostSigOp(), sbf);
 
  229            compMostSigOp.succeed(generalizeTask);
 
  232        if (this->leastSigOp) {
 
  233            tf::Task compLeastSigOp = subflow.emplace([
this, &otherGeneralized, &leastSigOpEquivalent](tf::Subflow& sbf) {
 
  234                if (
const auto& otherBinary = 
static_cast<const DerivedGeneralized&
>(*otherGeneralized); otherBinary.HasLeastSigOp()) {
 
  235                    leastSigOpEquivalent = leastSigOp->StructurallyEquivalent(otherBinary.GetLeastSigOp(), sbf);
 
  239            compLeastSigOp.succeed(generalizeTask);
 
  244        return mostSigOpEquivalent && leastSigOpEquivalent;
 
 
  260        if (this->mostSigOp->template Is<DerivedT>()) {
 
  261            auto generalizedMostSigOp = this->mostSigOp->Generalize();
 
  262            const auto& mostSigOp = 
static_cast<const DerivedGeneralized&
>(*generalizedMostSigOp);
 
  263            mostSigOp.Flatten(out);
 
  265            out.push_back(this->mostSigOp->Copy());
 
  268        if (this->leastSigOp->template Is<DerivedT>()) {
 
  269            auto generalizedLeastSigOp = this->leastSigOp->Generalize();
 
  270            const auto& leastSigOp = 
static_cast<const DerivedGeneralized&
>(*generalizedLeastSigOp);
 
  271            leastSigOp.Flatten(out);
 
  273            out.push_back(this->leastSigOp->Copy());
 
 
  283        assert(mostSigOp != 
nullptr);
 
 
  293        assert(leastSigOp != 
nullptr);
 
 
  303        return mostSigOp != 
nullptr;
 
 
  312        return leastSigOp != 
nullptr;
 
 
  319    template <
typename T>
 
  324            this->mostSigOp = op.Copy();
 
  333        if (
auto castedOp = Oasis::RecursiveCast<MostSigOpT>(op); castedOp) {
 
  334            mostSigOp = std::move(castedOp);
 
 
  345    template <
typename T>
 
  350            this->leastSigOp = op.Copy();
 
  359        if (
auto castedOp = Oasis::RecursiveCast<LeastSigOpT>(op); castedOp) {
 
  360            leastSigOp = std::move(castedOp);
 
 
  371        DerivedGeneralized comb { *left, *right };
 
  372        auto ret = comb.Simplify();
 
 
  381        return DerivedT { *this->leastSigOp, *this->mostSigOp };
 
 
  386    void Serialize(SerializationVisitor& visitor)
 const override 
  389        const auto& derivedGeneralized = 
dynamic_cast<const DerivedGeneralized&
>(*generalized);
 
  390        visitor.Serialize(derivedGeneralized);
 
 
 
Definition BoundedBinaryExpression.hpp:15
auto Differentiate(const Expression &differentiationVariable) const -> std::unique_ptr< Expression > override
Tries to differentiate this function.
Definition BoundedBinaryExpression.hpp:64
auto SwapOperands() const -> DerivedSpecialized
Swaps the operands of this expression.
Definition BoundedBinaryExpression.hpp:379
auto GetMostSigOp() const -> const MostSigOpT &
Gets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:281
auto Flatten(std::vector< std::unique_ptr< Expression > > &out) const -> void
Flattens this expression.
Definition BoundedBinaryExpression.hpp:258
auto Simplify(tf::Subflow &subflow) const -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:162
BoundedBinaryExpression(const MostSigOpT &mostSigOp, const LeastSigOpT &leastSigOp)
Definition BoundedBinaryExpression.hpp:33
auto Simplify() const -> std::unique_ptr< Expression > override
Simplifies this expression.
Definition BoundedBinaryExpression.hpp:157
auto Substitute(const Expression &var, const Expression &val) -> std::unique_ptr< Expression > override
Definition BoundedBinaryExpression.hpp:367
auto Equals(const Expression &other) const -> bool final
Compares this expression to another expression for equality.
Definition BoundedBinaryExpression.hpp:68
auto SetMostSigOp(const T &op) -> bool
Sets the most significant operand of this expression.
Definition BoundedBinaryExpression.hpp:321
auto Generalize() const -> std::unique_ptr< Expression > final
Converts this expression to a more general expression.
Definition BoundedBinaryExpression.hpp:121
auto HasMostSigOp() const -> bool
Gets whether this expression has a most significant operand.
Definition BoundedBinaryExpression.hpp:301
void Serialize(SerializationVisitor &visitor) const override
Definition BoundedBinaryExpression.hpp:386
auto GetLeastSigOp() const -> const LeastSigOpT &
Gets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:291
auto HasLeastSigOp() const -> bool
Gets whether this expression has a least significant operand.
Definition BoundedBinaryExpression.hpp:310
auto SetLeastSigOp(const T &op) -> bool
Sets the least significant operand of this expression.
Definition BoundedBinaryExpression.hpp:347
auto Generalize(tf::Subflow &subflow) const -> std::unique_ptr< Expression > final
Definition BoundedBinaryExpression.hpp:136
auto Copy(tf::Subflow &subflow) const -> std::unique_ptr< Expression > final
Definition BoundedBinaryExpression.hpp:44
auto Copy() const -> std::unique_ptr< Expression > final
Copies this expression.
Definition BoundedBinaryExpression.hpp:39
auto StructurallyEquivalent(const Expression &other) const -> bool final
Checks whether this expression is structurally equivalent to another expression.
Definition BoundedBinaryExpression.hpp:180
auto operator=(const BoundedBinaryExpression &other) -> BoundedBinaryExpression &=default
auto StructurallyEquivalent(const Expression &other, tf::Subflow &subflow) const -> bool final
Definition BoundedBinaryExpression.hpp:208
BoundedBinaryExpression()=default
BoundedBinaryExpression(const BoundedBinaryExpression &other)
Definition BoundedBinaryExpression.hpp:22
Definition BoundedExpression.hpp:15
An expression.
Definition Expression.hpp:62
virtual auto GetCategory() const -> uint32_t
Gets the category of this expression.
Definition Expression.cpp:212
virtual auto GetType() const -> ExpressionType
Gets the type of this expression.
Definition Expression.cpp:220
virtual auto Simplify() const -> std::unique_ptr< Expression >
Simplifies this expression.
Definition Expression.cpp:244
Checks if type T is same as any of the provided types in U.
Definition Concepts.hpp:50
@ Associative
Definition Expression.hpp:49