[Poincare] First working BigInt addition!

This commit is contained in:
Romain Goyet
2015-09-14 18:57:31 +02:00
parent 1687bad6c2
commit 388f0ec954
3 changed files with 92 additions and 37 deletions

View File

@@ -4,20 +4,34 @@
#include <poincare/expression.h>
#include <stdint.h>
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

View File

@@ -3,21 +3,72 @@
#include <string.h>
#include <stdlib.h>
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<Integer *>(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; i<size; i++) {
if (m_bits[i] != other.m_bits[i]) {
return false;
}
}
return true;
}
Integer::Integer(native_uint_t i) {
//m_numberOfBits = sizeof(native_uint_t)*8;
m_numberOfBits = 16;
m_bits = (native_uint_t *)malloc(sizeof(native_uint_t));
*m_bits = i;
}
const Integer Integer::operator+(const Integer &other) const {
uint16_t sumSize = MAX(other.m_numberOfBits,m_numberOfBits) + 1;
uint16_t intArraySize = arraySize(sumSize);
native_uint_t * bits = (native_uint_t *)malloc(intArraySize*sizeof(native_uint_t));
bool carry = 0;
for (uint16_t i = 0; i<intArraySize; i++) {
native_uint_t a = other.m_bits[i];
native_uint_t b = m_bits[i];
native_uint_t sum = a + b + carry;
bits[i] = sum;
carry = ((a>sum)||(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<Integer *>(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;
}

View File

@@ -1,6 +1,11 @@
#include <quiz.h>
#include <poincare.h>
#include <assert.h>
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));
}