diff --git a/poincare/include/poincare/decimal.h b/poincare/include/poincare/decimal.h index e92d5f4e6..1f08f6554 100644 --- a/poincare/include/poincare/decimal.h +++ b/poincare/include/poincare/decimal.h @@ -86,7 +86,7 @@ class Decimal final : public Number { friend class Number; friend class DecimalNode; public: - static int Exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength); + static int Exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentIsNegative = false); Decimal(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, int exponent); Decimal(DecimalNode * node) : Number(node) {} Decimal(Integer m, int e); diff --git a/poincare/include/poincare/number.h b/poincare/include/poincare/number.h index 3199ac149..999a703fc 100644 --- a/poincare/include/poincare/number.h +++ b/poincare/include/poincare/number.h @@ -27,7 +27,8 @@ class Number : public Expression { public: Number(const NumberNode * node) : Expression(node) {} /* Return either a Rational, a Decimal or an Infinity. */ - static Number ParseDigits(const char * digits, size_t length); + static Number ParseDigits(const char * digits, size_t length); // TODO: remove me when homemade parser is ready + static Number ParseNumber(const char * integralPart, size_t integralLength, const char * decimalPart, size_t decimalLenght, bool exponentIsNegative, const char * exponentPart, size_t exponentLength); /* Return either a Decimal or an Infinity or an Undefined. */ template static Number DecimalNumber(T f); /* Return either a Float or an Infinity or an Undefined */ diff --git a/poincare/src/decimal.cpp b/poincare/src/decimal.cpp index 896c7b922..e8ed7ef85 100644 --- a/poincare/src/decimal.cpp +++ b/poincare/src/decimal.cpp @@ -220,8 +220,7 @@ template T DecimalNode::templatedApproximate() const { return f*std::pow((T)10.0, (T)(m_exponent-numberOfDigits+1)); } -int Decimal::Exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength) { - bool exponentNegative = false; +int Decimal::Exponent(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative) { if (exponentLength > 0 && exponent[0] == '-') { exponent++; exponentNegative = true; diff --git a/poincare/src/number.cpp b/poincare/src/number.cpp index 5fafca02a..df38e7f93 100644 --- a/poincare/src/number.cpp +++ b/poincare/src/number.cpp @@ -80,6 +80,32 @@ Number Number::ParseDigits(const char * digits, size_t length) { return Decimal(integral, integralLength, fractional, fractionalLength, exp); } +Number Number::ParseNumber(const char * integralPart, size_t integralLength, const char * decimalPart, size_t decimalLenght, bool exponentIsNegative, const char * exponentPart, size_t exponentLength) { + // Integer + if (exponentLength == 0 && decimalLenght == 0) { + Integer i(integralPart, integralLength, false); + if (!i.isInfinity()) { + return Rational(i); + } + } + int exp; + // Avoid overflowing int + if (exponentLength < Decimal::k_maxExponentLength) { + exp = Decimal::Exponent(integralPart, integralLength, decimalPart, decimalLenght, exponentPart, exponentLength, exponentIsNegative); + } else { + exp = exponentIsNegative ? -1 : 1; + } + // Avoid Decimal with exponent > k_maxExponentLength + if (exponentLength >= Decimal::k_maxExponentLength || exp > Decimal::k_maxExponent || exp < -Decimal::k_maxExponent) { + if (exp < 0) { + return Decimal(0.0); + } else { + return Infinity(false); + } + } + return Decimal(integralPart, integralLength, decimalPart, decimalLenght, exp); +} + template Number Number::DecimalNumber(T f) { if (std::isnan(f)) {