diff --git a/liba/include/stdint.h b/liba/include/stdint.h index f74c3ee01..73c095358 100644 --- a/liba/include/stdint.h +++ b/liba/include/stdint.h @@ -7,6 +7,7 @@ typedef unsigned long uint32_t; typedef unsigned long long uint64_t; typedef char int8_t; +typedef long int32_t; typedef long long int64_t; #endif diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 8c362509d..024618a18 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -20,7 +20,9 @@ class Integer : public Expression { // Arithmetic Integer operator+(const Integer &other) const; + Integer operator-(const Integer &other) const; Integer operator*(const Integer &other) const; + Integer operator/(const Integer &other) const; bool operator<(const Integer &other) const; bool operator==(const Integer &other) const; @@ -31,6 +33,9 @@ class Integer : public Expression { virtual ExpressionLayout * createLayout(); virtual float approximate(); private: + int8_t ucmp(const Integer &other) const; // -1, 0, or 1 + Integer usum(const Integer &other, bool subtract, bool output_negative) const; + Integer add(const Integer &other, bool inverse_other_negative) const; /* WARNING: This constructor takes ownership of the bits array and will free it! */ Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative); uint16_t m_numberOfDigits; // In base native_uint_max diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 033b8be88..0529da429 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -99,40 +99,41 @@ Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative) m_negative(negative) { } -// TODO: factor code with "==", they are very similar -bool Integer::operator<(const Integer &other) const { - if (m_negative && !other.m_negative) { - return true; - } else if (!m_negative && other.m_negative) { - return false; - } - if (m_numberOfDigits != other.m_numberOfDigits) { - return (m_numberOfDigits < other.m_numberOfDigits); +int8_t Integer::ucmp(const Integer &other) const { + if (m_numberOfDigits < other.m_numberOfDigits) { + return -1; + } else if (other.m_numberOfDigits < m_numberOfDigits) { + return 1; } for (uint16_t i = 0; i < m_numberOfDigits; i++) { // Digits are stored most-significant last native_uint_t digit = m_digits[m_numberOfDigits-i-1]; native_uint_t otherDigit = other.m_digits[m_numberOfDigits-i-1]; - if (digit != otherDigit) { - return (digit < otherDigit) != m_negative; + if (digit < otherDigit) { + return -1; + } else if (otherDigit < digit) { + return 1; } } - return false; + return 0; +} + +static inline int8_t sign(bool negative) { + return 1 - 2*(int8_t)negative; +} + +bool Integer::operator<(const Integer &other) const { + if (m_negative != other.m_negative) { + return m_negative; + } + return (sign(m_negative)*ucmp(other) < 0); } bool Integer::operator==(const Integer &other) const { - if (other.m_negative != m_negative) { + if (m_negative != other.m_negative) { return false; } - if (other.m_numberOfDigits != m_numberOfDigits) { - return false; - } - for (uint16_t i=0; iabs(other) : s = sign*udiff(this, other) + * 2/abs(other)>abs(this) : s = sign*udiff(other, this) + * sign? sign of the greater! */ + if (ucmp(other) >= 0) { + return usum(other, true, m_negative); + } else { + return other.usum(*this, true, other_negative); + } + } +} + Integer Integer::operator+(const Integer &other) const { - uint16_t sumSize = MAX(other.m_numberOfDigits,m_numberOfDigits)+1; - native_uint_t * digits = (native_uint_t *)malloc(sumSize*sizeof(native_uint_t)); - bool carry = 0; - for (uint16_t i = 0; i= m_numberOfDigits ? 0 : m_digits[i]); native_uint_t b = (i >= other.m_numberOfDigits ? 0 : other.m_digits[i]); - native_uint_t sum = a + b + carry; // TODO: Prove it cannot overflow - digits[i] = sum; - carry = ((a>sum)||(b>sum)); + native_uint_t result = (subtract ? a - b - carry : a + b + carry); + digits[i] = result; + carry = (subtract ? (aresult)||(b>result))); // There's been an underflow or overflow } - while (digits[sumSize-1] == 0) { - sumSize--; - /* At this point we may realloc m_digits to a smaller size. - * It might not be worth the trouble though : it won't happen very often - * and we're wasting a single native_uint_t. */ + while (digits[size-1] == 0) { + size--; + // We could realloc digits to a smaller size. Probably not worth the trouble. } - return Integer(digits, sumSize, false); + return Integer(digits, size, output_negative); } Integer Integer::operator*(const Integer &other) const { @@ -202,7 +232,56 @@ Integer Integer::operator*(const Integer &other) const { /* At this point we could realloc m_digits to a smaller size. */ } - return Integer(digits, productSize); + return Integer(digits, productSize, m_negative != other.m_negative); +} + +/* +Division::Division(const Integer &numerator, const Integer &denominator) : +m_quotient(Integer((native_uint_t)0)), +m_remainder(Integer((native_uint_t)0)) { + // FIXME: First, test if denominator is zero. + + if (numerator < denominator) { + m_quotient = Integer((native_uint_t)0); + m_remainder = numerator; + return; + } + + // Recursive case + *this = Division(numerator, denominator+denominator); + m_quotient = m_quotient + m_quotient; + if (!(m_remainder < denominator)) { + m_remainder = m_remainder - denominator; + m_quotient = m_quotient + 1; + } +} +*/ + + +Integer Integer::operator/(const Integer &other) const { + return Integer(2); + + /* We want to compute q so that this = q*other + remainder, with remainder + * smaller than other */ +/* + q' = 2*(x/(2*y)) + + q' = 2*(this/(2*other)) + */ + + /* Use recursive algorithm: + * Compute q' = 2 * (x/2y) + * Fact: q = q' or q'+1 + ***************************************/ +/* return q and r such that x = q*y + r + * + * this = x + * other =y + * q,r -> computed + * + * + * */ + } #if 0 diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index 9bb8a6e3f..cb7b5bdeb 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -29,6 +29,12 @@ QUIZ_CASE(poincare_integer_add) { assert(Integer("123456789123456789") + Integer(1) == Integer("123456789123456790")); } +QUIZ_CASE(poincare_integer_subtract) { + assert(Integer(123) - Integer(23) == Integer(100)); + assert(Integer("123456789123456789") - Integer("9999999999") == Integer("123456779123456790")); + assert(Integer(23) - Integer(100) == Integer(-77)); +} + QUIZ_CASE(poincare_integer_multiply) { assert(Integer(12) * Integer(34) == Integer(408)); assert(Integer(-12) * Integer(34) == Integer(-408));