15 static inline int max(
int x,
int y) {
return (x>y ? x : y); }
19 static_assert(nativeUnsignedIntegerBitCount < 256,
"uint8_t cannot contain the log2 of a native_uint_t");
20 for (
uint8_t i=0; i<nativeUnsignedIntegerBitCount; i++) {
32 static inline int8_t sign(
bool negative) {
33 return 1 - 2*(
int8_t)negative;
46 m_numberOfDigits = (mostSignificantDigit == 0) ? 1 : 2;
47 if (m_numberOfDigits == 1) {
48 m_digit = leastSignificantDigit;
51 digits[0] = leastSignificantDigit;
52 digits[1] = mostSignificantDigit;
62 if (digits !=
nullptr && digits[0] ==
'-') {
69 if (digits !=
nullptr) {
71 while (*digits >=
'0' && *digits <=
'9') {
78 *
this = std::move(result);
83 m_negative = negative;
89 for (
int i = 0; i < exponentLength; i++) {
94 if (exponentNegative) {
103 for (
int i = 0; i < fractionalPartLength; i++) {
130 releaseDynamicIvars();
135 if (other.usesImmediateDigit()) {
140 m_numberOfDigits = other.m_numberOfDigits;
141 m_negative = other.m_negative;
145 other.m_numberOfDigits = 1;
146 other.m_negative = 0;
151 if (other.usesImmediateDigit()) {
155 for (
int i=0; i<other.m_numberOfDigits; i++) {
160 m_numberOfDigits = other.m_numberOfDigits;
161 m_negative = other.m_negative;
165 if (
this != &other) {
166 releaseDynamicIvars();
168 if (other.usesImmediateDigit()) {
173 m_numberOfDigits = other.m_numberOfDigits;
174 m_negative = other.m_negative;
178 other.m_numberOfDigits = 1;
179 other.m_negative = 0;
185 if (
this != &other) {
186 releaseDynamicIvars();
188 if (other.usesImmediateDigit()) {
192 for (
int i=0; i<other.m_numberOfDigits; i++) {
197 m_numberOfDigits = other.m_numberOfDigits;
198 m_negative = other.m_negative;
207 m_negative = negative;
219 return ::Poincare::sign(i.
isNegative())*ucmp(i, j);
233 return addition(a, b,
false);
237 return addition(a, b,
true);
242 uint16_t productSize = a.m_numberOfDigits + b.m_numberOfDigits;
247 for (
uint16_t i=0; i<a.m_numberOfDigits; i++) {
250 for (
uint16_t j=0; j<b.m_numberOfDigits; j++) {
260 digits[i+b.m_numberOfDigits] += carry;
263 while (digits[productSize-1] == 0 && productSize>1) {
268 return Integer(digits, productSize, a.m_negative != b.m_negative);
318 while (!index.isEqualTo(
Integer(0))) {
329 m_numberOfDigits(numberOfDigits),
332 assert(digits !=
nullptr);
333 if (numberOfDigits == 1) {
341 assert(numberOfDigits > 1);
346 void Integer::releaseDynamicIvars() {
347 if (!usesImmediateDigit()) {
353 int8_t Integer::ucmp(
const Integer & a,
const Integer & b) {
354 if (a.m_numberOfDigits < b.m_numberOfDigits) {
356 }
else if (a.m_numberOfDigits > b.m_numberOfDigits) {
359 for (
uint16_t i = 0; i < a.m_numberOfDigits; i++) {
363 if (aDigit < bDigit) {
365 }
else if (aDigit > bDigit) {
372 Integer Integer::usum(
const Integer & a,
const Integer & b,
bool subtract,
bool outputNegative) {
373 uint16_t size = max(a.m_numberOfDigits, b.m_numberOfDigits);
381 native_uint_t aDigit = (i >= a.m_numberOfDigits ? 0 : a.digit(i));
382 native_uint_t bDigit = (i >= b.m_numberOfDigits ? 0 : b.digit(i));
383 native_uint_t result = (subtract ? aDigit - bDigit - carry : aDigit + bDigit + carry);
386 carry = (aDigit < result) || (carry && aDigit == result);
388 carry = (aDigit > result) || (bDigit > result);
391 while (digits[size-1] == 0 && size>1) {
395 return Integer(digits, size, outputNegative);
399 Integer Integer::addition(
const Integer & a,
const Integer & b,
bool inverseBNegative) {
400 bool bNegative = (inverseBNegative ? !b.m_negative : b.m_negative);
401 if (a.m_negative == bNegative) {
402 return usum(a, b,
false, a.m_negative);
409 if (ucmp(a, b) >= 0) {
410 return usum(a, b,
true, a.m_negative);
412 return usum(b, a,
true, bNegative);
417 Integer Integer::IntegerWithHalfDigitAtIndex(half_native_uint_t halfDigit,
int index) {
421 digits[index-1] = halfDigit;
422 int indexInBase32 = index%2 == 1 ? index/2+1 : index/2;
426 IntegerDivision Integer::udiv(
const Integer & numerator,
const Integer & denominator) {
431 IntegerDivision div = {.quotient = 0, .remainder =
numerator};
443 int n = B.numberOfHalfDigits();
444 int m = A.numberOfHalfDigits()-n;
447 Integer betam = IntegerWithHalfDigitAtIndex(1, m+1);
449 if (!A.isLowerThan(betaMB)) {
453 for (
int j = m-1; j >= 0; j--) {
457 Integer factor = qDigits[j] > 0 ? IntegerWithHalfDigitAtIndex(qDigits[j], j+1) :
Integer(0);
460 while (A.isLowerThan(
Integer(0))) {
461 qDigits[j] = qDigits[j]-1;
465 int qNumberOfDigits = m+1;
466 while (qDigits[qNumberOfDigits-1] == 0 && qNumberOfDigits > 1) {
470 int qNumberOfDigitsInBase32 = qNumberOfDigits%2 == 1 ? qNumberOfDigits/2+1 : qNumberOfDigits/2;
471 IntegerDivision div = {.quotient =
Integer((
native_uint_t *)qDigits, qNumberOfDigitsInBase32,
false), .remainder = A};
472 if (d != 1 && !div.remainder.isZero()) {
486 T result = m_negative ? -0.0 : 0.0;
489 assert(
sizeof(
T) == 4 ||
sizeof(
T) == 8);
500 bool sign = m_negative;
507 exponent += (m_numberOfDigits-1)*32;
508 exponent += numberOfBitsInLastDigit-1;
517 int numberOfBits = numberOfBitsInLastDigit;
523 while (m_numberOfDigits >= digitIndex && numberOfBits <
IEEE754<T>::size()) {
524 lastDigit = digit(m_numberOfDigits-digitIndex);
546 if (bufferSize == 0) {
549 buffer[bufferSize-1] = 0;
553 if (m_numberOfDigits > 25) {
554 return strlcpy(buffer,
"undef", bufferSize);
562 if (bufferSize == 1) {
566 buffer[size++] =
'0';
568 buffer[size++] =
'-';
572 char c = char_from_digit(d.
remainder.digit(0));
573 if (size >= bufferSize-1) {
574 return strlcpy(buffer,
"undef", bufferSize);
582 for (
int i=m_negative, j=size-1 ; i < j ; i++, j--) {
584 buffer[i] = buffer[j];
596 template float Poincare::Integer::approximate<float>()
const;
597 template double Poincare::Integer::approximate<double>()
const;
static Integer Power(const Integer &i, const Integer &j)
void * memset(void *b, int c, size_t len)
int writeTextInBuffer(char *buffer, int bufferSize) const
uint64_t double_native_uint_t
size_t strlcpy(char *dst, const char *src, size_t len)
static uint16_t exponentOffset()
bool isEqualTo(const Integer &other) const
static T buildFloat(bool sign, uint16_t exponent, uint64_t mantissa)
Integer & operator=(Integer &&other)
bool isLowerThan(const Integer &other) const
const native_uint_t * m_digits
static Integer Factorial(const Integer &i)
void setNegative(bool negative)
unsigned long long uint64_t
static Integer Addition(const Integer &i, const Integer &j)
static Integer exponent(int fractionalPartLength, const char *exponent, int exponentLength, bool exponentNegative)
uint8_t log2(Integer::native_uint_t v)
static int NaturalOrder(const Integer &i, const Integer &j)
static Integer numerator(const char *integralPart, int integralPartLength, const char *fractionalPart, int fractionalPartLength, bool negative, Integer *exponent)
static Integer Subtraction(const Integer &i, const Integer &j)
uint16_t half_native_uint_t
Integer(native_int_t i=0)
ExpressionLayout * createLayout() const
static Integer Multiplication(const Integer &i, const Integer &j)
static Integer denominator(Integer *exponent)
static IntegerDivision Division(const Integer &numerator, const Integer &denominator)
int64_t double_native_int_t