[poincare] Add Liter representation to classic unit conversion

This commit is contained in:
Émilie Feral
2020-04-22 09:54:04 +02:00
parent e2dc79c2d5
commit cc114900fa
6 changed files with 24 additions and 0 deletions

View File

@@ -118,6 +118,7 @@ public:
static int NumberOfBase10DigitsWithoutSign(const Integer & i);
bool isOne() const { return (numberOfDigits() == 1 && digit(0) == 1 && !m_negative); };
bool isTwo() const { return (numberOfDigits() == 1 && digit(0) == 2 && !m_negative); };
bool isThree() const { return (numberOfDigits() == 1 && digit(0) == 3 && !m_negative); };
bool isTen() const { return (numberOfDigits() == 1 && digit(0) == 10 && !m_negative); };
bool isMinusOne() const { return (numberOfDigits() == 1 && digit(0) == 1 && m_negative); };
bool isZero() const { return (numberOfDigits() == 0); };

View File

@@ -45,6 +45,7 @@ public:
// Basic test
bool isZero() const { return unsignedNumerator().isZero(); }
bool isOne() const { return signedNumerator().isOne() && isInteger(); }
bool isThree() const { return signedNumerator().isThree() && isInteger(); }
bool isMinusOne() const { return signedNumerator().isMinusOne() && isInteger(); }
bool isHalf() const { return signedNumerator().isOne() && denominator().isTwo(); }
bool isMinusHalf() const { return signedNumerator().isMinusOne() && denominator().isTwo(); }
@@ -89,6 +90,7 @@ public:
bool isNegative() const { return node()->isNegative(); }
bool isZero() const { return node()->isZero(); }
bool isOne() const { return node()->isOne(); }
bool isThree() const { return node()->isThree(); }
bool isMinusOne() const { return node()->isMinusOne(); }
bool isHalf() const { return node()->isHalf(); }
bool isMinusHalf() const { return node()->isMinusHalf(); }

View File

@@ -414,9 +414,11 @@ public:
Representative::Prefixable::Yes,
NegativePrefixes),
};
// TODO: find a better way to find defines these pointers
static const Representative constexpr * SecondRepresentative = &TimeRepresentatives[0];
static const Representative constexpr * HourRepresentative = &TimeRepresentatives[2];
static const Representative constexpr * MeterRepresentative = &DistanceRepresentatives[0];
static const Representative constexpr * LiterRepresentative = &VolumeRepresentatives[0];
static constexpr const Dimension DimensionTable[] = {
/* The current table is sorted from most to least simple units.
* The order determines the behavior of simplification.
@@ -721,8 +723,10 @@ public:
&EmptyPrefix
),
};
// TODO: find a better way to find defines these pointers
static const Dimension constexpr * TimeDimension = &DimensionTable[0] ;
static const Dimension constexpr * DistanceDimension = &DimensionTable[1];
static const Dimension constexpr * VolumeDimension = &DimensionTable[sizeof(DimensionTable)/sizeof(Dimension)-1];
static constexpr const Unit::Dimension * DimensionTableUpperBound =
DimensionTable + sizeof(DimensionTable)/sizeof(Dimension);
@@ -733,8 +737,10 @@ public:
static Unit Builder(const Dimension * dimension, const Representative * representative, const Prefix * prefix);
static Unit Kilometer() { return Builder(DistanceDimension, MeterRepresentative, &KiloPrefix); }
static Unit Hour() { return Builder(TimeDimension, HourRepresentative, &EmptyPrefix); }
static Unit Liter() { return Builder(VolumeDimension, LiterRepresentative, &EmptyPrefix); }
static bool IsISSpeed(Expression & e);
static bool IsISVolume(Expression & e);
bool isMeter() const;
bool isSecond() const;
@@ -743,6 +749,7 @@ public:
void chooseBestMultipleForValue(double & value, const int exponent, ExpressionNode::ReductionContext reductionContext);
static constexpr double MeterPerSecondToKilometerPerHourFactor = 60.0*60.0/1000.0;
static constexpr double CubicMeterToLiterFactor = 10.0*10.0*10.0;
private:
UnitNode * node() const { return static_cast<UnitNode *>(Expression::node()); }
Expression removeUnit(Expression * unit);

View File

@@ -475,6 +475,11 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu
)
);
}
if (Unit::IsISVolume(units)) {
value *= Unit::CubicMeterToLiterFactor;
units = Unit::Liter();
static_cast<Unit&>(units).chooseBestMultipleForValue(value, 1, reductionContext);
}
// TODO: what to do if no classic conversion?
}
if (result.isUninitialized()) {

View File

@@ -370,6 +370,13 @@ bool Unit::IsISSpeed(Expression & e) {
e.childAtIndex(1).childAtIndex(0).type() == ExpressionNode::Type::Unit && e.childAtIndex(1).childAtIndex(0).convert<Unit>().isSecond();
}
bool Unit::IsISVolume(Expression & e) {
// Form m^3
return e.type() == ExpressionNode::Type::Power &&
e.childAtIndex(0).type() == ExpressionNode::Type::Unit && e.childAtIndex(0).convert<Unit>().isMeter() &&
e.childAtIndex(1).type() == ExpressionNode::Type::Rational && e.childAtIndex(1).convert<const Rational>().isThree();
}
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;

View File

@@ -1285,6 +1285,8 @@ QUIZ_CASE(poincare_simplification_unit_conversion) {
assert_parsed_expression_simplify_to("1000000_cm", "1000000×_cm", User, Degree, Cartesian, ReplaceAllDefinedSymbolsWithDefinition, NoUnitConversion);
assert_parsed_expression_simplify_to("1000000_cm", "10000×_m", User, Degree, Cartesian, ReplaceAllDefinedSymbolsWithDefinition, InternationalSystemUnitConversion);
assert_parsed_expression_simplify_to("10_m/_h", "0.01×_km×_h^\x12-1\x13", User, Degree, Cartesian, ReplaceAllDefinedSymbolsWithDefinition, ClassicUnitConversion);
assert_parsed_expression_simplify_to("0.2_m^3", "200×_L", User, Degree, Cartesian, ReplaceAllDefinedSymbolsWithDefinition, ClassicUnitConversion);
assert_parsed_expression_simplify_to("0.000012_m^3", "1.2×_cL", User, Degree, Cartesian, ReplaceAllDefinedSymbolsWithDefinition, ClassicUnitConversion);
}
QUIZ_CASE(poincare_simplification_user_function) {