diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 5930ba648..622027252 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -4,20 +4,34 @@ #include #include +typedef uint32_t native_uint_t; + class Integer : public Expression { public: + Integer(native_uint_t i); Integer(char * string); - Integer(uint32_t integer); - ~Integer(); - //Number(int v); + virtual void draw(); virtual Expression ** children(); virtual bool identicalTo(Expression * e); + //Integer add(Integer * i); + const Integer operator+(const Integer &other) const; + bool operator==(const Integer &other) const; protected: virtual void layout(); 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; - void * m_bits; + native_uint_t * m_bits; + /* + // TODO: Small-int optimization + union { + uint32_t m_staticBits; + char * m_dynamicBits; + }; + */ }; #endif diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 8eb047ff3..f473b7fea 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -3,21 +3,72 @@ #include #include -Integer::Integer(uint32_t integer) { - // FIXME: Suboptimal (and somewhat wrong, too!) - m_numberOfBits = 32; - m_bits = malloc(4); - *(uint32_t *)m_bits = integer; +#define MAX(a,b) ((a)>(b)?a:b) + +#define INTEGER_IMMEDIATE_LIMIT 32 + +uint16_t Integer::arraySize(uint16_t bitSize) { + return (bitSize-1)/(8*sizeof(native_uint_t))+1; } -bool Integer::identicalTo(Expression * e) { - /* FIXME - Integer * i = dynamic_cast(e); - return (i != NULL); - */ +bool Integer::operator==(const Integer &other) const { + if (other.m_numberOfBits != m_numberOfBits) { + return false; + } + uint16_t size = arraySize(m_numberOfBits); + for (uint16_t i=0; isum)||(b>sum)); + } + if (carry) { + bits[intArraySize] = 0x1; + } else { + sumSize -= 1; + /* At this point we may realloc m_bits 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); +} + +/* + char * Integer::bits() { + if (m_numberOfBits > INTEGER_IMMEDIATE_LIMIT) { + return m_dynamicBits; + } else { + return &m_staticBits; + } +} +*/ + +Integer::Integer(native_uint_t * bits, uint16_t size) : + m_bits(bits), + m_numberOfBits(size) { +} + Integer::Integer(char * string) { int base = 10; int stringLength = strlen(string); @@ -47,32 +98,17 @@ Integer::Integer(char * string) { //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 = malloc(m_numberOfBits/8+1); - - - + m_bits = (native_uint_t *)malloc(arraySize(m_numberOfBits)*sizeof(native_uint_t)); } -Integer::~Integer() { - free(m_bits); +bool Integer::identicalTo(Expression * e) { + /* FIXME + Integer * i = dynamic_cast(e); + return (i != NULL); + */ + return false; } -/*Number::Number(int v) : m_value(v) { - for (int i=0; i<16; i++) { - m_stringValue[i] = 0; - } - - int value = v; - for (int i=0; i<15; i++) { - int digit = value - 10*(value/10); - m_stringValue[i] = '0' + digit; - value = value/10; - if (value == 0) { - break; - } - } -}*/ - Expression ** Integer::children() { return NULL; } diff --git a/poincare/test/integer.cpp b/poincare/test/integer.cpp index d72f3ef7d..3c8857233 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -1,6 +1,11 @@ #include #include +#include QUIZ_CASE(poincare_integer) { - Integer i = Integer((char *)"123"); + assert(Integer(123) == Integer(123)); +} + +QUIZ_CASE(poincare_integer_add) { + assert(Integer(123)+Integer(456) == Integer(579)); }