[poincare/unit] Restructure Unit

1. Information about a unit's dimension now uses inheritance.
   _m is an instance of DistanceAlias, which is derived from Alias.
   A UnitNode now keeps a pointer to an Alias and one to a Prefix.
   All aliases are still defined as constexpr.
   This cleans up a lot of the code used namely for computing the
   additional outputs in Calculation.

2. Instead of being defined with a string, each unit is described by its
   ratio with the base SI unit (ex: _L is 0.001 instead of "0.001_m^3").
   This greatly speeds up the calculations using units, as the algorithm
   to find the best unit used to parse the definition.

Change-Id: I4d6ed6ad4cb967026a3f01a335aec270066e2b9f
This commit is contained in:
Gabriel Ozouf
2020-07-31 16:00:07 +02:00
committed by Émilie Feral
parent e48e826536
commit 52dcd8e749
10 changed files with 1341 additions and 1495 deletions

View File

@@ -286,20 +286,19 @@ QUIZ_CASE(poincare_parsing_matrices) {
QUIZ_CASE(poincare_parsing_units) {
// Units
for (const Unit::Dimension * dim = Unit::DimensionTable; dim < Unit::DimensionTableUpperBound; dim++) {
for (const Unit::Representative * rep = dim->stdRepresentative(); rep < dim->representativesUpperBound(); rep++) {
for (int i = 0; i < Unit::Representative::k_numberOfDimensions; i++) {
const Unit::Representative * dim = Unit::Representative::DefaultRepresentatives()[i];
for (int j = 0; j < dim->numberOfRepresentatives(); j++) {
const Unit::Representative * rep = dim->representativesOfSameDimension() + j;
static constexpr size_t bufferSize = 10;
char buffer[bufferSize];
Unit::Builder(dim, rep, &Unit::EmptyPrefix).serialize(buffer, bufferSize, Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits);
Unit::Builder(rep, Unit::Prefix::EmptyPrefix()).serialize(buffer, bufferSize, Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits);
Expression unit = parse_expression(buffer, nullptr, false);
quiz_assert_print_if_failure(unit.type() == ExpressionNode::Type::Unit, "Should be parsed as a Unit");
if (rep->isPrefixable()) {
/* ton is only prefixable by positive prefixes */
bool isTon = strcmp("t", rep->rootSymbol()) == 0;
size_t numberOfPrefixes = ((isTon) ? sizeof(Unit::PositiveLongScalePrefixes) : sizeof(Unit::AllPrefixes))/sizeof(Unit::Prefix *);
for (size_t i = 0; i < numberOfPrefixes; i++) {
const Unit::Prefix * pre = (isTon) ? Unit::PositiveLongScalePrefixes[i] : Unit::AllPrefixes[i];
Unit::Builder(dim, rep, pre).serialize(buffer, bufferSize, Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits);
if (rep->isInputPrefixable()) {
for (size_t i = 0; i < Unit::Prefix::k_numberOfPrefixes; i++) {
const Unit::Prefix * pre = Unit::Prefix::Prefixes();
Unit::Builder(rep, pre).serialize(buffer, bufferSize, Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits);
Expression unit = parse_expression(buffer, nullptr, false);
quiz_assert_print_if_failure(unit.type() == ExpressionNode::Type::Unit, "Should be parsed as a Unit");
}