amath  1.8.5
Simple command line calculator
bigint.cpp File Reference
#include "bigint.h"
#include "mathr.h"
Include dependency graph for bigint.cpp:

Go to the source code of this file.

Functions

static int32_t BigInt_Compare (const BigInt &lhs, const BigInt &rhs)
 
static void BigInt_Add (BigInt *pResult, const BigInt &lhs, const BigInt &rhs)
 
static void BigInt_Multiply (BigInt *pResult, const BigInt &lhs, const BigInt &rhs)
 
static void BigInt_Multiply (BigInt *pResult, const BigInt &lhs, uint32_t rhs)
 
static void BigInt_Multiply2 (BigInt *pResult, const BigInt &in)
 
static void BigInt_Multiply2 (BigInt *pResult)
 
static void BigInt_Multiply10 (BigInt *pResult)
 
static void BigInt_Pow10 (BigInt *pResult, uint32_t exponent)
 
static void BigInt_MultiplyPow10 (BigInt *pResult, const BigInt &in, uint32_t exponent)
 
static void BigInt_Pow2 (BigInt *pResult, uint32_t exponent)
 
static uint32_t BigInt_DivideWithRemainder_MaxQuotient9 (BigInt *pDividend, const BigInt &divisor)
 
static void BigInt_ShiftLeft (BigInt *pResult, uint32_t shift)
 
uint32_t Dragon4 (const uint64_t mantissa, const int32_t exponent, const uint32_t mantissaHighBitIdx, const bool hasUnequalMargins, const tCutoffMode cutoffMode, uint32_t cutoffNumber, char *pOubooluffer, uint32_t bufferSize, int32_t *pOutExponent)
 

Variables

static uint32_t g_PowerOf10_U32 []
 
static BigInt g_PowerOf10_Big []
 

Function Documentation

◆ BigInt_Add()

static void BigInt_Add ( BigInt pResult,
const BigInt lhs,
const BigInt rhs 
)
static

Definition at line 79 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by Dragon4().

80 {
81  // determine which operand has the smaller length
82  const BigInt *pLarge;
83  const BigInt *pSmall;
84  if (lhs.m_length < rhs.m_length)
85  {
86  pSmall = &lhs;
87  pLarge = &rhs;
88  }
89  else
90  {
91  pSmall = &rhs;
92  pLarge = &lhs;
93  }
94 
95  const uint32_t largeLen = pLarge->m_length;
96  const uint32_t smallLen = pSmall->m_length;
97 
98  // The output will be at least as long as the largest input
99  pResult->m_length = largeLen;
100 
101  // Add each block and add carry the overflow to the next block
102  uint64_t carry = 0;
103  const uint32_t *pLargeCur = pLarge->m_blocks;
104  const uint32_t *pLargeEnd = pLargeCur + largeLen;
105  const uint32_t *pSmallCur = pSmall->m_blocks;
106  const uint32_t *pSmallEnd = pSmallCur + smallLen;
107  uint32_t *pResultCur = pResult->m_blocks;
108  while (pSmallCur != pSmallEnd)
109  {
110  uint64_t sum = carry + (uint64_t)(*pLargeCur) + (uint64_t)(*pSmallCur);
111  carry = sum >> 32;
112  (*pResultCur) = sum & 0xFFFFFFFF;
113  ++pLargeCur;
114  ++pSmallCur;
115  ++pResultCur;
116  }
117 
118  // Add the carry to any blocks that only exist in the large operand
119  while (pLargeCur != pLargeEnd)
120  {
121  uint64_t sum = carry + (uint64_t)(*pLargeCur);
122  carry = sum >> 32;
123  (*pResultCur) = sum & 0xFFFFFFFF;
124  ++pLargeCur;
125  ++pResultCur;
126  }
127 
128  // If there's still a carry, append a new block
129  if (carry != 0)
130  {
131  assert(carry == 1);
132  assert((uint32_t)(pResultCur - pResult->m_blocks) == largeLen && (largeLen < c_BigInt_MaxBlocks));
133  *pResultCur = 1;
134  pResult->m_length = largeLen + 1;
135  }
136  else
137  {
138  pResult->m_length = largeLen;
139  }
140 }
#define assert(x)
Definition: amath.h:124
Definition: bigint.h:61
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
const uint32_t c_BigInt_MaxBlocks
Definition: bigint.h:59
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ BigInt_Compare()

static int32_t BigInt_Compare ( const BigInt lhs,
const BigInt rhs 
)
static

Definition at line 57 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by BigInt_DivideWithRemainder_MaxQuotient9(), and Dragon4().

58 {
59  // A bigger length implies a bigger number.
60  int32_t lengthDiff = lhs.m_length - rhs.m_length;
61  if (lengthDiff != 0)
62  return lengthDiff;
63 
64  // Compare blocks one by one from high to low.
65  for (int32_t i = lhs.m_length - 1; i >= 0; --i)
66  {
67  if (lhs.m_blocks[i] == rhs.m_blocks[i])
68  continue;
69  else if (lhs.m_blocks[i] > rhs.m_blocks[i])
70  return 1;
71  else
72  return -1;
73  }
74 
75  // no blocks differed
76  return 0;
77 }
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ BigInt_DivideWithRemainder_MaxQuotient9()

static uint32_t BigInt_DivideWithRemainder_MaxQuotient9 ( BigInt pDividend,
const BigInt divisor 
)
static

Definition at line 452 of file bigint.cpp.

References BigInt_Compare(), BigInt::m_blocks, and BigInt::m_length.

