5#ifndef OASIS_BINARYEXPRESSION_HPP
6#define OASIS_BINARYEXPRESSION_HPP
24template <
typename MostSigOpT,
typename LeastSigOpT,
typename T>
27template <
template <
typename,
typename>
typename T>
36template <
template <
typename,
typename>
typename T>
40 if (ops.size() <= 1) {
44 using GeneralizedT = T<Expression, Expression>;
47 opsList.
resize(ops.size());
49 std::transform(ops.begin(), ops.end(), opsList.
begin(), [](
const auto& op) { return op->Copy(); });
54 opsList.
insert(i, std::move(node));
59 auto* result =
dynamic_cast<GeneralizedT*
>(opsList.
front().release());
78template <
template <IExpression, IExpression>
class DerivedT, IExpression MostSigOpT = Expression, IExpression LeastSigOpT = MostSigOpT>
81 using DerivedSpecialized = DerivedT<MostSigOpT, LeastSigOpT>;
82 using DerivedGeneralized = DerivedT<Expression, Expression>;
117 auto generalized = BuildFromVector<DerivedT>(opsVec);
130 return Generalize()->Differentiate(differentiationVariable);
134 if (this->
GetType() != other.GetType()) {
138 const auto otherGeneralized = other.Generalize();
139 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
141 bool mostSigOpMismatch =
false, leastSigOpMismatch =
false;
143 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
144 if (
mostSigOp && otherBinaryGeneralized.HasMostSigOp()) {
145 mostSigOpMismatch = !
mostSigOp->Equals(otherBinaryGeneralized.GetMostSigOp());
148 mostSigOpMismatch =
true;
151 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
152 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
153 leastSigOpMismatch = !
leastSigOp->Equals(otherBinaryGeneralized.GetLeastSigOp());
156 mostSigOpMismatch =
true;
159 if (!mostSigOpMismatch && !leastSigOpMismatch) {
171 otherBinaryGeneralized.Flatten(otherFlattened);
173 for (
const auto& thisOperand : thisFlattened) {
174 if (
std::find_if(otherFlattened.begin(), otherFlattened.end(), [&thisOperand](
const auto& otherOperand) {
175 return thisOperand->Equals(*otherOperand);
177 == otherFlattened.end()) {
187 DerivedGeneralized generalized;
190 generalized.SetMostSigOp(*this->
mostSigOp->Copy());
194 generalized.SetLeastSigOp(*this->
leastSigOp->Copy());
207 return Generalize()->Integrate(integrationVariable);
212 if (this->
GetType() != other.GetType()) {
217 const auto& otherBinaryGeneralized =
static_cast<const DerivedGeneralized&
>(*otherGeneralized);
219 if (this->
HasMostSigOp() == otherBinaryGeneralized.HasMostSigOp()) {
220 if (this->
HasMostSigOp() && otherBinaryGeneralized.HasMostSigOp()) {
221 if (!
mostSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetMostSigOp())) {
227 if (this->
HasLeastSigOp() == otherBinaryGeneralized.HasLeastSigOp()) {
228 if (this->
HasLeastSigOp() && otherBinaryGeneralized.HasLeastSigOp()) {
229 if (!
leastSigOp->StructurallyEquivalent(otherBinaryGeneralized.GetLeastSigOp())) {
252 if (this->
mostSigOp->template Is<DerivedT>()) {
253 auto generalizedMostSigOp = this->
mostSigOp->Generalize();
254 const auto&
mostSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedMostSigOp);
262 if (this->
leastSigOp->template Is<DerivedT>()) {
263 auto generalizedLeastSigOp = this->
leastSigOp->Generalize();
264 const auto&
leastSigOp =
static_cast<const DerivedGeneralized&
>(*generalizedLeastSigOp);
314 template <
typename T>
328 if (
auto castedOp = Oasis::RecursiveCast<MostSigOpT>(op); castedOp) {
340 template <
typename T>
354 if (
auto castedOp = Oasis::RecursiveCast<LeastSigOpT>(op); castedOp) {
366 DerivedT<Expression, Expression> comb = DerivedT<Expression, Expression> { *left, *right };
367 auto ret = comb.Simplify();
384 const auto& derivedGeneralized =
dynamic_cast<const DerivedGeneralized&
>(*generalized);
A binary expression.
Definition BinaryExpression.hpp:79
auto Simplify() const -> std::unique_ptr< Expression > override
Simplifies this expression.
Definition BinaryExpression.hpp:200
auto Copy() const -> std::unique_ptr< Expression > final
Copies this expression.
Definition BinaryExpression.hpp:123
BinaryExpression(const BinaryExpression &other)
Definition BinaryExpression.hpp:86
std::unique_ptr< LeastSigOpT > leastSigOp
Definition BinaryExpression.hpp:389
auto Differentiate(const Expression &differentiationVariable) const -> std::unique_ptr< Expression > override
Tries to differentiate this function.
Definition BinaryExpression.hpp:128
void Serialize(SerializationVisitor &visitor) const override
This function serializes the expression object.
Definition BinaryExpression.hpp:381
auto Substitute(const Expression &var, const Expression &val) -> std::unique_ptr< Expression > override
Definition BinaryExpression.hpp:362
auto GetLeastSigOp() const -> const LeastSigOpT &
Gets the least significant operand of this expression.
Definition BinaryExpression.hpp:286
auto operator=(const BinaryExpression &other) -> BinaryExpression &=default
auto SetLeastSigOp(const T &op) -> bool
Sets the least significant operand of this expression.
Definition BinaryExpression.hpp:342
auto Integrate(const Expression &integrationVariable) const -> std::unique_ptr< Expression > override
Attempts to integrate this expression using integration rules.
Definition BinaryExpression.hpp:205
auto Generalize() const -> std::unique_ptr< Expression > final
Converts this expression to a more general expression.
Definition BinaryExpression.hpp:185
auto GetMostSigOp() const -> const MostSigOpT &
Gets the most significant operand of this expression.
Definition BinaryExpression.hpp:276
std::unique_ptr< MostSigOpT > mostSigOp
Definition BinaryExpression.hpp:388
auto SwapOperands() const -> DerivedT< LeastSigOpT, MostSigOpT >
Swaps the operands of this expression.
Definition BinaryExpression.hpp:374
auto SetMostSigOp(const T &op) -> bool
Sets the most significant operand of this expression.
Definition BinaryExpression.hpp:316
auto StructurallyEquivalent(const Expression &other) const -> bool final
Checks whether this expression is structurally equivalent to another expression.
Definition BinaryExpression.hpp:210
auto Flatten(std::vector< std::unique_ptr< Expression > > &out) const -> void
Flattens this expression.
Definition BinaryExpression.hpp:249
auto HasLeastSigOp() const -> bool
Gets whether this expression has a least significant operand.
Definition BinaryExpression.hpp:305
BinaryExpression(const Op1T &op1, const Op2T &op2, const OpsT &... ops)
Definition BinaryExpression.hpp:104
BinaryExpression()=default
auto Equals(const Expression &other) const -> bool final
Compares this expression to another expression for equality.
Definition BinaryExpression.hpp:132
BinaryExpression(const MostSigOpT &mostSigOp, const LeastSigOpT &leastSigOp)
Definition BinaryExpression.hpp:97
auto HasMostSigOp() const -> bool
Gets whether this expression has a most significant operand.
Definition BinaryExpression.hpp:296
An expression.
Definition Expression.hpp:56
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 Serialization.hpp:50
virtual void Serialize(const Real &real)=0
Definition BinaryExpression.hpp:28
An expression concept.
Definition Concepts.hpp:25
A concept for an operand of a binary expression.
Definition BinaryExpression.hpp:25
Checks if type T is same as any of the provided types in U.
Definition Concepts.hpp:48
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:38
@ Commutative
Definition Expression.hpp:44
@ Associative
Definition Expression.hpp:43