1 // http://www.fractal-landscapes.co.uk/bigint.html
\r
8 /// Specifies the desired precision for a BigInt or a BigFloat.
\r
10 public struct PrecisionSpec
\r
13 /// Precision can be specified in a choice of 8 bases.
\r
14 /// Note that precision for decimals is approximate.
\r
16 public enum BaseType
\r
31 /// Hexadecimal base
\r
35 /// 8-bits per digit
\r
39 /// 16-bits per digit
\r
43 /// 32-bits per digit
\r
47 /// 64-bits per digit
\r
53 /// Constructor: Constructs a precision specification
\r
55 /// <param name="precision">The number of digits</param>
\r
56 /// <param name="numberBase">The base of the digits</param>
\r
57 public PrecisionSpec(int precision, BaseType numberBase)
\r
59 this.prec = precision;
\r
60 this.nB = numberBase;
\r
64 /// Explicit cast from integer value.
\r
66 /// <param name="value">The value in bits for the new precision specification</param>
\r
67 /// <returns>A new precision specification with the number of bits specified</returns>
\r
68 public static explicit operator PrecisionSpec(int value)
\r
70 return new PrecisionSpec(value, BaseType.BIN);
\r
76 /// <param name="spec1">the first parameter</param>
\r
77 /// <param name="spec2">the second parameter</param>
\r
78 /// <returns>true iff both precisions have the same number of bits</returns>
\r
79 public static bool operator ==(PrecisionSpec spec1, PrecisionSpec spec2)
\r
81 return (spec1.NumBits == spec2.NumBits);
\r
85 /// Inequality operator
\r
87 /// <param name="spec1">the first parameter</param>
\r
88 /// <param name="spec2">the second parameter</param>
\r
89 /// <returns>true iff the parameters do not have the same number of bits</returns>
\r
90 public static bool operator !=(PrecisionSpec spec1, PrecisionSpec spec2)
\r
92 return !(spec1 == spec2);
\r
96 /// Object equality override
\r
98 /// <param name="obj">the PrecisionSpec struct to compare</param>
\r
99 /// <returns>true iff obj has the same number of bits as this</returns>
\r
100 public override bool Equals(object obj)
\r
102 return NumBits == ((PrecisionSpec)obj).NumBits;
\r
106 /// Override of the hash code
\r
108 /// <returns>A basic hash</returns>
\r
109 public override int GetHashCode()
\r
111 return NumBits * prec + NumBits;
\r
115 /// The precision in units specified by the base type (e.g. number of decimal digits)
\r
117 public int Precision
\r
119 get { return prec; }
\r
123 /// The base type in which precision is specified
\r
125 public BaseType NumberBaseType
\r
131 /// Converts the number-base to an integer
\r
133 public int NumberBase
\r
135 get { return (int)nB; }
\r
139 /// The number of bits that this PrecisionSpec structure specifies.
\r
145 if (nB == BaseType.BIN) return prec;
\r
146 if (nB == BaseType.OCT) return prec * 3;
\r
147 if (nB == BaseType.HEX) return prec * 4;
\r
148 if (nB == BaseType.BYTES) return prec * 8;
\r
149 if (nB == BaseType.WORDS) return prec * 16;
\r
150 if (nB == BaseType.DWORDS) return prec * 32;
\r
151 if (nB == BaseType.QWORDS) return prec * 64;
\r
153 double factor = 3.322;
\r
154 int bits = ((int)Math.Ceiling(factor * (double)prec));
\r
160 private BaseType nB;
\r
165 /// An arbitrary-precision integer class
\r
168 /// Each number consists of an array of 32-bit unsigned integers, and a bool sign
\r
171 /// Applicability and Performance:
\r
172 /// This class is designed to be used for small extended precisions. It may not be
\r
173 /// safe (and certainly won't be fast) to use it with mixed-precision arguments.
\r
174 /// It does support, but will not be efficient for, numbers over around 2048 bits.
\r
177 /// All conversions to and from strings are slow.
\r
179 /// Conversions from simple integer types Int32, Int64, UInt32, UInt64 are performed
\r
180 /// using the appropriate constructor, and are relatively fast.
\r
182 /// The class is written entirely in managed C# code, with not native or managed
\r
183 /// assembler. The use of native assembler would speed up the multiplication operations
\r
184 /// many times over, and therefore all higher-order operations too.
\r
186 public class BigInt
\r
188 //*************** Constructors ******************
\r
191 /// Constructs an empty BigInt to the desired precision.
\r
193 /// <param name="precision"></param>
\r
194 public BigInt(PrecisionSpec precision)
\r
200 /// Constructs a BigInt from a string, using the string length to determine the precision
\r
201 /// Note, operations on BigInts of non-matching precision are slow, so avoid using this constructor
\r
203 /// <param name="init"></param>
\r
204 public BigInt(string init)
\r
206 InitFromString(init, (PrecisionSpec)init.Length, 10);
\r
210 /// Constructor for copying length and precision
\r
212 /// <param name="inputToCopy">The BigInt to copy</param>
\r
213 /// <param name="precision">The precision of the new BigInt</param>
\r
214 /// <param name="bCopyLengthOnly">decides whether to copy the actual input, or just its digit length</param>
\r
215 /// <example><code>//Create an integer
\r
216 /// BigInt four = new BigInt(4, new PrecisionSpec(128, PrecisionSpec.BaseType.BIN));
\r
218 /// //Pad four to double its usual number of digits (this does not affect the precision)
\r
221 /// //Create a new, empty integer with matching precision, also padded to twice the usual length
\r
222 /// BigInt newCopy = new BigInt(four, four.Precision, true);</code></example>
\r
223 public BigInt(BigInt inputToCopy, PrecisionSpec precision, bool bCopyLengthOnly)
\r
225 digitArray = new uint[inputToCopy.digitArray.Length];
\r
226 workingSet = new uint[inputToCopy.digitArray.Length];
\r
227 if (!bCopyLengthOnly) Array.Copy(inputToCopy.digitArray, digitArray, digitArray.Length);
\r
228 sign = inputToCopy.sign;
\r
229 pres = inputToCopy.pres;
\r
233 /// Constructs a bigint from the string, with the desired precision, using base 10
\r
235 /// <param name="init"></param>
\r
236 /// <param name="precision"></param>
\r
237 public BigInt(string init, PrecisionSpec precision)
\r
239 InitFromString(init, precision, 10);
\r
243 /// Constructs a BigInt from a string, using the specified precision and base
\r
245 /// <param name="init"></param>
\r
246 /// <param name="precision"></param>
\r
247 /// <param name="numberBase"></param>
\r
248 public BigInt(string init, PrecisionSpec precision, int numberBase)
\r
250 InitFromString(init, precision, numberBase);
\r
254 /// Constructs a bigint from the input.
\r
256 /// <param name="input"></param>
\r
257 public BigInt(BigInt input)
\r
259 digitArray = new uint[input.digitArray.Length];
\r
260 workingSet = new uint[input.digitArray.Length];
\r
261 Array.Copy(input.digitArray, digitArray, digitArray.Length);
\r
267 /// Constructs a bigint from the input, matching the new precision provided
\r
269 public BigInt(BigInt input, PrecisionSpec precision)
\r
271 //Casts the input to the new precision.
\r
273 int Min = (input.digitArray.Length < digitArray.Length) ? input.digitArray.Length : digitArray.Length;
\r
275 for (int i = 0; i < Min; i++)
\r
277 digitArray[i] = input.digitArray[i];
\r
284 /// Constructs a BigInt from a UInt32
\r
286 /// <param name="input"></param>
\r
287 /// <param name="precision"></param>
\r
288 public BigInt(UInt32 input, PrecisionSpec precision)
\r
291 digitArray[0] = input;
\r
295 /// Constructs a BigInt from a UInt64
\r
297 /// <param name="input"></param>
\r
298 /// <param name="precision"></param>
\r
299 public BigInt(UInt64 input, PrecisionSpec precision)
\r
302 digitArray[0] = (UInt32)(input & 0xffffffff);
\r
303 if (digitArray.Length > 1) digitArray[1] = (UInt32)(input >> 32);
\r
307 /// Constructs a BigInt from an Int32
\r
309 /// <param name="input"></param>
\r
310 /// <param name="precision"></param>
\r
311 public BigInt(Int32 input, PrecisionSpec precision)
\r
318 if (input == Int32.MinValue)
\r
320 digitArray[0] = 0x80000000;
\r
324 digitArray[0] = (UInt32)(-input);
\r
329 digitArray[0] = ((UInt32)input);
\r
334 /// Constructs a BigInt from a UInt32
\r
336 /// <param name="input"></param>
\r
337 /// <param name="precision"></param>
\r
338 public BigInt(Int64 input, PrecisionSpec precision)
\r
341 if (input < 0) sign = true;
\r
343 digitArray[0] = (UInt32)(input & 0xffffffff);
\r
345 if (digitArray.Length >= 2)
\r
347 if (input == Int64.MinValue)
\r
349 digitArray[1] = 0x80000000;
\r
353 digitArray[1] = (UInt32)((input >> 32) & 0x7fffffff);
\r
358 //***************** Properties *******************
\r
361 /// true iff the number is negative
\r
363 public bool Sign { get { return sign; } set { sign = value; } }
\r
366 /// The precision of the number.
\r
368 public PrecisionSpec Precision { get { return pres; } }
\r
370 //*************** Utility Functions **************
\r
373 /// Casts a BigInt to the new precision provided.
\r
374 /// Note: This will return the input if the precision already matches.
\r
376 /// <param name="input"></param>
\r
377 /// <param name="precision"></param>
\r
378 /// <returns></returns>
\r
379 public static BigInt CastToPrecision(BigInt input, PrecisionSpec precision)
\r
381 if (input.pres == precision) return input;
\r
382 return new BigInt(input, precision);
\r
386 //*************** Member Functions ***************
\r
389 /// Addition and assignment - without intermediate memory allocation.
\r
391 /// <param name="n2"></param>
\r
392 /// <returns></returns>
\r
393 public uint Add(BigInt n2)
\r
395 if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);
\r
397 if (sign == n2.sign)
\r
399 return AddInternalBits(n2.digitArray);
\r
403 bool lessThan = LtInt(this, n2);
\r
407 int Length = digitArray.Length;
\r
409 for (int i = 0; i < Length; i++)
\r
411 workingSet[i] = digitArray[i];
\r
412 digitArray[i] = n2.digitArray[i];
\r
416 return SubInternalBits(workingSet);
\r
420 return SubInternalBits(n2.digitArray);
\r
426 /// Subtraction and assignment - without intermediate memory allocation.
\r
428 /// <param name="n2"></param>
\r
429 public uint Sub(BigInt n2)
\r
431 if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);
\r
433 if (sign != n2.sign)
\r
435 return AddInternalBits(n2.digitArray);
\r
439 bool lessThan = LtInt(this, n2);
\r
443 int Length = digitArray.Length;
\r
445 for (int i = 0; i < Length; i++)
\r
447 workingSet[i] = digitArray[i];
\r
448 digitArray[i] = n2.digitArray[i];
\r
452 return SubInternalBits(workingSet);
\r
456 return SubInternalBits(n2.digitArray);
\r
462 /// Multiplication and assignmnet - with minimal intermediate memory allocation.
\r
464 /// <param name="n2"></param>
\r
465 public void Mul(BigInt n2)
\r
467 if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);
\r
469 int Length = n2.digitArray.Length;
\r
471 //Inner loop zero-mul avoidance
\r
473 for (int i = Length - 1; i >= 0; i--)
\r
475 if (digitArray[i] != 0)
\r
482 //Result is zero, 'this' is unchanged
\r
483 if (maxDigit == 0) return;
\r
485 //Temp storage for source (both working sets are used by the calculation)
\r
486 uint[] thisTemp = new uint [Length];
\r
487 for (int i = 0; i < Length; i++)
\r
489 thisTemp[i] = digitArray[i];
\r
493 for (int i = 0; i < Length; i++)
\r
495 //Clear the working set
\r
496 for (int j = 0; j < i; j++)
\r
499 n2.workingSet[j] = 0;
\r
502 n2.workingSet[i] = 0;
\r
504 ulong digit = n2.digitArray[i];
\r
505 if (digit == 0) continue;
\r
507 for (int j = 0; j + i < Length && j < maxDigit; j++)
\r
509 //Multiply n1 by each of the integer digits of n2.
\r
510 ulong temp = (ulong)thisTemp[j] * digit;
\r
511 //n1.workingSet stores the low bits of each piecewise multiplication
\r
512 workingSet[j + i] = (uint)(temp & 0xffffffff);
\r
513 if (j + i + 1 < Length)
\r
515 //n2.workingSet stores the high bits of each multiplication
\r
516 n2.workingSet[j + i + 1] = (uint)(temp >> 32);
\r
520 AddInternalBits(workingSet);
\r
521 AddInternalBits(n2.workingSet);
\r
524 sign = (sign != n2.sign);
\r
528 /// Squares the number.
\r
530 public void Square()
\r
532 int Length = digitArray.Length;
\r
534 //Inner loop zero-mul avoidance
\r
536 for (int i = Length - 1; i >= 0; i--)
\r
538 if (digitArray[i] != 0)
\r
545 //Result is zero, 'this' is unchanged
\r
546 if (maxDigit == 0) return;
\r
548 //Temp storage for source (both working sets are used by the calculation)
\r
549 uint[] thisTemp = new uint[Length];
\r
550 for (int i = 0; i < Length; i++)
\r
552 thisTemp[i] = digitArray[i];
\r
556 UInt32 [] workingSet2 = new UInt32[Length];
\r
558 for (int i = 0; i < Length; i++)
\r
560 //Clear the working set
\r
561 for (int j = 0; j < i; j++)
\r
564 workingSet2[j] = 0;
\r
567 workingSet2[i] = 0;
\r
569 ulong digit = thisTemp[i];
\r
570 if (digit == 0) continue;
\r
572 for (int j = 0; j + i < Length && j < maxDigit; j++)
\r
574 //Multiply n1 by each of the integer digits of n2.
\r
575 ulong temp = (ulong)thisTemp[j] * digit;
\r
576 //n1.workingSet stores the low bits of each piecewise multiplication
\r
577 workingSet[j + i] = (uint)(temp & 0xffffffff);
\r
578 if (j + i + 1 < Length)
\r
580 //n2.workingSet stores the high bits of each multiplication
\r
581 workingSet2[j + i + 1] = (uint)(temp >> 32);
\r
585 AddInternalBits(workingSet);
\r
586 AddInternalBits(workingSet2);
\r
593 /// Used for floating-point multiplication
\r
594 /// Stores the high bits of the multiplication only (the carry bit from the
\r
595 /// lower bits is missing, so the true answer might be 1 greater).
\r
597 /// <param name="n2"></param>
\r
598 public void MulHi(BigInt n2)
\r
600 if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);
\r
602 int Length = n2.digitArray.Length;
\r
604 //Inner loop zero-mul avoidance
\r
606 for (int i = Length - 1; i >= 0; i--)
\r
608 if (digitArray[i] != 0)
\r
615 //Result is zero, 'this' is unchanged
\r
616 if (maxDigit == 0) return;
\r
618 //Temp storage for source (both working sets are used by the calculation)
\r
619 uint[] thisTemp = new uint[Length];
\r
620 for (int i = 0; i < Length; i++)
\r
622 thisTemp[i] = digitArray[i];
\r
626 for (int i = 0; i < Length; i++)
\r
628 //Clear the working set
\r
629 for (int j = 0; j < Length; j++)
\r
632 n2.workingSet[j] = 0;
\r
635 n2.workingSet[i] = 0;
\r
637 ulong digit = n2.digitArray[i];
\r
638 if (digit == 0) continue;
\r
640 //Only the high bits
\r
641 if (maxDigit + i < Length - 1) continue;
\r
643 for (int j = 0; j < maxDigit; j++)
\r
645 if (j + i + 1 < Length) continue;
\r
646 //Multiply n1 by each of the integer digits of n2.
\r
647 ulong temp = (ulong)thisTemp[j] * digit;
\r
648 //n1.workingSet stores the low bits of each piecewise multiplication
\r
649 if (j + i >= Length)
\r
651 workingSet[j + i - Length] = (uint)(temp & 0xffffffff);
\r
654 //n2.workingSet stores the high bits of each multiplication
\r
655 n2.workingSet[j + i + 1 - Length] = (uint)(temp >> 32);
\r
658 AddInternalBits(workingSet);
\r
659 AddInternalBits(n2.workingSet);
\r
662 sign = (sign != n2.sign);
\r
666 /// Floating-point helper function.
\r
667 /// Squares the number and keeps the high bits of the calculation.
\r
668 /// Takes a temporary BigInt as a working set.
\r
670 public void SquareHiFast(BigInt scratch)
\r
672 int Length = digitArray.Length;
\r
673 uint[] tempDigits = scratch.digitArray;
\r
674 uint[] workingSet2 = scratch.workingSet;
\r
676 //Temp storage for source (both working sets are used by the calculation)
\r
677 for (int i = 0; i < Length; i++)
\r
679 tempDigits[i] = digitArray[i];
\r
683 for (int i = 0; i < Length; i++)
\r
685 //Clear the working set
\r
686 for (int j = i; j < Length; j++)
\r
689 workingSet2[j] = 0;
\r
692 if (i - 1 >= 0) workingSet[i - 1] = 0;
\r
694 ulong digit = tempDigits[i];
\r
695 if (digit == 0) continue;
\r
697 for (int j = 0; j < Length; j++)
\r
699 if (j + i + 1 < Length) continue;
\r
700 //Multiply n1 by each of the integer digits of n2.
\r
701 ulong temp = (ulong)tempDigits[j] * digit;
\r
702 //n1.workingSet stores the low bits of each piecewise multiplication
\r
703 if (j + i >= Length)
\r
705 workingSet[j + i - Length] = (uint)(temp & 0xffffffff);
\r
708 //n2.workingSet stores the high bits of each multiplication
\r
709 workingSet2[j + i + 1 - Length] = (uint)(temp >> 32);
\r
712 AddInternalBits(workingSet);
\r
713 AddInternalBits(workingSet2);
\r
720 /// This uses the schoolbook division algorithm, as decribed by http://www.treskal.com/kalle/exjobb/original-report.pdf
\r
721 /// Algorithms 3.1 (implemented by Div_31) and 3.2 (implemented by Div_32)
\r
723 /// <param name="n2"></param>
\r
724 public void Div(BigInt n2)
\r
726 if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);
\r
728 int OldLength = digitArray.Length;
\r
730 //First, we need to prepare the operands for division using Div_32, which requires
\r
731 //That the most significant digit of n2 be set. To do this, we need to shift n2 (and therefore n1) up.
\r
732 //This operation can potentially increase the precision of the operands.
\r
733 int shift = MakeSafeDiv(this, n2);
\r
735 BigInt Q = new BigInt(this, this.pres, true);
\r
736 BigInt R = new BigInt(this, this.pres, true);
\r
738 Div_32(this, n2, Q, R);
\r
740 //Restore n2 to its pre-shift value
\r
743 sign = (sign != n2.sign);
\r
745 //Reset the lengths of the operands
\r
746 SetNumDigits(OldLength);
\r
747 n2.SetNumDigits(OldLength);
\r
751 /// This function is used for floating-point division.
\r
753 /// <param name="n2"></param>
\r
754 //Given two numbers:
\r
755 // In floating point 1 <= a, b < 2, meaning that both numbers have their top bits set.
\r
756 // To calculate a / b, maintaining precision, we:
\r
757 // 1. Double the number of digits available to both numbers.
\r
758 // 2. set a = a * 2^d (where d is the number of digits)
\r
759 // 3. calculate the quotient a <- q: 2^(d-1) <= q < 2^(d+1)
\r
760 // 4. if a >= 2^d, s = 1, else s = 0
\r
761 // 6. shift a down by s, and undo the precision extension
\r
762 // 7. return 1 - shift (change necessary to exponent)
\r
763 public int DivAndShift(BigInt n2)
\r
765 if (n2.IsZero()) return -1;
\r
766 if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);
\r
768 int oldLength = digitArray.Length;
\r
770 //Double the number of digits, and shift a into the higher digits.
\r
774 //Do the divide (at double precision, ouch!)
\r
777 //Shift down if 'this' >= 2^d
\r
780 if (digitArray[oldLength] != 0)
\r
786 SetNumDigits(oldLength);
\r
787 n2.SetNumDigits(oldLength);
\r
793 /// Calculates 'this' mod n2 (using the schoolbook division algorithm as above)
\r
795 /// <param name="n2"></param>
\r
796 public void Mod(BigInt n2)
\r
798 if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);
\r
800 int OldLength = digitArray.Length;
\r
802 //First, we need to prepare the operands for division using Div_32, which requires
\r
803 //That the most significant digit of n2 be set. To do this, we need to shift n2 (and therefore n1) up.
\r
804 //This operation can potentially increase the precision of the operands.
\r
805 int shift = MakeSafeDiv(this, n2);
\r
807 BigInt Q = new BigInt(this.pres);
\r
808 BigInt R = new BigInt(this.pres);
\r
810 Q.digitArray = new UInt32[this.digitArray.Length];
\r
811 R.digitArray = new UInt32[this.digitArray.Length];
\r
813 Div_32(this, n2, Q, R);
\r
815 //Restore n2 to its pre-shift value
\r
818 R.sign = (sign != n2.sign);
\r
821 //Reset the lengths of the operands
\r
822 SetNumDigits(OldLength);
\r
823 n2.SetNumDigits(OldLength);
\r
827 /// Logical left shift
\r
829 /// <param name="shift"></param>
\r
830 public void LSH(int shift)
\r
832 if (shift <= 0) return;
\r
833 int length = digitArray.Length;
\r
834 int digits = shift >> 5;
\r
835 int rem = shift & 31;
\r
837 for (int i = length - 1; i >= digits; i--)
\r
839 digitArray[i] = digitArray[i - digits];
\r
844 for (int i = digits - 1; i >= 0; i--)
\r
850 UInt64 lastShift = 0;
\r
852 for (int i = 0; i < length; i++)
\r
854 UInt64 temp = (((UInt64)digitArray[i]) << rem) | lastShift;
\r
855 digitArray[i] = (UInt32)(temp & 0xffffffff);
\r
856 lastShift = temp >> 32;
\r
861 /// Logical right-shift
\r
863 /// <param name="shift"></param>
\r
864 public void RSH(int shift)
\r
866 if (shift < 0) return;
\r
867 int length = digitArray.Length;
\r
868 int digits = shift >> 5;
\r
869 int rem = shift & 31;
\r
871 for (int i = 0; i < length - digits; i++)
\r
873 digitArray[i] = digitArray[i + digits];
\r
876 int start = (length - digits);
\r
877 if (start < 0) start = 0;
\r
879 for (int i = start; i < length; i++)
\r
884 UInt64 lastShift = 0;
\r
886 for (int i = length - 1; i >= 0; i--)
\r
888 UInt64 temp = ((((UInt64)digitArray[i]) << 32) >> rem) | lastShift;
\r
889 digitArray[i] = (UInt32)(temp >> 32);
\r
890 lastShift = (temp & 0xffffffff) << 32;
\r
895 /// Changes the sign of the number
\r
897 public void Negate()
\r
903 /// Increments the number.
\r
905 public void Increment()
\r
918 /// Decrements the number.
\r
920 public void Decrement()
\r
933 /// Calculates the factorial 'this'!
\r
935 public void Factorial()
\r
939 //Clamp to a reasonable range.
\r
940 int factToUse = (int)(digitArray[0]);
\r
941 if (factToUse > 65536) factToUse = 65536;
\r
946 for (uint i = 1; i <= factToUse; i++)
\r
953 /// Calculates 'this'^power
\r
955 /// <param name="power"></param>
\r
956 public void Power(BigInt power)
\r
958 if (power.IsZero() || power.sign)
\r
965 BigInt pow = new BigInt(power);
\r
966 BigInt temp = new BigInt(this);
\r
967 BigInt powTerm = new BigInt(this);
\r
970 for (; !pow.IsZero(); pow.RSH(1))
\r
972 if ((pow.digitArray[0] & 1) == 1)
\r
983 //***************** Comparison member functions *****************
\r
986 /// returns true if this bigint == 0
\r
988 /// <returns></returns>
\r
989 public bool IsZero()
\r
991 for (int i = 0; i < digitArray.Length; i++)
\r
993 if (digitArray[i] != 0) return false;
\r
1000 /// true iff n2 (precision adjusted to this) is less than 'this'
\r
1002 /// <param name="n2"></param>
\r
1003 /// <returns></returns>
\r
1004 public bool LessThan(BigInt n2)
\r
1006 if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);
\r
1010 if (!n2.sign) return true;
\r
1011 return GtInt(this, n2);
\r
1015 if (n2.sign) return false;
\r
1016 return LtInt(this, n2);
\r
1021 /// true iff n2 (precision adjusted to this) is greater than 'this'
\r
1023 /// <param name="n2"></param>
\r
1024 /// <returns></returns>
\r
1025 public bool GreaterThan(BigInt n2)
\r
1027 if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);
\r
1031 if (!n2.sign) return false;
\r
1032 return LtInt(this, n2);
\r
1036 if (n2.sign) return true;
\r
1037 return GtInt(this, n2);
\r
1042 /// Override of base-class equals
\r
1044 /// <param name="obj"></param>
\r
1045 /// <returns></returns>
\r
1046 public override bool Equals(object obj)
\r
1048 BigInt n2 = ((BigInt)obj);
\r
1049 return Equals(n2);
\r
1055 /// <returns></returns>
\r
1056 public override int GetHashCode()
\r
1058 return (Int32)digitArray[0];
\r
1062 /// True iff n2 (precision-adjusted to this) == n1
\r
1064 /// <param name="n2"></param>
\r
1065 /// <returns></returns>
\r
1066 public bool Equals(BigInt n2)
\r
1068 if (IsZero() && n2.IsZero()) return true;
\r
1070 if (sign != n2.sign) return false;
\r
1072 int Length = digitArray.Length;
\r
1073 if (n2.digitArray.Length != Length) MakeSafe(ref n2);
\r
1075 for (int i = 0; i < Length; i++)
\r
1077 if (digitArray[i] != n2.digitArray[i]) return false;
\r
1083 //******************* Bitwise member functions ********************
\r
1086 /// Takes the bitwise complement of the number
\r
1088 public void Complement()
\r
1090 int Length = digitArray.Length;
\r
1092 for (int i = 0; i < Length; i++)
\r
1094 digitArray[i] = ~digitArray[i];
\r
1101 /// <param name="n2"></param>
\r
1102 public void And(BigInt n2)
\r
1104 int Length = digitArray.Length;
\r
1105 if (n2.digitArray.Length != Length) MakeSafe(ref n2);
\r
1107 for (int i = 0; i < Length; i++)
\r
1109 digitArray[i] &= n2.digitArray[i];
\r
1118 /// <param name="n2"></param>
\r
1119 public void Or(BigInt n2)
\r
1121 int Length = digitArray.Length;
\r
1122 if (n2.digitArray.Length != Length) MakeSafe(ref n2);
\r
1124 for (int i = 0; i < Length; i++)
\r
1126 digitArray[i] |= n2.digitArray[i];
\r
1135 /// <param name="n2"></param>
\r
1136 public void Xor(BigInt n2)
\r
1138 int Length = digitArray.Length;
\r
1139 if (n2.digitArray.Length != Length) MakeSafe(ref n2);
\r
1141 for (int i = 0; i < Length; i++)
\r
1143 digitArray[i] ^= n2.digitArray[i];
\r
1149 //*************** Fast Static Arithmetic Functions *****************
\r
1152 /// Adds n1 and n2 and puts result in dest, without intermediate memory allocation
\r
1153 /// (unsafe if n1 and n2 disagree in precision, safe even if dest is n1 or n2)
\r
1155 /// <param name="dest"></param>
\r
1156 /// <param name="n1"></param>
\r
1157 /// <param name="n2"></param>
\r
1158 public static void AddFast(BigInt dest, BigInt n1, BigInt n2)
\r
1160 //We cast to the highest input precision...
\r
1161 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1163 //Then we up the output precision if less than the input precision.
\r
1164 if (dest.digitArray.Length < n1.digitArray.Length) n1.MakeSafe(ref dest);
\r
1166 int Length = n1.digitArray.Length;
\r
1168 if (n1.sign == n2.sign)
\r
1170 //Copies sources into digit array and working set for all cases, to avoid
\r
1171 //problems when dest is n1 or n2
\r
1172 for (int i = 0; i < Length; i++)
\r
1174 dest.workingSet[i] = n2.digitArray[i];
\r
1175 dest.digitArray[i] = n1.digitArray[i];
\r
1177 dest.AddInternalBits(dest.workingSet);
\r
1178 dest.sign = n1.sign;
\r
1182 bool lessThan = LtInt(n1, n2);
\r
1186 for (int i = 0; i < Length; i++)
\r
1188 dest.workingSet[i] = n1.digitArray[i];
\r
1189 dest.digitArray[i] = n2.digitArray[i];
\r
1191 dest.SubInternalBits(dest.workingSet);
\r
1192 dest.sign = !n1.sign;
\r
1196 for (int i = 0; i < Length; i++)
\r
1198 dest.workingSet[i] = n2.digitArray[i];
\r
1199 dest.digitArray[i] = n1.digitArray[i];
\r
1201 dest.SubInternalBits(dest.workingSet);
\r
1202 dest.sign = n1.sign;
\r
1208 /// Adds n1 and n2 and puts result in dest, without intermediate memory allocation
\r
1209 /// (unsafe if n1 and n2 disagree in precision, safe even if dest is n1 or n2)
\r
1211 /// <param name="dest"></param>
\r
1212 /// <param name="n1"></param>
\r
1213 /// <param name="n2"></param>
\r
1214 public static void SubFast(BigInt dest, BigInt n1, BigInt n2)
\r
1216 //We cast to the highest input precision...
\r
1217 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1219 //Then we up the output precision if less than the input precision.
\r
1220 if (dest.digitArray.Length < n1.digitArray.Length) n1.MakeSafe(ref dest);
\r
1222 int Length = n1.digitArray.Length;
\r
1224 if (n1.sign != n2.sign)
\r
1226 //Copies sources into digit array and working set for all cases, to avoid
\r
1227 //problems when dest is n1 or n2
\r
1228 for (int i = 0; i < Length; i++)
\r
1230 dest.workingSet[i] = n2.digitArray[i];
\r
1231 dest.digitArray[i] = n1.digitArray[i];
\r
1233 dest.AddInternalBits(dest.workingSet);
\r
1234 dest.sign = n1.sign;
\r
1238 bool lessThan = LtInt(n1, n2);
\r
1242 for (int i = 0; i < Length; i++)
\r
1244 dest.workingSet[i] = n1.digitArray[i];
\r
1245 dest.digitArray[i] = n2.digitArray[i];
\r
1247 dest.SubInternalBits(dest.workingSet);
\r
1248 dest.sign = !n1.sign;
\r
1252 for (int i = 0; i < Length; i++)
\r
1254 dest.workingSet[i] = n2.digitArray[i];
\r
1255 dest.digitArray[i] = n1.digitArray[i];
\r
1257 dest.SubInternalBits(dest.workingSet);
\r
1258 dest.sign = n1.sign;
\r
1263 //*************** Static Arithmetic Functions ***************
\r
1266 /// signed addition of 2 numbers.
\r
1268 /// <param name="n1"></param>
\r
1269 /// <param name="n2"></param>
\r
1270 /// <returns></returns>
\r
1271 public static BigInt Add(BigInt n1, BigInt n2)
\r
1273 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1276 if (n1.sign == n2.sign)
\r
1278 result = new BigInt(n1);
\r
1279 result.AddInternal(n2);
\r
1280 result.sign = n1.sign;
\r
1284 bool lessThan = LtInt(n1, n2);
\r
1288 result = new BigInt(n2);
\r
1289 result.SubInternal(n1);
\r
1290 result.sign = !n1.sign;
\r
1294 result = new BigInt(n1);
\r
1295 result.SubInternal(n2);
\r
1296 result.sign = n1.sign;
\r
1304 /// signed subtraction of 2 numbers.
\r
1306 /// <param name="n1"></param>
\r
1307 /// <param name="n2"></param>
\r
1308 /// <returns></returns>
\r
1309 public static BigInt Sub(BigInt n1, BigInt n2)
\r
1311 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1314 if ((n1.sign && !n2.sign) || (!n1.sign && n2.sign))
\r
1316 result = new BigInt(n1);
\r
1317 result.AddInternal(n2);
\r
1318 result.sign = n1.sign;
\r
1322 bool lessThan = LtInt(n1, n2);
\r
1326 result = new BigInt(n2);
\r
1327 result.SubInternal(n1);
\r
1328 result.sign = !n1.sign;
\r
1332 result = new BigInt(n1);
\r
1333 result.SubInternal(n2);
\r
1334 result.sign = n1.sign;
\r
1342 /// Multiplication of two BigInts
\r
1344 /// <param name="n1"></param>
\r
1345 /// <param name="n2"></param>
\r
1346 /// <returns></returns>
\r
1347 public static BigInt Mul(BigInt n1, BigInt n2)
\r
1349 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1351 BigInt result = new BigInt(n1);
\r
1357 /// True arbitrary precision divide.
\r
1359 /// <param name="n1"></param>
\r
1360 /// <param name="n2"></param>
\r
1361 /// <returns></returns>
\r
1362 public static BigInt Div(BigInt n1, BigInt n2)
\r
1364 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1365 BigInt res = new BigInt(n1);
\r
1371 /// True arbitrary-precision mod operation
\r
1373 /// <param name="n1"></param>
\r
1374 /// <param name="n2"></param>
\r
1375 /// <returns></returns>
\r
1376 public static BigInt Mod(BigInt n1, BigInt n2)
\r
1378 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1379 BigInt res = new BigInt(n1);
\r
1385 /// Unsigned multiplication of a BigInt by a small number
\r
1387 /// <param name="n1"></param>
\r
1388 /// <param name="n2"></param>
\r
1389 /// <returns></returns>
\r
1390 public static BigInt Mul(BigInt n1, uint n2)
\r
1392 BigInt result = new BigInt(n1);
\r
1393 result.MulInternal(n2);
\r
1398 /// Division of a BigInt by a small (unsigned) number
\r
1400 /// <param name="n1"></param>
\r
1401 /// <param name="n2"></param>
\r
1402 /// <returns></returns>
\r
1403 public static BigInt Div(BigInt n1, uint n2)
\r
1405 BigInt result = new BigInt(n1);
\r
1406 result.DivInternal(n2);
\r
1411 /// Division and remainder of a BigInt by a small (unsigned) number
\r
1412 /// n1 / n2 = div remainder mod
\r
1414 /// <param name="n1">The number to divide (dividend)</param>
\r
1415 /// <param name="n2">The number to divide by (divisor)</param>
\r
1416 /// <param name="div">The quotient (output parameter)</param>
\r
1417 /// <param name="mod">The remainder (output parameter)</param>
\r
1418 public static void DivMod(BigInt n1, uint n2, out BigInt div, out BigInt mod)
\r
1420 div = Div(n1, n2);
\r
1421 mod = Mul(div, n2);
\r
1422 mod = Sub(n1, mod);
\r
1425 //**************** Static Comparison Functions ***************
\r
1428 /// true iff n1 is less than n2
\r
1430 /// <param name="n1"></param>
\r
1431 /// <param name="n2"></param>
\r
1432 /// <returns></returns>
\r
1433 public static bool LessThan(BigInt n1, BigInt n2)
\r
1435 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1439 if (!n2.sign) return true;
\r
1440 return GtInt(n1, n2);
\r
1444 if (n2.sign) return false;
\r
1445 return LtInt(n1, n2);
\r
1450 /// true iff n1 is greater than n2
\r
1452 /// <param name="n1"></param>
\r
1453 /// <param name="n2"></param>
\r
1454 /// <returns></returns>
\r
1455 public static bool GreaterThan(BigInt n1, BigInt n2)
\r
1457 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1461 if (!n2.sign) return false;
\r
1462 return LtInt(n1, n2);
\r
1466 if (n2.sign) return true;
\r
1467 return GtInt(n1, n2);
\r
1472 /// true iff n1 == n2
\r
1474 /// <param name="n1"></param>
\r
1475 /// <param name="n2"></param>
\r
1476 /// <returns></returns>
\r
1477 public static bool Equals(BigInt n1, BigInt n2)
\r
1479 return n1.Equals(n2);
\r
1482 //***************** Static Bitwise Functions *****************
\r
1487 /// <param name="n1"></param>
\r
1488 /// <param name="n2"></param>
\r
1489 /// <returns></returns>
\r
1490 public static BigInt And(BigInt n1, BigInt n2)
\r
1492 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1493 BigInt res = new BigInt(n1);
\r
1501 /// <param name="n1"></param>
\r
1502 /// <param name="n2"></param>
\r
1503 /// <returns></returns>
\r
1504 public static BigInt Or(BigInt n1, BigInt n2)
\r
1506 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1507 BigInt res = new BigInt(n1);
\r
1515 /// <param name="n1"></param>
\r
1516 /// <param name="n2"></param>
\r
1517 /// <returns></returns>
\r
1518 public static BigInt Xor(BigInt n1, BigInt n2)
\r
1520 if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);
\r
1521 BigInt res = new BigInt(n1);
\r
1526 //**************** Static Operator Overloads *****************
\r
1529 /// Addition operator
\r
1531 public static BigInt operator +(BigInt n1, BigInt n2)
\r
1533 return Add(n1, n2);
\r
1537 /// The subtraction operator
\r
1539 public static BigInt operator -(BigInt n1, BigInt n2)
\r
1541 return Sub(n1, n2);
\r
1545 /// The multiplication operator
\r
1547 public static BigInt operator *(BigInt n1, BigInt n2)
\r
1549 return Mul(n1, n2);
\r
1553 /// The division operator
\r
1555 public static BigInt operator /(BigInt n1, BigInt n2)
\r
1557 return Div(n1, n2);
\r
1561 /// The remainder (mod) operator
\r
1563 public static BigInt operator %(BigInt n1, BigInt n2)
\r
1565 return Mod(n1, n2);
\r
1569 /// The left-shift operator
\r
1571 public static BigInt operator <<(BigInt n1, int n2)
\r
1573 BigInt res = new BigInt(n1);
\r
1579 /// The right-shift operator
\r
1581 public static BigInt operator >>(BigInt n1, int n2)
\r
1583 BigInt res = new BigInt(n1);
\r
1589 /// The less than operator
\r
1591 public static bool operator <(BigInt n1, BigInt n2)
\r
1593 return LessThan(n1, n2);
\r
1597 /// The greater than operator
\r
1599 public static bool operator >(BigInt n1, BigInt n2)
\r
1601 return GreaterThan(n1, n2);
\r
1605 /// The less than or equal to operator
\r
1607 public static bool operator <=(BigInt n1, BigInt n2)
\r
1609 return !GreaterThan(n1, n2);
\r
1613 /// The greater than or equal to operator
\r
1615 public static bool operator >=(BigInt n1, BigInt n2)
\r
1617 return !LessThan(n1, n2);
\r
1621 /// The equality operator
\r
1623 public static bool operator ==(BigInt n1, BigInt n2)
\r
1625 return Equals(n1, n2);
\r
1629 /// The inequality operator
\r
1631 public static bool operator !=(BigInt n1, BigInt n2)
\r
1633 return !Equals(n1, n2);
\r
1637 /// The bitwise AND operator
\r
1639 public static BigInt operator &(BigInt n1, BigInt n2)
\r
1641 return And(n1, n2);
\r
1645 /// The bitwise OR operator
\r
1647 public static BigInt operator |(BigInt n1, BigInt n2)
\r
1649 return Or(n1, n2);
\r
1653 /// The bitwise eXclusive OR operator
\r
1655 public static BigInt operator ^(BigInt n1, BigInt n2)
\r
1657 return Xor(n1, n2);
\r
1661 /// The increment operator
\r
1663 public static BigInt operator ++(BigInt n1)
\r
1670 /// The decrement operator
\r
1672 public static BigInt operator --(BigInt n1)
\r
1678 //**************** Private Member Functions *****************
\r
1681 /// Unsigned multiplication and assignment by a small number
\r
1683 /// <param name="n2"></param>
\r
1684 private void MulInternal(uint n2)
\r
1686 int Length = digitArray.Length;
\r
1687 ulong n2long = (ulong)n2;
\r
1689 for (int i = 0; i < Length; i++)
\r
1691 workingSet[i] = 0;
\r
1694 for (int i = 0; i < Length; i++)
\r
1696 if (digitArray[i] == 0) continue;
\r
1697 ulong temp = (ulong)digitArray[i] * n2long;
\r
1698 digitArray[i] = (uint)(temp & 0xffffffff);
\r
1699 if (i + 1 < Length) workingSet[i + 1] = (uint)(temp >> 32);
\r
1702 AddInternalBits(workingSet);
\r
1706 /// Unsigned division and assignment by a small number
\r
1708 /// <param name="n2"></param>
\r
1709 private void DivInternal(uint n2)
\r
1711 int Length = digitArray.Length;
\r
1714 //Divide each digit by the small number.
\r
1715 for (int i = Length - 1; i >= 0; i--)
\r
1717 ulong temp = (ulong)digitArray[i] + (carry << 32);
\r
1718 digitArray[i] = (uint)(temp / (ulong)n2);
\r
1719 carry = temp % (ulong)n2;
\r
1724 /// Adds a signed integer to the number.
\r
1726 /// <param name="n1"></param>
\r
1727 private void AddInternal(int n1)
\r
1736 int length = digitArray.Length;
\r
1738 for (int i = 0; i < length && !(n1 == 0 && carry == 0); i++)
\r
1740 uint temp = digitArray[i];
\r
1741 digitArray[i] += (uint)n1 + carry;
\r
1743 carry = (digitArray[i] <= temp) ? 1u: 0u;
\r
1750 /// Subtract a signed integer from the number.
\r
1751 /// This is internal because it will fail spectacularly if this number is negative or if n1 is bigger than this number.
\r
1753 /// <param name="n1"></param>
\r
1754 private void SubInternal(int n1)
\r
1763 int length = digitArray.Length;
\r
1765 for (int i = 0; i < length && !(n1 == 0 && carry == 0); i++)
\r
1767 uint temp = digitArray[i];
\r
1768 digitArray[i] -= ((uint)n1 + carry);
\r
1770 carry = (digitArray[i] >= temp) ? 1u: 0u;
\r
1777 /// Adds a signed integer to the number.
\r
1779 /// <param name="n1"></param>
\r
1780 private bool AddInternal(uint n1)
\r
1783 int length = digitArray.Length;
\r
1785 for (int i = 0; i < length && !(n1 == 0 && carry == 0); i++)
\r
1787 uint temp = digitArray[i];
\r
1788 digitArray[i] += n1 + carry;
\r
1790 carry = (digitArray[i] <= temp) ? 1u: 0u;
\r
1795 return (carry != 0);
\r
1799 /// Internally subtracts a uint from the number (sign insensitive)
\r
1801 /// <param name="n1"></param>
\r
1802 /// <returns></returns>
\r
1803 private bool SubInternal(uint n1)
\r
1806 int length = digitArray.Length;
\r
1808 for (int i = 0; i < length && !(n1 == 0 && carry == 0); i++)
\r
1810 uint temp = digitArray[i];
\r
1811 digitArray[i] -= (n1 + carry);
\r
1813 carry = (digitArray[i] >= temp) ? 1u: 0u;
\r
1818 return (carry != 0);
\r
1822 /// Internal increment function (sign insensitive)
\r
1824 private bool IncrementInt()
\r
1828 int length = digitArray.Length;
\r
1830 for (int i = 0; i < length && carry != 0; i++)
\r
1832 uint temp = digitArray[i];
\r
1835 if (digitArray[i] > temp) carry = 0;
\r
1838 return (carry != 0);
\r
1842 /// Internal increment function (sign insensitive)
\r
1844 private bool DecrementInt()
\r
1848 int length = digitArray.Length;
\r
1850 for (int i = 0; i < length && carry != 0; i++)
\r
1852 uint temp = digitArray[i];
\r
1855 if (digitArray[i] < temp) carry = 0;
\r
1858 return (carry != 0);
\r
1862 /// Used to add a digit array to a big int.
\r
1864 /// <param name="digitsToAdd"></param>
\r
1865 private uint AddInternalBits(uint[] digitsToAdd)
\r
1869 int Length = digitArray.Length;
\r
1871 for (int i = 0; i < Length; i++)
\r
1873 //Necessary because otherwise the carry calculation could go bad.
\r
1874 if (digitsToAdd[i] == 0 && carry == 0) continue;
\r
1876 uint temp = digitArray[i];
\r
1877 digitArray[i] += (digitsToAdd[i] + carry);
\r
1880 if (digitArray[i] <= temp) carry = 1;
\r
1887 /// Used to add with matching signs (true addition of the digit arrays)
\r
1888 /// This is internal because it will fail spectacularly if n1 is negative.
\r
1890 /// <param name="n1"></param>
\r
1891 private uint AddInternal(BigInt n1)
\r
1893 return AddInternalBits(n1.digitArray);
\r
1896 private uint SubInternalBits(uint[] digitsToAdd)
\r
1900 int Length = digitArray.Length;
\r
1902 for (int i = 0; i < Length; i++)
\r
1904 //Necessary because otherwise the carry calculation could go bad.
\r
1905 if (digitsToAdd[i] == 0 && carry == 0) continue;
\r
1907 uint temp = digitArray[i];
\r
1908 digitArray[i] -= (digitsToAdd[i] + carry);
\r
1911 if (digitArray[i] >= temp) carry = 1;
\r
1918 /// Used to subtract n1 (true subtraction of digit arrays) - n1 must be less than or equal to this number
\r
1920 /// <param name="n1"></param>
\r
1921 private uint SubInternal(BigInt n1)
\r
1923 return SubInternalBits(n1.digitArray);
\r
1927 /// Returns the length of the BigInt in 32-bit words for a given decimal precision
\r
1929 /// <param name="precision"></param>
\r
1930 /// <returns></returns>
\r
1931 private static int GetRequiredDigitsForPrecision(PrecisionSpec precision)
\r
1933 int bits = precision.NumBits;
\r
1934 return ((bits - 1) >> 5) + 1;
\r
1938 /// Initialises the BigInt to a desired decimal precision
\r
1940 /// <param name="precision"></param>
\r
1941 private void Init(PrecisionSpec precision)
\r
1943 int numDigits = GetRequiredDigitsForPrecision(precision);
\r
1944 digitArray = new uint[numDigits];
\r
1945 workingSet = new uint[numDigits];
\r
1950 /// Initialises the BigInt from a string, given a base and precision
\r
1952 /// <param name="init"></param>
\r
1953 /// <param name="precision"></param>
\r
1954 /// <param name="numberBase"></param>
\r
1955 private void InitFromString(string init, PrecisionSpec precision, int numberBase)
\r
1957 PrecisionSpec test;
\r
1958 if (numberBase == 2)
\r
1960 test = new PrecisionSpec(init.Length, PrecisionSpec.BaseType.BIN);
\r
1962 else if (numberBase == 8)
\r
1964 test = new PrecisionSpec(init.Length, PrecisionSpec.BaseType.OCT);
\r
1966 else if (numberBase == 10)
\r
1968 test = new PrecisionSpec(init.Length, PrecisionSpec.BaseType.DEC);
\r
1970 else if (numberBase == 16)
\r
1972 test = new PrecisionSpec(init.Length, PrecisionSpec.BaseType.HEX);
\r
1976 throw new ArgumentOutOfRangeException();
\r
1979 //if (test.NumBits > precision.NumBits) precision = test;
\r
1981 FromStringInt(init, numberBase);
\r
1984 //************ Helper Functions for floating point *************
\r
1987 /// Returns true if only the top bit is set: i.e. if the floating-point number is a power of 2
\r
1989 /// <returns></returns>
\r
1990 public bool IsTopBitOnlyBit()
\r
1992 int length = digitArray.Length;
\r
1994 if (digitArray[length - 1] != 0x80000000u) return false;
\r
1996 for (int i = 0; i < length; i++)
\r
1998 if (digitArray[i] != 0) return false;
\r
2005 /// Zeroes the n most significant bits of the number
\r
2007 /// <param name="bits"></param>
\r
2008 public void ZeroBitsHigh(int bits)
\r
2011 if (bits <= 0) return;
\r
2013 int length = digitArray.Length;
\r
2015 //The entire digit array.
\r
2016 if ((bits >> 5) > length)
\r
2018 bits = length << 5;
\r
2021 int remBits = (bits & 31);
\r
2022 int startDigit = length - ((bits >> 5) + 1);
\r
2026 digitArray[startDigit] = digitArray[startDigit] & (0xffffffffu >> remBits);
\r
2029 for (int i = startDigit + 1; i < length; i++)
\r
2031 digitArray[i] = 0;
\r
2036 /// Zeroes the least-significant n bits.
\r
2038 /// <param name="bits"></param>
\r
2039 public void ZeroBits(int bits)
\r
2042 if (bits <= 0) return;
\r
2044 //The entire digit array.
\r
2045 if ((bits >> 5) > digitArray.Length)
\r
2047 bits = digitArray.Length << 5;
\r
2050 int remBits = (bits & 31);
\r
2051 int startDigit = bits >> 5;
\r
2055 UInt32 startMask = 0xffffffffu & ~(UInt32)(((1 << remBits) - 1));
\r
2056 digitArray[startDigit] = digitArray[startDigit] & startMask;
\r
2059 for (int i = startDigit - 1; i >= 0; i--)
\r
2061 digitArray[i] = 0;
\r
2066 /// Sets the number to 0
\r
2068 public void Zero()
\r
2070 int length = digitArray.Length;
\r
2072 for (int i = 0; i < length; i++)
\r
2074 digitArray[i] = 0;
\r
2079 /// Rounds off the least significant bits of the number.
\r
2080 /// Can only round off up to 31 bits.
\r
2082 /// <param name="bits">number of bits to round</param>
\r
2083 /// <returns></returns>
\r
2084 public bool Round(int bits)
\r
2086 //Always less than 32 bits, please!
\r
2089 uint pow2 = 1u << bits;
\r
2090 uint test = digitArray[0] & (pow2 >> 1);
\r
2092 //Zero the lower bits
\r
2093 digitArray[0] = digitArray[0] & ~(pow2 - 1);
\r
2097 bool bRet = AddInternal(pow2);
\r
2098 digitArray[digitArray.Length - 1] = digitArray[digitArray.Length - 1] | 0x80000000;
\r
2107 /// Used for casting between BigFloats of different precisions - this assumes
\r
2108 /// that the number is a normalised mantissa.
\r
2110 /// <param name="n2"></param>
\r
2111 /// <returns>true if a round-up caused the high bits to become zero</returns>
\r
2112 public bool AssignHigh(BigInt n2)
\r
2114 int length = digitArray.Length;
\r
2115 int length2 = n2.digitArray.Length;
\r
2116 int minWords = (length < length2) ? length: length2;
\r
2117 bool bRet = false;
\r
2119 for (int i = 1; i <= minWords; i++)
\r
2121 digitArray[length - i] = n2.digitArray[length2 - i];
\r
2124 if (length2 > length && n2.digitArray[length2 - (length + 1)] >= 0x80000000)
\r
2126 bRet = IncrementInt();
\r
2128 //Because we are assuming normalisation, we set the top bit (it will already be set if
\r
2130 digitArray[length - 1] = digitArray[length - 1] | 0x80000000;
\r
2139 /// Used for casting between long ints or doubles and floating-point numbers
\r
2141 /// <param name="digits"></param>
\r
2142 public void SetHighDigits(Int64 digits)
\r
2144 digitArray[digitArray.Length - 1] = (uint)(digits >> 32);
\r
2145 if (digitArray.Length > 1) digitArray[digitArray.Length - 2] = (uint)(digits & 0xffffffff);
\r
2149 /// Used for casting between ints and doubles or floats.
\r
2151 /// <param name="digit"></param>
\r
2152 public void SetHighDigit(UInt32 digit)
\r
2154 digitArray[digitArray.Length - 1] = digit;
\r
2158 /// Helper function for floating-point - extends the number to twice the precision
\r
2159 /// and shifts the digits into the upper bits.
\r
2163 int length = digitArray.Length;
\r
2164 int digits = length << 1;
\r
2166 UInt32[] newDigitArray = new UInt32[digits];
\r
2167 workingSet = new UInt32[digits];
\r
2169 for (int i = 0; i < length; i++)
\r
2171 newDigitArray[i + length] = digitArray[i];
\r
2174 digitArray = newDigitArray;
\r
2178 /// Helper function for floating-point - extends the number to twice the precision...
\r
2179 /// This is a necessary step in floating-point division.
\r
2181 public void Extend()
\r
2183 SetNumDigits(digitArray.Length * 2);
\r
2187 /// Gets the highest big of the integer (used for floating point stuff)
\r
2189 /// <returns></returns>
\r
2190 public uint GetTopBit()
\r
2192 return (digitArray[digitArray.Length - 1] >> 31);
\r
2196 /// Used for floating point multiplication, this shifts the number so that
\r
2197 /// the highest bit is set, and returns the number of places shifted.
\r
2199 /// <returns></returns>
\r
2200 public int Normalise()
\r
2202 if (IsZero()) return 0;
\r
2204 int MSD = GetMSD();
\r
2205 int digitShift = (digitArray.Length - (MSD + 1));
\r
2206 int bitShift = (31 - GetMSB(digitArray[MSD])) + (digitShift << 5);
\r
2212 /// Gets the most significant bit
\r
2214 /// <param name="value">the input to search for the MSB in</param>
\r
2215 /// <returns>-1 if the input was zero, the position of the MSB otherwise</returns>
\r
2216 public static int GetMSB(UInt32 value)
\r
2218 if (value == 0) return -1;
\r
2220 uint mask1 = 0xffff0000;
\r
2221 uint mask2 = 0xff00;
\r
2222 uint mask3 = 0xf0;
\r
2223 uint mask4 = 0xc; //1100 in binary
\r
2224 uint mask5 = 0x2; //10 in binary
\r
2228 //Unrolled binary search for the most significant bit.
\r
2229 if ((value & mask1) != 0) iPos += 16;
\r
2232 if ((value & mask2) != 0) iPos += 8;
\r
2235 if ((value & mask3) != 0) iPos += 4;
\r
2238 if ((value & mask4) != 0) iPos += 2;
\r
2241 if ((value & mask5) != 0) iPos++;
\r
2247 /// Gets the most significant bit
\r
2249 /// <param name="value">the input to search for the MSB in</param>
\r
2250 /// <returns>-1 if the input was zero, the position of the MSB otherwise</returns>
\r
2251 public static int GetMSB(UInt64 value)
\r
2253 if (value == 0) return -1;
\r
2255 UInt64 mask0 = 0xffffffff00000000ul;
\r
2256 UInt64 mask1 = 0xffff0000;
\r
2257 UInt64 mask2 = 0xff00;
\r
2258 UInt64 mask3 = 0xf0;
\r
2259 UInt64 mask4 = 0xc; //1100 in binary
\r
2260 UInt64 mask5 = 0x2; //10 in binary
\r
2264 //Unrolled binary search for the most significant bit.
\r
2265 if ((value & mask0) != 0) iPos += 32;
\r
2268 if ((value & mask1) != 0) iPos += 16;
\r
2271 if ((value & mask2) != 0) iPos += 8;
\r
2274 if ((value & mask3) != 0) iPos += 4;
\r
2277 if ((value & mask4) != 0) iPos += 2;
\r
2280 if ((value & mask5) != 0) iPos++;
\r
2286 /// Gets the most significant bit
\r
2288 /// <param name="value">the input to search for the MSB in</param>
\r
2289 /// <returns>-1 if the input was zero, the position of the MSB otherwise</returns>
\r
2290 public static int GetMSB(BigInt value)
\r
2292 int digit = value.GetMSD();
\r
2293 int bit = GetMSB(value.digitArray[digit]);
\r
2294 return (digit << 5) + bit;
\r
2297 //**************** Helper Functions for Div ********************
\r
2300 /// Gets the index of the most significant digit
\r
2302 /// <returns></returns>
\r
2303 private int GetMSD()
\r
2305 for (int i = digitArray.Length - 1; i >= 0; i--)
\r
2307 if (digitArray[i] != 0) return i;
\r
2314 /// Gets the required bitshift for the Div_32 algorithm
\r
2316 /// <returns></returns>
\r
2317 private int GetDivBitshift()
\r
2319 uint digit = digitArray[GetMSD()];
\r
2320 uint mask1 = 0xffff0000;
\r
2321 uint mask2 = 0xff00;
\r
2322 uint mask3 = 0xf0;
\r
2323 uint mask4 = 0xc; //1100 in binary
\r
2324 uint mask5 = 0x2; //10 in binary
\r
2328 //Unrolled binary search for the most significant bit.
\r
2329 if ((digit & mask1) != 0) iPos += 16;
\r
2332 if ((digit & mask2) != 0) iPos += 8;
\r
2335 if ((digit & mask3) != 0) iPos += 4;
\r
2338 if ((digit & mask4) != 0) iPos += 2;
\r
2341 if ((digit & mask5) != 0) return 30 - iPos;
\r
2347 /// Shifts and optionally precision-extends the arguments to prepare for Div_32
\r
2349 /// <param name="n1"></param>
\r
2350 /// <param name="n2"></param>
\r
2351 private static int MakeSafeDiv(BigInt n1, BigInt n2)
\r
2353 int shift = n2.GetDivBitshift();
\r
2354 int n1MSD = n1.GetMSD();
\r
2356 uint temp = n1.digitArray[n1MSD];
\r
2357 if (n1MSD == n1.digitArray.Length - 1 && ((temp << shift) >> shift) != n1.digitArray[n1MSD])
\r
2359 //Precision-extend n1 and n2 if necessary
\r
2360 int digits = n1.digitArray.Length;
\r
2361 n1.SetNumDigits(digits + 1);
\r
2362 n2.SetNumDigits(digits + 1);
\r
2365 //Logical left-shift n1 and n2
\r
2373 /// Schoolbook division helper function.
\r
2375 /// <param name="n1"></param>
\r
2376 /// <param name="n2"></param>
\r
2377 /// <param name="Q">Quotient output value</param>
\r
2378 /// <param name="R">Remainder output value</param>
\r
2379 private static void Div_31(BigInt n1, BigInt n2, BigInt Q, BigInt R)
\r
2381 int digitsN1 = n1.GetMSD() + 1;
\r
2382 int digitsN2 = n2.GetMSD() + 1;
\r
2384 if ((digitsN1 > digitsN2))
\r
2386 BigInt n1New = new BigInt(n2);
\r
2387 n1New.DigitShiftSelfLeft(1);
\r
2389 //If n1 >= n2 * 2^32
\r
2390 if (!LtInt(n1, n1New))
\r
2392 n1New.sign = n1.sign;
\r
2393 SubFast(n1New, n1, n1New);
\r
2395 Div_32(n1New, n2, Q, R);
\r
2397 //Q = (A - B*2^32)/B + 2^32
\r
2398 Q.Add2Pow32Self();
\r
2405 if (digitsN1 >= 2)
\r
2407 UInt64 q64 = ((((UInt64)n1.digitArray[digitsN1 - 1]) << 32) + n1.digitArray[digitsN1 - 2]) / (UInt64)n2.digitArray[digitsN2 - 1];
\r
2409 if (q64 > 0xfffffffful)
\r
2419 BigInt temp = Mul(n2, q);
\r
2421 if (GtInt(temp, n1))
\r
2423 temp.SubInternalBits(n2.digitArray);
\r
2426 if (GtInt(temp, n1))
\r
2428 temp.SubInternalBits(n2.digitArray);
\r
2434 Q.digitArray[0] = q;
\r
2436 R.SubInternalBits(temp.digitArray);
\r
2440 /// Schoolbook division algorithm
\r
2442 /// <param name="n1"></param>
\r
2443 /// <param name="n2"></param>
\r
2444 /// <param name="Q"></param>
\r
2445 /// <param name="R"></param>
\r
2446 private static void Div_32(BigInt n1, BigInt n2, BigInt Q, BigInt R)
\r
2448 int digitsN1 = n1.GetMSD() + 1;
\r
2449 int digitsN2 = n2.GetMSD() + 1;
\r
2451 //n2 is bigger than n1
\r
2452 if (digitsN1 < digitsN2)
\r
2459 if (digitsN1 == digitsN2)
\r
2461 //n2 is bigger than n1
\r
2462 if (LtInt(n1, n2))
\r
2469 //n2 >= n1, but less the 2x n1 (initial conditions make this certain)
\r
2471 Q.digitArray[0] = 1;
\r
2473 R.SubInternalBits(n2.digitArray);
\r
2477 int digits = digitsN1 - (digitsN2 + 1);
\r
2479 //Algorithm Div_31 can be used to get the answer in O(n) time.
\r
2482 Div_31(n1, n2, Q, R);
\r
2486 BigInt n1New = DigitShiftRight(n1, digits);
\r
2487 BigInt s = DigitTruncate(n1, digits);
\r
2489 BigInt Q2 = new BigInt(n1, n1.pres, true);
\r
2490 BigInt R2 = new BigInt(n1, n1.pres, true);
\r
2492 Div_31(n1New, n2, Q2, R2);
\r
2494 R2.DigitShiftSelfLeft(digits);
\r
2497 Div_32(R2, n2, Q, R);
\r
2499 Q2.DigitShiftSelfLeft(digits);
\r
2504 /// Sets the n-th bit of the number to 1
\r
2506 /// <param name="bit">the index of the bit to set</param>
\r
2507 public void SetBit(int bit)
\r
2509 int digit = (bit >> 5);
\r
2510 if (digit >= digitArray.Length) return;
\r
2511 digitArray[digit] = digitArray[digit] | (1u << (bit - (digit << 5)));
\r
2515 /// Sets the n-th bit of the number to 0
\r
2517 /// <param name="bit">the index of the bit to set</param>
\r
2518 public void ClearBit(int bit)
\r
2520 int digit = (bit >> 5);
\r
2521 if (digit >= digitArray.Length) return;
\r
2522 digitArray[digit] = digitArray[digit] & (~(1u << (bit - (digit << 5))));
\r
2526 /// Returns the n-th bit, counting from the MSB to the LSB
\r
2528 /// <param name="bit">the index of the bit to return</param>
\r
2529 /// <returns>1 if the bit is 1, 0 otherwise</returns>
\r
2530 public uint GetBitFromTop(int bit)
\r
2532 if (bit < 0) return 0;
\r
2533 int wordCount = (bit >> 5);
\r
2534 int upBit = 31 - (bit & 31);
\r
2535 if (wordCount >= digitArray.Length) return 0;
\r
2537 return ((digitArray[digitArray.Length - (wordCount + 1)] & (1u << upBit)) >> upBit);
\r
2541 /// Assigns n2 to 'this'
\r
2543 /// <param name="n2"></param>
\r
2544 public void Assign(BigInt n2)
\r
2546 if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);
\r
2552 /// Assign n2 to 'this', safe only if precision-matched
\r
2554 /// <param name="n2"></param>
\r
2555 /// <returns></returns>
\r
2556 private void AssignInt(BigInt n2)
\r
2558 int Length = digitArray.Length;
\r
2560 for (int i = 0; i < Length; i++)
\r
2562 digitArray[i] = n2.digitArray[i];
\r
2566 private static BigInt DigitShiftRight(BigInt n1, int digits)
\r
2568 BigInt res = new BigInt(n1);
\r
2570 int Length = res.digitArray.Length;
\r
2572 for (int i = 0; i < Length - digits; i++)
\r
2574 res.digitArray[i] = res.digitArray[i + digits];
\r
2577 for (int i = Length - digits; i < Length; i++)
\r
2579 res.digitArray[i] = 0;
\r
2585 private void DigitShiftSelfRight(int digits)
\r
2587 for (int i = digits; i < digitArray.Length; i++)
\r
2589 digitArray[i - digits] = digitArray[i];
\r
2592 for (int i = digitArray.Length - digits; i < digitArray.Length; i++)
\r
2594 digitArray[i] = 0;
\r
2598 private void DigitShiftSelfLeft(int digits)
\r
2600 for (int i = digitArray.Length - 1; i >= digits; i--)
\r
2602 digitArray[i] = digitArray[i - digits];
\r
2605 for (int i = digits - 1; i >= 0; i--)
\r
2607 digitArray[i] = 0;
\r
2611 private static BigInt DigitTruncate(BigInt n1, int digits)
\r
2613 BigInt res = new BigInt(n1);
\r
2615 for (int i = res.digitArray.Length - 1; i >= digits; i--)
\r
2617 res.digitArray[i] = 0;
\r
2623 private void Add2Pow32Self()
\r
2625 int Length = digitArray.Length;
\r
2629 for (int i = 1; i < Length; i++)
\r
2631 uint temp = digitArray[i];
\r
2632 digitArray[i] += carry;
\r
2633 if (digitArray[i] > temp) return;
\r
2640 /// Sets the number of digits without changing the precision
\r
2641 /// This method is made public only to facilitate fixed-point operations
\r
2642 /// It should under no circumstances be used for anything else, because
\r
2643 /// it breaks the BigNum(PrecisionSpec precision) constructor in dangerous
\r
2644 /// and unpredictable ways.
\r
2646 /// <param name="digits"></param>
\r
2647 public void SetNumDigits(int digits)
\r
2649 if (digits == digitArray.Length) return;
\r
2651 UInt32[] newDigitArray = new UInt32[digits];
\r
2652 workingSet = new UInt32[digits];
\r
2654 int numCopy = (digits < digitArray.Length) ? digits : digitArray.Length;
\r
2656 for (int i = 0; i < numCopy; i++)
\r
2658 newDigitArray[i] = digitArray[i];
\r
2661 digitArray = newDigitArray;
\r
2664 //********************** Explicit casts ***********************
\r
2669 /// <param name="value"></param>
\r
2670 /// <returns></returns>
\r
2671 public static explicit operator Int32(BigInt value)
\r
2673 if (value.digitArray[0] == 0x80000000 && value.sign) return Int32.MinValue;
\r
2674 int res = (int)(value.digitArray[0] & 0x7fffffff);
\r
2675 if (value.sign) res = -res;
\r
2680 /// explicit cast to unsigned int.
\r
2682 /// <param name="value"></param>
\r
2683 /// <returns></returns>
\r
2684 public static explicit operator UInt32(BigInt value)
\r
2686 if (value.sign) return (UInt32)((Int32)(value));
\r
2687 return (UInt32)value.digitArray[0];
\r
2691 /// explicit cast to 64-bit signed integer.
\r
2693 /// <param name="value"></param>
\r
2694 /// <returns></returns>
\r
2695 public static explicit operator Int64(BigInt value)
\r
2697 if (value.digitArray.Length < 2) return (value.sign ? -((Int64)value.digitArray[0]): ((Int64)value.digitArray[0]));
\r
2698 UInt64 ret = (((UInt64)value.digitArray[1]) << 32) + (UInt64)value.digitArray[0];
\r
2699 if (ret == 0x8000000000000000L && value.sign) return Int64.MinValue;
\r
2700 Int64 signedRet = (Int64)(ret & 0x7fffffffffffffffL);
\r
2701 if (value.sign) signedRet = -signedRet;
\r
2706 /// Explicit cast to UInt64
\r
2708 /// <param name="value"></param>
\r
2709 /// <returns></returns>
\r
2710 public static explicit operator UInt64(BigInt value)
\r
2712 if (value.sign) return (UInt64)((Int64)(value));
\r
2713 if (value.digitArray.Length < 2) return (UInt64)value.digitArray[0];
\r
2714 return ((((UInt64)value.digitArray[1]) << 32) + (UInt64)value.digitArray[0]);
\r
2718 /// Cast to string
\r
2720 /// <param name="value"></param>
\r
2721 /// <returns></returns>
\r
2722 public static explicit operator string(BigInt value)
\r
2724 return value.ToString();
\r
2728 /// Cast from string - this is not wholly safe, because precision is not
\r
2729 /// specified. You should try to construct a BigInt with the appropriate
\r
2730 /// constructor instead.
\r
2732 /// <param name="value">The decimal string to convert to a BigInt</param>
\r
2733 /// <returns>A BigInt of the precision required to encompass the string</returns>
\r
2734 public static explicit operator BigInt(string value)
\r
2736 return new BigInt(value);
\r
2739 //********************* ToString members **********************
\r
2742 /// Converts this to a string, in the specified base
\r
2744 /// <param name="numberBase">the base to use (min 2, max 16)</param>
\r
2745 /// <returns>a string representation of the number</returns>
\r
2746 public string ToString(int numberBase)
\r
2748 char[] digitChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
\r
2750 string output = "";
\r
2752 BigInt clone = new BigInt(this);
\r
2753 clone.sign = false;
\r
2755 int numDigits = 0;
\r
2756 while (!clone.IsZero())
\r
2758 if (numberBase == 10 && (numDigits % 3) == 0 && numDigits != 0)
\r
2760 output = String.Format(",{0}", output);
\r
2762 else if (numberBase != 10 && (numDigits % 8) == 0 && numDigits != 0)
\r
2764 output = String.Format(" {0}", output);
\r
2768 DivMod(clone, (uint)numberBase, out div, out mod);
\r
2769 int iMod = (int)mod;
\r
2770 output = String.Format("{0}{1}", digitChars[(int)mod], output);
\r
2777 if (output.Length == 0) output = String.Format("0");
\r
2779 if (sign) output = String.Format("-{0}", output);
\r
2785 /// Converts the number to a string, in base 10
\r
2787 /// <returns>a string representation of the number in base 10</returns>
\r
2788 public override string ToString()
\r
2790 return ToString(10);
\r
2793 //***************** Internal helper functions *****************
\r
2795 private void FromStringInt(string init, int numberBase)
\r
2797 char [] digitChars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
\r
2799 string formattedInput = init.Trim().ToUpper();
\r
2801 for (int i = 0; i < formattedInput.Length; i++)
\r
2803 int digitIndex = Array.IndexOf(digitChars, formattedInput[i]);
\r
2805 //Skip fractional part altogether
\r
2806 if (formattedInput[i] == '.') break;
\r
2808 //skip non-digit characters.
\r
2809 if (digitIndex < 0) continue;
\r
2812 MulInternal((uint)numberBase);
\r
2815 AddInternal(digitIndex);
\r
2818 if (init.Length > 0 && init[0] == '-') sign = true;
\r
2822 /// Sign-insensitive less than comparison.
\r
2823 /// unsafe if n1 and n2 disagree in precision
\r
2825 /// <param name="n1"></param>
\r
2826 /// <param name="n2"></param>
\r
2827 /// <returns></returns>
\r
2828 private static bool LtInt(BigInt n1, BigInt n2)
\r
2830 //MakeSafe(ref n1, ref n2);
\r
2832 for (int i = n1.digitArray.Length - 1; i >= 0; i--)
\r
2834 if (n1.digitArray[i] < n2.digitArray[i]) return true;
\r
2835 if (n1.digitArray[i] > n2.digitArray[i]) return false;
\r
2843 /// Sign-insensitive greater than comparison.
\r
2844 /// unsafe if n1 and n2 disagree in precision
\r
2846 /// <param name="n1"></param>
\r
2847 /// <param name="n2"></param>
\r
2848 /// <returns></returns>
\r
2849 private static bool GtInt(BigInt n1, BigInt n2)
\r
2851 //MakeSafe(ref n1, ref n2);
\r
2853 for (int i = n1.digitArray.Length - 1; i >= 0; i--)
\r
2855 if (n1.digitArray[i] > n2.digitArray[i]) return true;
\r
2856 if (n1.digitArray[i] < n2.digitArray[i]) return false;
\r
2864 /// Makes sure the numbers have matching precisions
\r
2866 /// <param name="n1"></param>
\r
2867 /// <param name="n2"></param>
\r
2868 private static void MakeSafe(ref BigInt n1, ref BigInt n2)
\r
2870 if (n1.digitArray.Length == n2.digitArray.Length)
\r
2874 else if (n1.digitArray.Length > n2.digitArray.Length)
\r
2876 n2 = new BigInt(n2, n1.pres);
\r
2880 n1 = new BigInt(n1, n2.pres);
\r
2885 /// Makes sure the numbers have matching precisions
\r
2887 /// <param name="n2">the number to match to this</param>
\r
2888 private void MakeSafe(ref BigInt n2)
\r
2890 n2 = new BigInt(n2, pres);
\r
2891 n2.SetNumDigits(digitArray.Length);
\r
2895 private PrecisionSpec pres;
\r
2896 private bool sign;
\r
2897 private uint[] digitArray;
\r
2898 private uint[] workingSet;
\r