5#ifndef OASIS_BINARYEXPRESSION_HPP
6#define OASIS_BINARYEXPRESSION_HPP
28template <
typename MostSigOpT,
typename LeastSigOpT,
typename T>
31template <
template <
typename,
typename>
typename T>
40template <
template <
typename,
typename>
typename T>
44 if (ops.size() <= 1) {
48 using GeneralizedT = T<Expression, Expression>;
51 opsList.
resize(ops.size());
53 std::transform(ops.begin(), ops.end(), opsList.
begin(), [](
const auto& op) { return op->Copy(); });
58 opsList.
insert(i, std::move(node));
63 auto* result =
dynamic_cast<GeneralizedT*
>(opsList.
front().release());
82template <
template <IExpression, IExpression>
class DerivedT, IExpression MostSigOpT = Expression, IExpression LeastSigOpT = MostSigOpT>
85 using DerivedSpecialized = DerivedT<MostSigOpT, LeastSigOpT>;
86 using DerivedGeneralized = DerivedT<Expression, Expression>;
121 auto generalized = BuildFromVector<DerivedT>(opsVec);
134 return Generalize()->Differentiate(differentiationVariable);
138 if (this->
GetType() != other.GetType()) {
142 const auto otherGeneralized = other.Generalize();
143 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
145 bool mostSigOpMismatch =
false, leastSigOpMismatch =
false;
147 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
148 if (
mostSigOp && otherBinaryGeneralized.HasMostSigOp()) {
149 mostSigOpMismatch = !
mostSigOp->Equals(otherBinaryGeneralized.GetMostSigOp());
152 mostSigOpMismatch =
true;
155 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
156 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
157 leastSigOpMismatch = !
leastSigOp->Equals(otherBinaryGeneralized.GetLeastSigOp());
160 mostSigOpMismatch =
true;
163 if (!mostSigOpMismatch && !leastSigOpMismatch) {
175 otherBinaryGeneralized.Flatten(otherFlattened);
177 for (
const auto& thisOperand : thisFlattened) {
178 if (
std::find_if(otherFlattened.begin(), otherFlattened.end(), [&thisOperand](
const auto& otherOperand) {
179 return thisOperand->Equals(*otherOperand);
181 == otherFlattened.end()) {
191 DerivedGeneralized generalized;
194 generalized.SetMostSigOp(*this->
mostSigOp->Copy());
198 generalized.SetLeastSigOp(*this->
leastSigOp->Copy());
206 return Generalize()->Integrate(integrationVariable);
211 if (this->
GetType() != other.GetType()) {
216 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
218 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
219 if (this->
HasMostSigOp() && otherBinaryGeneralized.HasMostSigOp()) {
220 if (!
mostSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetMostSigOp())) {
226 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
227 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
228 if (!
leastSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetLeastSigOp())) {
251 if (this->
mostSigOp->template Is<DerivedGeneralized>()) {
252 auto generalizedMostSigOp = this->
mostSigOp->Generalize();
253 const auto&
mostSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedMostSigOp);
261 if (this->
leastSigOp->template Is<DerivedGeneralized>()) {
262 auto generalizedLeastSigOp = this->
leastSigOp->Generalize();
263 const auto&
leastSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedLeastSigOp);
313 template <
typename T>
327 if (
auto castedOp = Oasis::RecursiveCast<MostSigOpT>(op); castedOp) {
339 template <
typename T>
353 if (
auto castedOp = Oasis::RecursiveCast<LeastSigOpT>(op); castedOp) {
366 DerivedT<Expression, Expression> comb = DerivedT<Expression, Expression> { *left, *right };
369 auto simplified = comb.Accept(simplifyVisitor);
371 return comb.Generalize();
373 return std::move(simplified.value());
389 const auto& derivedGeneralized =
dynamic_cast<const DerivedGeneralized&
>(*generalized);
390 return visitor.Visit(derivedGeneralized);
A binary expression.
Definition BinaryExpression.hpp:83
auto Copy() const -> std::unique_ptr< Expression > final
Copies this expression.
Definition BinaryExpression.hpp:127
BinaryExpression(const BinaryExpression &other)
Definition BinaryExpression.hpp:90
std::unique_ptr< LeastSigOpT > leastSigOp
Definition BinaryExpression.hpp:394
auto Differentiate(const Expression &differentiationVariable) const -> std::unique_ptr< Expression > override
Tries to differentiate this function.
Definition BinaryExpression.hpp:132
auto AcceptInternal(Visitor &visitor) const -> any override
This function serializes the expression object.
Definition BinaryExpression.hpp:386
auto Substitute(const Expression &var, const Expression &val) -> std::unique_ptr< Expression > override
Definition BinaryExpression.hpp:361
auto GetLeastSigOp() const -> const LeastSigOpT &
Gets the least significant operand of this expression.
Definition BinaryExpression.hpp:285
auto operator=(const BinaryExpression &other) -> BinaryExpression &=default
auto SetLeastSigOp(const T &op) -> bool
Sets the least significant operand of this expression.
Definition BinaryExpression.hpp:341
auto Integrate(const Expression &integrationVariable) const -> std::unique_ptr< Expression > override
Attempts to integrate this expression using integration rules.
Definition BinaryExpression.hpp:204
auto Generalize() const -> std::unique_ptr< Expression > final
Converts this expression to a more general expression.
Definition BinaryExpression.hpp:189
auto GetMostSigOp() const -> const MostSigOpT &
Gets the most significant operand of this expression.
Definition BinaryExpression.hpp:275
std::unique_ptr< MostSigOpT > mostSigOp
Definition BinaryExpression.hpp:393
auto SwapOperands() const -> DerivedT< LeastSigOpT, MostSigOpT >
Swaps the operands of this expression.
Definition BinaryExpression.hpp:379
auto SetMostSigOp(const T &op) -> bool
Sets the most significant operand of this expression.
Definition BinaryExpression.hpp:315
auto StructurallyEquivalent(const Expression &other) const -> bool final
Checks whether this expression is structurally equivalent to another expression.
Definition BinaryExpression.hpp:209
auto Flatten(std::vector< std::unique_ptr< Expression > > &out) const -> void
Flattens this expression.
Definition BinaryExpression.hpp:248
auto HasLeastSigOp() const -> bool
Gets whether this expression has a least significant operand.
Definition BinaryExpression.hpp:304
BinaryExpression(const Op1T &op1, const Op2T &op2, const OpsT &... ops)
Definition BinaryExpression.hpp:108
BinaryExpression()=default
auto Equals(const Expression &other) const -> bool final
Compares this expression to another expression for equality.
Definition BinaryExpression.hpp:136
BinaryExpression(const MostSigOpT &mostSigOp, const LeastSigOpT &leastSigOp)
Definition BinaryExpression.hpp:101
auto HasMostSigOp() const -> bool
Gets whether this expression has a most significant operand.
Definition BinaryExpression.hpp:295
An expression.
Definition Expression.hpp:63
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:219
virtual auto GetType() const -> ExpressionType
Gets the type of this expression.
Definition Expression.cpp:229
Definition SimplifyVisitor.hpp:25
Definition BinaryExpression.hpp:32
An expression concept.
Definition Concepts.hpp:30
A concept for an operand of a binary expression.
Definition BinaryExpression.hpp:29
Checks if type T is same as any of the provided types in U.
Definition Concepts.hpp:53
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:42
boost::anys::unique_any any
Definition Expression.hpp:15
@ Commutative
Definition Expression.hpp:51
@ Associative
Definition Expression.hpp:50