Referenced by Dragon4().

453 {
454  // Check that the divisor has been correctly shifted into range and that it is not
455  // smaller than the dividend in length.
456  assert(!divisor.IsZero() &&
457  divisor.m_blocks[divisor.m_length - 1] >= 8 &&
458  divisor.m_blocks[divisor.m_length - 1] < 0xFFFFFFFF &&
459  pDividend->m_length <= divisor.m_length);
460 
461  // If the dividend is smaller than the divisor, the quotient is zero and the divisor is already
462  // the remainder.
463  uint32_t length = divisor.m_length;
464  if (pDividend->m_length < divisor.m_length)
465  return 0;
466 
467  const uint32_t *pFinalDivisorBlock = divisor.m_blocks + length - 1;
468  uint32_t *pFinalDividendBlock = pDividend->m_blocks + length - 1;
469 
470  // Compute an estimated quotient based on the high block value. This will either match the actual quotient or
471  // undershoot by one.
472  uint32_t quotient = *pFinalDividendBlock / (*pFinalDivisorBlock + 1);
473  assert(quotient <= 9);
474 
475  // Divide out the estimated quotient
476  if (quotient != 0)
477  {
478  // dividend = dividend - divisor*quotient
479  const uint32_t *pDivisorCur = divisor.m_blocks;
480  uint32_t *pDividendCur = pDividend->m_blocks;
481 
482  uint64_t borrow = 0;
483  uint64_t carry = 0;
484  do
485  {
486  uint64_t product = (uint64_t)*pDivisorCur * (uint64_t)quotient + carry;
487  carry = product >> 32;
488 
489  uint64_t difference = (uint64_t)*pDividendCur - (product & 0xFFFFFFFF) - borrow;
490  borrow = (difference >> 32) & 1;
491 
492  *pDividendCur = difference & 0xFFFFFFFF;
493 
494  ++pDivisorCur;
495  ++pDividendCur;
496  } while (pDivisorCur <= pFinalDivisorBlock);
497 
498  // remove all leading zero blocks from dividend
499  while (length > 0 && pDividend->m_blocks[length - 1] == 0)
500  --length;
501 
502  pDividend->m_length = length;
503  }
504 
505  // If the dividend is still larger than the divisor, we overshot our estimate quotient. To correct,
506  // we increment the quotient and subtract one more divisor from the dividend.
507  if (BigInt_Compare(*pDividend, divisor) >= 0)
508  {
509  ++quotient;
510 
511  // dividend = dividend - divisor
512  const uint32_t *pDivisorCur = divisor.m_blocks;
513  uint32_t *pDividendCur = pDividend->m_blocks;
514 
515  uint64_t borrow = 0;
516  do
517  {
518  uint64_t difference = (uint64_t)*pDividendCur - (uint64_t)*pDivisorCur - borrow;
519  borrow = (difference >> 32) & 1;
520 
521  *pDividendCur = difference & 0xFFFFFFFF;
522 
523  ++pDivisorCur;
524  ++pDividendCur;
525  } while (pDivisorCur <= pFinalDivisorBlock);
526 
527  // remove all leading zero blocks from dividend
528  while (length > 0 && pDividend->m_blocks[length - 1] == 0)
529  --length;
530 
531  pDividend->m_length = length;
532  }
533 
534  return quotient;
535 }
#define assert(x)
Definition: amath.h:124
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
static int32_t BigInt_Compare(const BigInt &lhs, const BigInt &rhs)
Definition: bigint.cpp:57
uint32_t m_length
Definition: bigint.h:116
bool IsZero() const
Definition: bigint.h:80
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BigInt_Multiply() [1/2]

static void BigInt_Multiply ( BigInt pResult,
const BigInt lhs,
const BigInt rhs 
)
static

Definition at line 142 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by BigInt_MultiplyPow10(), BigInt_Pow10(), and Dragon4().

143 {
144  assert(pResult != &lhs && pResult != &rhs);
145 
146  // determine which operand has the smaller length
147  const BigInt *pLarge;
148  const BigInt *pSmall;
149  if (lhs.m_length < rhs.m_length)
150  {
151  pSmall = &lhs;
152  pLarge = &rhs;
153  }
154  else
155  {
156  pSmall = &rhs;
157  pLarge = &lhs;
158  }
159 
160  // set the maximum possible result length
161  uint32_t maxResultLen = pLarge->m_length + pSmall->m_length;
162  assert(maxResultLen <= c_BigInt_MaxBlocks);
163 
164  // clear the result data
165  for (uint32_t *pCur = pResult->m_blocks, *pEnd = pCur + maxResultLen; pCur != pEnd; ++pCur)
166  *pCur = 0;
167 
168  // perform standard long multiplication
169  const uint32_t *pLargeBeg = pLarge->m_blocks;
170  const uint32_t *pLargeEnd = pLargeBeg + pLarge->m_length;
171 
172  // for each small block
173  uint32_t *pResultStart = pResult->m_blocks;
174  for (const uint32_t *pSmallCur = pSmall->m_blocks, *pSmallEnd = pSmallCur + pSmall->m_length;
175  pSmallCur != pSmallEnd;
176  ++pSmallCur, ++pResultStart)
177  {
178  // if non-zero, multiply against all the large blocks and add into the result
179  const uint32_t multiplier = *pSmallCur;
180  if (multiplier != 0)
181  {
182  const uint32_t *pLargeCur = pLargeBeg;
183  uint32_t *pResultCur = pResultStart;
184  uint64_t carry = 0;
185  do
186  {
187  uint64_t product = (*pResultCur) + (*pLargeCur) * (uint64_t)multiplier + carry;
188  carry = product >> 32;
189  *pResultCur = product & 0xFFFFFFFF;
190  ++pLargeCur;
191  ++pResultCur;
192  } while (pLargeCur != pLargeEnd);
193 
194  assert(pResultCur < pResult->m_blocks + maxResultLen);
195  *pResultCur = (uint32_t)(carry & 0xFFFFFFFF);
196  }
197  }
198 
199  // check if the terminating block has no set bits
200  if (maxResultLen > 0 && pResult->m_blocks[maxResultLen - 1] == 0)
201  pResult->m_length = maxResultLen - 1;
202  else
203  pResult->m_length = maxResultLen;
204 }
#define assert(x)
Definition: amath.h:124
Definition: bigint.h:61
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
const uint32_t c_BigInt_MaxBlocks
Definition: bigint.h:59
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ BigInt_Multiply() [2/2]

