5#ifndef OASIS_BINARYEXPRESSION_HPP
6#define OASIS_BINARYEXPRESSION_HPP
27template <
typename MostSigOpT,
typename LeastSigOpT,
typename T>
30template <
template <
typename,
typename>
typename T>
39template <
template <
typename,
typename>
typename T>
43 if (ops.size() <= 1) {
47 using GeneralizedT = T<Expression, Expression>;
50 opsList.
resize(ops.size());
52 std::transform(ops.begin(), ops.end(), opsList.
begin(), [](
const auto& op) { return op->Copy(); });
57 opsList.
insert(i, std::move(node));
62 auto* result =
dynamic_cast<GeneralizedT*
>(opsList.
front().release());
81template <
template <IExpression, IExpression>
class DerivedT, IExpression MostSigOpT = Expression, IExpression LeastSigOpT = MostSigOpT>
84 using DerivedSpecialized = DerivedT<MostSigOpT, LeastSigOpT>;
85 using DerivedGeneralized = DerivedT<Expression, Expression>;
120 auto generalized = BuildFromVector<DerivedT>(opsVec);
133 return Generalize()->Differentiate(differentiationVariable);
137 if (this->
GetType() != other.GetType()) {
141 const auto otherGeneralized = other.Generalize();
142 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
144 bool mostSigOpMismatch =
false, leastSigOpMismatch =
false;
146 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
147 if (
mostSigOp && otherBinaryGeneralized.HasMostSigOp()) {
148 mostSigOpMismatch = !
mostSigOp->Equals(otherBinaryGeneralized.GetMostSigOp());
151 mostSigOpMismatch =
true;
154 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
155 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
156 leastSigOpMismatch = !
leastSigOp->Equals(otherBinaryGeneralized.GetLeastSigOp());
159 mostSigOpMismatch =
true;
162 if (!mostSigOpMismatch && !leastSigOpMismatch) {
174 otherBinaryGeneralized.Flatten(otherFlattened);
176 for (
const auto& thisOperand : thisFlattened) {
177 if (
std::find_if(otherFlattened.begin(), otherFlattened.end(), [&thisOperand](
const auto& otherOperand) {
178 return thisOperand->Equals(*otherOperand);
180 == otherFlattened.end()) {
190 DerivedGeneralized generalized;
193 generalized.SetMostSigOp(*this->
mostSigOp->Copy());
197 generalized.SetLeastSigOp(*this->
leastSigOp->Copy());
210 return Generalize()->Integrate(integrationVariable);
215 if (this->
GetType() != other.GetType()) {
220 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
222 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
223 if (this->
HasMostSigOp() && otherBinaryGeneralized.HasMostSigOp()) {
224 if (!
mostSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetMostSigOp())) {
230 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
231 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
232 if (!
leastSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetLeastSigOp())) {
255 if (this->
mostSigOp->template Is<DerivedGeneralized>()) {
256 auto generalizedMostSigOp = this->
mostSigOp->Generalize();
257 const auto&
mostSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedMostSigOp);
265 if (this->
leastSigOp->template Is<DerivedGeneralized>()) {
266 auto generalizedLeastSigOp = this->
leastSigOp->Generalize();
267 const auto&
leastSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedLeastSigOp);
317 template <
typename T>
331 if (
auto castedOp = Oasis::RecursiveCast<MostSigOpT>(op); castedOp) {
343 template <
typename T>
357 if (
auto castedOp = Oasis::RecursiveCast<LeastSigOpT>(op); castedOp) {
369 DerivedT<Expression, Expression> comb = DerivedT<Expression, Expression> { *left, *right };
370 auto ret = comb.Simplify();
387 const auto& derivedGeneralized =
dynamic_cast<const DerivedGeneralized&
>(*generalized);
388 return visitor.Visit(derivedGeneralized);
A binary expression.
Definition BinaryExpression.hpp:82
auto Simplify() const -> std::unique_ptr< Expression > override
Simplifies this expression.
Definition BinaryExpression.hpp:203
auto Copy() const -> std::unique_ptr< Expression > final
Copies this expression.
Definition BinaryExpression.hpp:126
BinaryExpression(const BinaryExpression &other)
Definition BinaryExpression.hpp:89
std::unique_ptr< LeastSigOpT > leastSigOp
Definition BinaryExpression.hpp:392
auto Differentiate(const Expression &differentiationVariable) const -> std::unique_ptr< Expression > override
Tries to differentiate this function.
Definition BinaryExpression.hpp:131
auto AcceptInternal(Visitor &visitor) const -> any override
This function serializes the expression object.
Definition BinaryExpression.hpp:384
auto Substitute(const Expression &var, const Expression &val) -> std::unique_ptr< Expression > override
Definition BinaryExpression.hpp:365
auto GetLeastSigOp() const -> const LeastSigOpT &
Gets the least significant operand of this expression.
Definition BinaryExpression.hpp:289
auto operator=(const BinaryExpression &other) -> BinaryExpression &=default
auto SetLeastSigOp(const T &op) -> bool
Sets the least significant operand of this expression.
Definition BinaryExpression.hpp:345
auto Integrate(const Expression &integrationVariable) const -> std::unique_ptr< Expression > override
Attempts to integrate this expression using integration rules.
Definition BinaryExpression.hpp:208
auto Generalize() const -> std::unique_ptr< Expression > final
Converts this expression to a more general expression.
Definition BinaryExpression.hpp:188
auto GetMostSigOp() const -> const MostSigOpT &
Gets the most significant operand of this expression.
Definition BinaryExpression.hpp:279
std::unique_ptr< MostSigOpT > mostSigOp
Definition BinaryExpression.hpp:391
auto SwapOperands() const -> DerivedT< LeastSigOpT, MostSigOpT >
Swaps the operands of this expression.
Definition BinaryExpression.hpp:377
auto SetMostSigOp(const T &op) -> bool
Sets the most significant operand of this expression.
Definition BinaryExpression.hpp:319
auto StructurallyEquivalent(const Expression &other) const -> bool final
Checks whether this expression is structurally equivalent to another expression.
Definition BinaryExpression.hpp:213
auto Flatten(std::vector< std::unique_ptr< Expression > > &out) const -> void
Flattens this expression.
Definition BinaryExpression.hpp:252
auto HasLeastSigOp() const -> bool
Gets whether this expression has a least significant operand.
Definition BinaryExpression.hpp:308
BinaryExpression(const Op1T &op1, const Op2T &op2, const OpsT &... ops)
Definition BinaryExpression.hpp:107
BinaryExpression()=default
auto Equals(const Expression &other) const -> bool final
Compares this expression to another expression for equality.
Definition BinaryExpression.hpp:135
BinaryExpression(const MostSigOpT &mostSigOp, const LeastSigOpT &leastSigOp)
Definition BinaryExpression.hpp:100
auto HasMostSigOp() const -> bool
Gets whether this expression has a most significant operand.
Definition BinaryExpression.hpp:299
An expression.
Definition Expression.hpp:62
virtual auto Copy() const -> std::unique_ptr< Expression >=0
Copies this expression.
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
Definition BinaryExpression.hpp:31
An expression concept.
Definition Concepts.hpp:28
A concept for an operand of a binary expression.
Definition BinaryExpression.hpp:28
Checks if type T is same as any of the provided types in U.
Definition Concepts.hpp:51
T emplace_back(T... args)
auto BuildFromVector(const std::vector< std::unique_ptr< Expression > > &ops) -> std::unique_ptr< T< Expression, Expression > >
Builds a reasonably balanced binary expression from a vector of operands.
Definition BinaryExpression.hpp:41
boost::anys::unique_any any
Definition Expression.hpp:15
@ Commutative
Definition Expression.hpp:50
@ Associative
Definition Expression.hpp:49