mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-19 05:40:38 +01:00
[poincare] Integer optimization: small digit doest not allocate anything
This commit is contained in:
@@ -52,7 +52,7 @@ public:
|
||||
Integer& operator=(const Integer& other); // C++11 copy assignment operator
|
||||
|
||||
// Getters
|
||||
const native_uint_t * digits() const { return m_digits; }
|
||||
const native_uint_t * digits() const { return usesImmediateDigit() ? &m_digit : m_digits; }
|
||||
size_t numberOfDigits() const { return m_numberOfDigits; }
|
||||
|
||||
// Serialization
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
|
||||
// Sign
|
||||
bool isNegative() const { return m_negative; }
|
||||
void setNegative(bool negative) { if (m_numberOfDigits > 0) { m_negative = negative; } }
|
||||
void setNegative(bool negative) { m_negative = m_numberOfDigits > 0 ? negative : false; }
|
||||
|
||||
// Properties
|
||||
static int NumberOfBase10DigitsWithoutSign(const Integer & i);
|
||||
@@ -135,17 +135,21 @@ private:
|
||||
if (i >= numberOfHalfDigits()) {
|
||||
return 0;
|
||||
}
|
||||
return ((half_native_uint_t *)m_digits)[i];
|
||||
return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)m_digits)[i]);
|
||||
}
|
||||
|
||||
bool usesImmediateDigit() const { return m_numberOfDigits == 1; }
|
||||
native_uint_t digit(int i) const {
|
||||
assert(i >= 0 && i < m_numberOfDigits);
|
||||
return m_digits[i];
|
||||
return (usesImmediateDigit() ? m_digit : m_digits[i]);
|
||||
}
|
||||
|
||||
bool m_negative;
|
||||
size_t m_numberOfDigits; // In base native_uint_t
|
||||
native_uint_t * m_digits;
|
||||
union {
|
||||
native_uint_t * m_digits; // Little-endian
|
||||
native_uint_t m_digit;
|
||||
};
|
||||
};
|
||||
|
||||
struct IntegerDivision {
|
||||
|
||||
@@ -37,10 +37,10 @@ static inline int8_t sign(bool negative) {
|
||||
#if POINCARE_INTEGER_LOG
|
||||
|
||||
void Integer::log() const {
|
||||
double d = 0;
|
||||
double d = 0.0;
|
||||
double base = 1.0;
|
||||
for (int i = 0; i < m_numberOfDigits; i++) {
|
||||
d += m_digits[i]*base;
|
||||
d += digit(i)*base;
|
||||
base *= std::pow(2.0,32.0);
|
||||
}
|
||||
std::cout << "Integer: " << d << std::endl;
|
||||
@@ -83,10 +83,15 @@ Integer::Integer(native_uint_t * digits, uint16_t numberOfDigits, bool negative,
|
||||
m_numberOfDigits(!enableOverflow && numberOfDigits > Integer::k_maxNumberOfDigits ? k_maxNumberOfDigits+1 : numberOfDigits),
|
||||
m_digits(digits)
|
||||
{
|
||||
if ((m_numberOfDigits == 0 || (!enableOverflow && m_numberOfDigits > k_maxNumberOfDigitsBase10)) && m_digits) {
|
||||
if ((m_numberOfDigits <= 1|| (!enableOverflow && m_numberOfDigits > k_maxNumberOfDigitsBase10)) && m_digits) {
|
||||
freeDigits(m_digits);
|
||||
m_digits = nullptr;
|
||||
if (m_numberOfDigits == 1) {
|
||||
m_digit = digits[0];
|
||||
} else {
|
||||
m_digits = nullptr;
|
||||
}
|
||||
}
|
||||
m_negative = m_numberOfDigits == 0 ? false : m_negative;
|
||||
}
|
||||
|
||||
Integer::Integer(native_int_t i) {
|
||||
@@ -97,9 +102,7 @@ Integer::Integer(native_int_t i) {
|
||||
return;
|
||||
}
|
||||
m_numberOfDigits = 1;
|
||||
native_uint_t * digits = allocDigits(1);
|
||||
digits[0] = i > 0 ? i : -i;
|
||||
m_digits = digits;
|
||||
m_digit = i > 0 ? i : -i;
|
||||
m_negative = i < 0;
|
||||
}
|
||||
|
||||
@@ -115,12 +118,14 @@ Integer::Integer(double_native_int_t i) {
|
||||
native_uint_t leastSignificantDigit = *d;
|
||||
native_uint_t mostSignificantDigit = *(d+1);
|
||||
m_numberOfDigits = (mostSignificantDigit == 0) ? 1 : 2;
|
||||
native_uint_t * digits = allocDigits(m_numberOfDigits);
|
||||
digits[0] = leastSignificantDigit;
|
||||
if (m_numberOfDigits > 1) {
|
||||
if (m_numberOfDigits == 1) {
|
||||
m_digit = leastSignificantDigit;
|
||||
} else {
|
||||
native_uint_t * digits = allocDigits(m_numberOfDigits);
|
||||
digits[0] = leastSignificantDigit;
|
||||
digits[1] = mostSignificantDigit;
|
||||
m_digits = digits;
|
||||
}
|
||||
m_digits = digits;
|
||||
m_negative = i < 0;
|
||||
}
|
||||
|
||||
@@ -145,7 +150,7 @@ Integer::Integer(const char * digits, size_t length, bool negative) :
|
||||
}
|
||||
|
||||
void Integer::releaseDynamicIvars() {
|
||||
if (m_digits) {
|
||||
if (!usesImmediateDigit() && m_digits) {
|
||||
freeDigits(m_digits);
|
||||
}
|
||||
}
|
||||
@@ -156,7 +161,11 @@ Integer::~Integer() {
|
||||
|
||||
Integer::Integer(Integer && other) {
|
||||
// Pilfer other's data
|
||||
m_digits = other.m_digits;
|
||||
if (other.usesImmediateDigit()) {
|
||||
m_digit = other.m_digit;
|
||||
} else {
|
||||
m_digits = other.m_digits;
|
||||
}
|
||||
m_numberOfDigits = other.m_numberOfDigits;
|
||||
m_negative = other.m_negative;
|
||||
|
||||
@@ -168,11 +177,15 @@ Integer::Integer(Integer && other) {
|
||||
|
||||
Integer::Integer(const Integer& other) {
|
||||
// Copy other's data
|
||||
native_uint_t * digits = allocDigits(other.m_numberOfDigits);
|
||||
for (int i=0; i<other.m_numberOfDigits; i++) {
|
||||
digits[i] = other.m_digits[i];
|
||||
if (other.usesImmediateDigit()) {
|
||||
m_digit = other.m_digit;
|
||||
} else {
|
||||
native_uint_t * digits = allocDigits(other.m_numberOfDigits);
|
||||
for (int i=0; i<other.m_numberOfDigits; i++) {
|
||||
digits[i] = other.m_digits[i];
|
||||
}
|
||||
m_digits = digits;
|
||||
}
|
||||
m_digits = digits;
|
||||
m_numberOfDigits = other.m_numberOfDigits;
|
||||
m_negative = other.m_negative;
|
||||
}
|
||||
@@ -181,7 +194,11 @@ Integer& Integer::operator=(Integer && other) {
|
||||
if (this != &other) {
|
||||
releaseDynamicIvars();
|
||||
// Pilfer other's ivars
|
||||
m_digits = other.m_digits;
|
||||
if (other.usesImmediateDigit()) {
|
||||
m_digit = other.m_digit;
|
||||
} else {
|
||||
m_digits = other.m_digits;
|
||||
}
|
||||
m_numberOfDigits = other.m_numberOfDigits;
|
||||
m_negative = other.m_negative;
|
||||
|
||||
@@ -197,11 +214,15 @@ Integer& Integer::operator=(const Integer& other) {
|
||||
if (this != &other) {
|
||||
releaseDynamicIvars();
|
||||
// Copy other's ivars
|
||||
native_uint_t * digits = allocDigits(other.m_numberOfDigits);
|
||||
for (int i=0; i<other.m_numberOfDigits; i++) {
|
||||
digits[i] = other.m_digits[i];
|
||||
if (other.usesImmediateDigit()) {
|
||||
m_digit = other.m_digit;
|
||||
} else {
|
||||
native_uint_t * digits = allocDigits(other.m_numberOfDigits);
|
||||
for (int i=0; i<other.m_numberOfDigits; i++) {
|
||||
digits[i] = other.m_digits[i];
|
||||
}
|
||||
m_digits = digits;
|
||||
}
|
||||
m_digits = digits;
|
||||
m_numberOfDigits = other.m_numberOfDigits;
|
||||
m_negative = other.m_negative;
|
||||
}
|
||||
@@ -522,8 +543,8 @@ Integer Integer::multiplyByPowerOf2(uint8_t pow) const {
|
||||
native_uint_t * digits = allocDigits(m_numberOfDigits+1);
|
||||
native_uint_t carry = 0;
|
||||
for (int i = 0; i < m_numberOfDigits; i++) {
|
||||
digits[i] = m_digits[i] << pow | carry;
|
||||
carry = pow == 0 ? 0 : m_digits[i] >> (32-pow);
|
||||
digits[i] = digit(i) << pow | carry;
|
||||
carry = pow == 0 ? 0 : digit(i) >> (32-pow);
|
||||
}
|
||||
digits[m_numberOfDigits] = carry;
|
||||
return Integer(digits, carry ? m_numberOfDigits + 1 : m_numberOfDigits, false, true);
|
||||
@@ -534,8 +555,8 @@ Integer Integer::divideByPowerOf2(uint8_t pow) const {
|
||||
native_uint_t * digits = allocDigits(m_numberOfDigits);
|
||||
native_uint_t carry = 0;
|
||||
for (int i = m_numberOfDigits - 1; i >= 0; i--) {
|
||||
digits[i] = m_digits[i] >> pow | carry;
|
||||
carry = pow == 0 ? 0 : m_digits[i] << (32-pow);
|
||||
digits[i] = digit(i) >> pow | carry;
|
||||
carry = pow == 0 ? 0 : digit(i) << (32-pow);
|
||||
}
|
||||
return Integer(digits, digits[m_numberOfDigits-1] > 0 ? m_numberOfDigits : m_numberOfDigits-1, false, true);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ Expression Opposite::shallowReduce(Context & context, Preferences::AngleUnit ang
|
||||
#if MATRIX_EXACT_REDUCING
|
||||
#endif
|
||||
result = Multiplication(Rational(-1), child);
|
||||
return result.shallowReduce(context, angleUnit, futureParent);
|
||||
return result.shallowReduce(context, angleUnit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,9 +63,9 @@ Expression Subtraction::shallowReduce(Context & context, Preferences::AngleUnit
|
||||
}
|
||||
Expression m = Multiplication(Rational(-1), childAtIndex(1));
|
||||
Addition a = Addition(childAtIndex(0));
|
||||
m = m.shallowReduce(context, angleUnit, a);
|
||||
m = m.shallowReduce(context, angleUnit);
|
||||
a.addChildAtIndexInPlace(m, a.numberOfChildren(), a.numberOfChildren());
|
||||
return a.shallowReduce(context, angleUnit, futureParent);
|
||||
return a.shallowReduce(context, angleUnit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ QUIZ_CASE(poincare_integer_constructor) {
|
||||
Integer nc(-12314);
|
||||
Integer d((int64_t)1234567891011121314);
|
||||
Integer nd((int64_t)(-1234567891011121314));
|
||||
Integer e = Integer::Overflow();
|
||||
Integer e = Integer::Overflow(false);
|
||||
assert_pool_size(initialPoolSize+9);
|
||||
}
|
||||
|
||||
@@ -212,14 +212,6 @@ QUIZ_CASE(poincare_integer_factorial) {
|
||||
|
||||
// Simplify
|
||||
|
||||
QUIZ_CASE(poincare_integer_simplify) {
|
||||
/* assert_parsed_expression_simplify_to("1234", "1234");
|
||||
assert_parsed_expression_simplify_to("12342345698765345678909876545678907655678900987654", "12342345698765345678909876545678907655678900987654");
|
||||
assert_parsed_expression_simplify_to("12342345698765345678909876545678907655678900987654", "12342345698765345678909876545678907655678900987654");
|
||||
assert_parsed_expression_simplify_to(MaxIntegerString, MaxIntegerString);
|
||||
//assert_parsed_expression_simplify_to(OverflowedIntegerString, "inf"); // parse as a Decimal and then simplify to Rational*/
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void assert_integer_evals_to(const char * i, T result) {
|
||||
quiz_assert(Integer(i).approximate<T>() == result);
|
||||
@@ -267,10 +259,16 @@ QUIZ_CASE(poincare_integer_evaluate) {
|
||||
|
||||
//Serialize
|
||||
|
||||
QUIZ_CASE(poincare_integer_serialize) {
|
||||
assert_parsed_expression_serialize_to(Integer(-2), "-2");
|
||||
assert_parsed_expression_serialize_to(Integer("2345678909876"), "2345678909876");
|
||||
assert_parsed_expression_serialize_to(Integer("-2345678909876"), "-2345678909876");
|
||||
assert_parsed_expression_serialize_to(MaxInteger(), MaxIntegerString);
|
||||
assert_parsed_expression_serialize_to(OverflowedInteger(), "inf");
|
||||
static inline void assert_integer_serializes_to(const Integer i, const char * serialization) {
|
||||
char buffer[500];
|
||||
i.serialize(buffer, 500);
|
||||
quiz_assert(strcmp(buffer, serialization) == 0);
|
||||
}
|
||||
|
||||
QUIZ_CASE(poincare_integer_serialize) {
|
||||
assert_integer_serializes_to(Integer(-2), "-2");
|
||||
assert_integer_serializes_to(Integer("2345678909876"), "2345678909876");
|
||||
assert_integer_serializes_to(Integer("-2345678909876"), "-2345678909876");
|
||||
assert_integer_serializes_to(MaxInteger(), MaxIntegerString);
|
||||
assert_integer_serializes_to(OverflowedInteger(), "inf");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user