static void BigInt_Multiply ( BigInt pResult,
const BigInt lhs,
uint32_t  rhs 
)
static

Definition at line 206 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by BigInt_MultiplyPow10().

207 {
208  // perform long multiplication
209  uint32_t carry = 0;
210  uint32_t *pResultCur = pResult->m_blocks;
211  const uint32_t *pLhsCur = lhs.m_blocks;
212  const uint32_t *pLhsEnd = lhs.m_blocks + lhs.m_length;
213  for (; pLhsCur != pLhsEnd; ++pLhsCur, ++pResultCur)
214  {
215  uint64_t product = (uint64_t)(*pLhsCur) * rhs + carry;
216  *pResultCur = (uint32_t)(product & 0xFFFFFFFF);
217  carry = product >> 32;
218  }
219 
220  // if there is a remaining carry, grow the array
221  if (carry != 0)
222  {
223  // grow the array
224  assert(lhs.m_length + 1 <= c_BigInt_MaxBlocks);
225  *pResultCur = (uint32_t)carry;
226  pResult->m_length = lhs.m_length + 1;
227  }
228  else
229  {
230  pResult->m_length = lhs.m_length;
231  }
232 }
#define assert(x)
Definition: amath.h:124
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
const uint32_t c_BigInt_MaxBlocks
Definition: bigint.h:59
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ BigInt_Multiply10()

static void BigInt_Multiply10 ( BigInt pResult)
static

Definition at line 285 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by Dragon4().

286 {
287  // multiply all the blocks
288  uint64_t carry = 0;
289 
290  uint32_t *pCur = pResult->m_blocks;
291  uint32_t *pEnd = pResult->m_blocks + pResult->m_length;
292  for (; pCur != pEnd; ++pCur)
293  {
294  uint64_t product = (uint64_t)(*pCur) * 10ull + carry;
295  (*pCur) = (uint32_t)(product & 0xFFFFFFFF);
296  carry = product >> 32;
297  }
298 
299  if (carry != 0)
300  {
301  // grow the array
302  assert(pResult->m_length + 1 <= c_BigInt_MaxBlocks);
303  *pCur = (uint32_t)carry;
304  ++pResult->m_length;
305  }
306 }
#define assert(x)
Definition: amath.h:124
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
const uint32_t c_BigInt_MaxBlocks
Definition: bigint.h:59
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ BigInt_Multiply2() [1/2]

static void BigInt_Multiply2 ( BigInt pResult,
const BigInt in 
)
static

Definition at line 234 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by Dragon4().

235 {
236  // shift all the blocks by one
237  uint32_t carry = 0;
238 
239  uint32_t *pResultCur = pResult->m_blocks;
240  const uint32_t *pLhsCur = in.m_blocks;
241  const uint32_t *pLhsEnd = in.m_blocks + in.m_length;
242  for (; pLhsCur != pLhsEnd; ++pLhsCur, ++pResultCur)
243  {
244  uint32_t cur = *pLhsCur;
245  *pResultCur = (cur << 1) | carry;
246  carry = cur >> 31;
247  }
248 
249  if (carry != 0)
250  {
251  // grow the array
253  *pResultCur = carry;
254  pResult->m_length = in.m_length + 1;
255  }
256  else
257  {
258  pResult->m_length = in.m_length;
259  }
260 }
#define assert(x)
Definition: amath.h:124
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
const uint32_t c_BigInt_MaxBlocks
Definition: bigint.h:59
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ BigInt_Multiply2() [2/2]

static void BigInt_Multiply2 ( BigInt pResult)
static

Definition at line 262 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by Dragon4().

263 {
264  // shift all the blocks by one
265  uint32_t carry = 0;
266 
267  uint32_t *pCur = pResult->m_blocks;
268  uint32_t *pEnd = pResult->m_blocks + pResult->m_length;
269  for (; pCur != pEnd; ++pCur)
270  {
271  uint32_t cur = *pCur;
272  *pCur = (cur << 1) | carry;
273  carry = cur >> 31;
274  }
275 
276  if (carry != 0)
277  {
278  // grow the array
279  assert(pResult->m_length + 1 <= c_BigInt_MaxBlocks);
280  *pCur = carry;
281  ++pResult->m_length;
282  }
283 }
#define assert(x)
Definition: amath.h:124
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
const uint32_t c_BigInt_MaxBlocks
Definition: bigint.h:59
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ BigInt_MultiplyPow10()

