OSDN Git Service

5
[psychlops/silverlight.git] / dev5 / psychlops / extension / math / BigInt.cs
diff --git a/dev5/psychlops/extension/math/BigInt.cs b/dev5/psychlops/extension/math/BigInt.cs
new file mode 100644 (file)
index 0000000..56a484e
--- /dev/null
@@ -0,0 +1,2901 @@
+// http://www.fractal-landscapes.co.uk/bigint.html\r
+\r
+using System;\r
+\r
+namespace BigNum\r
+{\r
+    /// <summary>\r
+    /// Specifies the desired precision for a BigInt or a BigFloat. \r
+    /// </summary>\r
+    public struct PrecisionSpec\r
+    {\r
+        /// <summary>\r
+        /// Precision can be specified in a choice of 8 bases.\r
+        /// Note that precision for decimals is approximate.\r
+        /// </summary>\r
+        public enum BaseType\r
+        {\r
+            /// <summary>\r
+            /// Binary base\r
+            /// </summary>\r
+            BIN,\r
+            /// <summary>\r
+            /// Octal base\r
+            /// </summary>\r
+            OCT,\r
+            /// <summary>\r
+            /// Decimal base\r
+            /// </summary>\r
+            DEC,\r
+            /// <summary>\r
+            /// Hexadecimal base\r
+            /// </summary>\r
+            HEX,\r
+            /// <summary>\r
+            /// 8-bits per digit\r
+            /// </summary>\r
+            BYTES,\r
+            /// <summary>\r
+            /// 16-bits per digit\r
+            /// </summary>\r
+            WORDS,\r
+            /// <summary>\r
+            /// 32-bits per digit\r
+            /// </summary>\r
+            DWORDS,\r
+            /// <summary>\r
+            /// 64-bits per digit\r
+            /// </summary>\r
+            QWORDS\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructor: Constructs a precision specification\r
+        /// </summary>\r
+        /// <param name="precision">The number of digits</param>\r
+        /// <param name="numberBase">The base of the digits</param>\r
+        public PrecisionSpec(int precision, BaseType numberBase)\r
+        {\r
+            this.prec = precision;\r
+            this.nB = numberBase;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Explicit cast from integer value.\r
+        /// </summary>\r
+        /// <param name="value">The value in bits for the new precision specification</param>\r
+        /// <returns>A new precision specification with the number of bits specified</returns>\r
+        public static explicit operator PrecisionSpec(int value)\r
+        {\r
+            return new PrecisionSpec(value, BaseType.BIN);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Equality test\r
+        /// </summary>\r
+        /// <param name="spec1">the first parameter</param>\r
+        /// <param name="spec2">the second parameter</param>\r
+        /// <returns>true iff both precisions have the same number of bits</returns>\r
+        public static bool operator ==(PrecisionSpec spec1, PrecisionSpec spec2)\r
+        {\r
+            return (spec1.NumBits == spec2.NumBits);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Inequality operator\r
+        /// </summary>\r
+        /// <param name="spec1">the first parameter</param>\r
+        /// <param name="spec2">the second parameter</param>\r
+        /// <returns>true iff the parameters do not have the same number of bits</returns>\r
+        public static bool operator !=(PrecisionSpec spec1, PrecisionSpec spec2)\r
+        {\r
+            return !(spec1 == spec2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Object equality override\r
+        /// </summary>\r
+        /// <param name="obj">the PrecisionSpec struct to compare</param>\r
+        /// <returns>true iff obj has the same number of bits as this</returns>\r
+        public override bool Equals(object obj)\r
+        {\r
+            return NumBits == ((PrecisionSpec)obj).NumBits;     \r
+        }\r
+\r
+        /// <summary>\r
+        /// Override of the hash code\r
+        /// </summary>\r
+        /// <returns>A basic hash</returns>\r
+        public override int GetHashCode()\r
+        {\r
+            return NumBits * prec + NumBits;\r
+        }\r
+\r
+        /// <summary>\r
+        /// The precision in units specified by the base type (e.g. number of decimal digits)\r
+        /// </summary>\r
+        public int Precision\r
+        {\r
+            get { return prec; }\r
+        }\r
+\r
+        /// <summary>\r
+        /// The base type in which precision is specified\r
+        /// </summary>\r
+        public BaseType NumberBaseType\r
+        {\r
+            get { return nB; }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Converts the number-base to an integer\r
+        /// </summary>\r
+        public int NumberBase\r
+        {\r
+            get { return (int)nB; }\r
+        }\r
+\r
+        /// <summary>\r
+        /// The number of bits that this PrecisionSpec structure specifies.\r
+        /// </summary>\r
+        public int NumBits\r
+        {\r
+            get\r
+            {\r
+                if (nB == BaseType.BIN) return prec;\r
+                if (nB == BaseType.OCT) return prec * 3;\r
+                if (nB == BaseType.HEX) return prec * 4;\r
+                if (nB == BaseType.BYTES) return prec * 8;\r
+                if (nB == BaseType.WORDS) return prec * 16;\r
+                if (nB == BaseType.DWORDS) return prec * 32;\r
+                if (nB == BaseType.QWORDS) return prec * 64;\r
+\r
+                double factor = 3.322;\r
+                int bits = ((int)Math.Ceiling(factor * (double)prec));\r
+                return bits;\r
+            }\r
+        }\r
+\r
+        private int prec;\r
+        private BaseType nB;\r
+    }\r
+\r
+    \r
+    /// <summary>\r
+    /// An arbitrary-precision integer class\r
+    /// \r
+    /// Format:\r
+    /// Each number consists of an array of 32-bit unsigned integers, and a bool sign\r
+    /// value.\r
+    /// \r
+    /// Applicability and Performance:\r
+    /// This class is designed to be used for small extended precisions. It may not be\r
+    /// safe (and certainly won't be fast) to use it with mixed-precision arguments.\r
+    /// It does support, but will not be efficient for, numbers over around 2048 bits.\r
+    /// \r
+    /// Notes:\r
+    /// All conversions to and from strings are slow.\r
+    /// \r
+    /// Conversions from simple integer types Int32, Int64, UInt32, UInt64 are performed\r
+    /// using the appropriate constructor, and are relatively fast.\r
+    /// \r
+    /// The class is written entirely in managed C# code, with not native or managed\r
+    /// assembler. The use of native assembler would speed up the multiplication operations\r
+    /// many times over, and therefore all higher-order operations too.\r
+    /// </summary>\r
+    public class BigInt\r
+    {\r
+        //*************** Constructors ******************\r
+\r
+        /// <summary>\r
+        /// Constructs an empty BigInt to the desired precision.\r
+        /// </summary>\r
+        /// <param name="precision"></param>\r
+        public BigInt(PrecisionSpec precision)\r
+        {\r
+            Init(precision);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a BigInt from a string, using the string length to determine the precision\r
+        /// Note, operations on BigInts of non-matching precision are slow, so avoid using this constructor\r
+        /// </summary>\r
+        /// <param name="init"></param>\r
+        public BigInt(string init)\r
+        {\r
+            InitFromString(init, (PrecisionSpec)init.Length, 10);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructor for copying length and precision\r
+        /// </summary>\r
+        /// <param name="inputToCopy">The BigInt to copy</param>\r
+        /// <param name="precision">The precision of the new BigInt</param>\r
+        /// <param name="bCopyLengthOnly">decides whether to copy the actual input, or just its digit length</param>\r
+        /// <example><code>//Create an integer\r
+        /// BigInt four = new BigInt(4, new PrecisionSpec(128, PrecisionSpec.BaseType.BIN));\r
+        /// \r
+        /// //Pad four to double its usual number of digits (this does not affect the precision)\r
+        /// four.Pad();\r
+        /// \r
+        /// //Create a new, empty integer with matching precision, also padded to twice the usual length\r
+        /// BigInt newCopy = new BigInt(four, four.Precision, true);</code></example>\r
+        public BigInt(BigInt inputToCopy, PrecisionSpec precision, bool bCopyLengthOnly)\r
+        {\r
+            digitArray = new uint[inputToCopy.digitArray.Length];\r
+            workingSet = new uint[inputToCopy.digitArray.Length];\r
+            if (!bCopyLengthOnly) Array.Copy(inputToCopy.digitArray, digitArray, digitArray.Length);\r
+            sign = inputToCopy.sign;\r
+            pres = inputToCopy.pres;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a bigint from the string, with the desired precision, using base 10\r
+        /// </summary>\r
+        /// <param name="init"></param>\r
+        /// <param name="precision"></param>\r
+        public BigInt(string init, PrecisionSpec precision)\r
+        {\r
+            InitFromString(init, precision, 10);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a BigInt from a string, using the specified precision and base\r
+        /// </summary>\r
+        /// <param name="init"></param>\r
+        /// <param name="precision"></param>\r
+        /// <param name="numberBase"></param>\r
+        public BigInt(string init, PrecisionSpec precision, int numberBase)\r
+        {\r
+            InitFromString(init, precision, numberBase);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a bigint from the input.\r
+        /// </summary>\r
+        /// <param name="input"></param>\r
+        public BigInt(BigInt input)\r
+        {\r
+            digitArray = new uint[input.digitArray.Length];\r
+            workingSet = new uint[input.digitArray.Length];\r
+            Array.Copy(input.digitArray, digitArray, digitArray.Length);\r
+            sign = input.sign;\r
+            pres = input.pres;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a bigint from the input, matching the new precision provided\r
+        /// </summary>\r
+        public BigInt(BigInt input, PrecisionSpec precision)\r
+        {\r
+            //Casts the input to the new precision.\r
+            Init(precision);\r
+            int Min = (input.digitArray.Length < digitArray.Length) ? input.digitArray.Length : digitArray.Length;\r
+\r
+            for (int i = 0; i < Min; i++)\r
+            {\r
+                digitArray[i] = input.digitArray[i];\r
+            }\r
+\r
+            sign = input.sign;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a BigInt from a UInt32\r
+        /// </summary>\r
+        /// <param name="input"></param>\r
+        /// <param name="precision"></param>\r
+        public BigInt(UInt32 input, PrecisionSpec precision)\r
+        {\r
+            Init(precision);\r
+            digitArray[0] = input;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a BigInt from a UInt64\r
+        /// </summary>\r
+        /// <param name="input"></param>\r
+        /// <param name="precision"></param>\r
+        public BigInt(UInt64 input, PrecisionSpec precision)\r
+        {\r
+            Init(precision);\r
+            digitArray[0] = (UInt32)(input & 0xffffffff);\r
+            if (digitArray.Length > 1) digitArray[1] = (UInt32)(input >> 32);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a BigInt from an Int32\r
+        /// </summary>\r
+        /// <param name="input"></param>\r
+        /// <param name="precision"></param>\r
+        public BigInt(Int32 input, PrecisionSpec precision)\r
+        {\r
+            Init(precision);\r
+            if (input < 0)\r
+            {\r
+                sign = true;\r
+\r
+                if (input == Int32.MinValue)\r
+                {\r
+                    digitArray[0] = 0x80000000;\r
+                }\r
+                else\r
+                {\r
+                    digitArray[0] = (UInt32)(-input);\r
+                }\r
+            }\r
+            else\r
+            {\r
+                digitArray[0] = ((UInt32)input);\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Constructs a BigInt from a UInt32\r
+        /// </summary>\r
+        /// <param name="input"></param>\r
+        /// <param name="precision"></param>\r
+        public BigInt(Int64 input, PrecisionSpec precision)\r
+        {\r
+            Init(precision);\r
+            if (input < 0) sign = true;\r
+\r
+            digitArray[0] = (UInt32)(input & 0xffffffff);\r
+\r
+            if (digitArray.Length >= 2)\r
+            {\r
+                if (input == Int64.MinValue)\r
+                {\r
+                    digitArray[1] = 0x80000000;\r
+                }\r
+                else\r
+                {\r
+                    digitArray[1] = (UInt32)((input >> 32) & 0x7fffffff);\r
+                }\r
+            }\r
+        }\r
+\r
+        //***************** Properties *******************\r
+\r
+        /// <summary>\r
+        /// true iff the number is negative\r
+        /// </summary>\r
+        public bool Sign { get { return sign; } set { sign = value; } }\r
+\r
+        /// <summary>\r
+        /// The precision of the number.\r
+        /// </summary>\r
+        public PrecisionSpec Precision { get { return pres; } }\r
+\r
+        //*************** Utility Functions **************\r
+\r
+        /// <summary>\r
+        /// Casts a BigInt to the new precision provided.\r
+        /// Note: This will return the input if the precision already matches.\r
+        /// </summary>\r
+        /// <param name="input"></param>\r
+        /// <param name="precision"></param>\r
+        /// <returns></returns>\r
+        public static BigInt CastToPrecision(BigInt input, PrecisionSpec precision)\r
+        {\r
+            if (input.pres == precision) return input;\r
+            return new BigInt(input, precision);\r
+        }\r
+\r
+\r
+        //*************** Member Functions ***************\r
+\r
+        /// <summary>\r
+        /// Addition and assignment - without intermediate memory allocation.\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public uint Add(BigInt n2)\r
+        {\r
+            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);\r
+\r
+            if (sign == n2.sign)\r
+            {\r
+                return AddInternalBits(n2.digitArray);\r
+            }\r
+            else\r
+            {\r
+                bool lessThan = LtInt(this, n2);\r
+\r
+                if (lessThan)\r
+                {\r
+                    int Length = digitArray.Length;\r
+\r
+                    for (int i = 0; i < Length; i++)\r
+                    {\r
+                        workingSet[i] = digitArray[i];\r
+                        digitArray[i] = n2.digitArray[i];\r
+                    }\r
+\r
+                    sign = !sign;\r
+                    return SubInternalBits(workingSet);\r
+                }\r
+                else\r
+                {\r
+                    return SubInternalBits(n2.digitArray);\r
+                }\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Subtraction and assignment - without intermediate memory allocation.\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public uint Sub(BigInt n2)\r
+        {\r
+            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);\r
+\r
+            if (sign != n2.sign)\r
+            {\r
+                return AddInternalBits(n2.digitArray);\r
+            }\r
+            else\r
+            {\r
+                bool lessThan = LtInt(this, n2);\r
+\r
+                if (lessThan)\r
+                {\r
+                    int Length = digitArray.Length;\r
+\r
+                    for (int i = 0; i < Length; i++)\r
+                    {\r
+                        workingSet[i] = digitArray[i];\r
+                        digitArray[i] = n2.digitArray[i];\r
+                    }\r
+\r
+                    sign = !sign;\r
+                    return SubInternalBits(workingSet);\r
+                }\r
+                else\r
+                {\r
+                    return SubInternalBits(n2.digitArray);\r
+                }\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Multiplication and assignmnet - with minimal intermediate memory allocation.\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public void Mul(BigInt n2)\r
+        {\r
+            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);\r
+\r
+            int Length = n2.digitArray.Length;\r
+\r
+            //Inner loop zero-mul avoidance\r
+            int maxDigit = 0;\r
+            for (int i = Length - 1; i >= 0; i--)\r
+            {\r
+                if (digitArray[i] != 0)\r
+                {\r
+                    maxDigit = i + 1;\r
+                    break;\r
+                }\r
+            }\r
+\r
+            //Result is zero, 'this' is unchanged\r
+            if (maxDigit == 0) return;\r
+\r
+            //Temp storage for source (both working sets are used by the calculation)\r
+            uint[] thisTemp = new uint [Length];\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                thisTemp[i] = digitArray[i];\r
+                digitArray[i] = 0;\r
+            }\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                //Clear the working set\r
+                for (int j = 0; j < i; j++)\r
+                {\r
+                    workingSet[j] = 0;\r
+                    n2.workingSet[j] = 0;\r
+                }\r
+\r
+                n2.workingSet[i] = 0;\r
+\r
+                ulong digit = n2.digitArray[i];\r
+                if (digit == 0) continue;\r
+\r
+                for (int j = 0; j + i < Length && j < maxDigit; j++)\r
+                {\r
+                    //Multiply n1 by each of the integer digits of n2.\r
+                    ulong temp = (ulong)thisTemp[j] * digit;\r
+                    //n1.workingSet stores the low bits of each piecewise multiplication\r
+                    workingSet[j + i] = (uint)(temp & 0xffffffff);\r
+                    if (j + i + 1 < Length)\r
+                    {\r
+                        //n2.workingSet stores the high bits of each multiplication\r
+                        n2.workingSet[j + i + 1] = (uint)(temp >> 32);\r
+                    }\r
+                }\r
+\r
+                AddInternalBits(workingSet);\r
+                AddInternalBits(n2.workingSet);\r
+            }\r
+\r
+            sign = (sign != n2.sign);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Squares the number.\r
+        /// </summary>\r
+        public void Square()\r
+        {\r
+            int Length = digitArray.Length;\r
+\r
+            //Inner loop zero-mul avoidance\r
+            int maxDigit = 0;\r
+            for (int i = Length - 1; i >= 0; i--)\r
+            {\r
+                if (digitArray[i] != 0)\r
+                {\r
+                    maxDigit = i + 1;\r
+                    break;\r
+                }\r
+            }\r
+\r
+            //Result is zero, 'this' is unchanged\r
+            if (maxDigit == 0) return;\r
+\r
+            //Temp storage for source (both working sets are used by the calculation)\r
+            uint[] thisTemp = new uint[Length];\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                thisTemp[i] = digitArray[i];\r
+                digitArray[i] = 0;\r
+            }\r
+\r
+            UInt32 [] workingSet2 = new UInt32[Length];\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                //Clear the working set\r
+                for (int j = 0; j < i; j++)\r
+                {\r
+                    workingSet[j] = 0;\r
+                    workingSet2[j] = 0;\r
+                }\r
+\r
+                workingSet2[i] = 0;\r
+\r
+                ulong digit = thisTemp[i];\r
+                if (digit == 0) continue;\r
+\r
+                for (int j = 0; j + i < Length && j < maxDigit; j++)\r
+                {\r
+                    //Multiply n1 by each of the integer digits of n2.\r
+                    ulong temp = (ulong)thisTemp[j] * digit;\r
+                    //n1.workingSet stores the low bits of each piecewise multiplication\r
+                    workingSet[j + i] = (uint)(temp & 0xffffffff);\r
+                    if (j + i + 1 < Length)\r
+                    {\r
+                        //n2.workingSet stores the high bits of each multiplication\r
+                        workingSet2[j + i + 1] = (uint)(temp >> 32);\r
+                    }\r
+                }\r
+\r
+                AddInternalBits(workingSet);\r
+                AddInternalBits(workingSet2);\r
+            }\r
+\r
+            sign = false;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Used for floating-point multiplication\r
+        /// Stores the high bits of the multiplication only (the carry bit from the\r
+        /// lower bits is missing, so the true answer might be 1 greater).\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public void MulHi(BigInt n2)\r
+        {\r
+            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);\r
+\r
+            int Length = n2.digitArray.Length;\r
+\r
+            //Inner loop zero-mul avoidance\r
+            int maxDigit = 0;\r
+            for (int i = Length - 1; i >= 0; i--)\r
+            {\r
+                if (digitArray[i] != 0)\r
+                {\r
+                    maxDigit = i + 1;\r
+                    break;\r
+                }\r
+            }\r
+\r
+            //Result is zero, 'this' is unchanged\r
+            if (maxDigit == 0) return;\r
+\r
+            //Temp storage for source (both working sets are used by the calculation)\r
+            uint[] thisTemp = new uint[Length];\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                thisTemp[i] = digitArray[i];\r
+                digitArray[i] = 0;\r
+            }\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                //Clear the working set\r
+                for (int j = 0; j < Length; j++)\r
+                {\r
+                    workingSet[j] = 0;\r
+                    n2.workingSet[j] = 0;\r
+                }\r
+\r
+                n2.workingSet[i] = 0;\r
+\r
+                ulong digit = n2.digitArray[i];\r
+                if (digit == 0) continue;\r
+\r
+                //Only the high bits\r
+                if (maxDigit + i < Length - 1) continue;\r
+\r
+                for (int j = 0; j < maxDigit; j++)\r
+                {\r
+                    if (j + i + 1 < Length) continue;\r
+                    //Multiply n1 by each of the integer digits of n2.\r
+                    ulong temp = (ulong)thisTemp[j] * digit;\r
+                    //n1.workingSet stores the low bits of each piecewise multiplication\r
+                    if (j + i >= Length)\r
+                    {\r
+                        workingSet[j + i - Length] = (uint)(temp & 0xffffffff);\r
+                    }\r
+                    \r
+                    //n2.workingSet stores the high bits of each multiplication\r
+                    n2.workingSet[j + i + 1 - Length] = (uint)(temp >> 32);\r
+                }\r
+\r
+                AddInternalBits(workingSet);\r
+                AddInternalBits(n2.workingSet);\r
+            }\r
+\r
+            sign = (sign != n2.sign);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Floating-point helper function.\r
+        /// Squares the number and keeps the high bits of the calculation.\r
+        /// Takes a temporary BigInt as a working set.\r
+        /// </summary>\r
+        public void SquareHiFast(BigInt scratch)\r
+        {\r
+            int Length = digitArray.Length;\r
+            uint[] tempDigits = scratch.digitArray;\r
+            uint[] workingSet2 = scratch.workingSet;\r
+\r
+            //Temp storage for source (both working sets are used by the calculation)\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                tempDigits[i] = digitArray[i];\r
+                digitArray[i] = 0;\r
+            }\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                //Clear the working set\r
+                for (int j = i; j < Length; j++)\r
+                {\r
+                    workingSet[j] = 0;\r
+                    workingSet2[j] = 0;\r
+                }\r
+\r
+                if (i - 1 >= 0) workingSet[i - 1] = 0;\r
+\r
+                ulong digit = tempDigits[i];\r
+                if (digit == 0) continue;\r
+\r
+                for (int j = 0; j < Length; j++)\r
+                {\r
+                    if (j + i + 1 < Length) continue;\r
+                    //Multiply n1 by each of the integer digits of n2.\r
+                    ulong temp = (ulong)tempDigits[j] * digit;\r
+                    //n1.workingSet stores the low bits of each piecewise multiplication\r
+                    if (j + i >= Length)\r
+                    {\r
+                        workingSet[j + i - Length] = (uint)(temp & 0xffffffff);\r
+                    }\r
+\r
+                    //n2.workingSet stores the high bits of each multiplication\r
+                    workingSet2[j + i + 1 - Length] = (uint)(temp >> 32);\r
+                }\r
+\r
+                AddInternalBits(workingSet);\r
+                AddInternalBits(workingSet2);\r
+            }\r
+\r
+            sign = false;\r
+        }\r
+\r
+        /// <summary>\r
+        /// This uses the schoolbook division algorithm, as decribed by http://www.treskal.com/kalle/exjobb/original-report.pdf\r
+        /// Algorithms 3.1 (implemented by Div_31) and 3.2 (implemented by Div_32)\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public void Div(BigInt n2)\r
+        {\r
+            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);\r
+\r
+            int OldLength = digitArray.Length;\r
+\r
+            //First, we need to prepare the operands for division using Div_32, which requires\r
+            //That the most significant digit of n2 be set. To do this, we need to shift n2 (and therefore n1) up.\r
+            //This operation can potentially increase the precision of the operands.\r
+            int shift = MakeSafeDiv(this, n2);\r
+\r
+            BigInt Q = new BigInt(this, this.pres, true);\r
+            BigInt R = new BigInt(this, this.pres, true);\r
+\r
+            Div_32(this, n2, Q, R);\r
+\r
+            //Restore n2 to its pre-shift value\r
+            n2.RSH(shift);\r
+            AssignInt(Q);\r
+            sign = (sign != n2.sign);\r
+\r
+            //Reset the lengths of the operands\r
+            SetNumDigits(OldLength);\r
+            n2.SetNumDigits(OldLength);\r
+        }\r
+\r
+        /// <summary>\r
+        /// This function is used for floating-point division.\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        //Given two numbers:\r
+        //  In floating point 1 <= a, b < 2, meaning that both numbers have their top bits set.\r
+        //  To calculate a / b, maintaining precision, we:\r
+        //    1. Double the number of digits available to both numbers.\r
+        //    2. set a = a * 2^d (where d is the number of digits)\r
+        //    3. calculate the quotient a <- q:  2^(d-1) <= q < 2^(d+1)\r
+        //    4. if a >= 2^d, s = 1, else s = 0\r
+        //    6. shift a down by s, and undo the precision extension\r
+        //    7. return 1 - shift (change necessary to exponent)\r
+        public int DivAndShift(BigInt n2)\r
+        {\r
+            if (n2.IsZero()) return -1;\r
+            if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);\r
+\r
+            int oldLength = digitArray.Length;\r
+\r
+            //Double the number of digits, and shift a into the higher digits.\r
+            Pad();\r
+            n2.Extend();\r
+\r
+            //Do the divide (at double precision, ouch!)\r
+            Div(n2);\r
+\r
+            //Shift down if 'this' >= 2^d\r
+            int ret = 1;\r
+\r
+            if (digitArray[oldLength] != 0)\r
+            {\r
+                RSH(1);\r
+                ret--;\r
+            }\r
+\r
+            SetNumDigits(oldLength);\r
+            n2.SetNumDigits(oldLength);\r
+\r
+            return ret;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Calculates 'this' mod n2 (using the schoolbook division algorithm as above)\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public void Mod(BigInt n2)\r
+        {\r
+            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);\r
+\r
+            int OldLength = digitArray.Length;\r
+\r
+            //First, we need to prepare the operands for division using Div_32, which requires\r
+            //That the most significant digit of n2 be set. To do this, we need to shift n2 (and therefore n1) up.\r
+            //This operation can potentially increase the precision of the operands.\r
+            int shift = MakeSafeDiv(this, n2);\r
+\r
+            BigInt Q = new BigInt(this.pres);\r
+            BigInt R = new BigInt(this.pres);\r
+\r
+            Q.digitArray = new UInt32[this.digitArray.Length];\r
+            R.digitArray = new UInt32[this.digitArray.Length];\r
+\r
+            Div_32(this, n2, Q, R);\r
+\r
+            //Restore n2 to its pre-shift value\r
+            n2.RSH(shift);\r
+            R.RSH(shift);\r
+            R.sign = (sign != n2.sign);\r
+            AssignInt(R);\r
+\r
+            //Reset the lengths of the operands\r
+            SetNumDigits(OldLength);\r
+            n2.SetNumDigits(OldLength);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Logical left shift\r
+        /// </summary>\r
+        /// <param name="shift"></param>\r
+        public void LSH(int shift)\r
+        {\r
+            if (shift <= 0) return;\r
+            int length = digitArray.Length;\r
+            int digits = shift >> 5;\r
+            int rem = shift & 31;\r
+\r
+            for (int i = length - 1; i >= digits; i--)\r
+            {\r
+                digitArray[i] = digitArray[i - digits];\r
+            }\r
+\r
+            if (digits > 0)\r
+            {\r
+                for (int i = digits - 1; i >= 0; i--)\r
+                {\r
+                    digitArray[i] = 0;\r
+                }\r
+            }\r
+\r
+            UInt64 lastShift = 0;\r
+\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                UInt64 temp = (((UInt64)digitArray[i]) << rem) | lastShift;\r
+                digitArray[i] = (UInt32)(temp & 0xffffffff);\r
+                lastShift = temp >> 32;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Logical right-shift\r
+        /// </summary>\r
+        /// <param name="shift"></param>\r
+        public void RSH(int shift)\r
+        {\r
+            if (shift < 0) return;\r
+            int length = digitArray.Length;\r
+            int digits = shift >> 5;\r
+            int rem = shift & 31;\r
+\r
+            for (int i = 0; i < length - digits; i++)\r
+            {\r
+                digitArray[i] = digitArray[i + digits];\r
+            }\r
+\r
+            int start = (length - digits);\r
+            if (start < 0) start = 0;\r
+\r
+            for (int i = start; i < length; i++)\r
+            {\r
+                digitArray[i] = 0;\r
+            }\r
+\r
+            UInt64 lastShift = 0;\r
+\r
+            for (int i = length - 1; i >= 0; i--)\r
+            {\r
+                UInt64 temp = ((((UInt64)digitArray[i]) << 32) >> rem) | lastShift;\r
+                digitArray[i] = (UInt32)(temp >> 32);\r
+                lastShift = (temp & 0xffffffff) << 32;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Changes the sign of the number\r
+        /// </summary>\r
+        public void Negate()\r
+        {\r
+            sign = !sign;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Increments the number.\r
+        /// </summary>\r
+        public void Increment()\r
+        {\r
+            if (sign)\r
+            {\r
+                DecrementInt();\r
+            }\r
+            else\r
+            {\r
+                IncrementInt();\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Decrements the number.\r
+        /// </summary>\r
+        public void Decrement()\r
+        {\r
+            if (sign)\r
+            {\r
+                IncrementInt();\r
+            }\r
+            else\r
+            {\r
+                DecrementInt();\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Calculates the factorial 'this'!\r
+        /// </summary>\r
+        public void Factorial()\r
+        {\r
+            if (sign) return;\r
+\r
+            //Clamp to a reasonable range.\r
+            int factToUse = (int)(digitArray[0]);\r
+            if (factToUse > 65536) factToUse = 65536;\r
+\r
+            Zero();\r
+            digitArray[0] = 1;\r
+\r
+            for (uint i = 1; i <= factToUse; i++)\r
+            {\r
+                MulInternal(i);\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Calculates 'this'^power\r
+        /// </summary>\r
+        /// <param name="power"></param>\r
+        public void Power(BigInt power)\r
+        {\r
+            if (power.IsZero() || power.sign)\r
+            {\r
+                Zero();\r
+                digitArray[0] = 1;\r
+                return;\r
+            }\r
+\r
+            BigInt pow = new BigInt(power);\r
+            BigInt temp = new BigInt(this);\r
+            BigInt powTerm = new BigInt(this);\r
+\r
+            pow.Decrement();\r
+            for (; !pow.IsZero(); pow.RSH(1))\r
+            {\r
+                if ((pow.digitArray[0] & 1) == 1)\r
+                {\r
+                    temp.Mul(powTerm);\r
+                }\r
+\r
+                powTerm.Square();\r
+            }\r
+\r
+            Assign(temp);\r
+        }\r
+\r
+        //***************** Comparison member functions *****************\r
+\r
+        /// <summary>\r
+        /// returns true if this bigint == 0\r
+        /// </summary>\r
+        /// <returns></returns>\r
+        public bool IsZero()\r
+        {\r
+            for (int i = 0; i < digitArray.Length; i++)\r
+            {\r
+                if (digitArray[i] != 0) return false;\r
+            }\r
+\r
+            return true;\r
+        }\r
+\r
+        /// <summary>\r
+        /// true iff n2 (precision adjusted to this) is less than 'this'\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public bool LessThan(BigInt n2)\r
+        {\r
+            if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);\r
+\r
+            if (sign)\r
+            {\r
+                if (!n2.sign) return true;\r
+                return GtInt(this, n2);\r
+            }\r
+            else\r
+            {\r
+                if (n2.sign) return false;\r
+                return LtInt(this, n2);\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// true iff n2 (precision adjusted to this) is greater than 'this'\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public bool GreaterThan(BigInt n2)\r
+        {\r
+            if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);\r
+\r
+            if (sign)\r
+            {\r
+                if (!n2.sign) return false;\r
+                return LtInt(this, n2);\r
+            }\r
+            else\r
+            {\r
+                if (n2.sign) return true;\r
+                return GtInt(this, n2);\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Override of base-class equals\r
+        /// </summary>\r
+        /// <param name="obj"></param>\r
+        /// <returns></returns>\r
+        public override bool Equals(object obj)\r
+        {\r
+            BigInt n2 = ((BigInt)obj);\r
+            return Equals(n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Get hash code\r
+        /// </summary>\r
+        /// <returns></returns>\r
+        public override int GetHashCode()\r
+        {\r
+            return (Int32)digitArray[0];\r
+        }\r
+\r
+        /// <summary>\r
+        /// True iff n2 (precision-adjusted to this) == n1\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public bool Equals(BigInt n2)\r
+        {\r
+            if (IsZero() && n2.IsZero()) return true;\r
+\r
+            if (sign != n2.sign) return false;\r
+\r
+            int Length = digitArray.Length;\r
+            if (n2.digitArray.Length != Length) MakeSafe(ref n2);\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                if (digitArray[i] != n2.digitArray[i]) return false;\r
+            }\r
+\r
+            return true;\r
+        }\r
+\r
+        //******************* Bitwise member functions ********************\r
+\r
+        /// <summary>\r
+        /// Takes the bitwise complement of the number\r
+        /// </summary>\r
+        public void Complement()\r
+        {\r
+            int Length = digitArray.Length;\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                digitArray[i] = ~digitArray[i];\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Bitwise And\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public void And(BigInt n2)\r
+        {\r
+            int Length = digitArray.Length;\r
+            if (n2.digitArray.Length != Length) MakeSafe(ref n2);\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                digitArray[i] &= n2.digitArray[i];\r
+            }\r
+\r
+            sign &= n2.sign;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Bitwise Or\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public void Or(BigInt n2)\r
+        {\r
+            int Length = digitArray.Length;\r
+            if (n2.digitArray.Length != Length) MakeSafe(ref n2);\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                digitArray[i] |= n2.digitArray[i];\r
+            }\r
+\r
+            sign |= n2.sign;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Bitwise Xor\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public void Xor(BigInt n2)\r
+        {\r
+            int Length = digitArray.Length;\r
+            if (n2.digitArray.Length != Length) MakeSafe(ref n2);\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                digitArray[i] ^= n2.digitArray[i];\r
+            }\r
+\r
+            sign ^= n2.sign;\r
+        }\r
+\r
+        //*************** Fast Static Arithmetic Functions *****************\r
+\r
+        /// <summary>\r
+        /// Adds n1 and n2 and puts result in dest, without intermediate memory allocation\r
+        /// (unsafe if n1 and n2 disagree in precision, safe even if dest is n1 or n2)\r
+        /// </summary>\r
+        /// <param name="dest"></param>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        public static void AddFast(BigInt dest, BigInt n1, BigInt n2)\r
+        {\r
+            //We cast to the highest input precision...\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+\r
+            //Then we up the output precision if less than the input precision.\r
+            if (dest.digitArray.Length < n1.digitArray.Length) n1.MakeSafe(ref dest);\r
+\r
+            int Length = n1.digitArray.Length;\r
+\r
+            if (n1.sign == n2.sign)\r
+            {\r
+                //Copies sources into digit array and working set for all cases, to avoid\r
+                //problems when dest is n1 or n2\r
+                for (int i = 0; i < Length; i++)\r
+                {\r
+                    dest.workingSet[i] = n2.digitArray[i];\r
+                    dest.digitArray[i] = n1.digitArray[i];\r
+                }\r
+                dest.AddInternalBits(dest.workingSet);\r
+                dest.sign = n1.sign;\r
+            }\r
+            else\r
+            {\r
+                bool lessThan = LtInt(n1, n2);\r
+\r
+                if (lessThan)\r
+                {\r
+                    for (int i = 0; i < Length; i++)\r
+                    {\r
+                        dest.workingSet[i] = n1.digitArray[i];\r
+                        dest.digitArray[i] = n2.digitArray[i];\r
+                    }\r
+                    dest.SubInternalBits(dest.workingSet);\r
+                    dest.sign = !n1.sign;\r
+                }\r
+                else\r
+                {\r
+                    for (int i = 0; i < Length; i++)\r
+                    {\r
+                        dest.workingSet[i] = n2.digitArray[i];\r
+                        dest.digitArray[i] = n1.digitArray[i];\r
+                    }\r
+                    dest.SubInternalBits(dest.workingSet);\r
+                    dest.sign = n1.sign;\r
+                }\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Adds n1 and n2 and puts result in dest, without intermediate memory allocation\r
+        /// (unsafe if n1 and n2 disagree in precision, safe even if dest is n1 or n2)\r
+        /// </summary>\r
+        /// <param name="dest"></param>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        public static void SubFast(BigInt dest, BigInt n1, BigInt n2)\r
+        {\r
+            //We cast to the highest input precision...\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+\r
+            //Then we up the output precision if less than the input precision.\r
+            if (dest.digitArray.Length < n1.digitArray.Length) n1.MakeSafe(ref dest);\r
+\r
+            int Length = n1.digitArray.Length;\r
+\r
+            if (n1.sign != n2.sign)\r
+            {\r
+                //Copies sources into digit array and working set for all cases, to avoid\r
+                //problems when dest is n1 or n2\r
+                for (int i = 0; i < Length; i++)\r
+                {\r
+                    dest.workingSet[i] = n2.digitArray[i];\r
+                    dest.digitArray[i] = n1.digitArray[i];\r
+                }\r
+                dest.AddInternalBits(dest.workingSet);\r
+                dest.sign = n1.sign;\r
+            }\r
+            else\r
+            {\r
+                bool lessThan = LtInt(n1, n2);\r
+\r
+                if (lessThan)\r
+                {\r
+                    for (int i = 0; i < Length; i++)\r
+                    {\r
+                        dest.workingSet[i] = n1.digitArray[i];\r
+                        dest.digitArray[i] = n2.digitArray[i];\r
+                    }\r
+                    dest.SubInternalBits(dest.workingSet);\r
+                    dest.sign = !n1.sign;\r
+                }\r
+                else\r
+                {\r
+                    for (int i = 0; i < Length; i++)\r
+                    {\r
+                        dest.workingSet[i] = n2.digitArray[i];\r
+                        dest.digitArray[i] = n1.digitArray[i];\r
+                    }\r
+                    dest.SubInternalBits(dest.workingSet);\r
+                    dest.sign = n1.sign;\r
+                }\r
+            }\r
+        }\r
+\r
+        //*************** Static Arithmetic Functions ***************\r
+\r
+        /// <summary>\r
+        /// signed addition of 2 numbers.\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Add(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+            BigInt result; \r
+\r
+            if (n1.sign == n2.sign)\r
+            {\r
+                result = new BigInt(n1);\r
+                result.AddInternal(n2);\r
+                result.sign = n1.sign;\r
+            }\r
+            else\r
+            {\r
+                bool lessThan = LtInt(n1, n2);\r
+\r
+                if (lessThan)\r
+                {\r
+                    result = new BigInt(n2);\r
+                    result.SubInternal(n1);\r
+                    result.sign = !n1.sign;\r
+                }\r
+                else\r
+                {\r
+                    result = new BigInt(n1);\r
+                    result.SubInternal(n2);\r
+                    result.sign = n1.sign;\r
+                }\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        /// <summary>\r
+        /// signed subtraction of 2 numbers.\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Sub(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+            BigInt result;\r
+\r
+            if ((n1.sign && !n2.sign) || (!n1.sign && n2.sign))\r
+            {\r
+                result = new BigInt(n1);\r
+                result.AddInternal(n2);\r
+                result.sign = n1.sign;\r
+            }\r
+            else\r
+            {\r
+                bool lessThan = LtInt(n1, n2);\r
+\r
+                if (lessThan)\r
+                {\r
+                    result = new BigInt(n2);\r
+                    result.SubInternal(n1);\r
+                    result.sign = !n1.sign;\r
+                }\r
+                else\r
+                {\r
+                    result = new BigInt(n1);\r
+                    result.SubInternal(n2);\r
+                    result.sign = n1.sign;\r
+                }\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Multiplication of two BigInts\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Mul(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+            \r
+            BigInt result = new BigInt(n1);\r
+            result.Mul(n2);\r
+            return result;\r
+        }\r
+\r
+        /// <summary>\r
+        /// True arbitrary precision divide.\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Div(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+            BigInt res = new BigInt(n1);\r
+            res.Div(n2);\r
+            return res;\r
+        }\r
+\r
+        /// <summary>\r
+        /// True arbitrary-precision mod operation\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Mod(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+            BigInt res = new BigInt(n1);\r
+            res.Mod(n2);\r
+            return res;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Unsigned multiplication of a BigInt by a small number\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Mul(BigInt n1, uint n2)\r
+        {\r
+            BigInt result = new BigInt(n1);\r
+            result.MulInternal(n2);\r
+            return result;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Division of a BigInt by a small (unsigned) number\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Div(BigInt n1, uint n2)\r
+        {\r
+            BigInt result = new BigInt(n1);\r
+            result.DivInternal(n2);\r
+            return result;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Division and remainder of a BigInt by a small (unsigned) number\r
+        /// n1 / n2 = div remainder mod\r
+        /// </summary>\r
+        /// <param name="n1">The number to divide (dividend)</param>\r
+        /// <param name="n2">The number to divide by (divisor)</param>\r
+        /// <param name="div">The quotient (output parameter)</param>\r
+        /// <param name="mod">The remainder (output parameter)</param>\r
+        public static void DivMod(BigInt n1, uint n2, out BigInt div, out BigInt mod)\r
+        {\r
+            div = Div(n1, n2);\r
+            mod = Mul(div, n2);\r
+            mod = Sub(n1, mod);\r
+        }\r
+\r
+        //**************** Static Comparison Functions ***************\r
+\r
+        /// <summary>\r
+        /// true iff n1 is less than n2\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static bool LessThan(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+\r
+            if (n1.sign)\r
+            {\r
+                if (!n2.sign) return true;\r
+                return GtInt(n1, n2);\r
+            }\r
+            else\r
+            {\r
+                if (n2.sign) return false;\r
+                return LtInt(n1, n2);\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// true iff n1 is greater than n2\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static bool GreaterThan(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+\r
+            if (n1.sign)\r
+            {\r
+                if (!n2.sign) return false;\r
+                return LtInt(n1, n2);\r
+            }\r
+            else\r
+            {\r
+                if (n2.sign) return true;\r
+                return GtInt(n1, n2);\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// true iff n1 == n2\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static bool Equals(BigInt n1, BigInt n2)\r
+        {\r
+            return n1.Equals(n2);\r
+        }\r
+\r
+        //***************** Static Bitwise Functions *****************\r
+\r
+        /// <summary>\r
+        /// Bitwise And\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt And(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+            BigInt res = new BigInt(n1);\r
+            res.And(n2);\r
+            return res;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Bitwise Or\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Or(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+            BigInt res = new BigInt(n1);\r
+            res.Or(n2);\r
+            return res;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Bitwise Xor\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        public static BigInt Xor(BigInt n1, BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length != n2.digitArray.Length) MakeSafe(ref n1, ref n2);\r
+            BigInt res = new BigInt(n1);\r
+            res.And(n2);\r
+            return res;\r
+        }\r
+\r
+        //**************** Static Operator Overloads *****************\r
+\r
+        /// <summary>\r
+        /// Addition operator\r
+        /// </summary>\r
+        public static BigInt operator +(BigInt n1, BigInt n2)\r
+        {\r
+            return Add(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The subtraction operator\r
+        /// </summary>\r
+        public static BigInt operator -(BigInt n1, BigInt n2)\r
+        {\r
+            return Sub(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The multiplication operator\r
+        /// </summary>\r
+        public static BigInt operator *(BigInt n1, BigInt n2)\r
+        {\r
+            return Mul(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The division operator\r
+        /// </summary>\r
+        public static BigInt operator /(BigInt n1, BigInt n2)\r
+        {\r
+            return Div(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The remainder (mod) operator\r
+        /// </summary>\r
+        public static BigInt operator %(BigInt n1, BigInt n2)\r
+        {\r
+            return Mod(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The left-shift operator\r
+        /// </summary>\r
+        public static BigInt operator <<(BigInt n1, int n2)\r
+        {\r
+            BigInt res = new BigInt(n1);\r
+            res.LSH(n2);\r
+            return res;\r
+        }\r
+\r
+        /// <summary>\r
+        /// The right-shift operator\r
+        /// </summary>\r
+        public static BigInt operator >>(BigInt n1, int n2)\r
+        {\r
+            BigInt res = new BigInt(n1);\r
+            res.RSH(n2);\r
+            return res;\r
+        }\r
+\r
+        /// <summary>\r
+        /// The less than operator\r
+        /// </summary>\r
+        public static bool operator <(BigInt n1, BigInt n2)\r
+        {\r
+            return LessThan(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The greater than operator\r
+        /// </summary>\r
+        public static bool operator >(BigInt n1, BigInt n2)\r
+        {\r
+            return GreaterThan(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The less than or equal to operator\r
+        /// </summary>\r
+        public static bool operator <=(BigInt n1, BigInt n2)\r
+        {\r
+            return !GreaterThan(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The greater than or equal to operator\r
+        /// </summary>\r
+        public static bool operator >=(BigInt n1, BigInt n2)\r
+        {\r
+            return !LessThan(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The equality operator\r
+        /// </summary>\r
+        public static bool operator ==(BigInt n1, BigInt n2)\r
+        {\r
+            return Equals(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The inequality operator\r
+        /// </summary>\r
+        public static bool operator !=(BigInt n1, BigInt n2)\r
+        {\r
+            return !Equals(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The bitwise AND operator\r
+        /// </summary>\r
+        public static BigInt operator &(BigInt n1, BigInt n2)\r
+        {\r
+            return And(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The bitwise OR operator\r
+        /// </summary>\r
+        public static BigInt operator |(BigInt n1, BigInt n2)\r
+        {\r
+            return Or(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The bitwise eXclusive OR operator\r
+        /// </summary>\r
+        public static BigInt operator ^(BigInt n1, BigInt n2)\r
+        {\r
+            return Xor(n1, n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// The increment operator\r
+        /// </summary>\r
+        public static BigInt operator ++(BigInt n1)\r
+        {\r
+            n1.Increment();\r
+            return n1;\r
+        }\r
+\r
+        /// <summary>\r
+        /// The decrement operator\r
+        /// </summary>\r
+        public static BigInt operator --(BigInt n1)\r
+        {\r
+            n1.Decrement();\r
+            return n1;\r
+        }\r
+\r
+        //**************** Private Member Functions *****************\r
+\r
+        /// <summary>\r
+        /// Unsigned multiplication and assignment by a small number\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        private void MulInternal(uint n2)\r
+        {\r
+            int Length = digitArray.Length;\r
+            ulong n2long = (ulong)n2;\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                workingSet[i] = 0;\r
+            }\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                if (digitArray[i] == 0) continue;\r
+                ulong temp = (ulong)digitArray[i] * n2long;\r
+                digitArray[i] = (uint)(temp & 0xffffffff);\r
+                if (i + 1 < Length) workingSet[i + 1] = (uint)(temp >> 32);\r
+            }\r
+\r
+            AddInternalBits(workingSet);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Unsigned division and assignment by a small number\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        private void DivInternal(uint n2)\r
+        {\r
+            int Length = digitArray.Length;\r
+            ulong carry = 0;\r
+\r
+            //Divide each digit by the small number.\r
+            for (int i = Length - 1; i >= 0; i--)\r
+            {\r
+                ulong temp = (ulong)digitArray[i] + (carry << 32);\r
+                digitArray[i] = (uint)(temp / (ulong)n2);\r
+                carry = temp % (ulong)n2;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Adds a signed integer to the number.\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        private void AddInternal(int n1)\r
+        {\r
+            if (n1 < 0)\r
+            {\r
+                SubInternal(-n1);\r
+                return;\r
+            }\r
+\r
+            uint carry = 0;\r
+            int length = digitArray.Length;\r
+\r
+            for (int i = 0; i < length && !(n1 == 0 && carry == 0); i++)\r
+            {\r
+                uint temp = digitArray[i];\r
+                digitArray[i] += (uint)n1 + carry;\r
+\r
+                carry = (digitArray[i] <= temp) ? 1u: 0u;\r
+                \r
+                n1 = 0;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Subtract a signed integer from the number.\r
+        /// This is internal because it will fail spectacularly if this number is negative or if n1 is bigger than this number.\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        private void SubInternal(int n1)\r
+        {\r
+            if (n1 < 0)\r
+            {\r
+                AddInternal(-n1);\r
+                return;\r
+            }\r
+\r
+            uint carry = 0;\r
+            int length = digitArray.Length;\r
+\r
+            for (int i = 0; i < length && !(n1 == 0 && carry == 0); i++)\r
+            {\r
+                uint temp = digitArray[i];\r
+                digitArray[i] -= ((uint)n1 + carry);\r
+\r
+                carry = (digitArray[i] >= temp) ? 1u: 0u;\r
+\r
+                n1 = 0;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Adds a signed integer to the number.\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        private bool AddInternal(uint n1)\r
+        {\r
+            uint carry = 0;\r
+            int length = digitArray.Length;\r
+\r
+            for (int i = 0; i < length && !(n1 == 0 && carry == 0); i++)\r
+            {\r
+                uint temp = digitArray[i];\r
+                digitArray[i] += n1 + carry;\r
+\r
+                carry = (digitArray[i] <= temp) ? 1u: 0u;\r
+\r
+                n1 = 0;\r
+            }\r
+\r
+            return (carry != 0);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Internally subtracts a uint from the number (sign insensitive)\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <returns></returns>\r
+        private bool SubInternal(uint n1)\r
+        {\r
+            uint carry = 0;\r
+            int length = digitArray.Length;\r
+\r
+            for (int i = 0; i < length && !(n1 == 0 && carry == 0); i++)\r
+            {\r
+                uint temp = digitArray[i];\r
+                digitArray[i] -= (n1 + carry);\r
+\r
+                carry = (digitArray[i] >= temp) ? 1u: 0u;\r
+\r
+                n1 = 0;\r
+            }\r
+\r
+            return (carry != 0);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Internal increment function (sign insensitive)\r
+        /// </summary>\r
+        private bool IncrementInt()\r
+        {\r
+            uint carry = 1;\r
+\r
+            int length = digitArray.Length;\r
+\r
+            for (int i = 0; i < length && carry != 0; i++)\r
+            {\r
+                uint temp = digitArray[i];\r
+                digitArray[i]++;\r
+\r
+                if (digitArray[i] > temp) carry = 0;\r
+            }\r
+\r
+            return (carry != 0);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Internal increment function (sign insensitive)\r
+        /// </summary>\r
+        private bool DecrementInt()\r
+        {\r
+            uint carry = 1;\r
+\r
+            int length = digitArray.Length;\r
+\r
+            for (int i = 0; i < length && carry != 0; i++)\r
+            {\r
+                uint temp = digitArray[i];\r
+                digitArray[i]--;\r
+\r
+                if (digitArray[i] < temp) carry = 0;\r
+            }\r
+\r
+            return (carry != 0);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Used to add a digit array to a big int.\r
+        /// </summary>\r
+        /// <param name="digitsToAdd"></param>\r
+        private uint AddInternalBits(uint[] digitsToAdd)\r
+        {\r
+            uint carry = 0;\r
+\r
+            int Length = digitArray.Length;\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                //Necessary because otherwise the carry calculation could go bad.\r
+                if (digitsToAdd[i] == 0 && carry == 0) continue;\r
+\r
+                uint temp = digitArray[i];\r
+                digitArray[i] += (digitsToAdd[i] + carry);\r
+\r
+                carry = 0;\r
+                if (digitArray[i] <= temp) carry = 1;\r
+            }\r
+\r
+            return carry;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Used to add with matching signs (true addition of the digit arrays)\r
+        /// This is internal because it will fail spectacularly if n1 is negative.\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        private uint AddInternal(BigInt n1)\r
+        {\r
+            return AddInternalBits(n1.digitArray);\r
+        }\r
+\r
+        private uint SubInternalBits(uint[] digitsToAdd)\r
+        {\r
+            uint carry = 0;\r
+\r
+            int Length = digitArray.Length;\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                //Necessary because otherwise the carry calculation could go bad.\r
+                if (digitsToAdd[i] == 0 && carry == 0) continue;\r
+\r
+                uint temp = digitArray[i];\r
+                digitArray[i] -= (digitsToAdd[i] + carry);\r
+\r
+                carry = 0;\r
+                if (digitArray[i] >= temp) carry = 1;\r
+            }\r
+\r
+            return carry;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Used to subtract n1 (true subtraction of digit arrays) - n1 must be less than or equal to this number\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        private uint SubInternal(BigInt n1)\r
+        {\r
+            return SubInternalBits(n1.digitArray);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Returns the length of the BigInt in 32-bit words for a given decimal precision\r
+        /// </summary>\r
+        /// <param name="precision"></param>\r
+        /// <returns></returns>\r
+        private static int GetRequiredDigitsForPrecision(PrecisionSpec precision)\r
+        {\r
+            int bits = precision.NumBits;\r
+            return ((bits - 1) >> 5) + 1;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Initialises the BigInt to a desired decimal precision\r
+        /// </summary>\r
+        /// <param name="precision"></param>\r
+        private void Init(PrecisionSpec precision)\r
+        {\r
+            int numDigits = GetRequiredDigitsForPrecision(precision);\r
+            digitArray = new uint[numDigits];\r
+            workingSet = new uint[numDigits];\r
+            pres = precision;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Initialises the BigInt from a string, given a base and precision\r
+        /// </summary>\r
+        /// <param name="init"></param>\r
+        /// <param name="precision"></param>\r
+        /// <param name="numberBase"></param>\r
+        private void InitFromString(string init, PrecisionSpec precision, int numberBase)\r
+        {\r
+            PrecisionSpec test;\r
+            if (numberBase == 2)\r
+            {\r
+                test = new PrecisionSpec(init.Length, PrecisionSpec.BaseType.BIN);\r
+            }\r
+            else if (numberBase == 8)\r
+            {\r
+                test = new PrecisionSpec(init.Length, PrecisionSpec.BaseType.OCT);\r
+            }\r
+            else if (numberBase == 10)\r
+            {\r
+                test = new PrecisionSpec(init.Length, PrecisionSpec.BaseType.DEC);\r
+            }\r
+            else if (numberBase == 16)\r
+            {\r
+                test = new PrecisionSpec(init.Length, PrecisionSpec.BaseType.HEX);\r
+            }\r
+            else\r
+            {\r
+                throw new ArgumentOutOfRangeException();\r
+            }\r
+\r
+            //if (test.NumBits > precision.NumBits) precision = test;\r
+            Init(precision);\r
+            FromStringInt(init, numberBase);\r
+        }\r
+\r
+        //************ Helper Functions for floating point *************\r
+\r
+        /// <summary>\r
+        /// Returns true if only the top bit is set: i.e. if the floating-point number is a power of 2\r
+        /// </summary>\r
+        /// <returns></returns>\r
+        public bool IsTopBitOnlyBit()\r
+        {\r
+            int length = digitArray.Length;\r
+\r
+            if (digitArray[length - 1] != 0x80000000u) return false;\r
+            length--;\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                if (digitArray[i] != 0) return false;\r
+            }\r
+\r
+            return true;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Zeroes the n most significant bits of the number\r
+        /// </summary>\r
+        /// <param name="bits"></param>\r
+        public void ZeroBitsHigh(int bits)\r
+        {\r
+            //Already done.\r
+            if (bits <= 0) return;\r
+\r
+            int length = digitArray.Length;\r
+\r
+            //The entire digit array.\r
+            if ((bits >> 5) > length)\r
+            {\r
+                bits = length << 5;\r
+            }\r
+\r
+            int remBits = (bits & 31);\r
+            int startDigit = length - ((bits >> 5) + 1);\r
+\r
+            if (remBits != 0)\r
+            {\r
+                digitArray[startDigit] = digitArray[startDigit] & (0xffffffffu >> remBits);\r
+            }\r
+\r
+            for (int i = startDigit + 1; i < length; i++)\r
+            {\r
+                digitArray[i] = 0;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Zeroes the least-significant n bits.\r
+        /// </summary>\r
+        /// <param name="bits"></param>\r
+        public void ZeroBits(int bits)\r
+        {\r
+            //Already done.\r
+            if (bits <= 0) return;\r
+\r
+            //The entire digit array.\r
+            if ((bits >> 5) > digitArray.Length)\r
+            {\r
+                bits = digitArray.Length << 5;\r
+            }\r
+\r
+            int remBits = (bits & 31);\r
+            int startDigit = bits >> 5;\r
+            \r
+            if (remBits != 0)\r
+            {\r
+                UInt32 startMask = 0xffffffffu & ~(UInt32)(((1 << remBits) - 1));\r
+                digitArray[startDigit] = digitArray[startDigit] & startMask;\r
+            }\r
+\r
+            for (int i = startDigit - 1; i >= 0; i--)\r
+            {\r
+                digitArray[i] = 0;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Sets the number to 0\r
+        /// </summary>\r
+        public void Zero()\r
+        {\r
+            int length = digitArray.Length;\r
+\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                digitArray[i] = 0;\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Rounds off the least significant bits of the number.\r
+        /// Can only round off up to 31 bits.\r
+        /// </summary>\r
+        /// <param name="bits">number of bits to round</param>\r
+        /// <returns></returns>\r
+        public bool Round(int bits)\r
+        {\r
+            //Always less than 32 bits, please!\r
+            if (bits < 32)\r
+            {\r
+                uint pow2 = 1u << bits;\r
+                uint test = digitArray[0] & (pow2 >> 1);\r
+\r
+                //Zero the lower bits\r
+                digitArray[0] = digitArray[0] & ~(pow2 - 1);\r
+\r
+                if (test != 0)\r
+                {\r
+                    bool bRet = AddInternal(pow2);\r
+                    digitArray[digitArray.Length - 1] = digitArray[digitArray.Length - 1] | 0x80000000;\r
+                    return bRet;\r
+                }\r
+            }\r
+\r
+            return false;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Used for casting between BigFloats of different precisions - this assumes\r
+        /// that the number is a normalised mantissa.\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        /// <returns>true if a round-up caused the high bits to become zero</returns>\r
+        public bool AssignHigh(BigInt n2)\r
+        {\r
+            int length = digitArray.Length;\r
+            int length2 = n2.digitArray.Length;\r
+            int minWords = (length < length2) ? length: length2;\r
+            bool bRet = false;\r
+\r
+            for (int i = 1; i <= minWords; i++)\r
+            {\r
+                digitArray[length - i] = n2.digitArray[length2 - i];\r
+            }\r
+\r
+            if (length2 > length && n2.digitArray[length2 - (length + 1)] >= 0x80000000)\r
+            {\r
+                bRet = IncrementInt();\r
+\r
+                //Because we are assuming normalisation, we set the top bit (it will already be set if\r
+                //bRet is false.\r
+                digitArray[length - 1] = digitArray[length - 1] | 0x80000000;\r
+            }\r
+\r
+            sign = n2.sign;\r
+\r
+            return bRet;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Used for casting between long ints or doubles and floating-point numbers\r
+        /// </summary>\r
+        /// <param name="digits"></param>\r
+        public void SetHighDigits(Int64 digits)\r
+        {\r
+            digitArray[digitArray.Length - 1] = (uint)(digits >> 32);\r
+            if (digitArray.Length > 1) digitArray[digitArray.Length - 2] = (uint)(digits & 0xffffffff);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Used for casting between ints and doubles or floats.\r
+        /// </summary>\r
+        /// <param name="digit"></param>\r
+        public void SetHighDigit(UInt32 digit)\r
+        {\r
+            digitArray[digitArray.Length - 1] = digit;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Helper function for floating-point - extends the number to twice the precision\r
+        /// and shifts the digits into the upper bits.\r
+        /// </summary>\r
+        public void Pad()\r
+        {\r
+            int length = digitArray.Length;\r
+            int digits = length << 1;\r
+\r
+            UInt32[] newDigitArray = new UInt32[digits];\r
+            workingSet = new UInt32[digits];\r
+\r
+            for (int i = 0; i < length; i++)\r
+            {\r
+                newDigitArray[i + length] = digitArray[i];\r
+            }\r
+\r
+            digitArray = newDigitArray;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Helper function for floating-point - extends the number to twice the precision...\r
+        /// This is a necessary step in floating-point division.\r
+        /// </summary>\r
+        public void Extend()\r
+        {\r
+            SetNumDigits(digitArray.Length * 2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Gets the highest big of the integer (used for floating point stuff)\r
+        /// </summary>\r
+        /// <returns></returns>\r
+        public uint GetTopBit()\r
+        {\r
+            return (digitArray[digitArray.Length - 1] >> 31);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Used for floating point multiplication, this shifts the number so that\r
+        /// the highest bit is set, and returns the number of places shifted.\r
+        /// </summary>\r
+        /// <returns></returns>\r
+        public int Normalise()\r
+        {\r
+            if (IsZero()) return 0;\r
+\r
+            int MSD = GetMSD();\r
+            int digitShift = (digitArray.Length - (MSD + 1));\r
+            int bitShift = (31 - GetMSB(digitArray[MSD])) + (digitShift << 5);\r
+            LSH(bitShift);\r
+            return bitShift;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Gets the most significant bit\r
+        /// </summary>\r
+        /// <param name="value">the input to search for the MSB in</param>\r
+        /// <returns>-1 if the input was zero, the position of the MSB otherwise</returns>\r
+        public static int GetMSB(UInt32 value)\r
+        {\r
+            if (value == 0) return -1;\r
+\r
+            uint mask1 = 0xffff0000;\r
+            uint mask2 = 0xff00;\r
+            uint mask3 = 0xf0;\r
+            uint mask4 = 0xc;   //1100 in binary\r
+            uint mask5 = 0x2;   //10 in binary\r
+\r
+            int iPos = 0;\r
+\r
+            //Unrolled binary search for the most significant bit.\r
+            if ((value & mask1) != 0) iPos += 16;\r
+            mask2 <<= iPos;\r
+\r
+            if ((value & mask2) != 0) iPos += 8;\r
+            mask3 <<= iPos;\r
+\r
+            if ((value & mask3) != 0) iPos += 4;\r
+            mask4 <<= iPos;\r
+\r
+            if ((value & mask4) != 0) iPos += 2;\r
+            mask5 <<= iPos;\r
+\r
+            if ((value & mask5) != 0) iPos++;\r
+\r
+            return iPos;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Gets the most significant bit\r
+        /// </summary>\r
+        /// <param name="value">the input to search for the MSB in</param>\r
+        /// <returns>-1 if the input was zero, the position of the MSB otherwise</returns>\r
+        public static int GetMSB(UInt64 value)\r
+        {\r
+            if (value == 0) return -1;\r
+\r
+            UInt64 mask0 = 0xffffffff00000000ul;\r
+            UInt64 mask1 = 0xffff0000;\r
+            UInt64 mask2 = 0xff00;\r
+            UInt64 mask3 = 0xf0;\r
+            UInt64 mask4 = 0xc;   //1100 in binary\r
+            UInt64 mask5 = 0x2;   //10 in binary\r
+\r
+            int iPos = 0;\r
+\r
+            //Unrolled binary search for the most significant bit.\r
+            if ((value & mask0) != 0) iPos += 32;\r
+            mask1 <<= iPos;\r
+\r
+            if ((value & mask1) != 0) iPos += 16;\r
+            mask2 <<= iPos;\r
+\r
+            if ((value & mask2) != 0) iPos += 8;\r
+            mask3 <<= iPos;\r
+\r
+            if ((value & mask3) != 0) iPos += 4;\r
+            mask4 <<= iPos;\r
+\r
+            if ((value & mask4) != 0) iPos += 2;\r
+            mask5 <<= iPos;\r
+\r
+            if ((value & mask5) != 0) iPos++;\r
+\r
+            return iPos;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Gets the most significant bit\r
+        /// </summary>\r
+        /// <param name="value">the input to search for the MSB in</param>\r
+        /// <returns>-1 if the input was zero, the position of the MSB otherwise</returns>\r
+        public static int GetMSB(BigInt value)\r
+        {\r
+            int digit = value.GetMSD();\r
+            int bit = GetMSB(value.digitArray[digit]);\r
+            return (digit << 5) + bit;\r
+        }\r
+\r
+        //**************** Helper Functions for Div ********************\r
+\r
+        /// <summary>\r
+        /// Gets the index of the most significant digit\r
+        /// </summary>\r
+        /// <returns></returns>\r
+        private int GetMSD()\r
+        {\r
+            for (int i = digitArray.Length - 1; i >= 0; i--)\r
+            {\r
+                if (digitArray[i] != 0) return i;\r
+            }\r
+\r
+            return 0;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Gets the required bitshift for the Div_32 algorithm\r
+        /// </summary>\r
+        /// <returns></returns>\r
+        private int GetDivBitshift()\r
+        {\r
+            uint digit = digitArray[GetMSD()];\r
+            uint mask1 = 0xffff0000;\r
+            uint mask2 = 0xff00;\r
+            uint mask3 = 0xf0;  \r
+            uint mask4 = 0xc;   //1100 in binary\r
+            uint mask5 = 0x2;   //10 in binary\r
+\r
+            int iPos = 0;\r
+\r
+            //Unrolled binary search for the most significant bit.\r
+            if ((digit & mask1) != 0) iPos += 16;\r
+            mask2 <<= iPos;\r
+\r
+            if ((digit & mask2) != 0) iPos += 8;\r
+            mask3 <<= iPos;\r
+            \r
+            if ((digit & mask3) != 0) iPos += 4;\r
+            mask4 <<= iPos;\r
+\r
+            if ((digit & mask4) != 0) iPos += 2;\r
+            mask5 <<= iPos;\r
+\r
+            if ((digit & mask5) != 0) return 30 - iPos;\r
+\r
+            return 31 - iPos;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Shifts and optionally precision-extends the arguments to prepare for Div_32\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        private static int MakeSafeDiv(BigInt n1, BigInt n2)\r
+        {\r
+            int shift = n2.GetDivBitshift();\r
+            int n1MSD = n1.GetMSD();\r
+\r
+            uint temp = n1.digitArray[n1MSD];\r
+            if (n1MSD == n1.digitArray.Length - 1 && ((temp << shift) >> shift) != n1.digitArray[n1MSD])\r
+            {\r
+                //Precision-extend n1 and n2 if necessary\r
+                int digits = n1.digitArray.Length;\r
+                n1.SetNumDigits(digits + 1);\r
+                n2.SetNumDigits(digits + 1);\r
+            }\r
+\r
+            //Logical left-shift n1 and n2\r
+            n1.LSH(shift);\r
+            n2.LSH(shift);\r
+\r
+            return shift;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Schoolbook division helper function.\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <param name="Q">Quotient output value</param>\r
+        /// <param name="R">Remainder output value</param>\r
+        private static void Div_31(BigInt n1, BigInt n2, BigInt Q, BigInt R)\r
+        {\r
+            int digitsN1 = n1.GetMSD() + 1;\r
+            int digitsN2 = n2.GetMSD() + 1;            \r
+\r
+            if ((digitsN1 > digitsN2))\r
+            {\r
+                BigInt n1New = new BigInt(n2);\r
+                n1New.DigitShiftSelfLeft(1);\r
+\r
+                //If n1 >= n2 * 2^32\r
+                if (!LtInt(n1, n1New))\r
+                {\r
+                    n1New.sign = n1.sign;\r
+                    SubFast(n1New, n1, n1New);\r
+\r
+                    Div_32(n1New, n2, Q, R);\r
+\r
+                    //Q = (A - B*2^32)/B + 2^32\r
+                    Q.Add2Pow32Self();\r
+                    return;\r
+                }\r
+            }\r
+\r
+            UInt32 q = 0;\r
+\r
+            if (digitsN1 >= 2)\r
+            {\r
+                UInt64 q64 = ((((UInt64)n1.digitArray[digitsN1 - 1]) << 32) + n1.digitArray[digitsN1 - 2]) / (UInt64)n2.digitArray[digitsN2 - 1];\r
+\r
+                if (q64 > 0xfffffffful)\r
+                {\r
+                    q = 0xffffffff;\r
+                }\r
+                else\r
+                {\r
+                    q = (UInt32)q64;\r
+                }\r
+            }\r
+\r
+            BigInt temp = Mul(n2, q);\r
+\r
+            if (GtInt(temp, n1))\r
+            {\r
+                temp.SubInternalBits(n2.digitArray);\r
+                q--;\r
+\r
+                if (GtInt(temp, n1))\r
+                {\r
+                    temp.SubInternalBits(n2.digitArray);\r
+                    q--;\r
+                }\r
+            }\r
+\r
+            Q.Zero();\r
+            Q.digitArray[0] = q;\r
+            R.Assign(n1);\r
+            R.SubInternalBits(temp.digitArray);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Schoolbook division algorithm\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <param name="Q"></param>\r
+        /// <param name="R"></param>\r
+        private static void Div_32(BigInt n1, BigInt n2, BigInt Q, BigInt R)\r
+        {\r
+            int digitsN1 = n1.GetMSD() + 1;\r
+            int digitsN2 = n2.GetMSD() + 1;\r
+\r
+            //n2 is bigger than n1\r
+            if (digitsN1 < digitsN2)\r
+            {\r
+                R.AssignInt(n1);\r
+                Q.Zero();\r
+                return;\r
+            }\r
+\r
+            if (digitsN1 == digitsN2)\r
+            {\r
+                //n2 is bigger than n1\r
+                if (LtInt(n1, n2))\r
+                {\r
+                    R.AssignInt(n1);\r
+                    Q.Zero();\r
+                    return;\r
+                }\r
+\r
+                //n2 >= n1, but less the 2x n1 (initial conditions make this certain)\r
+                Q.Zero();\r
+                Q.digitArray[0] = 1;\r
+                R.Assign(n1);\r
+                R.SubInternalBits(n2.digitArray);\r
+                return;\r
+            }\r
+\r
+            int digits = digitsN1 - (digitsN2 + 1);\r
+\r
+            //Algorithm Div_31 can be used to get the answer in O(n) time.\r
+            if (digits == 0)\r
+            {\r
+                Div_31(n1, n2, Q, R);\r
+                return;\r
+            }\r
+\r
+            BigInt n1New = DigitShiftRight(n1, digits);\r
+            BigInt s = DigitTruncate(n1, digits);\r
+\r
+            BigInt Q2 = new BigInt(n1, n1.pres, true);\r
+            BigInt R2 = new BigInt(n1, n1.pres, true);\r
+\r
+            Div_31(n1New, n2, Q2, R2);\r
+\r
+            R2.DigitShiftSelfLeft(digits);\r
+            R2.Add(s);\r
+\r
+            Div_32(R2, n2, Q, R);\r
+\r
+            Q2.DigitShiftSelfLeft(digits);\r
+            Q.Add(Q2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Sets the n-th bit of the number to 1\r
+        /// </summary>\r
+        /// <param name="bit">the index of the bit to set</param>\r
+        public void SetBit(int bit)\r
+        {\r
+            int digit = (bit >> 5);\r
+            if (digit >= digitArray.Length) return;\r
+            digitArray[digit] = digitArray[digit] | (1u << (bit - (digit << 5)));\r
+        }\r
+\r
+        /// <summary>\r
+        /// Sets the n-th bit of the number to 0\r
+        /// </summary>\r
+        /// <param name="bit">the index of the bit to set</param>\r
+        public void ClearBit(int bit)\r
+        {\r
+            int digit = (bit >> 5);\r
+            if (digit >= digitArray.Length) return;\r
+            digitArray[digit] = digitArray[digit] & (~(1u << (bit - (digit << 5))));\r
+        }\r
+\r
+        /// <summary>\r
+        /// Returns the n-th bit, counting from the MSB to the LSB\r
+        /// </summary>\r
+        /// <param name="bit">the index of the bit to return</param>\r
+        /// <returns>1 if the bit is 1, 0 otherwise</returns>\r
+        public uint GetBitFromTop(int bit)\r
+        {\r
+            if (bit < 0) return 0;\r
+            int wordCount = (bit >> 5);\r
+            int upBit = 31 - (bit & 31);\r
+            if (wordCount >= digitArray.Length) return 0;\r
+\r
+            return ((digitArray[digitArray.Length - (wordCount + 1)] & (1u << upBit)) >> upBit);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Assigns n2 to 'this'\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        public void Assign(BigInt n2)\r
+        {\r
+            if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);\r
+            sign = n2.sign;\r
+            AssignInt(n2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Assign n2 to 'this', safe only if precision-matched\r
+        /// </summary>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        private void AssignInt(BigInt n2)\r
+        {\r
+            int Length = digitArray.Length;\r
+\r
+            for (int i = 0; i < Length; i++)\r
+            {\r
+                digitArray[i] = n2.digitArray[i];\r
+            }\r
+        }\r
+\r
+        private static BigInt DigitShiftRight(BigInt n1, int digits)\r
+        {\r
+            BigInt res = new BigInt(n1);\r
+\r
+            int Length = res.digitArray.Length;\r
+\r
+            for (int i = 0; i < Length - digits; i++)\r
+            {\r
+                res.digitArray[i] = res.digitArray[i + digits];\r
+            }\r
+\r
+            for (int i = Length - digits; i < Length; i++)\r
+            {\r
+                res.digitArray[i] = 0;\r
+            }\r
+\r
+            return res;\r
+        }\r
+\r
+        private void DigitShiftSelfRight(int digits)\r
+        {\r
+            for (int i = digits; i < digitArray.Length; i++)\r
+            {\r
+                digitArray[i - digits] = digitArray[i];\r
+            }\r
+\r
+            for (int i = digitArray.Length - digits; i < digitArray.Length; i++)\r
+            {\r
+                digitArray[i] = 0;\r
+            }\r
+        }\r
+\r
+        private void DigitShiftSelfLeft(int digits)\r
+        {\r
+            for (int i = digitArray.Length - 1; i >= digits; i--)\r
+            {\r
+                digitArray[i] = digitArray[i - digits];\r
+            }\r
+\r
+            for (int i = digits - 1; i >= 0; i--)\r
+            {\r
+                digitArray[i] = 0;\r
+            }\r
+        }\r
+\r
+        private static BigInt DigitTruncate(BigInt n1, int digits)\r
+        {\r
+            BigInt res = new BigInt(n1);\r
+\r
+            for (int i = res.digitArray.Length - 1; i >= digits; i--)\r
+            {\r
+                res.digitArray[i] = 0;\r
+            }\r
+\r
+            return res;\r
+        }\r
+\r
+        private void Add2Pow32Self()\r
+        {\r
+            int Length = digitArray.Length;\r
+\r
+            uint carry = 1;\r
+\r
+            for (int i = 1; i < Length; i++)\r
+            {\r
+                uint temp = digitArray[i];\r
+                digitArray[i] += carry;\r
+                if (digitArray[i] > temp) return;\r
+            }\r
+\r
+            return;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Sets the number of digits without changing the precision\r
+        /// This method is made public only to facilitate fixed-point operations\r
+        /// It should under no circumstances be used for anything else, because\r
+        /// it breaks the BigNum(PrecisionSpec precision) constructor in dangerous\r
+        /// and unpredictable ways.\r
+        /// </summary>\r
+        /// <param name="digits"></param>\r
+        public void SetNumDigits(int digits)\r
+        {\r
+            if (digits == digitArray.Length) return;\r
+\r
+            UInt32[] newDigitArray = new UInt32[digits];\r
+            workingSet = new UInt32[digits];\r
+\r
+            int numCopy = (digits < digitArray.Length) ? digits : digitArray.Length;\r
+\r
+            for (int i = 0; i < numCopy; i++)\r
+            {\r
+                newDigitArray[i] = digitArray[i];\r
+            }\r
+\r
+            digitArray = newDigitArray;\r
+        }\r
+\r
+        //********************** Explicit casts ***********************\r
+\r
+        /// <summary>\r
+        /// Cast to int\r
+        /// </summary>\r
+        /// <param name="value"></param>\r
+        /// <returns></returns>\r
+        public static explicit operator Int32(BigInt value)\r
+        {\r
+            if (value.digitArray[0] == 0x80000000 && value.sign) return Int32.MinValue;\r
+            int res = (int)(value.digitArray[0] & 0x7fffffff);\r
+            if (value.sign) res = -res;\r
+            return res;\r
+        }\r
+\r
+        /// <summary>\r
+        /// explicit cast to unsigned int.\r
+        /// </summary>\r
+        /// <param name="value"></param>\r
+        /// <returns></returns>\r
+        public static explicit operator UInt32(BigInt value)\r
+        {\r
+            if (value.sign) return (UInt32)((Int32)(value));\r
+            return (UInt32)value.digitArray[0];\r
+        }\r
+\r
+        /// <summary>\r
+        /// explicit cast to 64-bit signed integer.\r
+        /// </summary>\r
+        /// <param name="value"></param>\r
+        /// <returns></returns>\r
+        public static explicit operator Int64(BigInt value)\r
+        {\r
+            if (value.digitArray.Length < 2) return (value.sign ? -((Int64)value.digitArray[0]): ((Int64)value.digitArray[0]));\r
+            UInt64 ret = (((UInt64)value.digitArray[1]) << 32) + (UInt64)value.digitArray[0];\r
+            if (ret == 0x8000000000000000L && value.sign) return Int64.MinValue;\r
+            Int64 signedRet = (Int64)(ret & 0x7fffffffffffffffL);\r
+            if (value.sign) signedRet = -signedRet;\r
+            return signedRet;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Explicit cast to UInt64\r
+        /// </summary>\r
+        /// <param name="value"></param>\r
+        /// <returns></returns>\r
+        public static explicit operator UInt64(BigInt value)\r
+        {\r
+            if (value.sign) return (UInt64)((Int64)(value));\r
+            if (value.digitArray.Length < 2) return (UInt64)value.digitArray[0];\r
+            return ((((UInt64)value.digitArray[1]) << 32) + (UInt64)value.digitArray[0]);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Cast to string\r
+        /// </summary>\r
+        /// <param name="value"></param>\r
+        /// <returns></returns>\r
+        public static explicit operator string(BigInt value)\r
+        {\r
+            return value.ToString();\r
+        }\r
+\r
+        /// <summary>\r
+        /// Cast from string - this is not wholly safe, because precision is not\r
+        /// specified. You should try to construct a BigInt with the appropriate\r
+        /// constructor instead.\r
+        /// </summary>\r
+        /// <param name="value">The decimal string to convert to a BigInt</param>\r
+        /// <returns>A BigInt of the precision required to encompass the string</returns>\r
+        public static explicit operator BigInt(string value)\r
+        {\r
+            return new BigInt(value);\r
+        }\r
+\r
+        //********************* ToString members **********************\r
+\r
+        /// <summary>\r
+        /// Converts this to a string, in the specified base\r
+        /// </summary>\r
+        /// <param name="numberBase">the base to use (min 2, max 16)</param>\r
+        /// <returns>a string representation of the number</returns>\r
+        public string ToString(int numberBase)\r
+        {\r
+            char[] digitChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };\r
+\r
+            string output = "";\r
+\r
+            BigInt clone = new BigInt(this);\r
+            clone.sign = false;\r
+\r
+            int numDigits = 0;\r
+            while (!clone.IsZero())\r
+            {\r
+                if (numberBase == 10 && (numDigits % 3) == 0 && numDigits != 0)\r
+                {\r
+                    output = String.Format(",{0}", output);\r
+                }\r
+                else if (numberBase != 10 && (numDigits % 8) == 0 && numDigits != 0)\r
+                {\r
+                    output = String.Format(" {0}", output);\r
+                }\r
+\r
+                BigInt div, mod;\r
+                DivMod(clone, (uint)numberBase, out div, out mod);\r
+                int iMod = (int)mod;\r
+                output = String.Format("{0}{1}", digitChars[(int)mod], output);\r
+\r
+                numDigits++;\r
+\r
+                clone = div;\r
+            }\r
+\r
+            if (output.Length == 0) output = String.Format("0");\r
+\r
+            if (sign) output = String.Format("-{0}", output);\r
+\r
+            return output;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Converts the number to a string, in base 10\r
+        /// </summary>\r
+        /// <returns>a string representation of the number in base 10</returns>\r
+        public override string ToString()\r
+        {\r
+            return ToString(10);\r
+        }\r
+\r
+        //***************** Internal helper functions *****************\r
+\r
+        private void FromStringInt(string init, int numberBase)\r
+        {\r
+            char [] digitChars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
+\r
+            string formattedInput = init.Trim().ToUpper();\r
+\r
+            for (int i = 0; i < formattedInput.Length; i++)\r
+            {\r
+                int digitIndex = Array.IndexOf(digitChars, formattedInput[i]);\r
+\r
+                //Skip fractional part altogether\r
+                if (formattedInput[i] == '.') break;\r
+\r
+                //skip non-digit characters.\r
+                if (digitIndex < 0) continue;\r
+\r
+                //Multiply\r
+                MulInternal((uint)numberBase);\r
+              \r
+                //Add\r
+                AddInternal(digitIndex);\r
+            }\r
+\r
+            if (init.Length > 0 && init[0] == '-') sign = true;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Sign-insensitive less than comparison. \r
+        /// unsafe if n1 and n2 disagree in precision\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        private static bool LtInt(BigInt n1, BigInt n2)\r
+        {\r
+            //MakeSafe(ref n1, ref n2);\r
+\r
+            for (int i = n1.digitArray.Length - 1; i >= 0; i--)\r
+            {\r
+                if (n1.digitArray[i] < n2.digitArray[i]) return true;\r
+                if (n1.digitArray[i] > n2.digitArray[i]) return false;\r
+            }\r
+\r
+            //equal\r
+            return false;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Sign-insensitive greater than comparison. \r
+        /// unsafe if n1 and n2 disagree in precision\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        /// <returns></returns>\r
+        private static bool GtInt(BigInt n1, BigInt n2)\r
+        {\r
+            //MakeSafe(ref n1, ref n2);\r
+\r
+            for (int i = n1.digitArray.Length - 1; i >= 0; i--)\r
+            {\r
+                if (n1.digitArray[i] > n2.digitArray[i]) return true;\r
+                if (n1.digitArray[i] < n2.digitArray[i]) return false;\r
+            }\r
+\r
+            //equal\r
+            return false;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Makes sure the numbers have matching precisions\r
+        /// </summary>\r
+        /// <param name="n1"></param>\r
+        /// <param name="n2"></param>\r
+        private static void MakeSafe(ref BigInt n1, ref BigInt n2)\r
+        {\r
+            if (n1.digitArray.Length == n2.digitArray.Length)\r
+            {\r
+                return;\r
+            }\r
+            else if (n1.digitArray.Length > n2.digitArray.Length)\r
+            {\r
+                n2 = new BigInt(n2, n1.pres);\r
+            }\r
+            else\r
+            {\r
+                n1 = new BigInt(n1, n2.pres);\r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Makes sure the numbers have matching precisions\r
+        /// </summary>\r
+        /// <param name="n2">the number to match to this</param>\r
+        private void MakeSafe(ref BigInt n2)\r
+        {\r
+            n2 = new BigInt(n2, pres);\r
+            n2.SetNumDigits(digitArray.Length);\r
+        }\r
+\r
+\r
+        private PrecisionSpec pres;\r
+        private bool sign;\r
+        private uint[] digitArray;\r
+        private uint[] workingSet;\r
+    }\r
+\r
+}
\ No newline at end of file