Numworks Epsilon  1.4.1
Graphing Calculator Operating System
integer.cpp
Go to the documentation of this file.
1 #include <poincare/integer.h>
2 extern "C" {
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6 }
7 #include <cmath>
8 #include <poincare/complex.h>
9 #include <poincare/ieee754.h>
10 #include "layout/string_layout.h"
11 #include <utility>
12 
13 namespace Poincare {
14 
15 static inline int max(int x, int y) { return (x>y ? x : y); }
16 
18  constexpr int nativeUnsignedIntegerBitCount = 8*sizeof(Integer::native_uint_t);
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++) {
21  if (v < ((Integer::native_uint_t)1<<i)) {
22  return i;
23  }
24  }
25  return 32;
26 }
27 
28 static inline char char_from_digit(Integer::native_uint_t digit) {
29  return '0'+digit;
30 }
31 
32 static inline int8_t sign(bool negative) {
33  return 1 - 2*(int8_t)negative;
34 }
35 
36 // Constructors
37 
38 static_assert(sizeof(Integer::double_native_int_t) == 2*sizeof(Integer::native_int_t), "double_native_int_t type has not the right size compared to native_int_t");
39 static_assert(sizeof(Integer::native_int_t) == sizeof(Integer::native_uint_t), "native_int_t type has not the right size compared to native_uint_t");
40 
42  double_native_uint_t j = i < 0 ? -i : i;
43  native_uint_t * digits = (native_uint_t *)&j;
44  native_uint_t leastSignificantDigit = *digits;
45  native_uint_t mostSignificantDigit = *(digits+1);
46  m_numberOfDigits = (mostSignificantDigit == 0) ? 1 : 2;
47  if (m_numberOfDigits == 1) {
48  m_digit = leastSignificantDigit;
49  } else {
50  native_uint_t * digits = new native_uint_t [2];
51  digits[0] = leastSignificantDigit;
52  digits[1] = mostSignificantDigit;
53  m_digits = digits;
54  }
55  m_negative = i < 0;
56 }
57 
58 /* Caution: string is NOT guaranteed to be NULL-terminated! */
59 Integer::Integer(const char * digits, bool negative) :
60  Integer(0)
61 {
62  if (digits != nullptr && digits[0] == '-') {
63  negative = true;
64  digits++;
65  }
66 
67  Integer result = Integer(0);
68 
69  if (digits != nullptr) {
70  Integer base = Integer(10);
71  while (*digits >= '0' && *digits <= '9') {
72  result = Multiplication(result, base);
73  result = Addition(result, Integer(*digits-'0'));
74  digits++;
75  }
76  }
77 
78  *this = std::move(result);
79 
80  if (isZero()) {
81  negative = false;
82  }
83  m_negative = negative;
84 }
85 
86 Integer Integer::exponent(int fractionalPartLength, const char * exponent, int exponentLength, bool exponentNegative) {
87  Integer base = Integer(10);
88  Integer power = Integer(0);
89  for (int i = 0; i < exponentLength; i++) {
90  power = Multiplication(power, base);
91  power = Addition(power, Integer(*exponent-'0'));
92  exponent++;
93  }
94  if (exponentNegative) {
95  power.setNegative(true);
96  }
97  return Subtraction(Integer(fractionalPartLength), power);
98 }
99 
100 Integer Integer::numerator(const char * integralPart, int integralPartLength, const char * fractionalPart, int fractionalPartLength, bool negative, Integer * exponent) {
101  Integer base = Integer(10);
102  Integer numerator = Integer(integralPart, negative);
103  for (int i = 0; i < fractionalPartLength; i++) {
105  numerator = Addition(numerator, Integer(*fractionalPart-'0'));
106  fractionalPart++;
107  }
108  if (exponent->isNegative()) {
109  while (!exponent->isEqualTo(Integer(0))) {
112  }
113  }
114  return numerator;
115 }
116 
118  Integer base = Integer(10);
120  if (!exponent->isNegative()) {
121  while (!exponent->isEqualTo(Integer(0))) {
124  }
125  }
126  return denominator;
127 }
128 
130  releaseDynamicIvars();
131 }
132 
134  // Pilfer other's data
135  if (other.usesImmediateDigit()) {
136  m_digit = other.m_digit;
137  } else {
138  m_digits = other.m_digits;
139  }
140  m_numberOfDigits = other.m_numberOfDigits;
141  m_negative = other.m_negative;
142 
143  // Reset other
144  other.m_digit = 0;
145  other.m_numberOfDigits = 1;
146  other.m_negative = 0;
147 }
148 
149 Integer::Integer(const Integer& other) {
150  // Copy other's data
151  if (other.usesImmediateDigit()) {
152  m_digit = other.m_digit;
153  } else {
154  native_uint_t * digits = new native_uint_t [other.m_numberOfDigits];
155  for (int i=0; i<other.m_numberOfDigits; i++) {
156  digits[i] = other.m_digits[i];
157  }
158  m_digits = digits;
159  }
160  m_numberOfDigits = other.m_numberOfDigits;
161  m_negative = other.m_negative;
162 }
163 
165  if (this != &other) {
166  releaseDynamicIvars();
167  // Pilfer other's ivars
168  if (other.usesImmediateDigit()) {
169  m_digit = other.m_digit;
170  } else {
171  m_digits = other.m_digits;
172  }
173  m_numberOfDigits = other.m_numberOfDigits;
174  m_negative = other.m_negative;
175 
176  // Reset other
177  other.m_digit = 0;
178  other.m_numberOfDigits = 1;
179  other.m_negative = 0;
180  }
181  return *this;
182 }
183 
185  if (this != &other) {
186  releaseDynamicIvars();
187  // Copy other's ivars
188  if (other.usesImmediateDigit()) {
189  m_digit = other.m_digit;
190  } else {
191  native_uint_t * digits = new native_uint_t [other.m_numberOfDigits];
192  for (int i=0; i<other.m_numberOfDigits; i++) {
193  digits[i] = other.m_digits[i];
194  }
195  m_digits = digits;
196  }
197  m_numberOfDigits = other.m_numberOfDigits;
198  m_negative = other.m_negative;
199  }
200  return *this;
201 }
202 
203 void Integer::setNegative(bool negative) {
204  if (isZero()) { // Zero cannot be negative
205  return;
206  }
207  m_negative = negative;
208 }
209 
210 // Comparison
211 
212 int Integer::NaturalOrder(const Integer & i, const Integer & j) {
213  if (i.isNegative() && !j.isNegative()) {
214  return -1;
215  }
216  if (!i.isNegative() && j.isNegative()) {
217  return 1;
218  }
219  return ::Poincare::sign(i.isNegative())*ucmp(i, j);
220 }
221 
222 bool Integer::isEqualTo(const Integer & other) const {
223  return (NaturalOrder(*this, other) == 0);
224 }
225 
226 bool Integer::isLowerThan(const Integer & other) const {
227  return (NaturalOrder(*this, other) < 0);
228 }
229 
230 // Arithmetic
231 
232 Integer Integer::Addition(const Integer & a, const Integer & b) {
233  return addition(a, b, false);
234 }
235 
237  return addition(a, b, true);
238 }
239 
241  assert(sizeof(double_native_uint_t) == 2*sizeof(native_uint_t));
242  uint16_t productSize = a.m_numberOfDigits + b.m_numberOfDigits;
243  native_uint_t * digits = new native_uint_t [productSize];
244  memset(digits, 0, productSize*sizeof(native_uint_t));
245 
246  double_native_uint_t carry = 0;
247  for (uint16_t i=0; i<a.m_numberOfDigits; i++) {
248  double_native_uint_t aDigit = a.digit(i);
249  carry = 0;
250  for (uint16_t j=0; j<b.m_numberOfDigits; j++) {
251  double_native_uint_t bDigit = b.digit(j);
252  /* The fact that aDigit and bDigit are double_native is very important,
253  * otherwise the product might end up being computed on single_native size
254  * and then zero-padded. */
255  double_native_uint_t p = aDigit*bDigit + carry + (double_native_uint_t)(digits[i+j]); // TODO: Prove it cannot overflow double_native type
256  native_uint_t * l = (native_uint_t *)&p;
257  digits[i+j] = l[0];
258  carry = l[1];
259  }
260  digits[i+b.m_numberOfDigits] += carry;
261  }
262 
263  while (digits[productSize-1] == 0 && productSize>1) {
264  productSize--;
265  /* At this point we could realloc m_digits to a smaller size. */
266  }
267 
268  return Integer(digits, productSize, a.m_negative != b.m_negative);
269 }
270 
272  Integer j = Integer(2);
273  Integer result = Integer(1);
274  while (!i.isLowerThan(j)) {
275  result = Multiplication(j, result);
276  j = Addition(j, Integer(1));
277  }
278  return result;
279 }
280 
281 IntegerDivision Integer::Division(const Integer & numerator, const Integer & denominator) {
283  return udiv(numerator, denominator);
284  }
285  Integer absNumerator = numerator;
286  absNumerator.setNegative(false);
287  Integer absDenominator = denominator;
288  absDenominator.setNegative(false);
289  IntegerDivision usignedDiv = udiv(absNumerator, absDenominator);
290  if (usignedDiv.remainder.isEqualTo(Integer(0))) {
292  usignedDiv.quotient.setNegative(true);
293  }
294  return usignedDiv;
295  }
296  if (numerator.isNegative()) {
297  if (denominator.isNegative()) {
298  usignedDiv.remainder.setNegative(true);
299  usignedDiv.quotient = Addition(usignedDiv.quotient, Integer(1));
300  usignedDiv.remainder = Integer::Subtraction(usignedDiv.remainder, denominator);
301  } else {
302  usignedDiv.quotient.setNegative(true);
303  usignedDiv.quotient = Subtraction(usignedDiv.quotient, Integer(1));
304  usignedDiv.remainder = Integer::Subtraction(denominator, usignedDiv.remainder);
305  }
306  } else {
308  usignedDiv.quotient.setNegative(true);
309  }
310  return usignedDiv;
311 }
312 
313 Integer Integer::Power(const Integer & i, const Integer & j) {
314  // TODO: optimize with dichotomia
315  assert(!j.isNegative());
316  Integer index = j;
317  Integer result = Integer(1);
318  while (!index.isEqualTo(Integer(0))) {
319  result = Multiplication(result, i);
320  index = Subtraction(index, Integer(1));
321  }
322  return result;
323 }
324 
325 // Private methods
326 
327  /* WARNING: This constructor takes ownership of the digits array! */
328 Integer::Integer(const native_uint_t * digits, uint16_t numberOfDigits, bool negative) :
329  m_numberOfDigits(numberOfDigits),
330  m_negative(negative)
331 {
332  assert(digits != nullptr);
333  if (numberOfDigits == 1) {
334  m_digit = digits[0];
335  delete[] digits;
336  if (isZero()) {
337  // Normalize zero
338  m_negative = false;
339  }
340  } else {
341  assert(numberOfDigits > 1);
342  m_digits = digits;
343  }
344 }
345 
346 void Integer::releaseDynamicIvars() {
347  if (!usesImmediateDigit()) {
348  assert(m_digits != nullptr);
349  delete[] m_digits;
350  }
351 }
352 
353 int8_t Integer::ucmp(const Integer & a, const Integer & b) {
354  if (a.m_numberOfDigits < b.m_numberOfDigits) {
355  return -1;
356  } else if (a.m_numberOfDigits > b.m_numberOfDigits) {
357  return 1;
358  }
359  for (uint16_t i = 0; i < a.m_numberOfDigits; i++) {
360  // Digits are stored most-significant last
361  native_uint_t aDigit = a.digit(a.m_numberOfDigits-i-1);
362  native_uint_t bDigit = b.digit(b.m_numberOfDigits-i-1);
363  if (aDigit < bDigit) {
364  return -1;
365  } else if (aDigit > bDigit) {
366  return 1;
367  }
368  }
369  return 0;
370 }
371 
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);
374  if (!subtract) {
375  // Addition can overflow
376  size += 1;
377  }
378  native_uint_t * digits = new native_uint_t [size];
379  bool carry = false;
380  for (uint16_t i = 0; i<size; i++) {
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);
384  digits[i] = result;
385  if (subtract) {
386  carry = (aDigit < result) || (carry && aDigit == result); // There's been an underflow
387  } else {
388  carry = (aDigit > result) || (bDigit > result); // There's been an overflow
389  }
390  }
391  while (digits[size-1] == 0 && size>1) {
392  size--;
393  // We could realloc digits to a smaller size. Probably not worth the trouble.
394  }
395  return Integer(digits, size, outputNegative);
396 }
397 
398 
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);
403  } else {
404  /* The signs are different, this is in fact a subtraction
405  * s = a+b = (abs(a)-abs(b) OR abs(b)-abs(a))
406  * 1/abs(a)>abs(b) : s = sign*udiff(a, b)
407  * 2/abs(b)>abs(a) : s = sign*udiff(b, a)
408  * sign? sign of the greater! */
409  if (ucmp(a, b) >= 0) {
410  return usum(a, b, true, a.m_negative);
411  } else {
412  return usum(b, a, true, bNegative);
413  }
414  }
415 }
416 
417 Integer Integer::IntegerWithHalfDigitAtIndex(half_native_uint_t halfDigit, int index) {
418  assert(halfDigit != 0);
419  half_native_uint_t * digits = (half_native_uint_t *)new native_uint_t [(index+1)/2];
420  memset(digits, 0, (index+1)/2*sizeof(native_uint_t));
421  digits[index-1] = halfDigit;
422  int indexInBase32 = index%2 == 1 ? index/2+1 : index/2;
423  return Integer((native_uint_t *)digits, indexInBase32, false);
424 }
425 
426 IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denominator) {
427  /* Modern Computer Arithmetic, Richard P. Brent and Paul Zimmermann
428  * (Algorithm 1.6) */
431  IntegerDivision div = {.quotient = 0, .remainder = numerator};
432  return div;
433  }
434 
435  Integer A = numerator;
436  Integer B = denominator;
437  native_int_t base = 1 << 16;
438  // TODO: optimize by just swifting digit and finding 2^kB that makes B normalized
439  native_int_t d = base/(native_int_t)(B.halfDigit(B.numberOfHalfDigits()-1)+1);
440  A = Multiplication(Integer(d), A);
441  B = Multiplication(Integer(d), B);
442 
443  int n = B.numberOfHalfDigits();
444  int m = A.numberOfHalfDigits()-n;
445  half_native_uint_t * qDigits = (half_native_uint_t *)new native_uint_t [m/2+1];
446  memset(qDigits, 0, (m/2+1)*sizeof(native_uint_t));
447  Integer betam = IntegerWithHalfDigitAtIndex(1, m+1);
448  Integer betaMB = Multiplication(betam, B); // TODO: can swift all digits by m! B.swift16(mg)
449  if (!A.isLowerThan(betaMB)) {
450  qDigits[m] = 1;
451  A = Subtraction(A, betaMB);
452  }
453  for (int j = m-1; j >= 0; j--) {
454  native_uint_t qj2 = ((native_uint_t)A.halfDigit(n+j)*base+(native_uint_t)A.halfDigit(n+j-1))/(native_uint_t)B.halfDigit(n-1);
455  half_native_uint_t baseMinus1 = (1 << 16) -1;
456  qDigits[j] = qj2 < (native_uint_t)baseMinus1 ? (half_native_uint_t)qj2 : baseMinus1;
457  Integer factor = qDigits[j] > 0 ? IntegerWithHalfDigitAtIndex(qDigits[j], j+1) : Integer(0);
458  A = Subtraction(A, Multiplication(factor, B));
459  Integer m = Multiplication(IntegerWithHalfDigitAtIndex(1, j+1), B);
460  while (A.isLowerThan(Integer(0))) {
461  qDigits[j] = qDigits[j]-1;
462  A = Addition(A, m);
463  }
464  }
465  int qNumberOfDigits = m+1;
466  while (qDigits[qNumberOfDigits-1] == 0 && qNumberOfDigits > 1) {
467  qNumberOfDigits--;
468  // We could realloc digits to a smaller size. Probably not worth the trouble.
469  }
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()) {
473  div.remainder = udiv(div.remainder, Integer(d)).quotient;
474  }
475  return div;
476 }
477 
478 template<typename T>
480  if (isZero()) {
481  /* This special case for 0 is needed, because the current algorithm assumes
482  * that the big integer is non zero, thus puts the exponent to 126 (integer
483  * area), the issue is that when the mantissa is 0, a "shadow bit" is
484  * assumed to be there, thus 126 0x000000 is equal to 0.5 and not zero.
485  */
486  T result = m_negative ? -0.0 : 0.0;
487  return result;
488  }
489  assert(sizeof(T) == 4 || sizeof(T) == 8);
490  /* We're generating an IEEE 754 compliant float(double).
491  * We can tell that:
492  * - the sign depends on m_negative
493  * - the exponent is the length of our BigInt, in bits - 1 + 127 (-1+1023);
494  * - the mantissa is the beginning of our BigInt, discarding the first bit
495  */
496 
497  native_uint_t lastDigit = digit(m_numberOfDigits-1);
498  uint8_t numberOfBitsInLastDigit = log2(lastDigit);
499 
500  bool sign = m_negative;
501 
503  /* Escape case if the exponent is too big to be stored */
504  if ((m_numberOfDigits-1)*32+numberOfBitsInLastDigit-1> IEEE754<T>::maxExponent()-IEEE754<T>::exponentOffset()) {
505  return INFINITY;
506  }
507  exponent += (m_numberOfDigits-1)*32;
508  exponent += numberOfBitsInLastDigit-1;
509 
510  uint64_t mantissa = 0;
511  /* Shift the most significant int to the left of the mantissa. The most
512  * significant 1 will be ignore at the end when inserting the mantissa in
513  * the resulting uint64_t (as required by IEEE754). */
514  assert(IEEE754<T>::size()-numberOfBitsInLastDigit >= 0 && IEEE754<T>::size()-numberOfBitsInLastDigit < 64); // Shift operator behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand
515  mantissa |= ((uint64_t)lastDigit << (IEEE754<T>::size()-numberOfBitsInLastDigit));
516  int digitIndex = 2;
517  int numberOfBits = numberOfBitsInLastDigit;
518  /* Complete the mantissa by inserting, from left to right, every digit of the
519  * Integer from the most significant one to the last from. We break when
520  * the mantissa is complete to avoid undefined right shifting (Shift operator
521  * behavior is undefined if the right operand is negative, or greater than or
522  * equal to the length in bits of the promoted left operand). */
523  while (m_numberOfDigits >= digitIndex && numberOfBits < IEEE754<T>::size()) {
524  lastDigit = digit(m_numberOfDigits-digitIndex);
525  numberOfBits += 32;
526  if (IEEE754<T>::size() > numberOfBits) {
527  assert(IEEE754<T>::size()-numberOfBits > 0 && IEEE754<T>::size()-numberOfBits < 64);
528  mantissa |= ((uint64_t)lastDigit << (IEEE754<T>::size()-numberOfBits));
529  } else {
530  mantissa |= ((uint64_t)lastDigit >> (numberOfBits-IEEE754<T>::size()));
531  }
532  digitIndex++;
533  }
534 
535  T result = IEEE754<T>::buildFloat(sign, exponent, mantissa);
536 
537  /* If exponent is 255 and the float is undefined, we have exceed IEEE 754
538  * representable float. */
539  if (exponent == IEEE754<T>::maxExponent() && std::isnan(result)) {
540  return INFINITY;
541  }
542  return result;
543 }
544 
545 int Integer::writeTextInBuffer(char * buffer, int bufferSize) const {
546  if (bufferSize == 0) {
547  return -1;
548  }
549  buffer[bufferSize-1] = 0;
550  /* If the integer is too long, this method may be too slow.
551  * Experimentally, we can display at most integer whose number of digits is
552  * around 25. */
553  if (m_numberOfDigits > 25) {
554  return strlcpy(buffer, "undef", bufferSize);
555  }
556 
557  Integer base = Integer(10);
558  Integer abs = *this;
559  abs.setNegative(false);
560  IntegerDivision d = udiv(abs, base);
561  int size = 0;
562  if (bufferSize == 1) {
563  return 0;
564  }
565  if (isEqualTo(Integer(0))) {
566  buffer[size++] = '0';
567  } else if (isNegative()) {
568  buffer[size++] = '-';
569  }
570  while (!(d.remainder.isEqualTo(Integer(0)) &&
571  d.quotient.isEqualTo(Integer(0)))) {
572  char c = char_from_digit(d.remainder.digit(0));
573  if (size >= bufferSize-1) {
574  return strlcpy(buffer, "undef", bufferSize);
575  }
576  buffer[size++] = c;
577  d = Division(d.quotient, base);
578  }
579  buffer[size] = 0;
580 
581  // Flip the string
582  for (int i=m_negative, j=size-1 ; i < j ; i++, j--) {
583  char c = buffer[i];
584  buffer[i] = buffer[j];
585  buffer[j] = c;
586  }
587  return size;
588 }
589 
591  char buffer[255];
592  int numberOfChars = writeTextInBuffer(buffer, 255);
593  return new StringLayout(buffer, numberOfChars);
594 }
595 
596 template float Poincare::Integer::approximate<float>() const;
597 template double Poincare::Integer::approximate<double>() const;
598 
599 }
int32_t native_int_t
Definition: integer.h:18
T approximate() const
Definition: integer.cpp:479
uint32_t native_uint_t
Definition: integer.h:20
static Integer Power(const Integer &i, const Integer &j)
Definition: integer.cpp:313
void * memset(void *b, int c, size_t len)
Definition: memset.c:3
bool isZero() const
Definition: integer.h:72
#define assert(e)
Definition: assert.h:9
int writeTextInBuffer(char *buffer, int bufferSize) const
Definition: integer.cpp:545
#define T(x)
Definition: events.cpp:26
uint64_t double_native_uint_t
Definition: integer.h:21
size_t strlcpy(char *dst, const char *src, size_t len)
Definition: strlcpy.c:3
static uint16_t exponentOffset()
Definition: ieee754.h:21
unsigned short uint16_t
Definition: stdint.h:5
bool isEqualTo(const Integer &other) const
Definition: integer.cpp:222
unsigned char uint8_t
Definition: stdint.h:4
static T buildFloat(bool sign, uint16_t exponent, uint64_t mantissa)
Definition: ieee754.h:31
Integer & operator=(Integer &&other)
Definition: integer.cpp:164
bool isLowerThan(const Integer &other) const
Definition: integer.cpp:226
const native_uint_t * m_digits
Definition: integer.h:102
c(generic_all_nodes)
static Integer Factorial(const Integer &i)
Definition: integer.cpp:271
void setNegative(bool negative)
Definition: integer.cpp:203
unsigned long long uint64_t
Definition: stdint.h:7
static Integer Addition(const Integer &i, const Integer &j)
Definition: integer.cpp:232
bool isNegative() const
Definition: integer.h:43
static Integer exponent(int fractionalPartLength, const char *exponent, int exponentLength, bool exponentNegative)
Definition: integer.cpp:86
uint8_t log2(Integer::native_uint_t v)
Definition: integer.cpp:17
signed char int8_t
Definition: stdint.h:9
static int NaturalOrder(const Integer &i, const Integer &j)
Definition: integer.cpp:212
#define isnan(x)
Definition: math.h:43
#define INFINITY
Definition: math.h:29
static Integer numerator(const char *integralPart, int integralPartLength, const char *fractionalPart, int fractionalPartLength, bool negative, Integer *exponent)
Definition: integer.cpp:100
static Integer Subtraction(const Integer &i, const Integer &j)
Definition: integer.cpp:236
uint16_t half_native_uint_t
Definition: integer.h:17
Integer(native_int_t i=0)
Definition: integer.h:24
ExpressionLayout * createLayout() const
Definition: integer.cpp:590
static Integer Multiplication(const Integer &i, const Integer &j)
Definition: integer.cpp:240
static Integer denominator(Integer *exponent)
Definition: integer.cpp:117
static IntegerDivision Division(const Integer &numerator, const Integer &denominator)
Definition: integer.cpp:281
native_uint_t m_digit
Definition: integer.h:103
int64_t double_native_int_t
Definition: integer.h:19