[poincare] Make code more object oriented

Turn ExponentsOfBaseUnits function into a static method of the
Unit::Dimension::Vector class
This commit is contained in:
Ruben Dashyan
2020-02-20 10:26:15 +01:00
committed by Émilie Feral
parent b6d07cbd90
commit 67241bb564
4 changed files with 39 additions and 37 deletions

View File

@@ -117,6 +117,7 @@ class Expression : public TreeHandle {
friend class NAryExpressionNode;
friend class StoreNode;
friend class SymbolNode;
friend class UnitNode;
public:
static bool IsExpression() { return true; }

View File

@@ -90,6 +90,7 @@ public:
T norm;
};
Metrics metrics() const;
static Vector FromBaseUnits(const Expression baseUnits);
const T coefficientAtIndex(size_t i) const {
assert(i < NumberOfBaseUnits);
return *(reinterpret_cast<const T*>(this) + i);
@@ -512,8 +513,6 @@ public:
static bool CanParse(const char * symbol, size_t length,
const Dimension * * dimension, const Representative * * representative, const Prefix * * prefix);
const Dimension * dimension() const { return static_cast<const UnitNode *>(node())->dimension(); }
Unit(const UnitNode * node) : Expression(node) {}
static Unit Builder(const Dimension * dimension, const Representative * representative, const Prefix * prefix);
Expression getUnit() const { return clone(); }

View File

@@ -302,39 +302,6 @@ Expression Multiplication::shallowReduce(ExpressionNode::ReductionContext reduct
return privateShallowReduce(reductionContext, true, true);
}
static Unit::Dimension::Vector<Integer> ExponentsOfBaseUnits(const Expression units) {
Unit::Dimension::Vector<Integer> exponents;
// Make sure the provided Expression is a Multiplication
Expression u = units;
if (u.type() == ExpressionNode::Type::Unit || u.type() == ExpressionNode::Type::Power) {
u = Multiplication::Builder(u.clone());
}
const int numberOfChildren = u.numberOfChildren();
for (int i = 0; i < numberOfChildren; i++) {
Expression factor = u.childAtIndex(i);
// Get the unit's exponent
Integer exponent(1);
if (factor.type() == ExpressionNode::Type::Power) {
Expression exp = factor.childAtIndex(1);
assert(exp.type() == ExpressionNode::Type::Rational && static_cast<Rational &>(exp).isInteger());
exponent = static_cast<Rational &>(exp).signedIntegerNumerator();
factor = factor.childAtIndex(0);
}
// The leading factors may not be of Unit type
if (factor.type() != ExpressionNode::Type::Unit) {
continue;
}
// Fill the exponents array with the unit's exponent
const int indexInTable = static_cast<Unit &>(factor).dimension() - Unit::DimensionTable;
assert(0 <= indexInTable && indexInTable < Unit::NumberOfBaseUnits);
exponents.setCoefficientAtIndex(indexInTable, exponent);
}
return exponents;
}
static bool CanSimplifyUnitProduct(
const Unit::Dimension::Vector<Integer> &unitsExponents, const Unit::Dimension::Vector<Integer> &entryUnitExponents, const Integer entryUnitNorm, const Expression entryUnit,
Integer (*operationOnExponents)(const Integer & unitsExponent, const Integer & entryUnitExponent),
@@ -391,7 +358,7 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu
* - Repeat those steps until no more simplification is possible.
*/
Multiplication unitsAccu = Multiplication::Builder();
Unit::Dimension::Vector<Integer> unitsExponents = ExponentsOfBaseUnits(units);
Unit::Dimension::Vector<Integer> unitsExponents = Unit::Dimension::Vector<Integer>::FromBaseUnits(units);
Unit::Dimension::Vector<Integer>::Metrics unitsMetrics = unitsExponents.metrics();
Unit::Dimension::Vector<Integer> bestRemainderExponents;
while (unitsMetrics.supportSize > 1) {
@@ -400,7 +367,7 @@ Expression Multiplication::shallowBeautify(ExpressionNode::ReductionContext redu
Unit::Dimension::Vector<Integer>::Metrics bestRemainderMetrics = {.supportSize = unitsMetrics.supportSize - 1, .norm = unitsMetrics.norm};
for (const Unit::Dimension * dim = Unit::DimensionTable + Unit::NumberOfBaseUnits; dim < Unit::DimensionTableUpperBound; dim++) {
Unit entryUnit = Unit::Builder(dim, dim->stdRepresentative(), dim->stdRepresentativePrefix());
Unit::Dimension::Vector<Integer> entryUnitExponents = ExponentsOfBaseUnits(entryUnit.clone().shallowReduce(reductionContext));
Unit::Dimension::Vector<Integer> entryUnitExponents = Unit::Dimension::Vector<Integer>::FromBaseUnits(entryUnit.clone().shallowReduce(reductionContext));
Integer entryUnitNorm = entryUnitExponents.metrics().norm;
CanSimplifyUnitProduct(
unitsExponents, entryUnitExponents, entryUnitNorm, entryUnit,

View File

@@ -91,6 +91,41 @@ Unit::Dimension::Vector<Integer>::Metrics UnitNode::Dimension::Vector<Integer>::
return {.supportSize = supportSize, .norm = norm};
}
template<>
Unit::Dimension::Vector<Integer> UnitNode::Dimension::Vector<Integer>::FromBaseUnits(const Expression baseUnits) {
Vector<Integer> vector;
// Make sure the provided Expression is a Multiplication
Expression u = baseUnits;
if (u.type() == ExpressionNode::Type::Unit || u.type() == ExpressionNode::Type::Power) {
u = Multiplication::Builder(u.clone());
}
const int numberOfChildren = u.numberOfChildren();
for (int i = 0; i < numberOfChildren; i++) {
Expression factor = u.childAtIndex(i);
// Get the unit's exponent
Integer exponent(1);
if (factor.type() == ExpressionNode::Type::Power) {
Expression exp = factor.childAtIndex(1);
assert(exp.type() == ExpressionNode::Type::Rational && static_cast<Rational &>(exp).isInteger());
exponent = static_cast<Rational &>(exp).signedIntegerNumerator();
factor = factor.childAtIndex(0);
}
// FIXME Remove this once this case may not occur anymore
// The leading factors may not be of Unit type
if (factor.type() != ExpressionNode::Type::Unit) {
continue;
}
// Fill the vector with the unit's exponent
const ptrdiff_t indexInTable = static_cast<UnitNode *>(factor.node())->dimension() - Unit::DimensionTable;
assert(0 <= indexInTable && indexInTable < NumberOfBaseUnits);
vector.setCoefficientAtIndex(indexInTable, exponent);
}
return vector;
}
bool UnitNode::Dimension::canParse(const char * symbol, size_t length,
const Representative * * representative, const Prefix * * prefix) const
{