From d5b07f1f90dff2a6ed9952afbf6eea20d9183752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 5 Feb 2020 12:13:47 +0100 Subject: [PATCH] [poincare] Implemment getUnit --- poincare/include/poincare/absolute_value.h | 1 + poincare/include/poincare/addition.h | 1 + poincare/include/poincare/division.h | 1 + poincare/include/poincare/empty_expression.h | 1 + poincare/include/poincare/expression.h | 4 ++++ poincare/include/poincare/expression_node.h | 2 ++ poincare/include/poincare/function.h | 3 +++ poincare/include/poincare/multiplication.h | 2 ++ poincare/include/poincare/nth_root.h | 1 + poincare/include/poincare/parenthesis.h | 1 + poincare/include/poincare/power.h | 2 ++ poincare/include/poincare/subtraction.h | 1 + poincare/include/poincare/symbol.h | 2 ++ poincare/include/poincare/unit.h | 2 ++ poincare/include/poincare/unit_convert.h | 1 + poincare/src/absolute_value.cpp | 4 ++++ poincare/src/addition.cpp | 5 ++++ poincare/src/expression.cpp | 6 +++++ poincare/src/expression_node.cpp | 4 ++++ poincare/src/multiplication.cpp | 24 ++++++++++++++++++++ poincare/src/power.cpp | 11 +++++++++ poincare/src/unit.cpp | 4 ++++ poincare/src/unit_convert.cpp | 2 +- 23 files changed, 84 insertions(+), 1 deletion(-) diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 3673751a8..411259dd8 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -33,6 +33,7 @@ public: Evaluation approximate(DoublePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { return ApproximationHelper::Map(this, context, complexFormat, angleUnit, computeOnComplex); } + Expression getUnit() const override; // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index cf90a80ef..1cb04f8a8 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -35,6 +35,7 @@ public: template static MatrixComplex computeOnComplexAndMatrix(const std::complex c, const MatrixComplex m, Preferences::ComplexFormat complexFormat) { return MatrixComplex::Undefined(); } + Expression getUnit() const override; // Simplification LayoutShape leftLayoutShape() const override { diff --git a/poincare/include/poincare/division.h b/poincare/include/poincare/division.h index 9dfb23690..5c2bb56b2 100644 --- a/poincare/include/poincare/division.h +++ b/poincare/include/poincare/division.h @@ -25,6 +25,7 @@ public: // Properties Type type() const override { return Type::Division; } int polynomialDegree(Context * context, const char * symbolName) const override; + Expression getUnit() const override { assert(false); return ExpressionNode::getUnit(); } // Approximation virtual Evaluation approximate(SinglePrecision p, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const override { diff --git a/poincare/include/poincare/empty_expression.h b/poincare/include/poincare/empty_expression.h index 451d192db..eb2824fb8 100644 --- a/poincare/include/poincare/empty_expression.h +++ b/poincare/include/poincare/empty_expression.h @@ -22,6 +22,7 @@ public: // Properties Type type() const override { return Type::EmptyExpression; } int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; + Expression getUnit() const override { assert(false); return ExpressionNode::getUnit(); } // Simplification LayoutShape leftLayoutShape() const override { diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index ca767f68c..001780b64 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -198,6 +198,10 @@ public: int getPolynomialReducedCoefficients(const char * symbolName, Expression coefficients[], Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation) const; Expression replaceSymbolWithExpression(const SymbolAbstract & symbol, const Expression & expression) { return node()->replaceSymbolWithExpression(symbol, expression); } + /* Units */ + Expression getUnit() const { return node()->getUnit(); } + bool hasUnit() const; + /* Complex */ static bool EncounteredComplex(); static void SetEncounteredComplex(bool encounterComplex); diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 1fc7aaa28..0da4e71ab 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -177,6 +177,8 @@ public: virtual float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const; bool isOfType(Type * types, int length) const; + virtual Expression getUnit() const; // Only reduced nodes should answer + /* Simplification */ /* SimplificationOrder returns: * 1 if e1 > e2 diff --git a/poincare/include/poincare/function.h b/poincare/include/poincare/function.h index 422140032..c627aa8e3 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -28,6 +28,9 @@ public: int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const override; int getVariables(Context * context, isVariableTest isVariable, char * variables, int maxSizeVariable, int nextVariableIndex) const override; float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const override; + /* getUnit() is ExpressionNode::getUnit -> + * as the function is reduced, it would have been replaced if it had a + * definition. It thus has no definition, so no unit. */ private: char m_name[0]; // MUST be the last member variable diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index 30eaf218d..c75144cf4 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -25,6 +25,7 @@ public: int polynomialDegree(Context * context, const char * symbolName) const override; int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const override; bool childAtIndexNeedsUserParentheses(const Expression & child, int childIndex) const override; + Expression getUnit() const override; // Approximation template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex::Builder(c*d); } @@ -77,6 +78,7 @@ public: // Properties int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const; + Expression getUnit() const; // Approximation template static void computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns); // Simplification diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 9deab541e..3edec4e1c 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -20,6 +20,7 @@ public: #endif private: + Expression getUnit() const override { assert(false); return ExpressionNode::getUnit(); } // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index 177776860..ec203e55b 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -21,6 +21,7 @@ public: // Properties Type type() const override { return Type::Parenthesis; } int polynomialDegree(Context * context, const char * symbolName) const override; + Expression getUnit() const override { assert(false); return ExpressionNode::getUnit(); } // Layout Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index 55861e502..c5860e77e 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -29,6 +29,7 @@ public: Sign sign(Context * context) const override; Expression setSign(Sign s, ReductionContext reductionContext) override; bool childAtIndexNeedsUserParentheses(const Expression & child, int childIndex) const override; + Expression getUnit() const override; int polynomialDegree(Context * context, const char * symbolName) const override; int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const override; @@ -76,6 +77,7 @@ public: int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[]) const; Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); Expression shallowBeautify(ExpressionNode::ReductionContext reductionContext); + Expression getUnit() const; private: constexpr static int k_maxExactPowerMatrix = 100; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index 30f856288..53b77bc60 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -24,6 +24,7 @@ public: Type type() const override { return Type::Subtraction; } int polynomialDegree(Context * context, const char * symbolName) const override; bool childAtIndexNeedsUserParentheses(const Expression & child, int childIndex) const override; + Expression getUnit() const override { assert(false); return ExpressionNode::getUnit(); } // Approximation template static Complex compute(const std::complex c, const std::complex d, Preferences::ComplexFormat complexFormat) { return Complex::Builder(c - d); } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 67fe92d5f..2fb4fb6a6 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -26,6 +26,8 @@ public: int getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const override; int getVariables(Context * context, isVariableTest isVariable, char * variables, int maxSizeVariable, int nextVariableIndex) const override; float characteristicXRange(Context * context, Preferences::AngleUnit angleUnit) const override; + /* getUnit returns Undefined, because the symbol would have + * already been replaced if it should have been.*/ /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; diff --git a/poincare/include/poincare/unit.h b/poincare/include/poincare/unit.h index ca91bc214..42a2b8e89 100644 --- a/poincare/include/poincare/unit.h +++ b/poincare/include/poincare/unit.h @@ -112,6 +112,7 @@ public: // Expression Properties Type type() const override { return Type::Unit; } Sign sign(Context * context) const override; + Expression getUnit() const override; /* Layout */ Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; @@ -509,6 +510,7 @@ public: Unit(const UnitNode * node) : Expression(node) {} static Unit Builder(const Dimension * dimension, const Representative * representative, const Prefix * prefix); + Expression getUnit() const { return clone(); } // Simplification Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); diff --git a/poincare/include/poincare/unit_convert.h b/poincare/include/poincare/unit_convert.h index a8b621268..7125b6ed3 100644 --- a/poincare/include/poincare/unit_convert.h +++ b/poincare/include/poincare/unit_convert.h @@ -20,6 +20,7 @@ public: Type type() const override { return Type::UnitConvert; } private: + Expression getUnit() const override { assert(false); return ExpressionNode::getUnit(); } // Simplification Expression shallowReduce(ReductionContext reductionContext) override; // Evalutation diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index d87705ccd..6f0de1535 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -19,6 +19,10 @@ Expression AbsoluteValueNode::setSign(Sign s, ReductionContext reductionContext) return AbsoluteValue(this); } +Expression AbsoluteValueNode::getUnit() const { + return childAtIndex(0)->getUnit(); +} + Layout AbsoluteValueNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { return AbsoluteValueLayout::Builder(childAtIndex(0)->createLayout(floatDisplayMode, numberOfSignificantDigits)); } diff --git a/poincare/src/addition.cpp b/poincare/src/addition.cpp index 6d176c597..e17be8625 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -29,6 +29,11 @@ int AdditionNode::getPolynomialCoefficients(Context * context, const char * symb return Addition(this).getPolynomialCoefficients(context, symbolName, coefficients, symbolicComputation); } +Expression AdditionNode::getUnit() const { + // The expression is reduced, so we can just ask the unit of the first child + return childAtIndex(0)->getUnit(); +} + // Layout Layout AdditionNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 2121011ef..95013be9b 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -453,6 +453,12 @@ int Expression::getPolynomialReducedCoefficients(const char * symbolName, Expres return degree; } +/* Units */ + +bool Expression::hasUnit() const { + return !getUnit().isUndefined(); +} + /* Complex */ bool Expression::EncounteredComplex() { diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index 4041cd92e..9889b69d1 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -124,6 +124,10 @@ bool ExpressionNode::isOfType(Type * types, int length) const { return false; } +Expression ExpressionNode::getUnit() const { + return Undefined::Builder(); +} + void ExpressionNode::setChildrenInPlace(Expression other) { Expression(this).defaultSetChildrenInPlace(other); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index 5b314a32f..132445486 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -62,6 +62,10 @@ bool MultiplicationNode::childAtIndexNeedsUserParentheses(const Expression & chi return child.isOfType(types, 2); } +Expression MultiplicationNode::getUnit() const { + return Multiplication(this).getUnit(); +} + template MatrixComplex MultiplicationNode::computeOnMatrices(const MatrixComplex m, const MatrixComplex n, Preferences::ComplexFormat complexFormat) { if (m.numberOfColumns() != n.numberOfRows()) { @@ -252,6 +256,26 @@ int Multiplication::getPolynomialCoefficients(Context * context, const char * sy return deg; } +Expression Multiplication::getUnit() const { + const int childrenCount = numberOfChildren(); + if (childrenCount == 1) { + return childAtIndex(0).getUnit(); + } + Multiplication result = Multiplication::Builder(); + int resultChildrenCount = 0; + for (int i = 0; i < childrenCount; i++) { + Expression currentUnit = childAtIndex(i).getUnit(); + if (!currentUnit.isUndefined()) { + result.addChildAtIndexInPlace(currentUnit, resultChildrenCount, resultChildrenCount); + resultChildrenCount++; + } + } + if (resultChildrenCount == 0) { + return Undefined::Builder(); + } + return std::move(result); +} + template void Multiplication::computeOnArrays(T * m, T * n, T * result, int mNumberOfColumns, int mNumberOfRows, int nNumberOfColumns) { for (int i = 0; i < mNumberOfRows; i++) { diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index a2a1d1551..c5527edbe 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -82,6 +82,10 @@ int PowerNode::polynomialDegree(Context * context, const char * symbolName) cons return -1; } +Expression PowerNode::getUnit() const { + return Power(this).getUnit(); +} + int PowerNode::getPolynomialCoefficients(Context * context, const char * symbolName, Expression coefficients[], ExpressionNode::SymbolicComputation symbolicComputation) const { return Power(this).getPolynomialCoefficients(context, symbolName, coefficients); } @@ -912,6 +916,13 @@ Expression Power::shallowBeautify(ExpressionNode::ReductionContext reductionCont return *this; } +Expression Power::getUnit() const { + if (childAtIndex(0).type() == ExpressionNode::Type::Unit) { + return clone(); + } + return Power::Builder(childAtIndex(0).getUnit(), childAtIndex(1).clone()); +} + // Private // Simplification diff --git a/poincare/src/unit.cpp b/poincare/src/unit.cpp index b546dccc9..7455b6e76 100644 --- a/poincare/src/unit.cpp +++ b/poincare/src/unit.cpp @@ -98,6 +98,10 @@ ExpressionNode::Sign UnitNode::sign(Context * context) const { return Sign::Positive; } +Expression UnitNode::getUnit() const { + return Unit(this).getUnit(); +} + int UnitNode::simplificationOrderSameType(const ExpressionNode * e, bool ascending, bool canBeInterrupted) const { if (!ascending) { return e->simplificationOrderSameType(this, true, canBeInterrupted); diff --git a/poincare/src/unit_convert.cpp b/poincare/src/unit_convert.cpp index 80cf772fa..9b12780e7 100644 --- a/poincare/src/unit_convert.cpp +++ b/poincare/src/unit_convert.cpp @@ -33,7 +33,7 @@ Expression UnitConvert::shallowReduce(ExpressionNode::ReductionContext reduction } } // Find the unit - ReductionContext unitReductionContext = ReductionContext( + ExpressionNode::ReductionContext unitReductionContext = ExpressionNode::ReductionContext( reductionContext.context(), reductionContext.complexFormat(), reductionContext.angleUnit(),