diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index ccdb354e1..7449cd8bd 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -52,7 +52,7 @@ public: Integer& operator=(const Integer& other); // C++11 copy assignment operator // Getters - const native_uint_t * digits() const { return m_digits; } + const native_uint_t * digits() const { return usesImmediateDigit() ? &m_digit : m_digits; } size_t numberOfDigits() const { return m_numberOfDigits; } // Serialization @@ -66,7 +66,7 @@ public: // Sign bool isNegative() const { return m_negative; } - void setNegative(bool negative) { if (m_numberOfDigits > 0) { m_negative = negative; } } + void setNegative(bool negative) { m_negative = m_numberOfDigits > 0 ? negative : false; } // Properties static int NumberOfBase10DigitsWithoutSign(const Integer & i); @@ -135,17 +135,21 @@ private: if (i >= numberOfHalfDigits()) { return 0; } - return ((half_native_uint_t *)m_digits)[i]; + return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)m_digits)[i]); } + bool usesImmediateDigit() const { return m_numberOfDigits == 1; } native_uint_t digit(int i) const { assert(i >= 0 && i < m_numberOfDigits); - return m_digits[i]; + return (usesImmediateDigit() ? m_digit : m_digits[i]); } bool m_negative; size_t m_numberOfDigits; // In base native_uint_t - native_uint_t * m_digits; + union { + native_uint_t * m_digits; // Little-endian + native_uint_t m_digit; + }; }; struct IntegerDivision { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 5809cd2cb..54ef043e5 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -37,10 +37,10 @@ static inline int8_t sign(bool negative) { #if POINCARE_INTEGER_LOG void Integer::log() const { - double d = 0; + double d = 0.0; double base = 1.0; for (int i = 0; i < m_numberOfDigits; i++) { - d += m_digits[i]*base; + d += digit(i)*base; base *= std::pow(2.0,32.0); } std::cout << "Integer: " << d << std::endl; @@ -83,10 +83,15 @@ Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative, m_numberOfDigits(!enableOverflow && numberOfDigits > Integer::k_maxNumberOfDigits ? k_maxNumberOfDigits+1 : numberOfDigits), m_digits(digits) { - if ((m_numberOfDigits == 0 || (!enableOverflow && m_numberOfDigits > k_maxNumberOfDigitsBase10)) && m_digits) { + if ((m_numberOfDigits <= 1|| (!enableOverflow && m_numberOfDigits > k_maxNumberOfDigitsBase10)) && m_digits) { freeDigits(m_digits); - m_digits = nullptr; + if (m_numberOfDigits == 1) { + m_digit = digits[0]; + } else { + m_digits = nullptr; + } } + m_negative = m_numberOfDigits == 0 ? false : m_negative; } Integer::Integer(native_int_t i) { @@ -97,9 +102,7 @@ Integer::Integer(native_int_t i) { return; } m_numberOfDigits = 1; - native_uint_t * digits = allocDigits(1); - digits[0] = i > 0 ? i : -i; - m_digits = digits; + m_digit = i > 0 ? i : -i; m_negative = i < 0; } @@ -115,12 +118,14 @@ Integer::Integer(double_native_int_t i) { native_uint_t leastSignificantDigit = *d; native_uint_t mostSignificantDigit = *(d+1); m_numberOfDigits = (mostSignificantDigit == 0) ? 1 : 2; - native_uint_t * digits = allocDigits(m_numberOfDigits); - digits[0] = leastSignificantDigit; - if (m_numberOfDigits > 1) { + if (m_numberOfDigits == 1) { + m_digit = leastSignificantDigit; + } else { + native_uint_t * digits = allocDigits(m_numberOfDigits); + digits[0] = leastSignificantDigit; digits[1] = mostSignificantDigit; + m_digits = digits; } - m_digits = digits; m_negative = i < 0; } @@ -145,7 +150,7 @@ Integer::Integer(const char * digits, size_t length, bool negative) : } void Integer::releaseDynamicIvars() { - if (m_digits) { + if (!usesImmediateDigit() && m_digits) { freeDigits(m_digits); } } @@ -156,7 +161,11 @@ Integer::~Integer() { Integer::Integer(Integer && other) { // Pilfer other's data - m_digits = other.m_digits; + if (other.usesImmediateDigit()) { + m_digit = other.m_digit; + } else { + m_digits = other.m_digits; + } m_numberOfDigits = other.m_numberOfDigits; m_negative = other.m_negative; @@ -168,11 +177,15 @@ Integer::Integer(Integer && other) { Integer::Integer(const Integer& other) { // Copy other's data - native_uint_t * digits = allocDigits(other.m_numberOfDigits); - for (int i=0; i> (32-pow); + digits[i] = digit(i) << pow | carry; + carry = pow == 0 ? 0 : digit(i) >> (32-pow); } digits[m_numberOfDigits] = carry; return Integer(digits, carry ? m_numberOfDigits + 1 : m_numberOfDigits, false, true); @@ -534,8 +555,8 @@ Integer Integer::divideByPowerOf2(uint8_t pow) const { native_uint_t * digits = allocDigits(m_numberOfDigits); native_uint_t carry = 0; for (int i = m_numberOfDigits - 1; i >= 0; i--) { - digits[i] = m_digits[i] >> pow | carry; - carry = pow == 0 ? 0 : m_digits[i] << (32-pow); + digits[i] = digit(i) >> pow | carry; + carry = pow == 0 ? 0 : digit(i) << (32-pow); } return Integer(digits, digits[m_numberOfDigits-1] > 0 ? m_numberOfDigits : m_numberOfDigits-1, false, true); } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index b0889a7f7..b6899fb93 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -78,7 +78,7 @@ Expression Opposite::shallowReduce(Context & context, Preferences::AngleUnit ang #if MATRIX_EXACT_REDUCING #endif result = Multiplication(Rational(-1), child); - return result.shallowReduce(context, angleUnit, futureParent); + return result.shallowReduce(context, angleUnit); } } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index 13b825368..7b23cda09 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -63,9 +63,9 @@ Expression Subtraction::shallowReduce(Context & context, Preferences::AngleUnit } Expression m = Multiplication(Rational(-1), childAtIndex(1)); Addition a = Addition(childAtIndex(0)); - m = m.shallowReduce(context, angleUnit, a); + m = m.shallowReduce(context, angleUnit); a.addChildAtIndexInPlace(m, a.numberOfChildren(), a.numberOfChildren()); - return a.shallowReduce(context, angleUnit, futureParent); + return a.shallowReduce(context, angleUnit); } } diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index 253333330..09d458d99 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -21,7 +21,7 @@ QUIZ_CASE(poincare_integer_constructor) { Integer nc(-12314); Integer d((int64_t)1234567891011121314); Integer nd((int64_t)(-1234567891011121314)); - Integer e = Integer::Overflow(); + Integer e = Integer::Overflow(false); assert_pool_size(initialPoolSize+9); } @@ -212,14 +212,6 @@ QUIZ_CASE(poincare_integer_factorial) { // Simplify -QUIZ_CASE(poincare_integer_simplify) { -/* assert_parsed_expression_simplify_to("1234", "1234"); - assert_parsed_expression_simplify_to("12342345698765345678909876545678907655678900987654", "12342345698765345678909876545678907655678900987654"); - assert_parsed_expression_simplify_to("12342345698765345678909876545678907655678900987654", "12342345698765345678909876545678907655678900987654"); - assert_parsed_expression_simplify_to(MaxIntegerString, MaxIntegerString); - //assert_parsed_expression_simplify_to(OverflowedIntegerString, "inf"); // parse as a Decimal and then simplify to Rational*/ -} - template void assert_integer_evals_to(const char * i, T result) { quiz_assert(Integer(i).approximate() == result); @@ -267,10 +259,16 @@ QUIZ_CASE(poincare_integer_evaluate) { //Serialize -QUIZ_CASE(poincare_integer_serialize) { - assert_parsed_expression_serialize_to(Integer(-2), "-2"); - assert_parsed_expression_serialize_to(Integer("2345678909876"), "2345678909876"); - assert_parsed_expression_serialize_to(Integer("-2345678909876"), "-2345678909876"); - assert_parsed_expression_serialize_to(MaxInteger(), MaxIntegerString); - assert_parsed_expression_serialize_to(OverflowedInteger(), "inf"); +static inline void assert_integer_serializes_to(const Integer i, const char * serialization) { + char buffer[500]; + i.serialize(buffer, 500); + quiz_assert(strcmp(buffer, serialization) == 0); +} + +QUIZ_CASE(poincare_integer_serialize) { + assert_integer_serializes_to(Integer(-2), "-2"); + assert_integer_serializes_to(Integer("2345678909876"), "2345678909876"); + assert_integer_serializes_to(Integer("-2345678909876"), "-2345678909876"); + assert_integer_serializes_to(MaxInteger(), MaxIntegerString); + assert_integer_serializes_to(OverflowedInteger(), "inf"); }