mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[poincare/unit] Split for several dimensions
A split (such as _h+_min+_s) can now be generated for distances, volumes and masses using imperial units. Change-Id: Ib3ad63614979eddd02fbe0e99f16cf09dcf7c1fc
This commit is contained in:
committed by
Émilie Feral
parent
4d9f3aae97
commit
9f40e45b20
@@ -505,11 +505,28 @@ public:
|
||||
static const Representative constexpr * MonthRepresentative = &TimeRepresentatives[5];
|
||||
static const Representative constexpr * YearRepresentative = &TimeRepresentatives[6];
|
||||
static const Representative constexpr * MeterRepresentative = &DistanceRepresentatives[0];
|
||||
static_assert(sizeof(DistanceRepresentatives)/sizeof(Representative) == 8, "The Unit::MileRepresentative et al. might require to be fixed if the DistanceRepresentatives table was changed.");
|
||||
static const Representative constexpr * InchRepresentative = &DistanceRepresentatives[4];
|
||||
static const Representative constexpr * FootRepresentative = &DistanceRepresentatives[5];
|
||||
static const Representative constexpr * YardRepresentative = &DistanceRepresentatives[6];
|
||||
static const Representative constexpr * MileRepresentative = &DistanceRepresentatives[7];
|
||||
static const Representative constexpr * KilogramRepresentative = &MassRepresentatives[0];
|
||||
static const Representative constexpr * GramRepresentative = &MassRepresentatives[1];
|
||||
static_assert(sizeof(MassRepresentatives)/sizeof(Representative) == 7, "The Unit::OunceRepresentative et al. might require to be fixed if the MassRepresentatives table was changed.");
|
||||
static const Representative constexpr * OunceRepresentative = &MassRepresentatives[4];
|
||||
static const Representative constexpr * PoundRepresentative = &MassRepresentatives[5];
|
||||
static const Representative constexpr * LiterRepresentative = &VolumeRepresentatives[0];
|
||||
static_assert(sizeof(VolumeRepresentatives)/sizeof(Representative) == 8, "The Unit::FluidOunceRepresentative et al. might require to be fixed if the VolumeRepresentatives table was changed.");
|
||||
static const Representative constexpr * FluidOunceRepresentative = &VolumeRepresentatives[3];
|
||||
static const Representative constexpr * CupRepresentative = &VolumeRepresentatives[4];
|
||||
static const Representative constexpr * GallonRepresentative = &VolumeRepresentatives[7];
|
||||
static const Representative constexpr * WattRepresentative = &PowerRepresentatives[0];
|
||||
static_assert(sizeof(EnergyRepresentatives)/sizeof(Representative) == 2, "The Unit::ElectronVoltRepresentative might require to be fixed if the EnergyRepresentatives table was changed.");
|
||||
static const Representative constexpr * ElectronVoltRepresentative = &EnergyRepresentatives[1];
|
||||
static_assert(sizeof(SurfaceRepresentatives)/sizeof(Representative) == 2, "The Unit::HectareRepresentative et al. might require to be fixed if the VolumeRepresentatives table was changed.");
|
||||
static const Representative constexpr * HectareRepresentative = &SurfaceRepresentatives[0];
|
||||
static const Representative constexpr * AcreRepresentative = &SurfaceRepresentatives[1];
|
||||
|
||||
static constexpr const Dimension DimensionTable[] = {
|
||||
/* The current table is sorted from most to least simple units.
|
||||
* The order determines the behavior of simplification.
|
||||
@@ -821,6 +838,7 @@ public:
|
||||
static const Dimension constexpr * MassDimension = &DimensionTable[2];
|
||||
static const Dimension constexpr * EnergyDimension = &DimensionTable[10];
|
||||
static const Dimension constexpr * PowerDimension = &DimensionTable[11];
|
||||
static const Dimension constexpr * SurfaceDimension = &DimensionTable[sizeof(DimensionTable)/sizeof(Dimension)-2];
|
||||
static const Dimension constexpr * VolumeDimension = &DimensionTable[sizeof(DimensionTable)/sizeof(Dimension)-1];
|
||||
|
||||
static constexpr const Unit::Dimension * DimensionTableUpperBound =
|
||||
@@ -830,7 +848,12 @@ public:
|
||||
|
||||
Unit(const UnitNode * node) : Expression(node) {}
|
||||
static Unit Builder(const Dimension * dimension, const Representative * representative, const Prefix * prefix);
|
||||
static Unit Meter() { return Builder(DistanceDimension, MeterRepresentative, &EmptyPrefix); }
|
||||
static Unit Kilometer() { return Builder(DistanceDimension, MeterRepresentative, &KiloPrefix); }
|
||||
static Unit Inch() { return Builder(DistanceDimension, InchRepresentative, &EmptyPrefix); }
|
||||
static Unit Foot() { return Builder(DistanceDimension, FootRepresentative, &EmptyPrefix); }
|
||||
static Unit Yard() { return Builder(DistanceDimension, YardRepresentative, &EmptyPrefix); }
|
||||
static Unit Mile() { return Builder(DistanceDimension, MileRepresentative, &EmptyPrefix); }
|
||||
static Unit Second() { return Builder(TimeDimension, SecondRepresentative, &EmptyPrefix); }
|
||||
static Unit Minute() { return Builder(TimeDimension, MinuteRepresentative, &EmptyPrefix); }
|
||||
static Unit Hour() { return Builder(TimeDimension, HourRepresentative, &EmptyPrefix); }
|
||||
@@ -840,8 +863,19 @@ public:
|
||||
static Unit Liter() { return Builder(VolumeDimension, LiterRepresentative, &EmptyPrefix); }
|
||||
static Unit ElectronVolt() { return Builder(EnergyDimension, ElectronVoltRepresentative, &EmptyPrefix); }
|
||||
static Unit Watt() { return Builder(PowerDimension, WattRepresentative, &EmptyPrefix); }
|
||||
static Expression BuildSplit(double baseValue, const Unit * units, const double * conversionFactors, int numberOfUnits, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
|
||||
static Expression BuildTimeSplit(double seconds, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
|
||||
static Unit Gram() { return Builder(MassDimension, GramRepresentative, &EmptyPrefix); }
|
||||
static Unit Ounce() { return Builder(MassDimension, OunceRepresentative, &EmptyPrefix); }
|
||||
static Unit Pound() { return Builder(MassDimension, PoundRepresentative, &EmptyPrefix); }
|
||||
static Unit FluidOunce() { return Builder(VolumeDimension, FluidOunceRepresentative, &EmptyPrefix); }
|
||||
static Unit Cup() { return Builder(VolumeDimension, CupRepresentative, &EmptyPrefix); }
|
||||
static Unit Gallon() { return Builder(VolumeDimension, GallonRepresentative, &EmptyPrefix); }
|
||||
static Unit Hectare() { return Builder(SurfaceDimension, HectareRepresentative, &EmptyPrefix); }
|
||||
static Unit Acre() { return Builder(SurfaceDimension, AcreRepresentative, &EmptyPrefix); }
|
||||
static Expression BuildSplit(double baseValue, const Unit * units, const double * conversionFactors, int numberOfUnits, Context * context);
|
||||
static Expression BuildTimeSplit(double seconds, Context * context);
|
||||
static Expression BuildImperialDistanceSplit(double inches, Context * context);
|
||||
static Expression BuildImperialMassSplit(double ounces, Context * context);
|
||||
static Expression BuildImperialVolumeSplit(double fluidOunces, Context * context);
|
||||
|
||||
static bool IsSI(Expression & e);
|
||||
static bool IsSISpeed(Expression & e);
|
||||
@@ -866,6 +900,12 @@ private:
|
||||
static constexpr double DaysPerYear = 365.25;
|
||||
static constexpr double MonthPerYear = 12.0;
|
||||
static constexpr double DaysPerMonth = DaysPerYear/MonthPerYear;
|
||||
static constexpr double InchesPerFoot = 12.;
|
||||
static constexpr double FeetPerYard = 3.;
|
||||
static constexpr double YardsPerMile = 1760.;
|
||||
static constexpr double OuncesPerPound = 16.;
|
||||
static constexpr double FluidOuncesPerCup = 8.;
|
||||
static constexpr double CupsPerGallon = 16.;
|
||||
UnitNode * node() const { return static_cast<UnitNode *>(Expression::node()); }
|
||||
bool isSI() const;
|
||||
static void ChooseBestMultipleForValue(Expression * units, double * value, bool tuneRepresentative, ExpressionNode::ReductionContext reductionContext);
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
#include <poincare/float.h>
|
||||
#include <poincare/ieee754.h>
|
||||
#include <poincare/infinity.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/multiplication.h>
|
||||
#include <poincare/power.h>
|
||||
#include <poincare/rational.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/unit_convert.h>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
@@ -514,7 +515,7 @@ bool Unit::IsSITime(Expression & e) {
|
||||
return e.type() == ExpressionNode::Type::Unit && static_cast<Unit &>(e).isSecond();
|
||||
}
|
||||
|
||||
Expression Unit::BuildSplit(double baseValue, Unit const * units, double const * conversionFactors, const int numberOfUnits, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit 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>()) {
|
||||
return Multiplication::Builder(Number::FloatNumber(baseValue), units[numberOfUnits-1]);
|
||||
@@ -545,16 +546,37 @@ Expression Unit::BuildSplit(double baseValue, Unit const * units, double const *
|
||||
}
|
||||
}
|
||||
|
||||
ExpressionNode::ReductionContext reductionContext(context, complexFormat, angleUnit, ExpressionNode::ReductionTarget::User, ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, ExpressionNode::UnitConversion::None);
|
||||
ExpressionNode::ReductionContext reductionContext(context, Preferences::ComplexFormat::Real, Preferences::AngleUnit::Degree, ExpressionNode::ReductionTarget::User, ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, ExpressionNode::UnitConversion::None);
|
||||
// Beautify the addition into an subtraction if necessary
|
||||
return a.squashUnaryHierarchyInPlace().shallowBeautify(reductionContext);
|
||||
}
|
||||
|
||||
Expression Unit::BuildTimeSplit(double seconds, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) {
|
||||
Expression Unit::BuildTimeSplit(double seconds, Context * context) {
|
||||
constexpr static int numberOfTimeUnits = 6;
|
||||
Unit units[numberOfTimeUnits] = {Unit::Year(), Unit::Month(), Unit::Day(), Unit::Hour(), Unit::Minute(), Unit::Second()};
|
||||
constexpr static double timeFactors[numberOfTimeUnits] = {MonthPerYear*DaysPerMonth*HoursPerDay*MinutesPerHour*SecondsPerMinute, DaysPerMonth*HoursPerDay*MinutesPerHour*SecondsPerMinute, HoursPerDay*MinutesPerHour*SecondsPerMinute, MinutesPerHour*SecondsPerMinute, SecondsPerMinute, 1.0};
|
||||
return BuildSplit(seconds, units, timeFactors, numberOfTimeUnits, context, complexFormat, angleUnit);
|
||||
return BuildSplit(seconds, units, timeFactors, numberOfTimeUnits, context);
|
||||
}
|
||||
|
||||
Expression Unit::BuildImperialDistanceSplit(double inches, Context * context) {
|
||||
constexpr static int numberOfUnits = 4;
|
||||
Unit units[numberOfUnits] = {Unit::Mile(), Unit::Yard(), Unit::Foot(), Unit::Inch()};
|
||||
constexpr static double factors[numberOfUnits] = {InchesPerFoot*FeetPerYard*YardsPerMile, InchesPerFoot*FeetPerYard, InchesPerFoot, 1.};
|
||||
return BuildSplit(inches, units, factors, numberOfUnits, context);
|
||||
}
|
||||
|
||||
Expression Unit::BuildImperialMassSplit(double ounces, Context * context) {
|
||||
constexpr static int numberOfUnits = 2;
|
||||
Unit units[numberOfUnits] = {Unit::Pound(), Unit::Ounce()};
|
||||
constexpr static double factors[numberOfUnits] = {OuncesPerPound, 1.};
|
||||
return BuildSplit(ounces, units, factors, numberOfUnits, context);
|
||||
}
|
||||
|
||||
Expression Unit::BuildImperialVolumeSplit(double fluidOunces, Context * context) {
|
||||
constexpr static int numberOfUnits = 3;
|
||||
Unit units[numberOfUnits] = {Unit::Gallon(), Unit::Cup(), Unit::FluidOunce()};
|
||||
constexpr static double factors[numberOfUnits] = {FluidOuncesPerCup*CupsPerGallon, FluidOuncesPerCup, 1.};
|
||||
return BuildSplit(fluidOunces, units, factors, numberOfUnits, context);
|
||||
}
|
||||
|
||||
template Evaluation<float> UnitNode::templatedApproximate<float>(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const;
|
||||
|
||||
Reference in New Issue
Block a user