diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 323804f15..14def7d80 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -239,11 +239,11 @@ public: * account the complex format required in the expression they return. * (For instance, in Polar mode, they return an expression of the form * r*e^(i*th) reduced and approximated.) */ - static Expression ParseAndSimplify(const char * text, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation = ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition); + static Expression ParseAndSimplify(const char * text, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation = ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, ExpressionNode::UnitConversion unitConversion = ExpressionNode::UnitConversion::Default); Expression simplify(ExpressionNode::ReductionContext reductionContext); - static void ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation = ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition); - void simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation = ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition); + static void ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation = ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, ExpressionNode::UnitConversion unitConversion = ExpressionNode::UnitConversion::Default); + void simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation = ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, ExpressionNode::UnitConversion unitConversion = ExpressionNode::UnitConversion::Default); Expression reduce(ExpressionNode::ReductionContext context); Expression mapOnMatrixFirstChild(ExpressionNode::ReductionContext reductionContext); diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 1a06b3b6e..6a5f576b3 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -128,8 +128,13 @@ public: ReplaceAllSymbolsWithDefinitionsOrUndefined = 0, ReplaceAllDefinedSymbolsWithDefinition = 1, ReplaceDefinedFunctionsWithDefinitions = 2, - ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits = 3, // Used in UnitConvert::shallowReduce - ReplaceAllSymbolsWithUndefinedAndReplaceUnits = 4 // Used in UnitConvert::shallowReduce + ReplaceAllSymbolsWithUndefined = 3 // Used in UnitConvert::shallowReduce + }; + enum class UnitConversion { + None = 0, + Default, + InternationalSystem, + Classic // km/h, days + hours + minute }; enum class Sign { Negative = -1, @@ -139,24 +144,27 @@ public: class ReductionContext { public: - ReductionContext(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target, SymbolicComputation symbolicComputation = SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition) : + ReductionContext(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ReductionTarget target, SymbolicComputation symbolicComputation = SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, UnitConversion unitConversion = UnitConversion::Default) : m_context(context), m_complexFormat(complexFormat), m_angleUnit(angleUnit), m_target(target), - m_symbolicComputation(symbolicComputation) + m_symbolicComputation(symbolicComputation), + m_unitConversion(unitConversion) {} Context * context() { return m_context; } Preferences::ComplexFormat complexFormat() const { return m_complexFormat; } Preferences::AngleUnit angleUnit() const { return m_angleUnit; } ReductionTarget target() const { return m_target; } SymbolicComputation symbolicComputation() const { return m_symbolicComputation; } + UnitConversion unitConversion() const { return m_unitConversion; } private: Context * m_context; Preferences::ComplexFormat m_complexFormat; Preferences::AngleUnit m_angleUnit; ReductionTarget m_target; SymbolicComputation m_symbolicComputation; + UnitConversion m_unitConversion; }; virtual Sign sign(Context * context) const { return Sign::Unknown; } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 119574427..444741c38 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -571,12 +571,12 @@ int Expression::serialize(char * buffer, int bufferSize, Preferences::PrintFloat /* Simplification */ -Expression Expression::ParseAndSimplify(const char * text, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation) { +Expression Expression::ParseAndSimplify(const char * text, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation, ExpressionNode::UnitConversion unitConversion) { Expression exp = Parse(text, context, false); if (exp.isUninitialized()) { return Undefined::Builder(); } - exp = exp.simplify(ExpressionNode::ReductionContext(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User, symbolicComputation)); + exp = exp.simplify(ExpressionNode::ReductionContext(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User, symbolicComputation, unitConversion)); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (exp.isUninitialized()) { @@ -585,7 +585,7 @@ Expression Expression::ParseAndSimplify(const char * text, Context * context, Pr return exp; } -void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation) { +void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation, ExpressionNode::UnitConversion unitConversion) { assert(simplifiedExpression); Expression exp = Parse(text, context, false); if (exp.isUninitialized()) { @@ -593,7 +593,7 @@ void Expression::ParseAndSimplifyAndApproximate(const char * text, Expression * *approximateExpression = Undefined::Builder(); return; } - exp.simplifyAndApproximate(simplifiedExpression, approximateExpression, context, complexFormat, angleUnit, symbolicComputation); + exp.simplifyAndApproximate(simplifiedExpression, approximateExpression, context, complexFormat, angleUnit, symbolicComputation, unitConversion); /* simplify might have been interrupted, in which case the resulting * expression is uninitialized, so we need to check that. */ if (simplifiedExpression->isUninitialized()) { @@ -675,16 +675,16 @@ void Expression::beautifyAndApproximateScalar(Expression * simplifiedExpression, } } -void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation) { +void Expression::simplifyAndApproximate(Expression * simplifiedExpression, Expression * approximateExpression, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit, ExpressionNode::SymbolicComputation symbolicComputation, ExpressionNode::UnitConversion unitConversion) { assert(simplifiedExpression); sSimplificationHasBeenInterrupted = false; // Step 1: we reduce the expression - ExpressionNode::ReductionContext userReductionContext = ExpressionNode::ReductionContext(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User, symbolicComputation); + ExpressionNode::ReductionContext userReductionContext = ExpressionNode::ReductionContext(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User, symbolicComputation, unitConversion); const bool isUnitConvert = type() == ExpressionNode::Type::UnitConvert; Expression e = clone().reduce(userReductionContext); if (sSimplificationHasBeenInterrupted) { sSimplificationHasBeenInterrupted = false; - ExpressionNode::ReductionContext systemReductionContext = ExpressionNode::ReductionContext(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::SystemForApproximation, symbolicComputation); + ExpressionNode::ReductionContext systemReductionContext = ExpressionNode::ReductionContext(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::SystemForApproximation, symbolicComputation, unitConversion); e = reduce(systemReductionContext); } *simplifiedExpression = Expression(); diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 9ed5e7fae..6aa0695d6 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -115,8 +115,7 @@ Expression Function::replaceSymbolWithExpression(const SymbolAbstract & symbol, } Expression Function::shallowReduce(ExpressionNode::ReductionContext reductionContext) { - if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits - || reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefinedAndReplaceUnits + if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined || childAtIndex(0).isUndefined()) { return replaceWithUndefinedInPlace(); diff --git a/poincare/src/multiplication.cpp b/poincare/src/multiplication.cpp index d3b6391ee..11cdca1af 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -355,75 +355,77 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu return std::move(o); } + // Step 2: Handle the units Expression self = *this; Expression units; self = removeUnit(&units); Expression result; if (!units.isUninitialized()) { - /* Step 2: Handle the units - * - * Recognize derived units - * - Look up in the table of derived units, the one which itself or its inverse simplifies 'units' the most. - * - If an entry is found, simplify 'units' and add the corresponding unit or its inverse in 'unitsAccu'. - * - Repeat those steps until no more simplification is possible. - */ - Multiplication unitsAccu = Multiplication::Builder(); - Unit::Dimension::Vector unitsExponents = Unit::Dimension::Vector::FromBaseUnits(units); - Unit::Dimension::Vector::Metrics unitsMetrics = unitsExponents.metrics(); - Unit::Dimension::Vector bestRemainderExponents; - Unit::Dimension::Vector::Metrics bestRemainderMetrics; - while (unitsMetrics.supportSize > 1) { - const Unit::Dimension * bestDim = nullptr; - int8_t bestUnitExponent = 0; - for (const Unit::Dimension * dim = Unit::DimensionTable + Unit::NumberOfBaseUnits; dim < Unit::DimensionTableUpperBound; dim++) { - const Unit::Dimension::Vector * entryUnitExponents = dim->vector(); - int8_t entryUnitNorm = entryUnitExponents->metrics().norm; - if (CanSimplifyUnitProduct( - unitsExponents, unitsMetrics, - entryUnitExponents, entryUnitNorm, 1, - bestUnitExponent, bestRemainderExponents, bestRemainderMetrics - ) - || - CanSimplifyUnitProduct( - unitsExponents, unitsMetrics, - entryUnitExponents, entryUnitNorm, -1, - bestUnitExponent, bestRemainderExponents, bestRemainderMetrics - )) - { - bestDim = dim; + ExpressionNode::UnitConversion unitConversionMode = reductionContext.unitConversion(); + if (unitConversionMode == ExpressionNode::UnitConversion::Default || unitConversionMode == ExpressionNode::UnitConversion::Classic) { + /* Step 2a: Recognize derived units + * - Look up in the table of derived units, the one which itself or its inverse simplifies 'units' the most. + * - If an entry is found, simplify 'units' and add the corresponding unit or its inverse in 'unitsAccu'. + * - Repeat those steps until no more simplification is possible. + */ + Multiplication unitsAccu = Multiplication::Builder(); + Unit::Dimension::Vector unitsExponents = Unit::Dimension::Vector::FromBaseUnits(units); + Unit::Dimension::Vector::Metrics unitsMetrics = unitsExponents.metrics(); + Unit::Dimension::Vector bestRemainderExponents; + Unit::Dimension::Vector::Metrics bestRemainderMetrics; + while (unitsMetrics.supportSize > 1) { + const Unit::Dimension * bestDim = nullptr; + int8_t bestUnitExponent = 0; + for (const Unit::Dimension * dim = Unit::DimensionTable + Unit::NumberOfBaseUnits; dim < Unit::DimensionTableUpperBound; dim++) { + const Unit::Dimension::Vector * entryUnitExponents = dim->vector(); + int8_t entryUnitNorm = entryUnitExponents->metrics().norm; + if (CanSimplifyUnitProduct( + unitsExponents, unitsMetrics, + entryUnitExponents, entryUnitNorm, 1, + bestUnitExponent, bestRemainderExponents, bestRemainderMetrics + ) + || + CanSimplifyUnitProduct( + unitsExponents, unitsMetrics, + entryUnitExponents, entryUnitNorm, -1, + bestUnitExponent, bestRemainderExponents, bestRemainderMetrics + )) + { + bestDim = dim; + } } + if (bestDim == nullptr) { + break; + } + Expression derivedUnit = Unit::Builder(bestDim, bestDim->stdRepresentative(), bestDim->stdRepresentativePrefix()); + assert(bestUnitExponent == 1 || bestUnitExponent == -1); + if (bestUnitExponent == -1) { + derivedUnit = Power::Builder(derivedUnit, Rational::Builder(-1)); + } + const int position = unitsAccu.numberOfChildren(); + unitsAccu.addChildAtIndexInPlace(derivedUnit, position, position); + unitsExponents = bestRemainderExponents; + unitsMetrics = bestRemainderMetrics; } - if (bestDim == nullptr) { - break; - } - Expression derivedUnit = Unit::Builder(bestDim, bestDim->stdRepresentative(), bestDim->stdRepresentativePrefix()); - assert(bestUnitExponent == 1 || bestUnitExponent == -1); - if (bestUnitExponent == -1) { - derivedUnit = Power::Builder(derivedUnit, Rational::Builder(-1)); - } - const int position = unitsAccu.numberOfChildren(); - unitsAccu.addChildAtIndexInPlace(derivedUnit, position, position); - unitsExponents = bestRemainderExponents; - unitsMetrics = bestRemainderMetrics; - } - if (unitsAccu.numberOfChildren() > 0) { - units = Division::Builder(units, unitsAccu.clone()).deepReduce(reductionContext); - Expression newUnits; - units = units.removeUnit(&newUnits); - Multiplication m = Multiplication::Builder(units); - self.replaceWithInPlace(m); - m.addChildAtIndexInPlace(self, 0, 1); - self = m; - if (newUnits.isUninitialized()) { - units = unitsAccu; - } else { - units = Multiplication::Builder(unitsAccu, newUnits); - static_cast(units).mergeSameTypeChildrenInPlace(); + if (unitsAccu.numberOfChildren() > 0) { + units = Division::Builder(units, unitsAccu.clone()).deepReduce(reductionContext); + Expression newUnits; + units = units.removeUnit(&newUnits); + Multiplication m = Multiplication::Builder(units); + self.replaceWithInPlace(m); + m.addChildAtIndexInPlace(self, 0, 1); + self = m; + if (newUnits.isUninitialized()) { + units = unitsAccu; + } else { + units = Multiplication::Builder(unitsAccu, newUnits); + static_cast(units).mergeSameTypeChildrenInPlace(); + } } } - /* Turn into 'Float x units'. + /* Step 2b: Turn into 'Float x units'. * Choose a unit multiple adequate for the numerical value. * An exhaustive exploration of all possible multiples would have * exponential complexity with respect to the number of factors. Instead, @@ -436,41 +438,46 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu // If the value is undefined, return "undef" without any unit result = Undefined::Builder(); } else { - Expression resultWithoutUnit; - if (std::isinf(value)) { - resultWithoutUnit = Infinity::Builder(value < 0.0); + if (unitConversionMode == ExpressionNode::UnitConversion::Classic) { + // TODO create new result 1h 23min 24secondes ? + // Utiliser store ? } else { - // Find the right unit prefix when the value ≠ 0 - if (value != 0.0 && value != 1.0) { - // Identify the first Unit factor and its exponent - Expression firstFactor = units; - int exponent = 1; - if (firstFactor.type() == ExpressionNode::Type::Multiplication) { - firstFactor = firstFactor.childAtIndex(0); - } - if (firstFactor.type() == ExpressionNode::Type::Power) { - Expression exp = firstFactor.childAtIndex(1); - firstFactor = firstFactor.childAtIndex(0); - assert(exp.type() == ExpressionNode::Type::Rational && static_cast(exp).isInteger()); - Integer expInt = static_cast(exp).signedIntegerNumerator(); - if (expInt.isLowerThan(Integer(Integer::k_maxExtractableInteger))) { - exponent = expInt.extractedInt(); - } else { - // The exponent is too large to be extracted, so do not try to use it. - exponent = 0; + Expression resultWithoutUnit; + if (std::isinf(value)) { + resultWithoutUnit = Infinity::Builder(value < 0.0); + } else { + // Find the right unit prefix when the value ≠ 0 + if (unitConversionMode == ExpressionNode::UnitConversion::Default && value != 0.0 && value != 1.0) { + // Identify the first Unit factor and its exponent + Expression firstFactor = units; + int exponent = 1; + if (firstFactor.type() == ExpressionNode::Type::Multiplication) { + firstFactor = firstFactor.childAtIndex(0); + } + if (firstFactor.type() == ExpressionNode::Type::Power) { + Expression exp = firstFactor.childAtIndex(1); + firstFactor = firstFactor.childAtIndex(0); + assert(exp.type() == ExpressionNode::Type::Rational && static_cast(exp).isInteger()); + Integer expInt = static_cast(exp).signedIntegerNumerator(); + if (expInt.isLowerThan(Integer(Integer::k_maxExtractableInteger))) { + exponent = expInt.extractedInt(); + } else { + // The exponent is too large to be extracted, so do not try to use it. + exponent = 0; + } + } + assert(firstFactor.type() == ExpressionNode::Type::Unit); + // Choose its multiple and update value accordingly + if (exponent != 0) { + static_cast(firstFactor).chooseBestMultipleForValue(value, exponent, reductionContext); } } - assert(firstFactor.type() == ExpressionNode::Type::Unit); - // Choose its multiple and update value accordingly - if (exponent != 0) { - static_cast(firstFactor).chooseBestMultipleForValue(value, exponent, reductionContext); - } + resultWithoutUnit = Float::Builder(value); } - resultWithoutUnit = Float::Builder(value); + // Build final Expression + result = Multiplication::Builder(resultWithoutUnit, units); + static_cast(result).mergeSameTypeChildrenInPlace(); } - // Build final Expression - result = Multiplication::Builder(resultWithoutUnit, units); - static_cast(result).mergeSameTypeChildrenInPlace(); } } else { diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 7f58b44b9..3a2a47c50 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -154,9 +154,7 @@ Expression Symbol::shallowReduce(ExpressionNode::ReductionContext reductionConte if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceDefinedFunctionsWithDefinitions) { return *this; } - if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits - || reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefinedAndReplaceUnits) - { + if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined) { return replaceWithUndefinedInPlace(); } { diff --git a/poincare/src/unit.cpp b/poincare/src/unit.cpp index 8501d3e0a..3b1e58654 100644 --- a/poincare/src/unit.cpp +++ b/poincare/src/unit.cpp @@ -282,7 +282,7 @@ Unit Unit::Builder(const Dimension * dimension, const Representative * represent } Expression Unit::shallowReduce(ExpressionNode::ReductionContext reductionContext) { - if (reductionContext.symbolicComputation() == ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits) { + if (reductionContext.unitConversion() == ExpressionNode::UnitConversion::None) { return *this; } UnitNode * unitNode = static_cast(node()); diff --git a/poincare/src/unit_convert.cpp b/poincare/src/unit_convert.cpp index 2ca423e48..ed3c62a20 100644 --- a/poincare/src/unit_convert.cpp +++ b/poincare/src/unit_convert.cpp @@ -35,12 +35,13 @@ Expression UnitConvert::shallowReduce(ExpressionNode::ReductionContext reduction // Find the unit { + // ExpressionNode::ReductionContext reductionContextWithUnits = ExpressionNode::ReductionContext( reductionContext.context(), reductionContext.complexFormat(), reductionContext.angleUnit(), reductionContext.target(), - ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefinedAndReplaceUnits); + ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined); Expression unit; childAtIndex(1).clone().reduce(reductionContextWithUnits).removeUnit(&unit); if (unit.isUninitialized()) { @@ -54,7 +55,8 @@ Expression UnitConvert::shallowReduce(ExpressionNode::ReductionContext reduction reductionContext.complexFormat(), reductionContext.angleUnit(), reductionContext.target(), - ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits); + ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined, + ExpressionNode::UnitConversion::None); Expression finalUnit; childAtIndex(1).reduce(reductionContextWithoutUnits).removeUnit(&finalUnit); diff --git a/poincare/test/expression_properties.cpp b/poincare/test/expression_properties.cpp index 5d03ca620..ffb6f7229 100644 --- a/poincare/test/expression_properties.cpp +++ b/poincare/test/expression_properties.cpp @@ -368,9 +368,9 @@ QUIZ_CASE(poincare_properties_get_polynomial_coefficients) { Ion::Storage::sharedStorage()->recordNamed("x.exp").destroy(); } -void assert_reduced_expression_unit(const char * expression, const char * unit, ExpressionNode::SymbolicComputation symbolicComutation) { +void assert_reduced_expression_unit_is(const char * expression, const char * unit) { Shared::GlobalContext globalContext; - ExpressionNode::ReductionContext redContext(&globalContext, Real, Degree, SystemForApproximation, symbolicComutation); + ExpressionNode::ReductionContext redContext(&globalContext, Real, Degree, SystemForApproximation); Expression e = parse_expression(expression, &globalContext, false); e = e.reduce(redContext); Expression u1; @@ -383,15 +383,9 @@ void assert_reduced_expression_unit(const char * expression, const char * unit, } QUIZ_CASE(poincare_properties_get_unit) { - assert_reduced_expression_unit("_km", "_km", ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits); - assert_reduced_expression_unit("_min/_km", "_km^(-1)×_min", ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits); - assert_reduced_expression_unit("_km^3", "_km^3", ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits); - assert_reduced_expression_unit("1_m+_km", Undefined::Name(), ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits); - assert_reduced_expression_unit("_L^2×3×_s", "_L^2×_s", ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits); - - assert_reduced_expression_unit("_km", "_m", ReplaceAllSymbolsWithDefinitionsOrUndefined); - assert_reduced_expression_unit("_min/_km", "_m^(-1)×_s", ReplaceAllSymbolsWithDefinitionsOrUndefined); - assert_reduced_expression_unit("_km^3", "_m^3", ReplaceAllSymbolsWithDefinitionsOrUndefined); - assert_reduced_expression_unit("1_m+_km", "_m", ReplaceAllSymbolsWithDefinitionsOrUndefined); - assert_reduced_expression_unit("_L^2×3×_s", "_m^6×_s", ReplaceAllSymbolsWithDefinitionsOrUndefined); + assert_reduced_expression_unit_is("_km", "_m"); + assert_reduced_expression_unit_is("_min/_km", "_m^(-1)×_s"); + assert_reduced_expression_unit_is("_km^3", "_m^3"); + assert_reduced_expression_unit_is("1_m+_km", "_m"); + assert_reduced_expression_unit_is("_L^2×3×_s", "_m^6×_s"); } diff --git a/poincare/test/helper.h b/poincare/test/helper.h index 5e7f5942e..91febd09a 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -11,7 +11,11 @@ constexpr Poincare::ExpressionNode::ReductionTarget User = Poincare::ExpressionN constexpr Poincare::ExpressionNode::SymbolicComputation ReplaceAllDefinedSymbolsWithDefinition = Poincare::ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition; constexpr Poincare::ExpressionNode::SymbolicComputation ReplaceAllSymbolsWithDefinitionsOrUndefined = Poincare::ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined; constexpr Poincare::ExpressionNode::SymbolicComputation ReplaceDefinedFunctionsWithDefinitions = Poincare::ExpressionNode::SymbolicComputation::ReplaceDefinedFunctionsWithDefinitions; -constexpr Poincare::ExpressionNode::SymbolicComputation ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits = Poincare::ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefinedAndDoNotReplaceUnits; +constexpr Poincare::ExpressionNode::SymbolicComputation ReplaceAllSymbolsWithUndefined = Poincare::ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithUndefined; +constexpr Poincare::ExpressionNode::UnitConversion NoUnitConversion = Poincare::ExpressionNode::UnitConversion::None; +constexpr Poincare::ExpressionNode::UnitConversion DefaultUnitConversion = Poincare::ExpressionNode::UnitConversion::Default; +constexpr Poincare::ExpressionNode::UnitConversion ClassicUnitConversion = Poincare::ExpressionNode::UnitConversion::Classic; +constexpr Poincare::ExpressionNode::UnitConversion InternationalSystemUnitConversion = Poincare::ExpressionNode::UnitConversion::InternationalSystem; constexpr Poincare::Preferences::AngleUnit Degree = Poincare::Preferences::AngleUnit::Degree; constexpr Poincare::Preferences::AngleUnit Radian = Poincare::Preferences::AngleUnit::Radian; constexpr Poincare::Preferences::AngleUnit Gradian = Poincare::Preferences::AngleUnit::Gradian;