[poincare/unit] Standard unit methods

Added methods to return the standard format for each dimension,
depending on the chosen unit system.

Change-Id: I3591a806beca315674cc09093b57e8753db5db6a
This commit is contained in:
Gabriel Ozouf
2020-07-21 11:56:50 +02:00
committed by Émilie Feral
parent 9f40e45b20
commit 3ff25fb5c1
2 changed files with 62 additions and 0 deletions

View File

@@ -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);

View File

@@ -515,6 +515,15 @@ bool Unit::IsSITime(Expression & e) {
return e.type() == ExpressionNode::Type::Unit && static_cast<Unit &>(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<double>(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<double>()) {
@@ -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<float> UnitNode::templatedApproximate<float>(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
template Evaluation<double> UnitNode::templatedApproximate<double>(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;