From 7b2d020128dc46553069355cb6a320698793c570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 7 May 2020 11:48:52 +0200 Subject: [PATCH] [poincare] Unit: implement IsIS --- poincare/include/poincare/unit.h | 2 ++ poincare/src/unit.cpp | 30 +++++++++++++++++++++++++ poincare/test/expression_properties.cpp | 10 +++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/poincare/include/poincare/unit.h b/poincare/include/poincare/unit.h index e78b58905..d286d4bc6 100644 --- a/poincare/include/poincare/unit.h +++ b/poincare/include/poincare/unit.h @@ -766,6 +766,7 @@ public: static Unit Watt() { return Builder(PowerDimension, WattRepresentative, &EmptyPrefix); } static Expression BuildTimeSplit(double seconds, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + static bool IsIS(Expression & e); static bool IsISSpeed(Expression & e); static bool IsISVolume(Expression & e); static bool IsISEnergy(Expression & e); @@ -788,6 +789,7 @@ private: static constexpr double MonthPerYear = 12.0; static constexpr double DaysPerMonth = DaysPerYear/MonthPerYear; UnitNode * node() const { return static_cast(Expression::node()); } + bool isIS() const; static void ChooseBestMultipleForValue(Expression * units, double * value, bool tuneRepresentative, ExpressionNode::ReductionContext reductionContext); void chooseBestMultipleForValue(double * value, const int exponent, bool tuneRepresentative, ExpressionNode::ReductionContext reductionContext); Expression removeUnit(Expression * unit); diff --git a/poincare/src/unit.cpp b/poincare/src/unit.cpp index 769e575a3..9065a1ccc 100644 --- a/poincare/src/unit.cpp +++ b/poincare/src/unit.cpp @@ -408,6 +408,36 @@ bool Unit::isKilogram() const { return node()->dimension() == MassDimension && node()->representative() == KilogramRepresentative && node()->prefix() == &KiloPrefix; } +bool Unit::isIS() const { + UnitNode * unitNode = node(); + const Dimension * dim = unitNode->dimension(); + const Representative * rep = unitNode->representative(); + return rep == dim->stdRepresentative() && + rep->definition() == nullptr && + unitNode->prefix() == dim->stdRepresentativePrefix(); +} + +bool Unit::IsIS(Expression & e) { + if (e.type() == ExpressionNode::Type::Multiplication) { + for (int i = 0; i < e.numberOfChildren(); i++) { + Expression child = e.childAtIndex(i); + assert(child.type() == ExpressionNode::Type::Power || child.type() == ExpressionNode::Type::Unit); + if (!IsIS(child)) { + return false; + } + } + return true; + } + if (e.type() == ExpressionNode::Type::Power) { + assert(e.childAtIndex(1).type() == ExpressionNode::Type::Rational && e.childAtIndex(1).convert().isInteger()); + Expression child = e.childAtIndex(0); + assert(child.type() == ExpressionNode::Type::Unit); + return IsIS(child); + } + assert(e.type() == ExpressionNode::Type::Unit); + return static_cast(e).isIS(); +} + bool Unit::IsISSpeed(Expression & e) { // Form m*s^-1 return e.type() == ExpressionNode::Type::Multiplication && e.numberOfChildren() == 2 && diff --git a/poincare/test/expression_properties.cpp b/poincare/test/expression_properties.cpp index 03074eb3e..e2b0133f2 100644 --- a/poincare/test/expression_properties.cpp +++ b/poincare/test/expression_properties.cpp @@ -400,7 +400,7 @@ void assert_seconds_split_to(double totalSeconds, const char * splittedTime, Con Expression extract_unit(const char * expression) { Shared::GlobalContext globalContext; - ExpressionNode::ReductionContext reductionContext = ExpressionNode::ReductionContext(&globalContext, Cartesian, Degree, User); + ExpressionNode::ReductionContext reductionContext = ExpressionNode::ReductionContext(&globalContext, Cartesian, Degree, User, ReplaceAllSymbolsWithUndefined, NoUnitConversion); Expression e = parse_expression(expression, &globalContext, false).reduce(reductionContext); Expression unit; e.removeUnit(&unit); @@ -428,5 +428,11 @@ QUIZ_CASE(poincare_expression_unit_helper) { // 4. Energy Expression kilogramMeter2PerSecond2 = extract_unit("_kg×_m^2×_s^-2"); quiz_assert(Unit::IsISEnergy(kilogramMeter2PerSecond2)); -} + // 5. International System + quiz_assert(Unit::IsIS(kilogramMeter2PerSecond2)); + quiz_assert(Unit::IsIS(meter3)); + quiz_assert(Unit::IsIS(meterPerSecond)); + Expression joule = extract_unit("_J"); + quiz_assert(!Unit::IsIS(joule)); +}