static void BigInt_MultiplyPow10 ( BigInt pResult,
const BigInt in,
uint32_t  exponent 
)
static

Definition at line 388 of file bigint.cpp.

References BigInt_Multiply(), g_PowerOf10_Big, g_PowerOf10_U32, and BigInt::operator=().

Referenced by Dragon4().

389 {
390  // make sure the exponent is within the bounds of the lookup table data
391  assert(exponent < 512);
392 
393  // create two temporary values to reduce large integer copy operations
394  BigInt temp1;
395  BigInt temp2;
396  BigInt *pCurTemp = &temp1;
397  BigInt *pNextTemp = &temp2;
398 
399  // initialize the result by looking up a 32-bit power of 10 corresponding to the first 3 bits
400  uint32_t smallExponent = exponent & 0x7;
401  if (smallExponent != 0)
402  {
403  BigInt_Multiply(pCurTemp, in, g_PowerOf10_U32[smallExponent]);
404  }
405  else
406  {
407  *pCurTemp = in;
408  }
409 
410  // remove the low bits that we used for the 32-bit lookup table
411  exponent >>= 3;
412  uint32_t tableIdx = 0;
413 
414  // while there are remaining bits in the exponent to be processed
415  while (exponent != 0)
416  {
417  // if the current bit is set, multiply it with the corresponding power of 10
418  if (exponent & 1)
419  {
420  // multiply into the next temporary
421  BigInt_Multiply(pNextTemp, *pCurTemp, g_PowerOf10_Big[tableIdx]);
422 
423  // swap to the next temporary
424  BigInt *pSwap = pCurTemp;
425  pCurTemp = pNextTemp;
426  pNextTemp = pSwap;
427  }
428 
429  // advance to the next bit
430  ++tableIdx;
431  exponent >>= 1;
432  }
433 
434  // output the result
435  *pResult = *pCurTemp;
436 }
#define assert(x)
Definition: amath.h:124
static void BigInt_Multiply(BigInt *pResult, const BigInt &lhs, const BigInt &rhs)
Definition: bigint.cpp:142
Definition: bigint.h:61
static uint32_t g_PowerOf10_U32[]
Definition: bigint.cpp:308
static BigInt g_PowerOf10_Big[]
Definition: bigint.cpp:320
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BigInt_Pow10()

static void BigInt_Pow10 ( BigInt pResult,
uint32_t  exponent 
)
static

Definition at line 345 of file bigint.cpp.

References BigInt_Multiply(), g_PowerOf10_Big, g_PowerOf10_U32, BigInt::operator=(), and BigInt::SetUInt32().

Referenced by Dragon4().

346 {
347  // make sure the exponent is within the bounds of the lookup table data
348  assert(exponent < 512);
349 
350  // create two temporary values to reduce large integer copy operations
351  BigInt temp1;
352  BigInt temp2;
353  BigInt *pCurTemp = &temp1;
354  BigInt *pNextTemp = &temp2;
355 
356  // initialize the result by looking up a 32-bit power of 10 corresponding to the first 3 bits
357  uint32_t smallExponent = exponent & 0x7;
358  pCurTemp->SetUInt32(g_PowerOf10_U32[smallExponent]);
359 
360  // remove the low bits that we used for the 32-bit lookup table
361  exponent >>= 3;
362  uint32_t tableIdx = 0;
363 
364  // while there are remaining bits in the exponent to be processed
365  while (exponent != 0)
366  {
367  // if the current bit is set, multiply it with the corresponding power of 10
368  if (exponent & 1)
369  {
370  // multiply into the next temporary
371  BigInt_Multiply(pNextTemp, *pCurTemp, g_PowerOf10_Big[tableIdx]);
372 
373  // swap to the next temporary
374  BigInt *pSwap = pCurTemp;
375  pCurTemp = pNextTemp;
376  pNextTemp = pSwap;
377  }
378 
379  // advance to the next bit
380  ++tableIdx;
381  exponent >>= 1;
382  }
383 
384  // output the result
385  *pResult = *pCurTemp;
386 }
#define assert(x)
Definition: amath.h:124
static void BigInt_Multiply(BigInt *pResult, const BigInt &lhs, const BigInt &rhs)
Definition: bigint.cpp:142
Definition: bigint.h:61
void SetUInt32(uint32_t val)
Definition: bigint.h:101
static uint32_t g_PowerOf10_U32[]
Definition: bigint.cpp:308
static BigInt g_PowerOf10_Big[]
Definition: bigint.cpp:320
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BigInt_Pow2()

static void BigInt_Pow2 ( BigInt pResult,
uint32_t  exponent 
)
inlinestatic

Definition at line 438 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by Dragon4().

439 {
440  uint32_t blockIdx = exponent / 32;
441  assert(blockIdx < c_BigInt_MaxBlocks);
442 
443  for (uint32_t i = 0; i <= blockIdx; ++i)
444  pResult->m_blocks[i] = 0;
445 
446  pResult->m_length = blockIdx + 1;
447 
448  uint32_t bitIdx = (exponent % 32);
449  pResult->m_blocks[blockIdx] |= (1 << bitIdx);
450 }
#define assert(x)
Definition: amath.h:124
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
const uint32_t c_BigInt_MaxBlocks
Definition: bigint.h:59
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ BigInt_ShiftLeft()

static void BigInt_ShiftLeft ( BigInt pResult,
uint32_t  shift 
)
static

Definition at line 537 of file bigint.cpp.

References BigInt::m_blocks, and BigInt::m_length.

Referenced by Dragon4().

