mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Add Unit::BuildTimeSplit and helpers for time units
This commit is contained in:
@@ -417,7 +417,11 @@ public:
|
||||
// TODO: find a better way to find defines these pointers
|
||||
static_assert(sizeof(TimeRepresentatives)/sizeof(Representative) == 7, "The Unit::SecondRepresentative, Unit::HourRepresentative might require to be fixed if the TimeRepresentatives table was changed.");
|
||||
static const Representative constexpr * SecondRepresentative = &TimeRepresentatives[0];
|
||||
static const Representative constexpr * MinuteRepresentative = &TimeRepresentatives[1];
|
||||
static const Representative constexpr * HourRepresentative = &TimeRepresentatives[2];
|
||||
static const Representative constexpr * DayRepresentative = &TimeRepresentatives[3];
|
||||
static const Representative constexpr * MonthRepresentative = &TimeRepresentatives[5];
|
||||
static const Representative constexpr * YearRepresentative = &TimeRepresentatives[6];
|
||||
static const Representative constexpr * MeterRepresentative = &DistanceRepresentatives[0];
|
||||
static const Representative constexpr * KilogramRepresentative = &MassRepresentatives[0];
|
||||
static const Representative constexpr * LiterRepresentative = &VolumeRepresentatives[0];
|
||||
@@ -742,13 +746,20 @@ public:
|
||||
Unit(const UnitNode * node) : Expression(node) {}
|
||||
static Unit Builder(const Dimension * dimension, const Representative * representative, const Prefix * prefix);
|
||||
static Unit Kilometer() { return Builder(DistanceDimension, MeterRepresentative, &KiloPrefix); }
|
||||
static Unit Second() { return Builder(TimeDimension, SecondRepresentative, &EmptyPrefix); }
|
||||
static Unit Minute() { return Builder(TimeDimension, MinuteRepresentative, &EmptyPrefix); }
|
||||
static Unit Hour() { return Builder(TimeDimension, HourRepresentative, &EmptyPrefix); }
|
||||
static Unit Day() { return Builder(TimeDimension, DayRepresentative, &EmptyPrefix); }
|
||||
static Unit Month() { return Builder(TimeDimension, MonthRepresentative, &EmptyPrefix); }
|
||||
static Unit Year() { return Builder(TimeDimension, YearRepresentative, &EmptyPrefix); }
|
||||
static Unit Liter() { return Builder(VolumeDimension, LiterRepresentative, &EmptyPrefix); }
|
||||
static Unit Watt() { return Builder(PowerDimension, WattRepresentative, &EmptyPrefix); }
|
||||
static Expression BuildTimeSplit(double seconds);
|
||||
|
||||
static bool IsISSpeed(Expression & e);
|
||||
static bool IsISVolume(Expression & e);
|
||||
static bool IsISEnergy(Expression & e);
|
||||
static bool IsISTime(Expression & e);
|
||||
bool isMeter() const;
|
||||
bool isSecond() const;
|
||||
bool isKilogram() const;
|
||||
|
||||
@@ -426,6 +426,34 @@ bool Unit::IsISEnergy(Expression & e) {
|
||||
e.childAtIndex(2).childAtIndex(1).type() == ExpressionNode::Type::Rational && e.childAtIndex(1).childAtIndex(1).convert<const Rational>().isMinusTwo();
|
||||
}
|
||||
|
||||
bool Unit::IsISTime(Expression & e) {
|
||||
return e.type() == ExpressionNode::Type::Unit && static_cast<Unit &>(e).isSecond();
|
||||
}
|
||||
|
||||
Expression Unit::BuildTimeSplit(double seconds) {
|
||||
assert(!std::isnan(seconds));
|
||||
if (std::isinf(seconds)) {
|
||||
return Multiplication::Builder(Infinity::Builder(seconds < 0.0), Unit::Second());
|
||||
}
|
||||
double remain = seconds;
|
||||
constexpr static int numberOfTimeUnits = 6;
|
||||
// This could be computed from the time representatives but we same time by using constexpr double
|
||||
constexpr static double timeFactors[numberOfTimeUnits] = {365.25*24.0*60.0*60.0, 365.25/12.0*24.0*60.0*60.0, 24.0*60.0*60.0, 60.0*60.0, 60.0, 1.0 };
|
||||
Unit units[numberOfTimeUnits] = {Unit::Year(), Unit::Month(), Unit::Day(), Unit::Hour(), Unit::Minute(), Unit::Second() };
|
||||
double valuesPerUnit[numberOfTimeUnits];
|
||||
Addition a = Addition::Builder();
|
||||
for (size_t i = 0; i < numberOfTimeUnits; i++) {
|
||||
valuesPerUnit[i] = std::floor(remain/timeFactors[i]);
|
||||
remain -= valuesPerUnit[i]*timeFactors[i];
|
||||
if (std::fabs(remain) < Expression::Epsilon<double>()) {
|
||||
break;
|
||||
}
|
||||
Multiplication m = Multiplication::Builder(Float<double>::Builder(valuesPerUnit[i]), units[i]);
|
||||
a.addChildAtIndexInPlace(m, a.numberOfChildren(), a.numberOfChildren());
|
||||
}
|
||||
return a.squashUnaryHierarchyInPlace();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user