mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] Make code more object oriented
Turn ExponentsOfBaseUnits function into a static method of the Unit::Dimension::Vector class
This commit is contained in:
committed by
Émilie Feral
parent
b6d07cbd90
commit
67241bb564
@@ -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; }
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user