538 {
539  assert(shift != 0);
540 
541  uint32_t shifboollocks = shift / 32;
542  uint32_t shifboolits = shift % 32;
543 
544  // process blocks high to low so that we can safely process in place
545  const uint32_t *pInBlocks = pResult->m_blocks;
546  int32_t inLength = pResult->m_length;
547  assert(inLength + shifboollocks < c_BigInt_MaxBlocks);
548 
549  // check if the shift is block aligned
550  if (shifboolits == 0)
551  {
552  // copy blcoks from high to low
553  for (uint32_t *pInCur = pResult->m_blocks + inLength, *pOutCur = pInCur + shifboollocks;
554  pInCur >= pInBlocks;
555  --pInCur, --pOutCur)
556  {
557  *pOutCur = *pInCur;
558  }
559 
560  // zero the remaining low blocks
561  for (uint32_t i = 0; i < shifboollocks; ++i)
562  pResult->m_blocks[i] = 0;
563 
564  pResult->m_length += shifboollocks;
565  }
566  // else we need to shift partial blocks
567  else
568  {
569  int32_t inBlockIdx = inLength - 1;
570  uint32_t ouboollockIdx = inLength + shifboollocks;
571 
572  // set the length to hold the shifted blocks
573  assert(ouboollockIdx < c_BigInt_MaxBlocks);
574  pResult->m_length = ouboollockIdx + 1;
575 
576  // output the initial blocks
577  const uint32_t lowBitsShift = (32 - shifboolits);
578  uint32_t highBits = 0;
579  uint32_t block = pResult->m_blocks[inBlockIdx];
580  uint32_t lowBits = block >> lowBitsShift;
581  while (inBlockIdx > 0)
582  {
583  pResult->m_blocks[ouboollockIdx] = highBits | lowBits;
584  highBits = block << shifboolits;
585 
586  --inBlockIdx;
587  --ouboollockIdx;
588 
589  block = pResult->m_blocks[inBlockIdx];
590  lowBits = block >> lowBitsShift;
591  }
592 
593  // output the final blocks
594  assert(ouboollockIdx == shifboollocks + 1);
595  pResult->m_blocks[ouboollockIdx] = highBits | lowBits;
596  pResult->m_blocks[ouboollockIdx - 1] = block << shifboolits;
597 
598  // zero the remaining low blocks
599  for (uint32_t i = 0; i < shifboollocks; ++i)
600  pResult->m_blocks[i] = 0;
601 
602  // check if the terminating block has no set bits
603  if (pResult->m_blocks[pResult->m_length - 1] == 0)
604  --pResult->m_length;
605  }
606 }
#define assert(x)
Definition: amath.h:124
uint32_t m_blocks[c_BigInt_MaxBlocks]
Definition: bigint.h:117
const uint32_t c_BigInt_MaxBlocks
Definition: bigint.h:59
uint32_t m_length
Definition: bigint.h:116
Here is the caller graph for this function:

◆ Dragon4()

uint32_t Dragon4 ( const uint64_t  mantissa,
const int32_t  exponent,
const uint32_t  mantissaHighBitIdx,
const bool  hasUnequalMargins,
const tCutoffMode  cutoffMode,
uint32_t  cutoffNumber,
char *  pOubooluffer,
uint32_t  bufferSize,
int32_t *  pOutExponent 
)

Definition at line 608 of file bigint.cpp.

References BigInt_Add(), BigInt_Compare(), BigInt_DivideWithRemainder_MaxQuotient9(), BigInt_Multiply(), BigInt_Multiply10(), BigInt_Multiply2(), BigInt_MultiplyPow10(), BigInt_Pow10(), BigInt_Pow2(), BigInt_ShiftLeft(), ceil(), CutoffMode_FractionLength, CutoffMode_TotalLength, CutoffMode_Unique, BigInt::Geboollock(), BigInt::GetLength(), BigInt::IsZero(), log2i(), BigInt::operator=(), BigInt::SetUInt32(), and BigInt::SetUInt64().

Referenced by DecimalSystem::GetText().

