{"id":435,"date":"2021-06-11T21:22:03","date_gmt":"2021-06-11T21:22:03","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=435"},"modified":"2021-06-12T03:13:54","modified_gmt":"2021-06-12T03:13:54","slug":"bigintx-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2021\/06\/11\/bigintx-cs\/","title":{"rendered":"BigIntX.cs"},"content":{"rendered":"\n<p><strong>Variable Bit Width Big Unsigned or Signed Integer 32,64,128,256,512,1024,204<\/strong>,4096 Bit. (Experimental)<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.Numerics;\nusing System.Text;\n[Serializable]\n[TypeConverter(typeof(BigIntXConverter))]\n[DebuggerDisplay(\"{DDisplay}\")]\npublic struct BigIntX : IComparable&lt;BigIntX>, IComparable, IEquatable&lt;BigIntX>, IConvertible, IFormattable\n{\n    internal DigitsArray _digitsArray;\n    public BigIntX(byte number) : this((ulong)number)\n    {\n    }\n    public BigIntX(sbyte number) : this((long)number)\n    {\n    }\n    public BigIntX(bool number) : this((ulong)(number ? 1 : 0))\n    {\n    }\n    public BigIntX(char number) : this((ulong)number)\n    {\n    }\n    public BigIntX(short number) : this((long)number)\n    {\n    }\n    public BigIntX(ushort number) : this((ulong)number)\n    {\n    }\n    public BigIntX(int number) : this((long)number)\n    {\n    }\n    public BigIntX(uint number) : this((ulong)number)\n    {\n    }\n    public BigIntX(BigDecimal number)\n    {\n        var array    = number.UnscaledValue.ToByteArray();\n        var length   = array.Length;\n        var offset   = 0;\n        var estSize  = length \/ 4;\n        var leftOver = length &amp; 3;\n        if (leftOver != 0)\n            ++estSize;\n        _digitsArray = new DigitsArray(estSize + 1, 0);\n        for (int i = offset + length - 1, j = 0; i - offset >= 3; i -= 4, j++)\n        {\n            _digitsArray[j] = (uint)((array[i - 3] &lt;&lt; 24) + (array[i - 2] &lt;&lt; 16) + (array[i - 1] &lt;&lt; 8) + array[i]);\n            _digitsArray.DataUsed++;\n        }\n        uint accumulator = 0;\n        for (var i = leftOver; i > 0; i--)\n        {\n            uint digit = array[offset + leftOver - i];\n            digit       =  digit &lt;&lt; ((i - 1) * 8);\n            accumulator |= digit;\n        }\n        _digitsArray[_digitsArray.DataUsed] = accumulator;\n        _digitsArray.ResetDataUsed();\n    }\n    public BigIntX(BigInteger number)\n    {\n        var array    = number.ToByteArray().Invert();\n        var length   = array.Length;\n        var offset   = 0;\n        var estSize  = length \/ 4;\n        var leftOver = length &amp; 3;\n        if (leftOver != 0)\n            ++estSize;\n        _digitsArray = new DigitsArray(estSize + 1, 0);\n        for (int i = offset + length - 1, j = 0; i - offset >= 3; i -= 4, j++)\n        {\n            _digitsArray[j] = (uint)((array[i - 3] &lt;&lt; 24) + (array[i - 2] &lt;&lt; 16) + (array[i - 1] &lt;&lt; 8) + array[i]);\n            _digitsArray.DataUsed++;\n        }\n        uint accumulator = 0;\n        for (var i = leftOver; i > 0; i--)\n        {\n            uint digit = array[offset + leftOver - i];\n            digit       =  digit &lt;&lt; ((i - 1) * 8);\n            accumulator |= digit;\n        }\n        _digitsArray[_digitsArray.DataUsed] = accumulator;\n        _digitsArray.ResetDataUsed();\n    }\n    public BigIntX(decimal number)\n    {\n        var bits   = decimal.GetBits(decimal.Truncate(number));\n        var length = 3;\n        while (length > 0 &amp;&amp; bits[length - 1] == 0)\n            --length;\n        var IsNegative = (bits[3] &amp; int.MinValue) != 0;\n        _digitsArray = new DigitsArray(3, 0);\n        if (length == 0)\n        {\n            ConstructFrom(new byte[] { 0 }, 0, 1);\n            return;\n        }\n        if (length == 1)\n        {\n            if (!IsNegative)\n            {\n                _digitsArray.Data[0] = (uint)bits[0];\n            }\n            else\n            {\n                _digitsArray.Data[0] = DigitsArray.AllBits - (uint)bits[0] + 1;\n                _digitsArray.Data[1] = DigitsArray.AllBits                 - (uint)bits[1];\n                _digitsArray.Data[2] = DigitsArray.AllBits                 - (uint)bits[2];\n                _digitsArray.Data[3] = DigitsArray.AllBits;\n            }\n            _digitsArray.ResetDataUsed();\n            return;\n        }\n        if (length == 2)\n        {\n            if (!IsNegative)\n            {\n                _digitsArray.Data[0] = (uint)bits[0];\n                _digitsArray.Data[1] = (uint)bits[1];\n            }\n            else\n            {\n                _digitsArray.Data[0] = DigitsArray.AllBits - (uint)bits[0] + 1;\n                _digitsArray.Data[1] = DigitsArray.AllBits                 - (uint)bits[1];\n                _digitsArray.Data[2] = DigitsArray.AllBits                 - (uint)bits[2];\n                _digitsArray.Data[3] = DigitsArray.AllBits;\n            }\n            _digitsArray.ResetDataUsed();\n            return;\n        }\n        if (length == 3)\n        {\n            if (!IsNegative)\n            {\n                _digitsArray.Data[0] = (uint)bits[0];\n                _digitsArray.Data[1] = (uint)bits[1];\n                _digitsArray.Data[2] = (uint)bits[2];\n            }\n            else\n            {\n                _digitsArray.Data[0] = DigitsArray.AllBits - (uint)bits[0] + 1;\n                _digitsArray.Data[1] = DigitsArray.AllBits                 - (uint)bits[1];\n                _digitsArray.Data[2] = DigitsArray.AllBits                 - (uint)bits[2];\n                _digitsArray.Data[3] = DigitsArray.AllBits;\n            }\n            _digitsArray.ResetDataUsed();\n        }\n    }\n    public BigIntX(double value) : this((decimal)value)\n    {\n    }\n    public BigIntX(float value) : this((decimal)value)\n    {\n    }\n    public BigIntX(Guid value) : this(value.ToByteArray())\n    {\n    }\n    public BigIntX(long number)\n    {\n        _digitsArray = new DigitsArray(8 \/ DigitsArray.DataSizeOf + 1, 0);\n        while (number != 0 &amp;&amp; _digitsArray.DataUsed &lt; _digitsArray.Count)\n        {\n            _digitsArray[_digitsArray.DataUsed] =   (uint)(number &amp; DigitsArray.AllBits);\n            number                              >>= DigitsArray.DataSizeBits;\n            _digitsArray.DataUsed++;\n        }\n        _digitsArray.ResetDataUsed();\n    }\n    public BigIntX(ulong number)\n    {\n        _digitsArray = new DigitsArray(8 \/ DigitsArray.DataSizeOf + 1, 0);\n        while (number != 0 &amp;&amp; _digitsArray.DataUsed &lt; _digitsArray.Count)\n        {\n            _digitsArray[_digitsArray.DataUsed] =   (uint)(number &amp; DigitsArray.AllBits);\n            number                              >>= DigitsArray.DataSizeBits;\n            _digitsArray.DataUsed++;\n        }\n        _digitsArray.ResetDataUsed();\n    }\n    public BigIntX(byte[] array) : this(array, 0, array.Length)\n    {\n    }\n    public BigIntX(byte[] array, int length) : this(array, 0, length)\n    {\n    }\n    public BigIntX(byte[] array, int offset, int length)\n    {\n        var estSize  = length \/ 4;\n        var leftOver = length &amp; 3;\n        if (leftOver != 0)\n            ++estSize;\n        _digitsArray = new DigitsArray(estSize + 1, 0);\n        for (int i = offset + length - 1, j = 0; i - offset >= 3; i -= 4, j++)\n        {\n            _digitsArray[j] = (uint)((array[i - 3] &lt;&lt; 24) + (array[i - 2] &lt;&lt; 16) + (array[i - 1] &lt;&lt; 8) + array[i]);\n            _digitsArray.DataUsed++;\n        }\n        uint accumulator = 0;\n        for (var i = leftOver; i > 0; i--)\n        {\n            uint digit = array[offset + leftOver - i];\n            digit       =  digit &lt;&lt; ((i - 1) * 8);\n            accumulator |= digit;\n        }\n        _digitsArray[_digitsArray.DataUsed] = accumulator;\n        _digitsArray.ResetDataUsed();\n    }\n    public BigIntX(string digits) : this(digits, 10)\n    {\n    }\n    public BigIntX(string digits, int radix)\n    {\n        if (digits == null)\n            throw new ArgumentNullException(\"digits\");\n        var multiplier = new BigIntX(1);\n        var result     = new BigIntX();\n        digits = digits.ToUpper(CultureInfo.CurrentCulture).Trim();\n        var nDigits = digits[0] == '-' ? 1 : 0;\n        for (var idx = digits.Length - 1; idx >= nDigits; idx--)\n        {\n            var d = (int)digits[idx];\n            if (d >= '0' &amp;&amp; d &lt;= '9')\n                d -= '0';\n            else if (d >= 'A' &amp;&amp; d &lt;= 'Z')\n                d = d - 'A' + 10;\n            else\n                throw new ArgumentOutOfRangeException(\"digits\");\n            if (d >= radix)\n                throw new ArgumentOutOfRangeException(\"digits\");\n            result     += multiplier * d;\n            multiplier *= radix;\n        }\n        if (digits[0] == '-')\n            result = -result;\n        _digitsArray = result._digitsArray;\n    }\n    private BigIntX(DigitsArray digits)\n    {\n        digits.ResetDataUsed();\n        _digitsArray = digits;\n    }\n    public BigIntX(xIntX value) : this(value.ToByteArray().Invert(), 0, value.ToByteArray().Length)\n    {\n    }\n    internal BigIntX(uint[] rgu)\n    {\n        _digitsArray      = new DigitsArray(1, 1);\n        _digitsArray.Data = rgu;\n        _digitsArray.ResetDataUsed();\n    }\n    [DebuggerBrowsable(DebuggerBrowsableState.Never)]\n    private string DDisplay => ToString();\n    public bool IsNegative => _digitsArray.IsNegative;\n    public bool IsZero     => _digitsArray.IsZero;\n    public int  Sign       => _digitsArray.Sign;\n    public bool IsPowerOfTwo\n    {\n        get\n        {\n            if (Sign != 1)\n                return false;\n            var index = Length(_digitsArray.Data) - 1;\n            if (((int)_digitsArray.Data[index] &amp; ((int)_digitsArray.Data[index] - 1)) != 0)\n                return false;\n            while (--index >= 0)\n                if (_digitsArray.Data[index] != 0U)\n                    return false;\n            return true;\n        }\n    }\n    public bool IsOne  => this     == 1;\n    public bool IsEven => this % 2 == 0;\n    int IComparable.CompareTo(object obj)\n    {\n        return Compare(this, (BigIntX)obj);\n    }\n    public int CompareTo(BigIntX value)\n    {\n        return Compare(this, value);\n    }\n    TypeCode IConvertible.GetTypeCode()\n    {\n        return TypeCode.Object;\n    }\n    public object ToType(Type conversionType, IFormatProvider provider)\n    {\n        object value;\n        if (TryConvert(conversionType, provider, out value))\n            return value;\n        throw new InvalidCastException();\n    }\n    bool IConvertible.ToBoolean(IFormatProvider provider)\n    {\n        return bool.Parse(ToString());\n    }\n    byte IConvertible.ToByte(IFormatProvider provider)\n    {\n        return byte.Parse(ToString());\n    }\n    char IConvertible.ToChar(IFormatProvider provider)\n    {\n        return char.Parse(ToString());\n    }\n    DateTime IConvertible.ToDateTime(IFormatProvider provider)\n    {\n        return DateTime.Parse(ToString());\n    }\n    decimal IConvertible.ToDecimal(IFormatProvider provider)\n    {\n        return decimal.Parse(ToString());\n    }\n    double IConvertible.ToDouble(IFormatProvider provider)\n    {\n        return double.Parse(ToString());\n    }\n    short IConvertible.ToInt16(IFormatProvider provider)\n    {\n        return short.Parse(ToString());\n    }\n    ushort IConvertible.ToUInt16(IFormatProvider provider)\n    {\n        return ushort.Parse(ToString());\n    }\n    int IConvertible.ToInt32(IFormatProvider provider)\n    {\n        return int.Parse(ToString());\n    }\n    uint IConvertible.ToUInt32(IFormatProvider provider)\n    {\n        return uint.Parse(ToString());\n    }\n    long IConvertible.ToInt64(IFormatProvider provider)\n    {\n        return long.Parse(ToString());\n    }\n    ulong IConvertible.ToUInt64(IFormatProvider provider)\n    {\n        return ulong.Parse(ToString());\n    }\n    sbyte IConvertible.ToSByte(IFormatProvider provider)\n    {\n        return sbyte.Parse(ToString());\n    }\n    float IConvertible.ToSingle(IFormatProvider provider)\n    {\n        return float.Parse(ToString());\n    }\n    string IConvertible.ToString(IFormatProvider provider)\n    {\n        return ToString(null, provider);\n    }\n    public bool Equals(BigIntX obj)\n    {\n        if (ReferenceEquals(obj, null))\n            return false;\n        if (ReferenceEquals(this, obj))\n            return true;\n        var c = obj;\n        if (_digitsArray.DataUsed != c._digitsArray.DataUsed)\n            return false;\n        for (var idx = 0; idx &lt; _digitsArray.DataUsed; idx++)\n            if (_digitsArray[idx] != c._digitsArray[idx])\n                return false;\n        return true;\n    }\n    public string ToString(string format, IFormatProvider formatProvider)\n    {\n        if (formatProvider == null)\n            formatProvider = CultureInfo.CurrentCulture;\n        if (!string.IsNullOrEmpty(format))\n        {\n            var ch = format[0];\n            if (ch == 'x' || ch == 'X')\n                if (int.TryParse(format.Substring(1).Trim(), out var min))\n                    return ToHexString();\n            if (ch != 'G' &amp;&amp; ch != 'g' &amp;&amp; ch != 'D' &amp;&amp; ch != 'd')\n                throw new NotSupportedException(\"Not supported format: \" + format);\n        }\n        return ToString(10);\n    }\n    public bool TryConvert(Type conversionType, IFormatProvider provider, out object value)\n    {\n        if (conversionType == typeof(bool))\n        {\n            value = bool.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(byte))\n        {\n            value = byte.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(char))\n        {\n            value = char.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(decimal))\n        {\n            value = decimal.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(double))\n        {\n            value = double.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(short))\n        {\n            value = short.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(int))\n        {\n            value = int.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(long))\n        {\n            value = long.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(sbyte))\n        {\n            value = sbyte.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(float))\n        {\n            value = float.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(string))\n        {\n            value = ToString(null, provider);\n            return true;\n        }\n        if (conversionType == typeof(ushort))\n        {\n            value = ushort.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(uint))\n        {\n            value = uint.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(ulong))\n        {\n            value = ulong.Parse(ToString());\n            return true;\n        }\n        if (conversionType == typeof(byte[]))\n        {\n            value = ToByteArray();\n            return true;\n        }\n        if (conversionType == typeof(Guid))\n        {\n            value = new Guid(ToByteArray());\n            return true;\n        }\n        value = null;\n        return false;\n    }\n    private void ConstructFrom(byte[] array, int offset, int length)\n    {\n        if (array == null)\n            throw new ArgumentNullException(\"Array is null\");\n        if (offset > array.Length || length > array.Length)\n            throw new ArgumentOutOfRangeException(\"Offset exceeds length\");\n        if (length > array.Length || offset + length > array.Length)\n            throw new ArgumentOutOfRangeException(\"Length exceeds array length\");\n        var estSize  = length \/ 4;\n        var leftOver = length &amp; 3;\n        if (leftOver != 0)\n            ++estSize;\n        _digitsArray = new DigitsArray(estSize + 1, 0);\n        for (int i = offset + length - 1, j = 0; i - offset >= 3; i -= 4, j++)\n        {\n            _digitsArray[j] = (uint)((array[i - 3] &lt;&lt; 24) + (array[i - 2] &lt;&lt; 16) + (array[i - 1] &lt;&lt; 8) + array[i]);\n            _digitsArray.DataUsed++;\n        }\n        uint accumulator = 0;\n        for (var i = leftOver; i > 0; i--)\n        {\n            uint digit = array[offset + leftOver - i];\n            digit       =  digit &lt;&lt; ((i - 1) * 8);\n            accumulator |= digit;\n        }\n        _digitsArray[_digitsArray.DataUsed] = accumulator;\n        _digitsArray.ResetDataUsed();\n    }\n    private void Construct(string digits, int radix)\n    {\n        if (digits == null)\n            throw new ArgumentNullException(\"digits\");\n        var multiplier = new BigIntX(1);\n        var result     = new BigIntX();\n        digits = digits.ToUpper(CultureInfo.CurrentCulture).Trim();\n        var nDigits = digits[0] == '-' ? 1 : 0;\n        for (var idx = digits.Length - 1; idx >= nDigits; idx--)\n        {\n            var d = (int)digits[idx];\n            if (d >= '0' &amp;&amp; d &lt;= '9')\n                d -= '0';\n            else if (d >= 'A' &amp;&amp; d &lt;= 'Z')\n                d = d - 'A' + 10;\n            else\n                throw new ArgumentOutOfRangeException(\"digits\");\n            if (d >= radix)\n                throw new ArgumentOutOfRangeException(\"digits\");\n            result     += multiplier * d;\n            multiplier *= radix;\n        }\n        if (digits[0] == '-')\n            result = -result;\n        _digitsArray = result._digitsArray;\n    }\n    public static bool TryParseNum(string digits, int radix, out BigIntX result)\n    {\n        result = new BigIntX();\n        if (digits == null)\n            return false;\n        var multiplier = new BigIntX(1);\n        digits = digits.ToUpper(CultureInfo.CurrentCulture).Trim();\n        var nDigits = digits[0] == '-' ? 1 : 0;\n        for (var idx = digits.Length - 1; idx >= nDigits; idx--)\n        {\n            var d = (int)digits[idx];\n            if (d >= '0' &amp;&amp; d &lt;= '9')\n                d -= '0';\n            else if (d >= 'A' &amp;&amp; d &lt;= 'Z')\n                d = d - 'A' + 10;\n            else\n                return false;\n            if (d >= radix)\n                return false;\n            result     += multiplier * d;\n            multiplier *= radix;\n        }\n        if (digits[0] == '-')\n            result = -result;\n        return true;\n    }\n    public static BigIntX Parse(string value)\n    {\n        return Parse(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);\n    }\n    public static BigIntX Parse(string value, NumberStyles style)\n    {\n        return Parse(value, style, NumberFormatInfo.CurrentInfo);\n    }\n    public static BigIntX Parse(string value, IFormatProvider provider)\n    {\n        return Parse(value, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));\n    }\n    public static BigIntX Parse(string value, NumberStyles style, IFormatProvider provider)\n    {\n        if (!TryParse(value, style, provider, out var result))\n            throw new Exception($\"TryParse value {value} failure.\");\n        return result;\n    }\n    public static bool TryParse(string value, out BigIntX result)\n    {\n        return TryParse(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);\n    }\n    public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigIntX result)\n    {\n        result = new BigIntX();\n        if (string.IsNullOrEmpty(value))\n            return false;\n        if (value.StartsWith(\"x\", StringComparison.OrdinalIgnoreCase))\n        {\n            style |= NumberStyles.AllowHexSpecifier;\n            value =  value.Substring(1);\n        }\n        else\n        {\n            if (value.StartsWith(\"0x\", StringComparison.OrdinalIgnoreCase))\n            {\n                style |= NumberStyles.AllowHexSpecifier;\n                value =  value.Substring(2);\n            }\n        }\n        if ((style &amp; NumberStyles.AllowHexSpecifier) == NumberStyles.AllowHexSpecifier)\n            return TryParseNum(value, 16, out result);\n        return TryParseNum(value, 10, out result);\n    }\n    public static implicit operator BigIntX(BigDecimal value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(BigInteger value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(xIntX value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(bool value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(byte value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(char value)\n    {\n        return new BigIntX(value);\n    }\n    public static explicit operator BigIntX(decimal value)\n    {\n        return new BigIntX(value);\n    }\n    public static explicit operator BigIntX(double value)\n    {\n        return new BigIntX(value);\n    }\n    public static explicit operator BigIntX(float value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(short value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(ushort value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(sbyte value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(long value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(ulong value)\n    {\n        return new BigIntX(value);\n    }\n    public static implicit operator BigIntX(int value)\n    {\n        return new BigIntX(value);\n    }\n    public static explicit operator byte(BigIntX value)\n    {\n        return checked((byte)(int)value);\n    }\n    public static explicit operator sbyte(BigIntX value)\n    {\n        return checked((sbyte)(int)value);\n    }\n    public static implicit operator BigIntX(uint value)\n    {\n        return new BigIntX((ulong)value);\n    }\n    public static explicit operator short(BigIntX value)\n    {\n        return checked((short)(int)value);\n    }\n    public static explicit operator ushort(BigIntX value)\n    {\n        return checked((ushort)(int)value);\n    }\n    public static explicit operator BigInteger(BigIntX value)\n    {\n        return new BigInteger(value.ToByteArray());\n    }\n    public static explicit operator xIntX(BigIntX value)\n    {\n        return new xIntX(value.ToByteArray());\n    }\n    public static explicit operator int(BigIntX value)\n    {\n        if (value.IsZero)\n            return 0;\n        if (value.Sign > 0)\n            return checked((int)value._digitsArray.Data[0]);\n        if (value > int.MaxValue)\n            throw new OverflowException(\"int overflow.\");\n        return -(int)value._digitsArray.Data[0];\n    }\n    public static explicit operator uint(BigIntX value)\n    {\n        return value._digitsArray.Data[0];\n    }\n    public static explicit operator long(BigIntX value)\n    {\n        if (value > long.MaxValue)\n            throw new OverflowException(\"long overflow.\");\n        var uu = value._digitsArray.Data.Length - 1 &lt;= 1 ? value._digitsArray.Data[0] : ((ulong)value._digitsArray.Data[1] &lt;&lt; 32) | value._digitsArray.Data[0];\n        var ll = value.Sign                         > 0 ? (long)uu : -(long)uu;\n        if (ll > 0L &amp;&amp; value.Sign > 0 || ll &lt; 0L &amp;&amp; value.Sign &lt; 0)\n            return ll;\n        throw new OverflowException(\"long overflow.\");\n    }\n    public static explicit operator ulong(BigIntX value)\n    {\n        if (value > ulong.MaxValue)\n            throw new OverflowException(\"ulong overflow.\");\n        if (value._digitsArray.Data.Length - 1 > 1)\n            return ((ulong)value._digitsArray.Data[1] &lt;&lt; 32) | value._digitsArray.Data[0];\n        return value._digitsArray.Data[0];\n    }\n    public static decimal ToDecimal(BigIntX value)\n    {\n        var len = value._digitsArray.Data.Length - 1;\n        if (len > 3)\n            throw new OverflowException(\"Decimal overflow.\");\n        ;\n        var lo  = 0;\n        var mid = 0;\n        var hi  = 0;\n        if (len > 2)\n            hi = (int)value._digitsArray.Data[2];\n        if (len > 1)\n            mid = (int)value._digitsArray.Data[1];\n        if (len > 0)\n            lo = (int)value._digitsArray.Data[0];\n        return new decimal(lo, mid, hi, value.Sign &lt; 0, 0);\n    }\n    public static explicit operator decimal(BigIntX value)\n    {\n        var len = value._digitsArray.Data.Length - 1;\n        if (len > 3)\n            throw new OverflowException(\"Decimal overflow.\");\n        ;\n        var lo  = 0;\n        var mid = 0;\n        var hi  = 0;\n        if (len > 2)\n            hi = (int)value._digitsArray.Data[2];\n        if (len > 1)\n            mid = (int)value._digitsArray.Data[1];\n        if (len > 0)\n            lo = (int)value._digitsArray.Data[0];\n        return new decimal(lo, mid, hi, value.Sign &lt; 0, 0);\n    }\n    public static BigIntX operator +(BigIntX left, BigIntX right)\n    {\n        var  size  = Math.Max(left._digitsArray.DataUsed, right._digitsArray.DataUsed);\n        var  da    = new DigitsArray(size + 1);\n        long carry = 0;\n        for (var i = 0; i &lt; da.Count; i++)\n        {\n            var sum = left._digitsArray[i] + (long)right._digitsArray[i] + carry;\n            carry = sum >> DigitsArray.DataSizeBits;\n            da[i] = (uint)(sum &amp; DigitsArray.AllBits);\n        }\n        return new BigIntX(da);\n    }\n    public static BigIntX Add(BigIntX left, BigIntX right)\n    {\n        return left + right;\n    }\n    public static BigIntX operator ++(BigIntX left)\n    {\n        return left + 1;\n    }\n    public static BigIntX Increment(BigIntX left)\n    {\n        return left + 1;\n    }\n    public static BigIntX operator -(BigIntX left, BigIntX right)\n    {\n        var  size  = Math.Max(left._digitsArray.DataUsed, right._digitsArray.DataUsed) + 1;\n        var  da    = new DigitsArray(size);\n        long carry = 0;\n        for (var i = 0; i &lt; da.Count; i++)\n        {\n            var diff = left._digitsArray[i] - (long)right._digitsArray[i] - carry;\n            da[i] = (uint)(diff &amp; DigitsArray.AllBits);\n            da.DataUsed++;\n            carry = diff &lt; 0 ? 1 : 0;\n        }\n        return new BigIntX(da);\n    }\n    public static BigIntX Subtract(BigIntX left, BigIntX right)\n    {\n        return left - right;\n    }\n    public static BigIntX operator --(BigIntX left)\n    {\n        return left - 1;\n    }\n    public static BigIntX Decrement(BigIntX left)\n    {\n        return left - 1;\n    }\n    public static BigIntX operator -(BigIntX left)\n    {\n        if (ReferenceEquals(left, null))\n            throw new ArgumentNullException(\"left\");\n        if (left.IsZero)\n            return new BigIntX(0);\n        var da = new DigitsArray(left._digitsArray.DataUsed + 1, left._digitsArray.DataUsed + 1);\n        for (var i = 0; i &lt; da.Count; i++)\n            da[i] = ~left._digitsArray[i];\n        var carry = true;\n        var index = 0;\n        while (carry &amp;&amp; index &lt; da.Count)\n        {\n            var val = (long)da[index] + 1;\n            da[index] = (uint)(val &amp; DigitsArray.AllBits);\n            carry     = val >> DigitsArray.DataSizeBits > 0;\n            index++;\n        }\n        return new BigIntX(da);\n    }\n    public BigIntX Negate()\n    {\n        return -this;\n    }\n    public static BigIntX Abs(BigIntX left)\n    {\n        if (ReferenceEquals(left, null))\n            throw new ArgumentNullException(\"left\");\n        if (left.IsNegative)\n            return -left;\n        return left;\n    }\n    public static BigIntX operator *(BigIntX left, BigIntX right)\n    {\n        if (ReferenceEquals(left, null))\n            throw new ArgumentNullException(\"left\");\n        if (ReferenceEquals(right, null))\n            throw new ArgumentNullException(\"right\");\n        var leftSideNeg  = left.IsNegative;\n        var rightSideNeg = right.IsNegative;\n        left  = Abs(left);\n        right = Abs(right);\n        var da = new DigitsArray(left._digitsArray.DataUsed + right._digitsArray.DataUsed);\n        da.DataUsed = da.Count;\n        for (var i = 0; i &lt; left._digitsArray.DataUsed; i++)\n        {\n            ulong carry = 0;\n            for (int j = 0, k = i; j &lt; right._digitsArray.DataUsed; j++, k++)\n            {\n                var val = left._digitsArray[i] * (ulong)right._digitsArray[j] + da[k] + carry;\n                da[k] = (uint)(val &amp; DigitsArray.AllBits);\n                carry = val >> DigitsArray.DataSizeBits;\n            }\n            if (carry != 0)\n                da[i + right._digitsArray.DataUsed] = (uint)carry;\n        }\n        var result = new BigIntX(da);\n        return leftSideNeg != rightSideNeg ? -result : result;\n    }\n    public static BigIntX Multiply(BigIntX left, BigIntX right)\n    {\n        return left * right;\n    }\n    public static BigIntX operator \/(BigIntX left, BigIntX right)\n    {\n        if (left == null)\n            throw new ArgumentNullException(\"left\");\n        if (right == null)\n            throw new ArgumentNullException(\"right\");\n        if (right.IsZero)\n            throw new DivideByZeroException();\n        var divisorNeg  = right.IsNegative;\n        var dividendNeg = left.IsNegative;\n        left  = Abs(left);\n        right = Abs(right);\n        if (left &lt; right)\n            return new BigIntX(0);\n        Divide(left, right, out var quotient, out var remainder);\n        return dividendNeg != divisorNeg ? -quotient : quotient;\n    }\n    public static BigIntX Divide(BigIntX left, BigIntX right)\n    {\n        return left \/ right;\n    }\n    private static void Divide(BigIntX left, BigIntX right, out BigIntX quotient, out BigIntX remainder)\n    {\n        if (left.IsZero)\n        {\n            quotient  = new BigIntX();\n            remainder = new BigIntX();\n            return;\n        }\n        if (right._digitsArray.DataUsed == 1)\n            SingleDivide(left, right, out quotient, out remainder);\n        else\n            MultiDivide(left, right, out quotient, out remainder);\n    }\n    private static void MultiDivide(BigIntX left, BigIntX right, out BigIntX quotient, out BigIntX remainder)\n    {\n        if (right.IsZero)\n            throw new DivideByZeroException();\n        var val = right._digitsArray[right._digitsArray.DataUsed - 1];\n        var d   = 0;\n        for (var mask = DigitsArray.HiBitSet; mask != 0 &amp;&amp; (val &amp; mask) == 0; mask >>= 1)\n            d++;\n        var remainderLen = left._digitsArray.DataUsed + 1;\n        var remainderDat = new uint[remainderLen];\n        left._digitsArray.CopyTo(remainderDat, 0, left._digitsArray.DataUsed);\n        DigitsArray.ShiftLeft(remainderDat, d);\n        right = right &lt;&lt; d;\n        ulong firstDivisor  = right._digitsArray[right._digitsArray.DataUsed - 1];\n        ulong secondDivisor = right._digitsArray.DataUsed &lt; 2 ? 0 : right._digitsArray[right._digitsArray.DataUsed - 2];\n        var   divisorLen    = right._digitsArray.DataUsed + 1;\n        var   dividendPart  = new DigitsArray(divisorLen, divisorLen);\n        var   result        = new uint[left._digitsArray.Count + 1];\n        var   resultPos     = 0;\n        var   carryBit      = (ulong)0x1 &lt;&lt; DigitsArray.DataSizeBits;\n        for (int j = remainderLen - right._digitsArray.DataUsed, pos = remainderLen - 1; j > 0; j--, pos--)\n        {\n            var dividend = ((ulong)remainderDat[pos] &lt;&lt; DigitsArray.DataSizeBits) + remainderDat[pos - 1];\n            var qHat     = dividend \/ firstDivisor;\n            var rHat     = dividend % firstDivisor;\n            while (pos >= 2)\n            {\n                if (qHat == carryBit || qHat * secondDivisor > (rHat &lt;&lt; DigitsArray.DataSizeBits) + remainderDat[pos - 2])\n                {\n                    qHat--;\n                    rHat += firstDivisor;\n                    if (rHat &lt; carryBit)\n                        continue;\n                }\n                break;\n            }\n            for (var h = 0; h &lt; divisorLen; h++)\n                dividendPart[divisorLen - h - 1] = remainderDat[pos - h];\n            var dTemp = new BigIntX(dividendPart);\n            var rTemp = right * (long)qHat;\n            while (rTemp > dTemp)\n            {\n                qHat--;\n                rTemp -= right;\n            }\n            rTemp = dTemp - rTemp;\n            for (var h = 0; h &lt; divisorLen; h++)\n                remainderDat[pos - h] = rTemp._digitsArray[right._digitsArray.DataUsed - h];\n            result[resultPos++] = (uint)qHat;\n        }\n        Array.Reverse(result, 0, resultPos);\n        quotient = new BigIntX(new DigitsArray(result));\n        var n   = DigitsArray.ShiftRight(remainderDat, d);\n        var rDA = new DigitsArray(n, n);\n        rDA.CopyFrom(remainderDat, 0, 0, rDA.DataUsed);\n        remainder = new BigIntX(rDA);\n    }\n    private static void SingleDivide(BigIntX left, BigIntX right, out BigIntX quotient, out BigIntX remainder)\n    {\n        if (right.IsZero)\n            throw new DivideByZeroException();\n        var remainderDigits = new DigitsArray(left._digitsArray);\n        remainderDigits.ResetDataUsed();\n        var pos      = remainderDigits.DataUsed - 1;\n        var divisor  = (ulong)right._digitsArray[0];\n        var dividend = (ulong)remainderDigits[pos];\n        var result   = new uint[left._digitsArray.Count];\n        left._digitsArray.CopyTo(result, 0, result.Length);\n        var resultPos = 0;\n        if (dividend >= divisor)\n        {\n            result[resultPos++]  = (uint)(dividend \/ divisor);\n            remainderDigits[pos] = (uint)(dividend % divisor);\n        }\n        pos--;\n        while (pos >= 0)\n        {\n            dividend                 = ((ulong)remainderDigits[pos + 1] &lt;&lt; DigitsArray.DataSizeBits) + remainderDigits[pos];\n            result[resultPos++]      = (uint)(dividend \/ divisor);\n            remainderDigits[pos + 1] = 0;\n            remainderDigits[pos--]   = (uint)(dividend % divisor);\n        }\n        remainder = new BigIntX(remainderDigits);\n        var quotientDigits = new DigitsArray(resultPos + 1, resultPos);\n        var j              = 0;\n        for (var i = quotientDigits.DataUsed - 1; i >= 0; i--, j++)\n            quotientDigits[j] = result[i];\n        quotient = new BigIntX(quotientDigits);\n    }\n    public static BigIntX operator %(BigIntX left, BigIntX right)\n    {\n        if (left == null)\n            throw new ArgumentNullException(\"left\");\n        if (right == null)\n            throw new ArgumentNullException(\"right\");\n        if (right.IsZero)\n            throw new DivideByZeroException();\n        BigIntX quotient;\n        BigIntX remainder;\n        var     dividendNeg = left.IsNegative;\n        left  = Abs(left);\n        right = Abs(right);\n        if (left &lt; right)\n            return left;\n        Divide(left, right, out quotient, out remainder);\n        return dividendNeg ? -remainder : remainder;\n    }\n    public static BigIntX Modulus(BigIntX left, BigIntX right)\n    {\n        return left % right;\n    }\n    public BigIntX Pow(BigIntX power)\n    {\n        return Pow(this, power);\n    }\n    public static BigIntX operator &amp;(BigIntX left, BigIntX right)\n    {\n        var len = Math.Max(left._digitsArray.DataUsed, right._digitsArray.DataUsed);\n        var da  = new DigitsArray(len, len);\n        for (var idx = 0; idx &lt; len; idx++)\n            da[idx] = left._digitsArray[idx] &amp; right._digitsArray[idx];\n        return new BigIntX(da);\n    }\n    public static BigIntX BitwiseAnd(BigIntX left, BigIntX right)\n    {\n        return left &amp; right;\n    }\n    public static BigIntX operator |(BigIntX left, BigIntX right)\n    {\n        var len = Math.Max(left._digitsArray.DataUsed, right._digitsArray.DataUsed);\n        var da  = new DigitsArray(len, len);\n        for (var idx = 0; idx &lt; len; idx++)\n            da[idx] = left._digitsArray[idx] | right._digitsArray[idx];\n        return new BigIntX(da);\n    }\n    public static BigIntX BitwiseOr(BigIntX left, BigIntX right)\n    {\n        return left | right;\n    }\n    public static BigIntX operator ^(BigIntX left, BigIntX right)\n    {\n        var len = Math.Max(left._digitsArray.DataUsed, right._digitsArray.DataUsed);\n        var da  = new DigitsArray(len, len);\n        for (var idx = 0; idx &lt; len; idx++)\n            da[idx] = left._digitsArray[idx] ^ right._digitsArray[idx];\n        return new BigIntX(da);\n    }\n    public static BigIntX Xor(BigIntX left, BigIntX right)\n    {\n        return left ^ right;\n    }\n    public static BigIntX operator ~(BigIntX left)\n    {\n        var da = new DigitsArray(left._digitsArray.Count);\n        for (var idx = 0; idx &lt; da.Count; idx++)\n            da[idx] = ~left._digitsArray[idx];\n        return new BigIntX(da);\n    }\n    public static BigIntX OnesComplement(BigIntX left)\n    {\n        return ~left;\n    }\n    public static BigIntX operator &lt;&lt;(BigIntX left, int shiftCount)\n    {\n        if (left == null)\n            throw new ArgumentNullException(\"left\");\n        var da = new DigitsArray(left._digitsArray);\n        da.DataUsed = da.ShiftLeftWithoutOverflow(shiftCount);\n        return new BigIntX(da);\n    }\n    public static BigIntX LeftShift(BigIntX left, int shiftCount)\n    {\n        return left &lt;&lt; shiftCount;\n    }\n    public static BigIntX operator >> (BigIntX left, int shiftCount)\n    {\n        if (left == null)\n            throw new ArgumentNullException(\"left\");\n        var da = new DigitsArray(left._digitsArray);\n        da.DataUsed = da.ShiftRight(shiftCount);\n        if (left.IsNegative)\n        {\n            for (var i = da.Count - 1; i >= da.DataUsed; i--)\n                da[i] = DigitsArray.AllBits;\n            var mask = DigitsArray.HiBitSet;\n            for (var i = 0; i &lt; DigitsArray.DataSizeBits; i++)\n            {\n                if ((da[da.DataUsed - 1] &amp; mask) == DigitsArray.HiBitSet)\n                    break;\n                da[da.DataUsed - 1] |=  mask;\n                mask                >>= 1;\n            }\n            da.DataUsed = da.Count;\n        }\n        return new BigIntX(da);\n    }\n    public static BigIntX RightShift(BigIntX left, int shiftCount)\n    {\n        if (left == null)\n            throw new ArgumentNullException(\"left\");\n        return left >> shiftCount;\n    }\n    public static int Compare(BigIntX left, BigIntX right)\n    {\n        if (ReferenceEquals(left, right))\n            return 0;\n        if (ReferenceEquals(left, null))\n            throw new ArgumentNullException(\"left\");\n        if (ReferenceEquals(right, null))\n            throw new ArgumentNullException(\"right\");\n        if (left > right) return 1;\n        if (left == right) return 0;\n        return -1;\n    }\n    public static bool operator ==(BigIntX left, BigIntX right)\n    {\n        if (ReferenceEquals(left, right))\n            return true;\n        if (ReferenceEquals(left, null) || ReferenceEquals(right, null))\n            return false;\n        if (left.IsNegative != right.IsNegative)\n            return false;\n        return left.Equals(right);\n    }\n    public static bool operator !=(BigIntX left, BigIntX right)\n    {\n        return !(left == right);\n    }\n    public static bool operator >(BigIntX left, BigIntX right)\n    {\n        if (ReferenceEquals(left, null))\n            throw new ArgumentNullException(\"left\");\n        if (ReferenceEquals(right, null))\n            throw new ArgumentNullException(\"right\");\n        if (left.IsNegative != right.IsNegative)\n            return right.IsNegative;\n        if (left._digitsArray.DataUsed != right._digitsArray.DataUsed)\n            return left._digitsArray.DataUsed > right._digitsArray.DataUsed;\n        for (var idx = left._digitsArray.DataUsed - 1; idx >= 0; idx--)\n            if (left._digitsArray[idx] != right._digitsArray[idx])\n                return left._digitsArray[idx] > right._digitsArray[idx];\n        return false;\n    }\n    public static bool operator &lt;(BigIntX left, BigIntX right)\n    {\n        if (ReferenceEquals(left, null))\n            throw new ArgumentNullException(\"left\");\n        if (ReferenceEquals(right, null))\n            throw new ArgumentNullException(\"right\");\n        if (left.IsNegative != right.IsNegative)\n            return left.IsNegative;\n        if (left._digitsArray.DataUsed != right._digitsArray.DataUsed)\n            return left._digitsArray.DataUsed &lt; right._digitsArray.DataUsed;\n        for (var idx = left._digitsArray.DataUsed - 1; idx >= 0; idx--)\n            if (left._digitsArray[idx] != right._digitsArray[idx])\n                return left._digitsArray[idx] &lt; right._digitsArray[idx];\n        return false;\n    }\n    public static bool operator >=(BigIntX left, BigIntX right)\n    {\n        return Compare(left, right) >= 0;\n    }\n    public static bool operator &lt;=(BigIntX left, BigIntX right)\n    {\n        return Compare(left, right) &lt;= 0;\n    }\n    public override bool Equals(object obj)\n    {\n        if (ReferenceEquals(obj, null))\n            return false;\n        if (ReferenceEquals(this, obj))\n            return true;\n        var c = (BigIntX)obj;\n        if (_digitsArray.DataUsed != c._digitsArray.DataUsed)\n            return false;\n        for (var idx = 0; idx &lt; _digitsArray.DataUsed; idx++)\n            if (_digitsArray[idx] != c._digitsArray[idx])\n                return false;\n        return true;\n    }\n    public override int GetHashCode()\n    {\n        var hash = 0x811c9dc5;\n        for (var i = 0; i &lt; _digitsArray.Data.Length; i++)\n        {\n            hash =  ((hash &lt;&lt; 13) | (hash >> 19)) ^ _digitsArray.Data[i];\n            hash *= 0x1000193;\n        }\n        return (int)hash;\n    }\n    public string GetDataAsString()\n    {\n        return _digitsArray.GetDataAsString();\n    }\n    public override string ToString()\n    {\n        return ToString(10);\n    }\n    public byte[] ToByteArray()\n    {\n        return _digitsArray.ToByteArray();\n    }\n    public uint[] ToUIn32Array()\n    {\n        return _digitsArray.ToUIn32Array();\n    }\n    public ulong[] ToUIn64Array()\n    {\n        return _digitsArray.ToUIn64Array();\n    }\n    public string ToString(int radix)\n    {\n        if (radix &lt; 2 || radix > 36)\n            throw new ArgumentOutOfRangeException(\"radix\");\n        if (IsZero)\n            return \"0\";\n        var a        = this;\n        var negative = a.IsNegative;\n        a = Abs(this);\n        BigIntX      quotient;\n        BigIntX      remainder;\n        var          biRadix = new BigIntX(radix);\n        const string charSet = \"0123456789abcdefghijklmnopqrstuvwxyz\";\n        var          al      = new ArrayList();\n        while (a._digitsArray.DataUsed > 1 || a._digitsArray.DataUsed == 1 &amp;&amp; a._digitsArray[0] != 0)\n        {\n            Divide(a, biRadix, out quotient, out remainder);\n            al.Insert(0, charSet[(int)remainder._digitsArray[0]]);\n            a = quotient;\n        }\n        var result = new string((char[])al.ToArray(typeof(char)));\n        if (radix == 10 &amp;&amp; negative)\n            return \"-\" + result;\n        return result;\n    }\n    public string ToHexString()\n    {\n        var sb = new StringBuilder();\n        sb.AppendFormat(\"{0:X}\", _digitsArray[_digitsArray.DataUsed - 1]);\n        var f = \"{0:X\" + 2 * DigitsArray.DataSizeOf + \"}\";\n        for (var i = _digitsArray.DataUsed - 2; i >= 0; i--)\n            sb.AppendFormat(f, _digitsArray[i]);\n        return sb.ToString();\n    }\n    public string ToBinaryString()\n    {\n        var bytes  = ToByteArray();\n        var index  = bytes.Length - 1;\n        var base2  = new StringBuilder(bytes.Length * 8);\n        var binary = Convert.ToString(bytes[index], 2);\n        if (binary[0] != '0' &amp;&amp; Sign == 1) base2.Append('0');\n        base2.Append(binary);\n        for (index--; index >= 0; index--)\n            base2.Append(Convert.ToString(bytes[index], 2).PadLeft(8, '0'));\n        return base2.ToString();\n    }\n    public string ToOctalString()\n    {\n        var bytes         = ToByteArray();\n        var index         = bytes.Length - 1;\n        var base8         = new StringBuilder((bytes.Length \/ 3 + 1) * 8);\n        var rem           = bytes.Length % 3;\n        if (rem == 0) rem = 3;\n        var base0         = 0;\n        while (rem != 0)\n        {\n            base0 &lt;&lt;= 8;\n            base0 +=  bytes[index--];\n            rem--;\n        }\n        var octal = Convert.ToString(base0, 8);\n        if (octal[0] != '0' &amp;&amp; Sign == 1) base8.Append('0');\n        base8.Append(octal);\n        while (index >= 0)\n        {\n            base0 = (bytes[index] &lt;&lt; 16) + (bytes[index - 1] &lt;&lt; 8) + bytes[index - 2];\n            base8.Append(Convert.ToString(base0, 8).PadLeft(8, '0'));\n            index -= 3;\n        }\n        return base8.ToString();\n    }\n    public static int ToInt16(BigIntX value)\n    {\n        if (ReferenceEquals(value, null))\n            throw new ArgumentNullException(\"value\");\n        return short.Parse(value.ToString(), NumberStyles.Integer, CultureInfo.CurrentCulture);\n    }\n    public static uint ToUInt16(BigIntX value)\n    {\n        if (ReferenceEquals(value, null))\n            throw new ArgumentNullException(\"value\");\n        return ushort.Parse(value.ToString(), NumberStyles.Integer, CultureInfo.CurrentCulture);\n    }\n    public static int ToInt32(BigIntX value)\n    {\n        if (ReferenceEquals(value, null))\n            throw new ArgumentNullException(\"value\");\n        return int.Parse(value.ToString(), NumberStyles.Integer, CultureInfo.CurrentCulture);\n    }\n    public static uint ToUInt32(BigIntX value)\n    {\n        if (ReferenceEquals(value, null))\n            throw new ArgumentNullException(\"value\");\n        return uint.Parse(value.ToString(), NumberStyles.Integer, CultureInfo.CurrentCulture);\n    }\n    public static long ToInt64(BigIntX value)\n    {\n        if (ReferenceEquals(value, null))\n            throw new ArgumentNullException(\"value\");\n        return long.Parse(value.ToString(), NumberStyles.Integer, CultureInfo.CurrentCulture);\n    }\n    public static ulong ToUInt64(BigIntX value)\n    {\n        if (ReferenceEquals(value, null))\n            throw new ArgumentNullException(\"value\");\n        return ulong.Parse(value.ToString(), NumberStyles.Integer, CultureInfo.CurrentCulture);\n    }\n    public static BigIntX Pow(BigIntX value, BigIntX exponent)\n    {\n        if (value == null)\n            throw new ArgumentNullException(\"Value cannot be null\");\n        if (exponent == null)\n            throw new ArgumentNullException(\"Exponent cannot be null\");\n        if (exponent &lt; 0)\n            throw new ArgumentOutOfRangeException(\"Exponent\", \"Exponent cannot be negative\");\n        BigIntX result = 1;\n        while (exponent != 0)\n        {\n            if ((exponent &amp; 1) != 0)\n                result *= value;\n            exponent >>= 1;\n            value    *=  value;\n        }\n        return result;\n    }\n    public static BigIntX ModPow(BigIntX n, BigIntX e, BigInteger m)\n    {\n        var n1 = n;\n        var e1 = e;\n        var c  = 0;\n        if (e1 == 0)\n            return 1;\n        if (e1 == 1)\n            return n1 % m;\n        if (e1 == 2)\n            return n1 * n1 % m;\n        BigIntX r;\n        n1 %= m;\n        r  =  1;\n        if ((e1 &amp; 1) == 1)\n            r = n1;\n        while (e1 > 1)\n        {\n            c++;\n            e1 >>= 1;\n            n1 =   n1 * n1 % m;\n            if ((e1 &amp; 1) == 1)\n                r = r * n1 % m;\n        }\n        return r;\n    }\n    public static BigIntX Sqrt(BigIntX n)\n    {\n        var q = (BigIntX)1 &lt;&lt; ((int)Log(n, 2) >> 1);\n        var m = (BigIntX)0;\n        while (Abs(q - m) >= 1)\n        {\n            m = q;\n            q = (m + n \/ m) >> 1;\n        }\n        return q;\n    }\n    public static double Log(BigIntX value, double baseValue)\n    {\n        Array.Resize(ref value._digitsArray.Data, value._digitsArray.DataUsed);\n        var c          = 0.0;\n        var d          = 0.5;\n        var dataLength = Length(value._digitsArray.Data);\n        var topBits    = BitLengthOfUInt(value._digitsArray.Data[dataLength - 1]);\n        var bitLength  = (dataLength - 1) * 32 + topBits;\n        var bit        = (uint)(1 &lt;&lt; (topBits - 1));\n        for (var index = dataLength - 1; index >= 0; --index)\n        {\n            for (; bit != 0U; bit >>= 1)\n            {\n                if (((int)value._digitsArray.Data[index] &amp; (int)bit) != 0)\n                    c += d;\n                d *= 0.5;\n            }\n            bit = 2147483648U;\n        }\n        return (Math.Log(c) + 0.693147180559945 * bitLength) \/ Math.Log(baseValue);\n    }\n    private static int BitLengthOfUInt(uint x)\n    {\n        var numBits = 0;\n        while (x > 0)\n        {\n            x >>= 1;\n            numBits++;\n        }\n        return numBits;\n    }\n    private static int Length(uint[] rgu)\n    {\n        var length = rgu.Length;\n        return rgu[length - 1] != 0U ? length : length - 1;\n    }\n    public static List&lt;BigIntX> GetFactors(BigIntX n)\n    {\n        var Factors = new List&lt;BigIntX>();\n        var s       = Sqrt(n);\n        var a       = (BigIntX)3;\n        while (a &lt; s)\n        {\n            if (n % a == 0)\n            {\n                Factors.Add(a);\n                if (a * a != n)\n                    Factors.Add(n \/ a);\n            }\n            a += 2;\n        }\n        return Factors;\n    }\n    public static BigIntX Gcd(BigIntX a, BigIntX b)\n    {\n        while (b > 0)\n        {\n            var r = a % b;\n            a = b;\n            b = r;\n        }\n        return a;\n    }\n    public static BigIntX Lcm(BigIntX a, BigIntX b)\n    {\n        return a * b \/ a.Gcd(b);\n    }\n    public static int GetBitWidth(BigIntX value)\n    {\n        var bw = 1;\n        var v  = value;\n        while ((v >>= 1) > 0)\n            bw++;\n        if (bw &lt; 8)\n            bw = 8;\n        return bw;\n    }\n    public static BigIntX GetMaxValueBitWidth(int bitLength)\n    {\n        return ((BigIntX)1 &lt;&lt; bitLength) - 1;\n    }\n    public static BigIntX GetMaxValue(BigIntX value)\n    {\n        var bitLength = GetBitWidth(value);\n        return ((BigIntX)1 &lt;&lt; bitLength) - 1;\n    }\n    public static BigIntX Min(BigIntX left, BigIntX right)\n    {\n        if (left.CompareTo(right) &lt;= 0)\n            return left;\n        return right;\n    }\n    public static BigIntX Max(BigIntX left, BigIntX right)\n    {\n        if (left.CompareTo(right) &lt; 0)\n            return right;\n        return left;\n    }\n    public static double Log10(BigIntX value)\n    {\n        return Log(value, 10.0);\n    }\n    public static double LogN(BigIntX value)\n    {\n        return Log(value, 2.0);\n    }\n    private class BigIntXConverter : TypeConverter\n    {\n        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)\n        {\n            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);\n        }\n        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)\n        {\n            if (value != null)\n                if (TryParse($\"{value}\", out var i))\n                    return i;\n            return new BigIntX();\n        }\n        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)\n        {\n            return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);\n        }\n        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)\n        {\n            return destinationType == typeof(string) ? $\"{value}\" : base.ConvertTo(context, culture, value, destinationType);\n        }\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Variable Bit Width Big Unsigned or Signed Integer 32,64,128,256,512,1024,204,4096 Bit. (Experimental)<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[14,185],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/435"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=435"}],"version-history":[{"count":4,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/435\/revisions"}],"predecessor-version":[{"id":448,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/435\/revisions\/448"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=435"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=435"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=435"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}