From 67241bb564ec78b3ab1998aef6e7f1b2090096e1 Mon Sep 17 00:00:00 2001 From: Ruben Dashyan Date: Thu, 20 Feb 2020 10:26:15 +0100 Subject: [PATCH] [poincare] Make code more object oriented Turn ExponentsOfBaseUnits function into a static method of the Unit::Dimension::Vector class --- poincare/include/poincare/expression.h | 1 + poincare/include/poincare/unit.h | 3 +-- poincare/src/multiplication.cpp | 37 ++------------------------ poincare/src/unit.cpp | 35 ++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index c8aa3cc10..54877d604 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -117,6 +117,7 @@ class Expression : public TreeHandle { friend class NAryExpressionNode; friend class StoreNode; friend class SymbolNode; + friend class UnitNode; public: static bool IsExpression() { return true; } diff --git a/poincare/include/poincare/unit.h b/poincare/include/poincare/unit.h index b340234e1..0475fff90 100644 --- a/poincare/include/poincare/unit.h +++ b/poincare/include/poincare/unit.h @@ -90,6 +90,7 @@ public: T norm; }; Metrics metrics() const; + static Vector FromBaseUnits(const Expression baseUnits); const T coefficientAtIndex(size_t i) const { assert(i < NumberOfBaseUnits); return *(reinterpret_cast(this) + i); @@ -512,8 +513,6 @@ public: static bool CanParse(const char * symbol, size_t length, const Dimension * * dimension, const Representative * * representative, const Prefix * * prefix); - const Dimension * dimension() const { return static_cast(node())->dimension(); } - Unit(const UnitNode * node) : Expression(node) {} static Unit Builder(const Dimension * dimension, const Representative * representative, const Prefix * prefix); Expression getUnit() const { return clone(); } diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index dadef4123..9776a17a1 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -302,39 +302,6 @@ Expression Multiplication::shallowReduce(ExpressionNode::ReductionContext reduct return privateShallowReduce(reductionContext, true, true); } -static Unit::Dimension::Vector ExponentsOfBaseUnits(const Expression units) { - Unit::Dimension::Vector exponents; - // Make sure the provided Expression is a Multiplication - Expression u = units; - if (u.type() == ExpressionNode::Type::Unit || u.type() == ExpressionNode::Type::Power) { - u = Multiplication::Builder(u.clone()); - } - const int numberOfChildren = u.numberOfChildren(); - for (int i = 0; i < numberOfChildren; i++) { - Expression factor = u.childAtIndex(i); - - // Get the unit's exponent - Integer exponent(1); - if (factor.type() == ExpressionNode::Type::Power) { - Expression exp = factor.childAtIndex(1); - assert(exp.type() == ExpressionNode::Type::Rational && static_cast(exp).isInteger()); - exponent = static_cast(exp).signedIntegerNumerator(); - factor = factor.childAtIndex(0); - } - - // The leading factors may not be of Unit type - if (factor.type() != ExpressionNode::Type::Unit) { - continue; - } - - // Fill the exponents array with the unit's exponent - const int indexInTable = static_cast(factor).dimension() - Unit::DimensionTable; - assert(0 <= indexInTable && indexInTable < Unit::NumberOfBaseUnits); - exponents.setCoefficientAtIndex(indexInTable, exponent); - } - return exponents; -} - static bool CanSimplifyUnitProduct( const Unit::Dimension::Vector &unitsExponents, const Unit::Dimension::Vector &entryUnitExponents, const Integer entryUnitNorm, const Expression entryUnit, Integer (*operationOnExponents)(const Integer & unitsExponent, const Integer & entryUnitExponent), @@ -391,7 +358,7 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu * - Repeat those steps until no more simplification is possible. */ Multiplication unitsAccu = Multiplication::Builder(); - Unit::Dimension::Vector unitsExponents = ExponentsOfBaseUnits(units); + Unit::Dimension::Vector unitsExponents = Unit::Dimension::Vector::FromBaseUnits(units); Unit::Dimension::Vector::Metrics unitsMetrics = unitsExponents.metrics(); Unit::Dimension::Vector bestRemainderExponents; while (unitsMetrics.supportSize > 1) { @@ -400,7 +367,7 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu Unit::Dimension::Vector::Metrics bestRemainderMetrics = {.supportSize = unitsMetrics.supportSize - 1, .norm = unitsMetrics.norm}; for (const Unit::Dimension * dim = Unit::DimensionTable + Unit::NumberOfBaseUnits; dim < Unit::DimensionTableUpperBound; dim++) { Unit entryUnit = Unit::Builder(dim, dim->stdRepresentative(), dim->stdRepresentativePrefix()); - Unit::Dimension::Vector entryUnitExponents = ExponentsOfBaseUnits(entryUnit.clone().shallowReduce(reductionContext)); + Unit::Dimension::Vector entryUnitExponents = Unit::Dimension::Vector::FromBaseUnits(entryUnit.clone().shallowReduce(reductionContext)); Integer entryUnitNorm = entryUnitExponents.metrics().norm; CanSimplifyUnitProduct( unitsExponents, entryUnitExponents, entryUnitNorm, entryUnit, diff --git a/poincare/src/unit.cpp b/poincare/src/unit.cpp index 25c8f0d04..8b02634f9 100644 --- a/poincare/src/unit.cpp +++ b/poincare/src/unit.cpp @@ -91,6 +91,41 @@ Unit::Dimension::Vector::Metrics UnitNode::Dimension::Vector:: return {.supportSize = supportSize, .norm = norm}; } +template<> +Unit::Dimension::Vector UnitNode::Dimension::Vector::FromBaseUnits(const Expression baseUnits) { + Vector vector; + // Make sure the provided Expression is a Multiplication + Expression u = baseUnits; + if (u.type() == ExpressionNode::Type::Unit || u.type() == ExpressionNode::Type::Power) { + u = Multiplication::Builder(u.clone()); + } + const int numberOfChildren = u.numberOfChildren(); + for (int i = 0; i < numberOfChildren; i++) { + Expression factor = u.childAtIndex(i); + + // Get the unit's exponent + Integer exponent(1); + if (factor.type() == ExpressionNode::Type::Power) { + Expression exp = factor.childAtIndex(1); + assert(exp.type() == ExpressionNode::Type::Rational && static_cast(exp).isInteger()); + exponent = static_cast(exp).signedIntegerNumerator(); + factor = factor.childAtIndex(0); + } + + // FIXME Remove this once this case may not occur anymore + // The leading factors may not be of Unit type + if (factor.type() != ExpressionNode::Type::Unit) { + continue; + } + + // Fill the vector with the unit's exponent + const ptrdiff_t indexInTable = static_cast(factor.node())->dimension() - Unit::DimensionTable; + assert(0 <= indexInTable && indexInTable < NumberOfBaseUnits); + vector.setCoefficientAtIndex(indexInTable, exponent); + } + return vector; +} + bool UnitNode::Dimension::canParse(const char * symbol, size_t length, const Representative * * representative, const Prefix * * prefix) const {