[poincare] Unit: implement IsIS

This commit is contained in:
Émilie Feral
2020-05-07 11:48:52 +02:00
parent 0f4eee2d71
commit 7b2d020128
3 changed files with 40 additions and 2 deletions

View File

@@ -766,6 +766,7 @@ public:
static Unit Watt() { return Builder(PowerDimension, WattRepresentative, &EmptyPrefix); }
static Expression BuildTimeSplit(double seconds, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
static bool IsIS(Expression & e);
static bool IsISSpeed(Expression & e);
static bool IsISVolume(Expression & e);
static bool IsISEnergy(Expression & e);
@@ -788,6 +789,7 @@ private:
static constexpr double MonthPerYear = 12.0;
static constexpr double DaysPerMonth = DaysPerYear/MonthPerYear;
UnitNode * node() const { return static_cast<UnitNode *>(Expression::node()); }
bool isIS() const;
static void ChooseBestMultipleForValue(Expression * units, double * value, bool tuneRepresentative, ExpressionNode::ReductionContext reductionContext);
void chooseBestMultipleForValue(double * value, const int exponent, bool tuneRepresentative, ExpressionNode::ReductionContext reductionContext);
Expression removeUnit(Expression * unit);

View File

@@ -408,6 +408,36 @@ bool Unit::isKilogram() const {
return node()->dimension() == MassDimension && node()->representative() == KilogramRepresentative && node()->prefix() == &KiloPrefix;
}
bool Unit::isIS() const {
UnitNode * unitNode = node();
const Dimension * dim = unitNode->dimension();
const Representative * rep = unitNode->representative();
return rep == dim->stdRepresentative() &&
rep->definition() == nullptr &&
unitNode->prefix() == dim->stdRepresentativePrefix();
}
bool Unit::IsIS(Expression & e) {
if (e.type() == ExpressionNode::Type::Multiplication) {
for (int i = 0; i < e.numberOfChildren(); i++) {
Expression child = e.childAtIndex(i);
assert(child.type() == ExpressionNode::Type::Power || child.type() == ExpressionNode::Type::Unit);
if (!IsIS(child)) {
return false;
}
}
return true;
}
if (e.type() == ExpressionNode::Type::Power) {
assert(e.childAtIndex(1).type() == ExpressionNode::Type::Rational && e.childAtIndex(1).convert<Rational>().isInteger());
Expression child = e.childAtIndex(0);
assert(child.type() == ExpressionNode::Type::Unit);
return IsIS(child);
}
assert(e.type() == ExpressionNode::Type::Unit);
return static_cast<Unit &>(e).isIS();
}
bool Unit::IsISSpeed(Expression & e) {
// Form m*s^-1
return e.type() == ExpressionNode::Type::Multiplication && e.numberOfChildren() == 2 &&

View File

@@ -400,7 +400,7 @@ void assert_seconds_split_to(double totalSeconds, const char * splittedTime, Con
Expression extract_unit(const char * expression) {
Shared::GlobalContext globalContext;
ExpressionNode::ReductionContext reductionContext = ExpressionNode::ReductionContext(&globalContext, Cartesian, Degree, User);
ExpressionNode::ReductionContext reductionContext = ExpressionNode::ReductionContext(&globalContext, Cartesian, Degree, User, ReplaceAllSymbolsWithUndefined, NoUnitConversion);
Expression e = parse_expression(expression, &globalContext, false).reduce(reductionContext);
Expression unit;
e.removeUnit(&unit);
@@ -428,5 +428,11 @@ QUIZ_CASE(poincare_expression_unit_helper) {
// 4. Energy
Expression kilogramMeter2PerSecond2 = extract_unit("_kg×_m^2×_s^-2");
quiz_assert(Unit::IsISEnergy(kilogramMeter2PerSecond2));
}
// 5. International System
quiz_assert(Unit::IsIS(kilogramMeter2PerSecond2));
quiz_assert(Unit::IsIS(meter3));
quiz_assert(Unit::IsIS(meterPerSecond));
Expression joule = extract_unit("_J");
quiz_assert(!Unit::IsIS(joule));
}