mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[poincare] Unit: ensure one unique instance of each prefix
This commit is contained in:
@@ -38,7 +38,6 @@ public:
|
||||
m_symbol(symbol),
|
||||
m_exponent(exponent)
|
||||
{}
|
||||
inline bool operator==(const Prefix& p) const { return m_exponent == p.m_exponent && strcmp(m_symbol, p.m_symbol) == 0; }
|
||||
const char * symbol() const { return m_symbol; }
|
||||
int8_t exponent() const { return m_exponent; }
|
||||
int serialize(char * buffer, int bufferSize) const;
|
||||
@@ -57,19 +56,19 @@ public:
|
||||
Yes
|
||||
};
|
||||
template <size_t N>
|
||||
constexpr Representative(const char * rootSymbol, const char * definition, const Prefixable prefixable, const Prefix (&outputPrefixes)[N]) :
|
||||
constexpr Representative(const char * rootSymbol, const char * definition, const Prefixable prefixable, const Prefix * const (&outputPrefixes)[N]) :
|
||||
m_rootSymbol(rootSymbol),
|
||||
m_definition(definition),
|
||||
m_prefixable(prefixable),
|
||||
m_outputPrefixes(outputPrefixes),
|
||||
m_outputPrefixesUpperBound(outputPrefixes + N)
|
||||
m_outputPrefixesLength(N)
|
||||
{
|
||||
}
|
||||
const char * rootSymbol() const { return m_rootSymbol; }
|
||||
const char * definition() const { return m_definition; }
|
||||
bool isPrefixable() const { return m_prefixable == Prefixable::Yes; }
|
||||
const Prefix * outputPrefixes() const { return m_outputPrefixes; }
|
||||
const Prefix * outputPrefixesUpperBound() const { return m_outputPrefixesUpperBound; }
|
||||
const Prefix * const * outputPrefixes() const { return m_outputPrefixes; }
|
||||
size_t outputPrefixesLength() const { return m_outputPrefixesLength; }
|
||||
bool canParse(const char * symbol, size_t length,
|
||||
const Prefix * * prefix) const;
|
||||
int serialize(char * buffer, int bufferSize, const Prefix * prefix) const;
|
||||
@@ -78,8 +77,8 @@ public:
|
||||
const char * m_rootSymbol;
|
||||
const char * m_definition;
|
||||
const Prefixable m_prefixable;
|
||||
const Prefix * m_outputPrefixes;
|
||||
const Prefix * m_outputPrefixesUpperBound;
|
||||
const Prefix * const * m_outputPrefixes;
|
||||
const size_t m_outputPrefixesLength;
|
||||
};
|
||||
|
||||
class Dimension {
|
||||
@@ -203,58 +202,57 @@ public:
|
||||
MegaPrefix = Prefix("M", 6),
|
||||
GigaPrefix = Prefix("G", 9),
|
||||
TeraPrefix = Prefix("T", 12);
|
||||
static constexpr const Prefix
|
||||
NoPrefix[] = {
|
||||
EmptyPrefix
|
||||
},
|
||||
NegativeLongScalePrefixes[] = {
|
||||
PicoPrefix,
|
||||
NanoPrefix,
|
||||
MicroPrefix,
|
||||
MilliPrefix,
|
||||
EmptyPrefix,
|
||||
},
|
||||
PositiveLongScalePrefixes[] = {
|
||||
EmptyPrefix,
|
||||
KiloPrefix,
|
||||
MegaPrefix,
|
||||
GigaPrefix,
|
||||
TeraPrefix,
|
||||
},
|
||||
LongScalePrefixes[] = {
|
||||
PicoPrefix,
|
||||
NanoPrefix,
|
||||
MicroPrefix,
|
||||
MilliPrefix,
|
||||
EmptyPrefix,
|
||||
KiloPrefix,
|
||||
MegaPrefix,
|
||||
GigaPrefix,
|
||||
TeraPrefix,
|
||||
},
|
||||
NegativePrefixes[] = {
|
||||
PicoPrefix,
|
||||
NanoPrefix,
|
||||
MicroPrefix,
|
||||
MilliPrefix,
|
||||
CentiPrefix,
|
||||
DeciPrefix,
|
||||
EmptyPrefix,
|
||||
},
|
||||
AllPrefixes[] = {
|
||||
PicoPrefix,
|
||||
NanoPrefix,
|
||||
MicroPrefix,
|
||||
MilliPrefix,
|
||||
CentiPrefix,
|
||||
DeciPrefix,
|
||||
EmptyPrefix,
|
||||
DecaPrefix,
|
||||
HectoPrefix,
|
||||
KiloPrefix,
|
||||
MegaPrefix,
|
||||
GigaPrefix,
|
||||
TeraPrefix,
|
||||
static constexpr const Prefix * NoPrefix[] = {
|
||||
&EmptyPrefix
|
||||
};
|
||||
static constexpr const Prefix * NegativeLongScalePrefixes[] = {
|
||||
&PicoPrefix,
|
||||
&NanoPrefix,
|
||||
&MicroPrefix,
|
||||
&MilliPrefix,
|
||||
&EmptyPrefix,
|
||||
};
|
||||
static constexpr const Prefix * PositiveLongScalePrefixes[] = {
|
||||
&EmptyPrefix,
|
||||
&KiloPrefix,
|
||||
&MegaPrefix,
|
||||
&GigaPrefix,
|
||||
&TeraPrefix,
|
||||
};
|
||||
static constexpr const Prefix * LongScalePrefixes[] = {
|
||||
&PicoPrefix,
|
||||
&NanoPrefix,
|
||||
&MicroPrefix,
|
||||
&MilliPrefix,
|
||||
&EmptyPrefix,
|
||||
&KiloPrefix,
|
||||
&MegaPrefix,
|
||||
&GigaPrefix,
|
||||
&TeraPrefix,
|
||||
};
|
||||
static constexpr const Prefix * NegativePrefixes[] = {
|
||||
&PicoPrefix,
|
||||
&NanoPrefix,
|
||||
&MicroPrefix,
|
||||
&MilliPrefix,
|
||||
&CentiPrefix,
|
||||
&DeciPrefix,
|
||||
&EmptyPrefix,
|
||||
};
|
||||
static constexpr const Prefix * AllPrefixes[] = {
|
||||
&PicoPrefix,
|
||||
&NanoPrefix,
|
||||
&MicroPrefix,
|
||||
&MilliPrefix,
|
||||
&CentiPrefix,
|
||||
&DeciPrefix,
|
||||
&EmptyPrefix,
|
||||
&DecaPrefix,
|
||||
&HectoPrefix,
|
||||
&KiloPrefix,
|
||||
&MegaPrefix,
|
||||
&GigaPrefix,
|
||||
&TeraPrefix,
|
||||
};
|
||||
static constexpr size_t NumberOfBaseUnits = UnitNode::NumberOfBaseUnits;
|
||||
static constexpr const Representative
|
||||
|
||||
@@ -30,8 +30,9 @@ bool UnitNode::Representative::canParse(const char * symbol, size_t length,
|
||||
*prefix = &Unit::EmptyPrefix;
|
||||
return length == 0;
|
||||
}
|
||||
const Prefix * pre = Unit::AllPrefixes;
|
||||
while (pre < Unit::AllPrefixes + sizeof(Unit::AllPrefixes)/sizeof(Unit::Prefix)) {
|
||||
size_t numberOfPrefixes = sizeof(Unit::AllPrefixes)/sizeof(Unit::Prefix *);
|
||||
for (size_t i = 0; i < numberOfPrefixes; i++) {
|
||||
const Prefix * pre = Unit::AllPrefixes[i];
|
||||
const char * prefixSymbol = pre->symbol();
|
||||
if (strncmp(symbol, prefixSymbol, length) == 0 &&
|
||||
prefixSymbol[length] == 0)
|
||||
@@ -66,7 +67,8 @@ const UnitNode::Prefix * UnitNode::Representative::bestPrefixForValue(double & v
|
||||
* magnitude of 'value'.
|
||||
*/
|
||||
const int orderOfMagnitude = IEEE754<double>::exponentBase10(std::fabs(value));
|
||||
for (const Prefix * pre = m_outputPrefixes; pre < m_outputPrefixesUpperBound; pre++) {
|
||||
for (size_t i = 0; i < m_outputPrefixesLength; i++) {
|
||||
const Prefix * pre = m_outputPrefixes[i];
|
||||
unsigned int newDiff = absInt(orderOfMagnitude - pre->exponent() * exponent);
|
||||
if (newDiff < diff) {
|
||||
diff = newDiff;
|
||||
@@ -234,13 +236,12 @@ constexpr const Unit::Prefix
|
||||
Unit::MegaPrefix,
|
||||
Unit::GigaPrefix,
|
||||
Unit::TeraPrefix;
|
||||
constexpr const Unit::Prefix
|
||||
Unit::NoPrefix[],
|
||||
Unit::NegativeLongScalePrefixes[],
|
||||
Unit::PositiveLongScalePrefixes[],
|
||||
Unit::LongScalePrefixes[],
|
||||
Unit::NegativePrefixes[],
|
||||
Unit::AllPrefixes[];
|
||||
constexpr const Unit::Prefix * const Unit::NoPrefix[];
|
||||
constexpr const Unit::Prefix * const Unit::NegativeLongScalePrefixes[];
|
||||
constexpr const Unit::Prefix * const Unit::PositiveLongScalePrefixes[];
|
||||
constexpr const Unit::Prefix * const Unit::LongScalePrefixes[];
|
||||
constexpr const Unit::Prefix * const Unit::NegativePrefixes[];
|
||||
constexpr const Unit::Prefix * const Unit::AllPrefixes[];
|
||||
constexpr const Unit::Representative
|
||||
Unit::TimeRepresentatives[],
|
||||
Unit::DistanceRepresentatives[],
|
||||
@@ -392,16 +393,16 @@ Expression Unit::removeUnit(Expression * unit) {
|
||||
}
|
||||
|
||||
bool Unit::isSecond() const {
|
||||
return node()->dimension() == TimeDimension && node()->representative() == SecondRepresentative && *(node()->prefix()) == EmptyPrefix;
|
||||
return node()->dimension() == TimeDimension && node()->representative() == SecondRepresentative && node()->prefix() == &EmptyPrefix;
|
||||
}
|
||||
|
||||
bool Unit::isMeter() const {
|
||||
return node()->dimension() == DistanceDimension && node()->representative() == MeterRepresentative && *(node()->prefix()) == EmptyPrefix;
|
||||
return node()->dimension() == DistanceDimension && node()->representative() == MeterRepresentative && node()->prefix() == &EmptyPrefix;
|
||||
}
|
||||
|
||||
|
||||
bool Unit::isKilogram() const {
|
||||
return node()->dimension() == MassDimension && node()->representative() == KilogramRepresentative && *(node()->prefix()) == KiloPrefix;
|
||||
return node()->dimension() == MassDimension && node()->representative() == KilogramRepresentative && node()->prefix() == &KiloPrefix;
|
||||
}
|
||||
|
||||
bool Unit::IsISSpeed(Expression & e) {
|
||||
|
||||
@@ -294,7 +294,9 @@ QUIZ_CASE(poincare_parsing_units) {
|
||||
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()) {
|
||||
for (const Unit::Prefix * pre = Unit::AllPrefixes; pre < Unit::AllPrefixes + sizeof(Unit::AllPrefixes)/sizeof(Unit::Prefix); pre++) {
|
||||
size_t numberOfPrefixes = sizeof(Unit::AllPrefixes)/sizeof(Unit::Prefix *);
|
||||
for (size_t i = 0; i < numberOfPrefixes; i++) {
|
||||
const Unit::Prefix * pre = Unit::AllPrefixes[i];
|
||||
Unit::Builder(dim, 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");
|
||||
|
||||
@@ -245,7 +245,8 @@ QUIZ_CASE(poincare_simplification_units) {
|
||||
Unit::Builder(dim, rep, &Unit::EmptyPrefix).serialize(buffer+strlen("1×"), bufferSize-strlen("1×"), Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits);
|
||||
assert_parsed_expression_simplify_to(buffer, buffer);
|
||||
if (rep->isPrefixable()) {
|
||||
for (const Unit::Prefix * pre = rep->outputPrefixes(); pre < rep->outputPrefixesUpperBound(); pre++) {
|
||||
for (size_t i = 0; i < rep->outputPrefixesLength(); i++) {
|
||||
const Unit::Prefix * pre = rep->outputPrefixes()[i];
|
||||
Unit::Builder(dim, rep, pre).serialize(buffer+strlen("1×"), bufferSize-strlen("1×"), Preferences::PrintFloatMode::Decimal, Preferences::VeryShortNumberOfSignificantDigits);
|
||||
assert_parsed_expression_simplify_to(buffer, buffer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user