diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index 4c96ccecc..7c36ee9cc 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -18,6 +18,7 @@ public: } #endif + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override { return childAtIndex(0)->isReal(context, angleUnit); } ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; @@ -46,7 +47,7 @@ public: static Expression UntypedBuilder(Expression children) { return Builder(children.childAtIndex(0)); } static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("conj", 1, &UntypedBuilder);; - Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit); + Expression shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target); private: explicit Conjugate(Expression child) : Expression(TreePool::sharedPool()->createTreeNode()) { replaceChildAtIndexInPlace(0, child); diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index 95a57169b..aecee8ad5 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -28,6 +28,7 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index ec529e55a..989bfef8f 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -27,6 +27,7 @@ public: float characteristicXRange(Context & context, Preferences::AngleUnit angleUnit) const override; // Complex + bool isReal(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexCartesian complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const override; ComplexPolar complexPolar(Context & context, Preferences::AngleUnit angleUnit) const override; diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index 97a264760..e5ffb9c2c 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -80,6 +80,7 @@ protected: SymbolAbstractNode * node() const { return static_cast(Expression::node()); } private: static Expression Expand(const SymbolAbstract & symbol, Context & context, bool clone); + static bool isReal(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); static ComplexCartesian complexCartesian(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); static ComplexPolar complexPolar(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit); static size_t AlignedNodeSize(size_t nameLength, size_t nodeSize); diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 1ee35cf23..eae04b0ac 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -47,7 +47,7 @@ int ConjugateNode::serialize(char * buffer, int bufferSize, Preferences::PrintFl } Expression ConjugateNode::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ReductionTarget target) { - return Conjugate(this).shallowReduce(context, angleUnit); + return Conjugate(this).shallowReduce(context, angleUnit, target); } template @@ -55,7 +55,7 @@ Complex ConjugateNode::computeOnComplex(const std::complex c, Preferences: return Complex(std::conj(c)); } -Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit angleUnit) { +Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit angleUnit, ExpressionNode::ReductionTarget target) { { Expression e = Expression::defaultShallowReduce(context, angleUnit); if (e.isUndefined()) { @@ -68,6 +68,18 @@ Expression Conjugate::shallowReduce(Context & context, Preferences::AngleUnit an return SimplificationHelper::Map(*this, context, angleUnit); } #endif + if (c.isReal(context, angleUnit)) { + replaceWithInPlace(c); + return c; + } + if (c.type() == ExpressionNode::Type::ComplexCartesian) { + ComplexCartesian complexChild = static_cast(c); + Multiplication m(Rational(-1), complexChild.imag()); + complexChild.replaceChildAtIndexInPlace(1, m); + m.shallowReduce(context, angleUnit, target); + replaceWithInPlace(complexChild); + return complexChild; + } if (c.type() == ExpressionNode::Type::Rational) { replaceWithInPlace(c); return c; diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 9103f4a85..2d6346f9f 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -14,6 +14,11 @@ ComplexCartesian FunctionNode::complexCartesian(Context & context, Preferences:: return SymbolAbstract::complexCartesian(f, context, angleUnit); } +bool FunctionNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { + Function f(this); + return SymbolAbstract::isReal(f, context, angleUnit); +} + ComplexPolar FunctionNode::complexPolar(Context & context, Preferences::AngleUnit angleUnit) const { Function f(this); return SymbolAbstract::complexPolar(f, context, angleUnit); diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 1e171fe8d..754f558cc 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -77,6 +77,11 @@ float SymbolNode::characteristicXRange(Context & context, Preferences::AngleUnit return 0.0f; } +bool SymbolNode::isReal(Context & context, Preferences::AngleUnit angleUnit) const { + Symbol s(this); + return SymbolAbstract::isReal(s, context, angleUnit); +} + ComplexCartesian SymbolNode::complexCartesian(Context & context, Preferences::AngleUnit angleUnit) const { Symbol s(this); return SymbolAbstract::complexCartesian(s, context, angleUnit); diff --git a/poincare/src/symbol_abstract.cpp b/poincare/src/symbol_abstract.cpp index faea41a33..c8f57e0c9 100644 --- a/poincare/src/symbol_abstract.cpp +++ b/poincare/src/symbol_abstract.cpp @@ -80,6 +80,14 @@ Expression SymbolAbstract::Expand(const SymbolAbstract & symbol, Context & conte return e; } +bool SymbolAbstract::isReal(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { + Expression e = SymbolAbstract::Expand(symbol, context, false); + if (e.isUninitialized()) { + return true; + } + return e.isReal(context, angleUnit); +} + ComplexCartesian SymbolAbstract::complexCartesian(const SymbolAbstract & symbol, Context & context, Preferences::AngleUnit angleUnit) { Expression e = SymbolAbstract::Expand(symbol, context, true); if (e.isUninitialized()) {