From 3ff25fb5c1df1153bc0972cae2b6061cf0a9e09d Mon Sep 17 00:00:00 2001 From: Gabriel Ozouf Date: Tue, 21 Jul 2020 11:56:50 +0200 Subject: [PATCH] [poincare/unit] Standard unit methods Added methods to return the standard format for each dimension, depending on the chosen unit system. Change-Id: I3591a806beca315674cc09093b57e8753db5db6a --- poincare/include/poincare/unit.h | 7 ++++ poincare/src/unit.cpp | 55 ++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/poincare/include/poincare/unit.h b/poincare/include/poincare/unit.h index 14cfe8377..c7a59123a 100644 --- a/poincare/include/poincare/unit.h +++ b/poincare/include/poincare/unit.h @@ -876,6 +876,7 @@ public: static Expression BuildImperialDistanceSplit(double inches, Context * context); static Expression BuildImperialMassSplit(double ounces, Context * context); static Expression BuildImperialVolumeSplit(double fluidOunces, Context * context); + static double ConvertedValueInUnit(Expression e, Unit unit, Context * context); static bool IsSI(Expression & e); static bool IsSISpeed(Expression & e); @@ -886,6 +887,12 @@ public: bool isSecond() const; bool isKilogram() const; + static Expression StandardSpeedConversion(Expression e, Preferences::UnitFormat format, Context * context); + static Expression StandardDistanceConversion(Expression e, Preferences::UnitFormat format, Context * context); + static Expression StandardVolumeConversion(Expression e, Preferences::UnitFormat format, Context * context); + static Expression StandardMassConversion(Expression e, Preferences::UnitFormat format, Context * context); + static Expression StandardSurfaceConversion(Expression e, Preferences::UnitFormat format, Context * context); + // Simplification Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); Expression shallowBeautify(ExpressionNode::ReductionContext reductionContext); diff --git a/poincare/src/unit.cpp b/poincare/src/unit.cpp index ddb3c48cb..5f0e8d674 100644 --- a/poincare/src/unit.cpp +++ b/poincare/src/unit.cpp @@ -515,6 +515,15 @@ bool Unit::IsSITime(Expression & e) { return e.type() == ExpressionNode::Type::Unit && static_cast(e).isSecond(); } + +double Unit::ConvertedValueInUnit(Expression e, Unit unit, Context * context) { + Expression conversion = UnitConvert::Builder(e.clone(), unit); + Expression newUnit; + conversion = conversion.simplify(ExpressionNode::ReductionContext(context, Preferences::ComplexFormat::Real, Preferences::sharedPreferences()->angleUnit(), ExpressionNode::ReductionTarget::User, ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, Poincare::ExpressionNode::UnitConversion::Default)); + conversion = conversion.removeUnit(&newUnit); + return conversion.approximateToScalar(context, Preferences::ComplexFormat::Real, Preferences::sharedPreferences()->angleUnit()); +} + Expression Unit::BuildSplit(double baseValue, Unit const * units, double const * conversionFactors, const int numberOfUnits, Context * context) { assert(!std::isnan(baseValue)); if (std::isinf(baseValue) || std::fabs(baseValue) < Expression::Epsilon()) { @@ -579,6 +588,52 @@ Expression Unit::BuildImperialVolumeSplit(double fluidOunces, Context * context) return BuildSplit(fluidOunces, units, factors, numberOfUnits, context); } +Expression Unit::StandardSpeedConversion(Expression e, Preferences::UnitFormat format, Context * context) { + return UnitConvert::Builder(e.clone(), Multiplication::Builder( + format == Preferences::UnitFormat::Metric ? Unit::Kilometer() : Unit::Mile(), + Power::Builder( + Unit::Hour(), + Rational::Builder(-1) + ) + ) + ); +} + +Expression Unit::StandardDistanceConversion(Expression e, Preferences::UnitFormat format, Context * context) { + if (format == Preferences::UnitFormat::Metric) { + return UnitConvert::Builder(e.clone(), Unit::Meter()); + } + assert(format == Preferences::UnitFormat::Imperial); + double rawValue = ConvertedValueInUnit(e, Unit::Inch(), context); + return BuildImperialDistanceSplit(rawValue, context); +} + +Expression Unit::StandardVolumeConversion(Expression e, Preferences::UnitFormat format, Context * context) { + if (format == Preferences::UnitFormat::Metric) { + return UnitConvert::Builder(e.clone(), Unit::Liter()); + } + assert(format == Preferences::UnitFormat::Imperial); + double rawValue = ConvertedValueInUnit(e, Unit::FluidOunce(), context); + return BuildImperialVolumeSplit(rawValue, context); +} + +Expression Unit::StandardMassConversion(Expression e, Preferences::UnitFormat format, Context * context) { + if (format == Preferences::UnitFormat::Metric) { + return UnitConvert::Builder(e.clone(), Unit::Gram()); + } + assert(format == Preferences::UnitFormat::Imperial); + double rawValue = ConvertedValueInUnit(e, Unit::Ounce(), context); + return BuildImperialMassSplit(rawValue, context); +} + +Expression Unit::StandardSurfaceConversion(Expression e, Preferences::UnitFormat format, Context * context) { + if (format == Preferences::UnitFormat::Metric) { + return UnitConvert::Builder(e.clone(), Unit::Hectare()); + } + assert(format == Preferences::UnitFormat::Imperial); + return UnitConvert::Builder(e.clone(), Unit::Acre()); +} + template Evaluation UnitNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const; template Evaluation UnitNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;