From 7848bcc750429f51146d7b43aee9a0364ecaa602 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Mon, 14 Sep 2015 23:01:44 +0200 Subject: [PATCH] [Poincare] Don't count bits, count digits --- poincare/include/poincare/integer.h | 9 +-- poincare/src/integer.cpp | 96 ++++++++++++----------------- poincare/test/integer.cpp | 10 ++- 3 files changed, 52 insertions(+), 63 deletions(-) diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index a93d714d9..74545560b 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -10,7 +10,7 @@ typedef uint64_t double_native_uint_t; class Integer : public Expression { public: Integer(native_uint_t i); - Integer(char * string); + static Integer parseInteger(char * string); virtual void draw(); virtual Expression ** children(); @@ -24,9 +24,10 @@ class Integer : public Expression { private: static uint16_t arraySize(uint16_t bitSize); /* WARNING: This constructor takes ownership of the bits array and will free it! */ - Integer(native_uint_t * bits, uint16_t length); - uint16_t m_numberOfBits; - native_uint_t * m_bits; // LITTLE-ENDIAN + Integer(native_uint_t * digits, uint16_t numberOfDigits); +//#error BAD DESIGN: use "number_of_digits", which is arraySize(m_numberOfBits) + uint16_t m_numberOfDigits; // In base native_uint_max + native_uint_t * m_digits; // LITTLE-ENDIAN /* // TODO: Small-int optimization union { diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index bc67a81a4..0fa742b4a 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -10,10 +10,6 @@ #define INTEGER_IMMEDIATE_LIMIT 32 -uint16_t Integer::arraySize(uint16_t bitSize) { - return (bitSize-1)/(8*sizeof(native_uint_t))+1; -} - uint8_t log2(native_uint_t v) { assert(NATIVE_UINT_BIT_COUNT < 256); // Otherwise uint8_t isn't OK for (uint8_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 - bits[i] = sum; + digits[i] = sum; carry = ((a>sum)||(b>sum)); } - if (carry) { - bits[intArraySize] = 0x1; - } else { - sumSize = (intArraySize-1)*NATIVE_UINT_BIT_COUNT + log2(bits[intArraySize-1]); - /* At this point we may realloc m_bits to a smaller size in some cases. + 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. */ } - return Integer(bits, sumSize); + return Integer(digits, sumSize); } const Integer Integer::operator*(const Integer &other) const { - uint16_t productSize = other.m_numberOfBits + m_numberOfBits; - uint16_t intArraySize = arraySize(productSize); - native_uint_t * bits = (native_uint_t *)malloc(intArraySize*sizeof(native_uint_t)); - memset(bits, 0, intArraySize*sizeof(native_uint_t)); - - uint16_t myArraySize = arraySize(m_numberOfBits); - uint16_t otherArraySize = arraySize(other.m_numberOfBits); + uint16_t productSize = other.m_numberOfDigits + m_numberOfDigits; + native_uint_t * bits = (native_uint_t *)malloc(productSize*sizeof(native_uint_t)); + memset(bits, 0, productSize*sizeof(native_uint_t)); native_uint_t carry = 0; - for (uint16_t i=0; i>32; //FIXME: 32 is hardcoded here! } - m_bits[i+otherArraySize] = carry; + m_digits[i+other.m_numberOfDigits] = carry; } return Integer(bits, productSize); @@ -96,7 +83,7 @@ const Integer Integer::operator*(const Integer &other) const { /* char * Integer::bits() { - if (m_numberOfBits > INTEGER_IMMEDIATE_LIMIT) { + if (m_numberOfDigits > INTEGER_IMMEDIATE_LIMIT) { return m_dynamicBits; } else { return &m_staticBits; @@ -104,12 +91,12 @@ const Integer Integer::operator*(const Integer &other) const { } */ -Integer::Integer(native_uint_t * bits, uint16_t size) : - m_numberOfBits(size), - m_bits(bits) { +Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits) : + m_numberOfDigits(numberOfDigits), + m_digits(digits) { } -Integer::Integer(char * string) { +Integer Integer::parseInteger(char * string) { int base = 10; int stringLength = strlen(string); /* @@ -126,19 +113,12 @@ Integer::Integer(char * string) { } */ - /* How many bits do we need to store that number knowing that it requires at - * most K digits in base N? - * - * We know that 2^(num_bits-1) < number < 2^num_bits - * So num_bits = ceil(log2(number)) - * = ceil(log2(N^K)) - * = ceil(log2(N)*K) - */ - float log2 = 3.32193f; // Caution: This value has to be round up! - //int num_bytes = ceilf(log2*stringLength)/8; - // FIXME: We don't have ceilf just yet. Do we really need it though? - m_numberOfBits = (log2*stringLength); - m_bits = (native_uint_t *)malloc(arraySize(m_numberOfBits)*sizeof(native_uint_t)); + Integer v = Integer(string[0]-'0'); + for (int i=1; i