619 {
620  char *pCurDigit = pOubooluffer;
621 
622  assert(bufferSize > 0);
623 
624  // if the mantissa is zero, the value is zero regardless of the exponent
625  if (mantissa == 0)
626  {
627  *pCurDigit = '0';
628  *pOutExponent = 0;
629  return 1;
630  }
631 
632  // compute the initial state in integral form such that
633  // value = scaledValue / scale
634  // marginLow = scaledMarginLow / scale
635  BigInt scale; // positive scale applied to value and margin such that they can be
636  // represented as whole numbers
637  BigInt scaledValue; // scale * mantissa
638  BigInt scaledMarginLow; // scale * 0.5 * (distance between this floating-point number and its
639  // immediate lower value)
640 
641  // For normalized IEEE floating point values, each time the exponent is incremented the margin also
642  // doubles. That creates a subset of transition numbers where the high margin is twice the size of
643  // the low margin.
644  BigInt *pScaledMarginHigh;
645  BigInt optionalMarginHigh;
646 
647  if (hasUnequalMargins)
648  {
649  // if we have no fractional component
650  if (exponent > 0)
651  {
652  // 1) Expand the input value by multiplying out the mantissa and exponent. This represents
653  // the input value in its whole number representation.
654  // 2) Apply an additional scale of 2 such that later comparisons against the margin values
655  // are simplified.
656  // 3) Set the margin value to the lowest mantissa bit's scale.
657 
658  // scaledValue = 2 * 2 * mantissa*2^exponent
659  scaledValue.SetUInt64(4 * mantissa);
660  BigInt_ShiftLeft(&scaledValue, exponent);
661 
662  // scale = 2 * 2 * 1
663  scale.SetUInt32(4);
664 
665  // scaledMarginLow = 2 * 2^(exponent-1)
666  BigInt_Pow2(&scaledMarginLow, exponent);
667 
668  // scaledMarginHigh = 2 * 2 * 2^(exponent-1)
669  BigInt_Pow2(&optionalMarginHigh, exponent + 1);
670  }
671  // else we have a fractional exponent
672  else
673  {
674  // In order to track the mantissa data as an integer, we store it as is with a large scale
675 
676  // scaledValue = 2 * 2 * mantissa
677  scaledValue.SetUInt64(4 * mantissa);
678 
679  // scale = 2 * 2 * 2^(-exponent)
680  BigInt_Pow2(&scale, -exponent + 2);
681 
682  // scaledMarginLow = 2 * 2^(-1)
683  scaledMarginLow.SetUInt32(1);
684 
685  // scaledMarginHigh = 2 * 2 * 2^(-1)
686  optionalMarginHigh.SetUInt32(2);
687  }
688 
689  // the high and low margins are different
690  pScaledMarginHigh = &optionalMarginHigh;
691  }
692  else
693  {
694  // if we have no fractional component
695  if (exponent > 0)
696  {
697  // 1) Expand the input value by multiplying out the mantissa and exponent. This represents
698  // the input value in its whole number representation.
699  // 2) Apply an additional scale of 2 such that later comparisons against the margin values
700  // are simplified.
701  // 3) Set the margin value to the lowest mantissa bit's scale.
702 
703  // scaledValue = 2 * mantissa*2^exponent
704  scaledValue.SetUInt64(2 * mantissa);
705  BigInt_ShiftLeft(&scaledValue, exponent);
706 
707  // scale = 2 * 1
708  scale.SetUInt32(2);
709 
710  // scaledMarginLow = 2 * 2^(exponent-1)
711  BigInt_Pow2(&scaledMarginLow, exponent);
712  }
713  // else we have a fractional exponent
714  else
715  {
716  // In order to track the mantissa data as an integer, we store it as is with a large scale
717 
718  // scaledValue = 2 * mantissa
719  scaledValue.SetUInt64(2 * mantissa);
720 
721  // scale = 2 * 2^(-exponent)
722  BigInt_Pow2(&scale, -exponent + 1);
723 
724  // scaledMarginLow = 2 * 2^(-1)
725  scaledMarginLow.SetUInt32(1);
726  }
727 
728  // the high and low margins are equal
729  pScaledMarginHigh = &scaledMarginLow;
730  }
731 
732  // Compute an estimate for digitExponent that will be correct or undershoot by one.
733  // This optimization is based on the paper "Printing Floating-Point Numbers Quickly and Accurately"
734  // by Burger and Dybvig http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.72.4656&rep=rep1&type=pdf
735  // We perform an additional subtraction of 0.69 to increase the frequency of a failed estimate
736  // because that lets us take a faster branch in the code. 0.69 is chosen because 0.69 + log10(2) is
737  // less than one by a reasonable epsilon that will account for any floating point error.
738  //
739  // We want to set digitExponent to floor(log10(v)) + 1
740  // v = mantissa*2^exponent
741  // log2(v) = log2(mantissa) + exponent;
742  // log10(v) = log2(v) * log10(2)
743  // floor(log2(v)) = mantissaHighBitIdx + exponent;
744  // log10(v) - log10(2) < (mantissaHighBitIdx + exponent) * log10(2) <= log10(v)
745  // log10(v) < (mantissaHighBitIdx + exponent) * log10(2) + log10(2) <= log10(v) + log10(2)
746  // floor( log10(v) ) < ceil( (mantissaHighBitIdx + exponent) * log10(2) ) <= floor( log10(v) ) + 1
747  const double log10_2 = 0.30102999566398119521373889472449;
748  int32_t digitExponent = (int32_t)(ceil(double((int32_t)mantissaHighBitIdx + exponent) * log10_2 - 0.69));
749 
750  // if the digit exponent is smaller than the smallest desired digit for fractional cutoff,
751  // pull the digit back into legal range at which point we will round to the appropriate value.
752  // Note that while our value for digitExponent is still an estimate, this is safe because it
753  // only increases the number. This will either correct digitExponent to an accurate value or it
754  // will clamp it above the accurate value.
755  if (cutoffMode == CutoffMode_FractionLength && digitExponent <= -(int32_t)cutoffNumber)
756  {
757  digitExponent = -(int32_t)cutoffNumber + 1;
758  }
759 
760  // Divide value by 10^digitExponent.
761  if (digitExponent > 0)
762  {
763  // The exponent is positive creating a division so we multiply up the scale.
764  BigInt temp;
765  BigInt_MultiplyPow10(&temp, scale, digitExponent);
766  scale = temp;
767  }
768  else if (digitExponent < 0)
769  {
770  // The exponent is negative creating a multiplication so we multiply up the scaledValue,
771  // scaledMarginLow and scaledMarginHigh.
772  BigInt pow10;
773  BigInt_Pow10(&pow10, -digitExponent);
774 
775  BigInt temp;
776  BigInt_Multiply(&temp, scaledValue, pow10);
777  scaledValue = temp;
778 
779  BigInt_Multiply(&temp, scaledMarginLow, pow10);
780  scaledMarginLow = temp;
781 
782  if (pScaledMarginHigh != &scaledMarginLow)
783  BigInt_Multiply2(pScaledMarginHigh, scaledMarginLow);
784  }
785 
786  // If (value >= 1), our estimate for digitExponent was too low
787  if (BigInt_Compare(scaledValue, scale) >= 0)
788  {
789  // The exponent estimate was incorrect.
790  // Increment the exponent and don't perform the premultiply needed
791  // for the first loop iteration.
792  digitExponent = digitExponent + 1;
793  }
794  else
795  {
796  // The exponent estimate was correct.
797  // Multiply larger by the output base to prepare for the first loop iteration.
798  BigInt_Multiply10(&scaledValue);
799  BigInt_Multiply10(&scaledMarginLow);
800  if (pScaledMarginHigh != &scaledMarginLow)
801  BigInt_Multiply2(pScaledMarginHigh, scaledMarginLow);
802  }
803 
804  // Compute the cutoff exponent (the exponent of the final digit to print).
805  // Default to the maximum size of the output buffer.
806  int32_t cutoffExponent = digitExponent - bufferSize;
807  switch (cutoffMode)
808  {
809  // print digits until we pass the accuracy margin limits or buffer size
810  case CutoffMode_Unique:
811  break;
812 
813  // print cutoffNumber of digits or until we reach the buffer size
815  {
816  int32_t desiredCutoffExponent = digitExponent - (int32_t)cutoffNumber;
817  if (desiredCutoffExponent > cutoffExponent)
818  cutoffExponent = desiredCutoffExponent;
819  }
820  break;
821 
822  // print cutoffNumber digits past the decimal point or until we reach the buffer size
824  {
825  int32_t desiredCutoffExponent = -(int32_t)cutoffNumber;
826  if (desiredCutoffExponent > cutoffExponent)
827  cutoffExponent = desiredCutoffExponent;
828  }
829  break;
830  }
831 
832  // Output the exponent of the first digit we will print
833  *pOutExponent = digitExponent - 1;
834 
835  // In preparation for calling BigInt_DivideWithRemainder_MaxQuotient9(),
836  // we need to scale up our values such that the highest block of the denominator
837  // is greater than or equal to 8. We also need to guarantee that the numerator
838  // can never have a length greater than the denominator after each loop iteration.
839  // This requires the highest block of the denominator to be less than or equal to
840  // 429496729 which is the highest number that can be multiplied by 10 without
841  // overflowing to a new block.
842  assert(scale.GetLength() > 0);
843  uint32_t hiBlock = scale.Geboollock(scale.GetLength() - 1);
844  if (hiBlock < 8 || hiBlock > 429496729)
845  {
846  // Perform a bit shift on all values to get the highest block of the denominator into
847  // the range [8,429496729]. We are more likely to make accurate quotient estimations
848  // in BigInt_DivideWithRemainder_MaxQuotient9() with higher denominator values so
849  // we shift the denominator to place the highest bit at index 27 of the highest block.
850  // This is safe because (2^28 - 1) = 268435455 which is less than 429496729. This means
851  // that all values with a highest bit at index 27 are within range.
852  uint32_t hiBlockLog2 = log2i(hiBlock);
853  assert(hiBlockLog2 < 3 || hiBlockLog2 > 27);
854  uint32_t shift = (32 + 27 - hiBlockLog2) % 32;
855 
856  BigInt_ShiftLeft(&scale, shift);
857  BigInt_ShiftLeft(&scaledValue, shift);
858  BigInt_ShiftLeft(&scaledMarginLow, shift);
859  if (pScaledMarginHigh != &scaledMarginLow)
860  BigInt_Multiply2(pScaledMarginHigh, scaledMarginLow);
861  }
862 
863  // These values are used to inspect why the print loop terminated so we can properly
864  // round the final digit.
865  bool low; // did the value get within marginLow distance from zero
866  bool high; // did the value get within marginHigh distance from one
867  uint32_t outputDigit; // current digit being output
868 
869  if (cutoffMode == CutoffMode_Unique)
870  {
871  // For the unique cutoff mode, we will try to print until we have reached a level of
872  // precision that uniquely distinguishes this value from its neighbors. If we run
873  // out of space in the output buffer, we terminate early.
874  for (;;)
875  {
876  digitExponent = digitExponent - 1;
877 
878  // divide out the scale to extract the digit
879  outputDigit = BigInt_DivideWithRemainder_MaxQuotient9(&scaledValue, scale);
880  assert(outputDigit < 10);
881 
882  // update the high end of the value
883  BigInt scaledValueHigh;
884  BigInt_Add(&scaledValueHigh, scaledValue, *pScaledMarginHigh);
885 
886  // stop looping if we are far enough away from our neighboring values
887  // or if we have reached the cutoff digit
888  low = BigInt_Compare(scaledValue, scaledMarginLow) < 0;
889  high = BigInt_Compare(scaledValueHigh, scale) > 0;
890  if (low | high | (digitExponent == cutoffExponent))
891  break;
892 
893  // store the output digit
894  *pCurDigit = (char)('0' + outputDigit);
895  ++pCurDigit;
896 
897  // multiply larger by the output base
898  BigInt_Multiply10(&scaledValue);
899  BigInt_Multiply10(&scaledMarginLow);
900  if (pScaledMarginHigh != &scaledMarginLow)
901  BigInt_Multiply2(pScaledMarginHigh, scaledMarginLow);
902  }
903  }
904  else
905  {
906  // For length based cutoff modes, we will try to print until we
907  // have exhausted all precision (i.e. all remaining digits are zeros) or
908  // until we reach the desired cutoff digit.
909  low = false;
910  high = false;
911 
912  for (;;)
913  {
914  digitExponent = digitExponent - 1;
915 
916  // divide out the scale to extract the digit
917  outputDigit = BigInt_DivideWithRemainder_MaxQuotient9(&scaledValue, scale);
918  assert(outputDigit < 10);
919 
920  if (scaledValue.IsZero() | (digitExponent == cutoffExponent))
921  break;
922 
923  // store the output digit
924  *pCurDigit = (char)('0' + outputDigit);
925  ++pCurDigit;
926 
927  // multiply larger by the output base
928  BigInt_Multiply10(&scaledValue);
929  }
930  }
931 
932  // round off the final digit
933  // default to rounding down if value got too close to 0
934  bool roundDown = low;
935 
936  // if it is legal to round up and down
937  if (low == high)
938  {
939  // round to the closest digit by comparing value with 0.5. To do this we need to convert
940  // the inequality to large integer values.
941  // compare( value, 0.5 )
942  // compare( scale * value, scale * 0.5 )
943  // compare( 2 * scale * value, scale )
944  BigInt_Multiply2(&scaledValue);
945  int32_t compare = BigInt_Compare(scaledValue, scale);
946  roundDown = compare < 0;
947 
948  // if we are directly in the middle, round towards the even digit (i.e. IEEE rouding rules)
949  if (compare == 0)
950  roundDown = (outputDigit & 1) == 0;
951  }
952 
953  // print the rounded digit
954  if (roundDown)
955  {
956  *pCurDigit = (char)('0' + outputDigit);
957  ++pCurDigit;
958  }
959  else
960  {
961  // handle rounding up
962  if (outputDigit == 9)
963  {
964  // find the first non-nine prior digit
965  for (;;)
966  {
967  // if we are at the first digit
968  if (pCurDigit == pOubooluffer)
969  {
970  // output 1 at the next highest exponent
971  *pCurDigit = '1';
972  ++pCurDigit;
973  *pOutExponent += 1;
974  break;
975  }
976 
977  --pCurDigit;
978  if (*pCurDigit != '9')
979  {
980  // increment the digit
981  *pCurDigit += 1;
982  ++pCurDigit;
983  break;
984  }
985  }
986  }
987  else
988  {
989  // values in the range [0,8] can perform a simple round up
990  *pCurDigit = (char)('0' + outputDigit + 1);
991  ++pCurDigit;
992  }
993  }
994 
995  // return the number of digits output
996  uint32_t outputLen = (uint32_t)(pCurDigit - pOubooluffer);
997  assert(outputLen <= bufferSize);
998  return outputLen;
999 }
#define assert(x)
Definition: amath.h:124
static void BigInt_ShiftLeft(BigInt *pResult, uint32_t shift)
Definition: bigint.cpp:537
double ceil(double x)
Ceiling function.
Definition: ceil.c:63
static void BigInt_Multiply10(BigInt *pResult)
Definition: bigint.cpp:285
static void BigInt_Multiply(BigInt *pResult, const BigInt &lhs, const BigInt &rhs)
Definition: bigint.cpp:142
Definition: bigint.h:61
uint32_t Geboollock(uint32_t idx) const
Definition: bigint.h:78
uint32_t GetLength() const
Definition: bigint.h:77
static void BigInt_Add(BigInt *pResult, const BigInt &lhs, const BigInt &rhs)
Definition: bigint.cpp:79
void SetUInt32(uint32_t val)
Definition: bigint.h:101
unsigned int log2i(unsigned int x)
static void BigInt_MultiplyPow10(BigInt *pResult, const BigInt &in, uint32_t exponent)
Definition: bigint.cpp:388
static int32_t BigInt_Compare(const BigInt &lhs, const BigInt &rhs)
Definition: bigint.cpp:57
static void BigInt_Multiply2(BigInt *pResult, const BigInt &in)
Definition: bigint.cpp:234
static void BigInt_Pow10(BigInt *pResult, uint32_t exponent)
Definition: bigint.cpp:345
void SetUInt64(uint64_t val)
Definition: bigint.h:82
bool IsZero() const
Definition: bigint.h:80
static void BigInt_Pow2(BigInt *pResult, uint32_t exponent)
Definition: bigint.cpp:438
static uint32_t BigInt_DivideWithRemainder_MaxQuotient9(BigInt *pDividend, const BigInt &divisor)
Definition: bigint.cpp:452
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ g_PowerOf10_Big

BigInt g_PowerOf10_Big[]
static
Initial value:
=
{
{1,
{100000000}},
{2,
{0x6fc10000, 0x002386f2}},
{4, {
0x00000000, 0x85acef81, 0x2d6d415b, 0x000004ee,
}},
{7, {
0x00000000, 0x00000000, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x00184f03,
}},
{14, {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2e953e01, 0x03df9909, 0x0f1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, 0xa6337f19, 0xe91f2603, 0x0000024e,
}},
{27, {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x000553f7,
}}}

Definition at line 320 of file bigint.cpp.

Referenced by BigInt_MultiplyPow10(), and BigInt_Pow10().

◆ g_PowerOf10_U32

uint32_t g_PowerOf10_U32[]
static
Initial value:
=
{
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
}

Definition at line 308 of file bigint.cpp.

Referenced by BigInt_MultiplyPow10(), and BigInt_Pow10().