[poincare] refactor Integer

This commit is contained in:
Romain Goyet
2015-09-17 15:10:45 +02:00
parent 310d4d2f11
commit 1a88f2b392
3 changed files with 81 additions and 57 deletions

View File

@@ -10,23 +10,25 @@ typedef uint64_t double_native_uint_t;
class Integer : public Expression {
public:
Integer(native_uint_t i);
static Integer parseInteger(const char * string);
Integer(const char * string); // NULL-terminated
~Integer();
//Integer& operator=(Integer&& other); // C++11 move assignment operator
// Arithmetic
const Integer operator+(const Integer &other) const;
const Integer operator*(const Integer &other) const;
bool operator==(const Integer &other) const;
virtual void draw();
virtual Expression ** children();
virtual bool identicalTo(Expression * e);
//Integer add(Integer * i);
const Integer operator+(const Integer &other) const;
const Integer operator*(const Integer &other) const;
bool operator==(const Integer &other) const;
virtual float approximate();
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 * 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
/*

View File

@@ -19,6 +19,59 @@ uint8_t log2(native_uint_t v) {
return 32;
}
Integer::Integer(native_uint_t i) {
m_numberOfDigits = 1;
m_digits = (native_uint_t *)malloc(sizeof(native_uint_t));
*m_digits = i;
}
Integer::Integer(const char * string) {
int stringLength = strlen(string);
/*
// Only support base 10 for now
if (stringLength > 2 && string[0] == '0')
switch (string[1]) {
case 'x':
base=16;
break;
case 'b':
base = 2;
break;
}
}
*/
Integer base = Integer(10);
Integer v = Integer(string[0]-'0');
for (int i=1; i<stringLength; i++) {
v = v * base;
v = v + Integer(string[i]-'0'); // ASCII encoding
}
// Pilfer v's ivars
m_numberOfDigits = v.m_numberOfDigits;
m_digits = v.m_digits;
// Zero-out v
v.m_numberOfDigits = 0;
v.m_digits = NULL;
}
Integer::~Integer() {
if (m_digits) {
//free(m_digits);
}
}
// Private methods
Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits) :
m_numberOfDigits(numberOfDigits),
m_digits(digits) {
}
bool Integer::operator==(const Integer &other) const {
if (other.m_numberOfDigits != m_numberOfDigits) {
return false;
@@ -31,11 +84,21 @@ bool Integer::operator==(const Integer &other) const {
return true;
}
Integer::Integer(native_uint_t i) {
m_numberOfDigits = 1;
m_digits = (native_uint_t *)malloc(sizeof(native_uint_t));
*m_digits = i;
/*
Integer& Integer::operator=(Integer&& other) {
if (this != &other) {
// Release our ivars
m_numberOfDigits = 0;
free(m_digits);
// Pilfer other's ivars
m_numberOfDigits = other.m_numberOfDigits;
m_digits = other.m_digits;
// Reset other
other.m_numberOfDigits = 0;
other.m_digits = NULL;
}
}
*/
const Integer Integer::operator+(const Integer &other) const {
uint16_t sumSize = MAX(other.m_numberOfDigits,m_numberOfDigits)+1;
@@ -88,47 +151,6 @@ const Integer Integer::operator*(const Integer &other) const {
return Integer(digits, productSize);
}
/*
char * Integer::bits() {
if (m_numberOfDigits > INTEGER_IMMEDIATE_LIMIT) {
return m_dynamicBits;
} else {
return &m_staticBits;
}
}
*/
Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits) :
m_numberOfDigits(numberOfDigits),
m_digits(digits) {
}
Integer Integer::parseInteger(const char * string) {
int base = 10;
int stringLength = strlen(string);
/*
// Only support base 10 for now
if (stringLength > 2 && string[0] == '0')
switch (string[1]) {
case 'x':
base=16;
break;
case 'b':
base = 2;
break;
}
}
*/
Integer v = Integer(string[0]-'0');
for (int i=1; i<stringLength; i++) {
v = v * Integer(10);
v = v + Integer(string[i]-'0'); // ASCII encoding
}
return v;
}
bool Integer::identicalTo(Expression * e) {
/* FIXME
Integer * i = dynamic_cast<Integer *>(e);

View File

@@ -9,20 +9,20 @@ QUIZ_CASE(poincare_integer) {
QUIZ_CASE(poincare_integer_add) {
//assert(Integer((uint32_t)0) + Integer((uint32_t)0) == Integer((uint32_t)0));
assert(Integer(123) + Integer(456) == Integer(579));
assert(Integer::parseInteger("123456789123456789") + Integer(1) == Integer::parseInteger("123456789123456790"));
assert(Integer("123456789123456789") + Integer(1) == Integer("123456789123456790"));
}
QUIZ_CASE(poincare_integer_multiply) {
assert(Integer(12) * Integer(34) == Integer(408));
assert(Integer(999999) * Integer(999999) == Integer::parseInteger("999998000001"));
assert(Integer::parseInteger("9999999999") * Integer::parseInteger("9999999999") == Integer::parseInteger("99999999980000000001"));
assert(Integer(999999) * Integer(999999) == Integer("999998000001"));
assert(Integer("9999999999") * Integer("9999999999") == Integer("99999999980000000001"));
}
QUIZ_CASE(poincare_integer_parse_integer) {
assert(Integer::parseInteger("123") == Integer(123));
assert(Integer("123") == Integer(123));
}
QUIZ_CASE(poincare_integer_approximate) {
assert(Integer(1).approximate() == 1.0f);
assert(Integer::parseInteger("12345678").approximate() == 12345678.0f);
assert(Integer("12345678").approximate() == 12345678.0f);
}