BigInteger、Complex、大数运算

创建时间:
2015-01-02 13:42
最近更新:
2018-08-06 22:31

Keyword

  • round-trip: 往返

Resource

  1. 浅谈 BigInteger
  2. .NET 4.0 的 BigInteger 和 Complex 类

Resource - MSDN

截至 .NET Framework 4.5,该命名空间下仅以下两个成员。2018-08-05 已增加了一系列 "启用了 SIMD 的矢量类型 (SIMD-enabled vector types)":

  • System.Numerics.BigInteger.ToString() - public override string ToString(). 将当前 BigInteger 对象的数值转换为其等效的字符串表示形式。 返回值使用通用格式说明符 G 进行格式设置。 ToString() 方法支持 50 位十进制数字的精度。也就是说,如果 BigInteger 值中的数字位数超过 50,则只有 50 个最高有效位保留在输出字符串中; 所有其他数字都被替换为零。
  • System.Numerics.BigInteger.ToString(String) - public string ToString(string format). 使用指定的格式将当前 BigInteger 对象的数值转换为它的等效字符串表示形式。 如果 format 等于 String.Empty 或者为 null,则当前 BigInteger 对象的返回值用通用数值格式说明符 G 进行格式设置。 在大多数的情况下,ToString 方法支持 50 位十进制数字的精度。也就是说,如果 BigInteger 值中的数字位数超过 50,则只有 50 个最高有效位保留在输出字符串中; 所有其他数字都被替换为零。然而,BigInteger 支持 R 标准格式说明符,用于往返的数值。使用 R 格式字符串的 ToString(String) 方法返回的字符串保留整个 BigInteger 值,然后可以使用 Parse 或 TryParse 方法解析以恢复原始值而不会有任何数据损失。
  • System.Numerics.BigInteger.ToByteArray() - public byte[] ToByteArray(). 将 BigInteger 值转换为字节数组。 此方法返回的数组中的各个字节以 little-endian 的顺序呈现。也就是说,值的 低位字节 先于 高位字节。 该数组的第一个字节 反映了 BigInteger 值 的 第一个 8bit,第二个字节 反映了 下一个 8bit,依次类推。例如,值 1024 (0x0400) 被存储为以下两个字节的数组: [0x00, 0x40]TonyRemark: 因此,该数组的最后一个 byte 的 第一个 bit 是 BigInteger 的符号位。 因此 120 (bin: 0111 1000) 被表示为 单字节数组 [0x78]、然而 128 (bin: 1000 0000) 被表示为 双字节数组 [0x80, 0x00],注意 数组中的最后一个字节 0x00 只是为了表示这是一个正数。

Documentation - MSDN

以下内容整理自 System.Numerics.BigInteger 结构:

实例化 BigInteger 对象

实例化一个 BigInteger 对象,其值在现有数值类型之一的范围内:

  • 途径一: var bi = new BigInteger(Int32/Int64/UInt32/UInt64/Decimal/Double/Single);。注意: 浮点数的小数部分将会丢弃。
  • 途径二: 声明 BigInteger 变量并向其分配任意整数,例如 BigInteger bi = anyInteger;。因为 BigInteger 定义了这一类隐式转换。
  • 途径三: 声明 BigInteger 变量并向其分配任意浮点数 的 转换结果,例如 BigInteger bi = (BigInteger)anyFloatingPointNumber;。因为 BigInteger 定义了这一类显式转换。

实例化一个 BigInteger 对象,其值超出现有数值类型的范围:

  • 途径一: var bi = new BigInteger(Byte[]);
  • 途径二: 调用 Parse 或 TryParse 方法,将数值的字符串表示形式转换为 BigInteger。
  • 途径三: 调用 BigInteger 类的某些静态方法,这些方法对数值表达式执行某些操作并返回计算的 BigInteger 结果。例如 BigInteger bi = BigInteger.Pow(UInt64.MaxValue, 3);

Other

  • BigInteger 的未初始化值是 Zero
  • C# 为 BigInteger 重载了 标准数值运算符,因此可以像使用其他任何整型一样使用 BigInteger 实例: 执行基本数学运算、位运算、对两个 BigInteger 值进行比较。
  • C# 之外的某些语言 不支持自定义运算符,为此 BigInteger 结构还提供了用于执行数学运算的等效方法,例如 Add、Divide、Multiply、Negate、Subtract 等。在 C# 中仅当重载的运算符不能满足需要时才使用这些方法。
  • BigInteger 类定义了一些成员,对应着 System.Math 类的成员,提供类似的功能。
  • BigInteger 对象是不可变的,例如 bi++ 会创建新 BigInteger 对象。.NET Framework 中的其他数值类型也是不可变的。但是,因为 BigInteger 类型没有上限或下限,所以其值可以变得非常大,并对性能产生显著影响。

使用字节数组和十六进制字符串

BigInteger 结构期望字节 数组中的各个字节以 little-endian 的顺序呈现。也就是说,值的 低位字节 先于 高位字节。

通过调用 ToByteArray() 然后将得到的字节数组传递给 BigInteger(Byte[]) 构造函数,可以 往返 BigInteger 值。

要从 一个表示其他整型的值 的 字节数组 实例化 一个 BigInteger 值,可以传递 这个整型值给 BitConverter.GetBytes() 然后 将 结果字节数组 传递 给 BigInteger(Byte[]) 构造函数。

由于 BigInteger 结构 表示 没有固定长度的数值,因此 BigInteger(Byte[]) 构造函数 总是 将 入参数组 的 最后一个 byte 的 第一个 bit 解释为符号位。

为了防止 BigInteger(Byte[]) 构造函数 将 负值的补码表示 与 正值的符号和大小表示 混淆,正值 的 字节数组中最后一个字节 通常会被设置为 "一个值为 0 的额外字节"。该页面中的以下示例演示了该 "额外字节":

byte[] tempPosBytes = BitConverter.GetBytes(positiveNumber);
byte[] positiveBytes = new byte[tempPosBytes.Length + 1];
Array.Copy(tempPosBytes, positiveBytes, tempPosBytes.Length);
BigInteger positiveBigInt = new BigInteger(positiveBytes);

BigInteger(Byte[]) 构造函数 页面中的以下示例也演示了该 "额外字节":

ulong originalNumber = UInt64.MaxValue;
byte[] bytes = BitConverter.GetBytes(originalNumber);
if(originalNumber > 0 && (bytes[bytes.Length - 1] & 0x80) > 0) {
    byte[] temp = new byte[bytes.Length];
    Array.Copy(bytes, temp, bytes.Length);
    bytes = new byte[temp.Length + 1];
    Array.Copy(temp, bytes, temp.Length);
}

BigInteger newNumber = new BigInteger(bytes);
Console.WriteLine(
    "Converted the UInt64 value {0:N0} to {1:N0}.",
    originalNumber,
    newNumber
);
// The example displays the following output:
//Converted the UInt64 value 18,446,744,073,709,551,615 to 18,446,744,073,709,551,615.

ToByteArray() 从正值创建的字节数组包括此额外零值字节。因此,BigInteger 结构 可以成功往返。

但是,您可能需要 向 由开发人员动态创建的 或 由 将无符号整数转换为字节数组的方法 (如 BitConverter.GetBytes(UInt16)BitConverter.GetBytes(UInt32)BitConverter.GetBytes(UInt64)) 返回的 字节数组 添加此附加零值字节,

在分析十六进制字符串时,BigInteger.ToString()BigInteger.Parse() 可以往返 BigInteger 值。但是,通过调用其他整型的 ToString 方法创建的 十六进制字符串 或 包括 toBase 参数的 ToString 方法的重载 不指示值的符号 或 派生十六进制字符串的源数据类型。从这样的字符串成功实例化 BigInteger 值需要一些附加的逻辑。

常用代码

//返回的字符串保留整个 BigInteger 值,然后可以使用 Parse 或 TryParse 方法解析以恢复原始值而不会有任何数据损失:
string str = bi.ToString("R");
BigInteger bi = BigInteger.Parse(str);

//往返 BigInteger 值:
byte[] bytes = bi.ToByteArray();
var bi = new BigInteger(bytes);

//往返 BigInteger 值,设置 "一个值为 0 的额外字节":
byte[] tempPosBytes = BitConverter.GetBytes(UInt16/UInt32/UInt64);
byte[] positiveBytes = new byte[tempPosBytes.Length + 1];
Array.Copy(tempPosBytes, positiveBytes, tempPosBytes.Length);
BigInteger positiveBigInt = new BigInteger(positiveBytes);

//幂:
BigInteger bi = BigInteger.Pow(UInt64.MaxValue, 3);

Source Code of System.Numerics.BigInteger from JetBrains dotPeek 1.0 at 2018-08-05

Complete Copy:

// Type: System.Numerics.BigInteger
// Assembly: System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll

using System;
using System.Diagnostics;
using System.Globalization;

namespace System.Numerics
{
  [__DynamicallyInvokable]
  [Serializable]
  public struct BigInteger : IFormattable, IComparable, IComparable<BigInteger>, IEquatable<BigInteger>
  {
    private const int knMaskHighBit = -2147483648;
    private const uint kuMaskHighBit = 2147483648U;
    private const int kcbitUint = 32;
    private const int kcbitUlong = 64;
    private const int DecimalScaleFactorMask = 16711680;
    private const int DecimalSignMask = -2147483648;
    internal int _sign;
    internal uint[] _bits;
    private static readonly BigInteger s_bnMinInt;
    private static readonly BigInteger s_bnOneInt;
    private static readonly BigInteger s_bnZeroInt;
    private static readonly BigInteger s_bnMinusOneInt;

    [__DynamicallyInvokable]
    public static BigInteger Zero
    {
      [__DynamicallyInvokable] get
      {
        return BigInteger.s_bnZeroInt;
      }
    }

    [__DynamicallyInvokable]
    public static BigInteger One
    {
      [__DynamicallyInvokable] get
      {
        return BigInteger.s_bnOneInt;
      }
    }

    [__DynamicallyInvokable]
    public static BigInteger MinusOne
    {
      [__DynamicallyInvokable] get
      {
        return BigInteger.s_bnMinusOneInt;
      }
    }

    [__DynamicallyInvokable]
    public bool IsPowerOfTwo
    {
      [__DynamicallyInvokable] get
      {
        if (this._bits == null)
        {
          if ((this._sign & this._sign - 1) == 0)
            return (uint) this._sign > 0U;
          else
            return false;
        }
        else
        {
          if (this._sign != 1)
            return false;
          int index = BigInteger.Length(this._bits) - 1;
          if (((int) this._bits[index] & (int) this._bits[index] - 1) != 0)
            return false;
          while (--index >= 0)
          {
            if ((int) this._bits[index] != 0)
              return false;
          }
          return true;
        }
      }
    }

    [__DynamicallyInvokable]
    public bool IsZero
    {
      [__DynamicallyInvokable] get
      {
        return this._sign == 0;
      }
    }

    [__DynamicallyInvokable]
    public bool IsOne
    {
      [__DynamicallyInvokable] get
      {
        if (this._sign == 1)
          return this._bits == null;
        else
          return false;
      }
    }

    [__DynamicallyInvokable]
    public bool IsEven
    {
      [__DynamicallyInvokable] get
      {
        if (this._bits != null)
          return ((int) this._bits[0] & 1) == 0;
        else
          return (this._sign & 1) == 0;
      }
    }

    [__DynamicallyInvokable]
    public int Sign
    {
      [__DynamicallyInvokable] get
      {
        return (this._sign >> 31) - (-this._sign >> 31);
      }
    }

    internal int _Sign
    {
      get
      {
        return this._sign;
      }
    }

    internal uint[] _Bits
    {
      get
      {
        return this._bits;
      }
    }

    static BigInteger()
    {
      int n = -1;
      uint[] rgu = new uint[1];
      int index = 0;
      int num = int.MinValue;
      rgu[index] = (uint) num;
      BigInteger.s_bnMinInt = new BigInteger(n, rgu);
      BigInteger.s_bnOneInt = new BigInteger(1);
      BigInteger.s_bnZeroInt = new BigInteger(0);
      BigInteger.s_bnMinusOneInt = new BigInteger(-1);
    }

    [__DynamicallyInvokable]
    public BigInteger(int value)
    {
      if (value == int.MinValue)
      {
        this = BigInteger.s_bnMinInt;
      }
      else
      {
        this._sign = value;
        this._bits = (uint[]) null;
      }
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public BigInteger(uint value)
    {
      if (value <= (uint) int.MaxValue)
      {
        this._sign = (int) value;
        this._bits = (uint[]) null;
      }
      else
      {
        this._sign = 1;
        this._bits = new uint[1];
        this._bits[0] = value;
      }
    }

    [__DynamicallyInvokable]
    public BigInteger(long value)
    {
      if ((long) int.MinValue <= value && value <= (long) int.MaxValue)
      {
        if (value == (long) int.MinValue)
        {
          this = BigInteger.s_bnMinInt;
        }
        else
        {
          this._sign = (int) value;
          this._bits = (uint[]) null;
        }
      }
      else
      {
        ulong num;
        if (value < 0L)
        {
          num = (ulong) -value;
          this._sign = -1;
        }
        else
        {
          num = (ulong) value;
          this._sign = 1;
        }
        this._bits = new uint[2];
        this._bits[0] = (uint) num;
        this._bits[1] = (uint) (num >> 32);
      }
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public BigInteger(ulong value)
    {
      if (value <= (ulong) int.MaxValue)
      {
        this._sign = (int) value;
        this._bits = (uint[]) null;
      }
      else
      {
        this._sign = 1;
        this._bits = new uint[2];
        this._bits[0] = (uint) value;
        this._bits[1] = (uint) (value >> 32);
      }
    }

    [__DynamicallyInvokable]
    public BigInteger(float value)
    {
      if (float.IsInfinity(value))
        throw new OverflowException(SR.GetString("Overflow_BigIntInfinity"));
      if (float.IsNaN(value))
        throw new OverflowException(SR.GetString("Overflow_NotANumber"));
      this._sign = 0;
      this._bits = (uint[]) null;
      this.SetBitsFromDouble((double) value);
    }

    [__DynamicallyInvokable]
    public BigInteger(double value)
    {
      if (double.IsInfinity(value))
        throw new OverflowException(SR.GetString("Overflow_BigIntInfinity"));
      if (double.IsNaN(value))
        throw new OverflowException(SR.GetString("Overflow_NotANumber"));
      this._sign = 0;
      this._bits = (uint[]) null;
      this.SetBitsFromDouble(value);
    }

    [__DynamicallyInvokable]
    public BigInteger(Decimal value)
    {
      int[] bits = Decimal.GetBits(Decimal.Truncate(value));
      int length = 3;
      while (length > 0 && bits[length - 1] == 0)
        --length;
      if (length == 0)
        this = BigInteger.s_bnZeroInt;
      else if (length == 1 && bits[0] > 0)
      {
        this._sign = bits[0];
        this._sign = this._sign * ((bits[3] & int.MinValue) != 0 ? -1 : 1);
        this._bits = (uint[]) null;
      }
      else
      {
        this._bits = new uint[length];
        this._bits[0] = (uint) bits[0];
        if (length > 1)
          this._bits[1] = (uint) bits[1];
        if (length > 2)
          this._bits[2] = (uint) bits[2];
        this._sign = (bits[3] & int.MinValue) != 0 ? -1 : 1;
      }
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public BigInteger(byte[] value)
    {
      if (value == null)
        throw new ArgumentNullException("value");
      int length1 = value.Length;
      bool flag1 = length1 > 0 && ((int) value[length1 - 1] & 128) == 128;
      while (length1 > 0 && (int) value[length1 - 1] == 0)
        --length1;
      if (length1 == 0)
      {
        this._sign = 0;
        this._bits = (uint[]) null;
      }
      else if (length1 <= 4)
      {
        this._sign = !flag1 ? 0 : -1;
        for (int index = length1 - 1; index >= 0; --index)
        {
          this._sign = this._sign << 8;
          this._sign = this._sign | (int) value[index];
        }
        this._bits = (uint[]) null;
        if (this._sign < 0 && !flag1)
        {
          this._bits = new uint[1];
          this._bits[0] = (uint) this._sign;
          this._sign = 1;
        }
        if (this._sign != int.MinValue)
          return;
        this = BigInteger.s_bnMinInt;
      }
      else
      {
        int num = length1 % 4;
        int length2 = length1 / 4 + (num == 0 ? 0 : 1);
        bool flag2 = true;
        uint[] d = new uint[length2];
        int index1 = 3;
        int index2;
        for (index2 = 0; index2 < length2 - (num == 0 ? 0 : 1); ++index2)
        {
          for (int index3 = 0; index3 < 4; ++index3)
          {
            if ((int) value[index1] != 0)
              flag2 = false;
            d[index2] <<= 8;
            d[index2] |= (uint) value[index1];
            --index1;
          }
          index1 += 8;
        }
        if (num != 0)
        {
          if (flag1)
            d[length2 - 1] = uint.MaxValue;
          for (int index3 = length1 - 1; index3 >= length1 - num; --index3)
          {
            if ((int) value[index3] != 0)
              flag2 = false;
            d[index2] <<= 8;
            d[index2] |= (uint) value[index3];
          }
        }
        if (flag2)
          this = BigInteger.s_bnZeroInt;
        else if (flag1)
        {
          NumericsHelpers.DangerousMakeTwosComplement(d);
          int length3 = d.Length;
          while (length3 > 0 && (int) d[length3 - 1] == 0)
            --length3;
          if (length3 == 1 && (int) d[0] > 0)
          {
            if ((int) d[0] == 1)
              this = BigInteger.s_bnMinusOneInt;
            else if ((int) d[0] == int.MinValue)
            {
              this = BigInteger.s_bnMinInt;
            }
            else
            {
              this._sign = -1 * (int) d[0];
              this._bits = (uint[]) null;
            }
          }
          else if (length3 != d.Length)
          {
            this._sign = -1;
            this._bits = new uint[length3];
            Array.Copy((Array) d, (Array) this._bits, length3);
          }
          else
          {
            this._sign = -1;
            this._bits = d;
          }
        }
        else
        {
          this._sign = 1;
          this._bits = d;
        }
      }
    }

    internal BigInteger(int n, uint[] rgu)
    {
      this._sign = n;
      this._bits = rgu;
    }

    internal BigInteger(uint[] value, bool negative)
    {
      if (value == null)
        throw new ArgumentNullException("value");
      int length = value.Length;
      while (length > 0 && (int) value[length - 1] == 0)
        --length;
      if (length == 0)
        this = BigInteger.s_bnZeroInt;
      else if (length == 1 && value[0] < (uint) int.MinValue)
      {
        this._sign = negative ? -(int) value[0] : (int) value[0];
        this._bits = (uint[]) null;
        if (this._sign != int.MinValue)
          return;
        this = BigInteger.s_bnMinInt;
      }
      else
      {
        this._sign = negative ? -1 : 1;
        this._bits = new uint[length];
        Array.Copy((Array) value, (Array) this._bits, length);
      }
    }

    private BigInteger(uint[] value)
    {
      if (value == null)
        throw new ArgumentNullException("value");
      int length1 = value.Length;
      bool flag = length1 > 0 && ((int) value[length1 - 1] & int.MinValue) == int.MinValue;
      while (length1 > 0 && (int) value[length1 - 1] == 0)
        --length1;
      if (length1 == 0)
        this = BigInteger.s_bnZeroInt;
      else if (length1 == 1)
      {
        if ((int) value[0] < 0 && !flag)
        {
          this._bits = new uint[1];
          this._bits[0] = value[0];
          this._sign = 1;
        }
        else if (int.MinValue == (int) value[0])
        {
          this = BigInteger.s_bnMinInt;
        }
        else
        {
          this._sign = (int) value[0];
          this._bits = (uint[]) null;
        }
      }
      else if (!flag)
      {
        if (length1 != value.Length)
        {
          this._sign = 1;
          this._bits = new uint[length1];
          Array.Copy((Array) value, (Array) this._bits, length1);
        }
        else
        {
          this._sign = 1;
          this._bits = value;
        }
      }
      else
      {
        NumericsHelpers.DangerousMakeTwosComplement(value);
        int length2 = value.Length;
        while (length2 > 0 && (int) value[length2 - 1] == 0)
          --length2;
        if (length2 == 1 && (int) value[0] > 0)
        {
          if ((int) value[0] == 1)
            this = BigInteger.s_bnMinusOneInt;
          else if ((int) value[0] == int.MinValue)
          {
            this = BigInteger.s_bnMinInt;
          }
          else
          {
            this._sign = -1 * (int) value[0];
            this._bits = (uint[]) null;
          }
        }
        else if (length2 != value.Length)
        {
          this._sign = -1;
          this._bits = new uint[length2];
          Array.Copy((Array) value, (Array) this._bits, length2);
        }
        else
        {
          this._sign = -1;
          this._bits = value;
        }
      }
    }

    [__DynamicallyInvokable]
    public static implicit operator BigInteger(byte value)
    {
      return new BigInteger((int) value);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static implicit operator BigInteger(sbyte value)
    {
      return new BigInteger((int) value);
    }

    [__DynamicallyInvokable]
    public static implicit operator BigInteger(short value)
    {
      return new BigInteger((int) value);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static implicit operator BigInteger(ushort value)
    {
      return new BigInteger((int) value);
    }

    [__DynamicallyInvokable]
    public static implicit operator BigInteger(int value)
    {
      return new BigInteger(value);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static implicit operator BigInteger(uint value)
    {
      return new BigInteger(value);
    }

    [__DynamicallyInvokable]
    public static implicit operator BigInteger(long value)
    {
      return new BigInteger(value);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static implicit operator BigInteger(ulong value)
    {
      return new BigInteger(value);
    }

    [__DynamicallyInvokable]
    public static explicit operator BigInteger(float value)
    {
      return new BigInteger(value);
    }

    [__DynamicallyInvokable]
    public static explicit operator BigInteger(double value)
    {
      return new BigInteger(value);
    }

    [__DynamicallyInvokable]
    public static explicit operator BigInteger(Decimal value)
    {
      return new BigInteger(value);
    }

    [__DynamicallyInvokable]
    public static explicit operator byte(BigInteger value)
    {
      return checked ((byte) (int) value);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static explicit operator sbyte(BigInteger value)
    {
      return checked ((sbyte) (int) value);
    }

    [__DynamicallyInvokable]
    public static explicit operator short(BigInteger value)
    {
      return checked ((short) (int) value);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static explicit operator ushort(BigInteger value)
    {
      return checked ((ushort) (int) value);
    }

    [__DynamicallyInvokable]
    public static explicit operator int(BigInteger value)
    {
      if (value._bits == null)
        return value._sign;
      if (BigInteger.Length(value._bits) > 1)
        throw new OverflowException(SR.GetString("Overflow_Int32"));
      if (value._sign > 0)
        return checked ((int) value._bits[0]);
      if (value._bits[0] > (uint) int.MinValue)
        throw new OverflowException(SR.GetString("Overflow_Int32"));
      else
        return -(int) value._bits[0];
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static explicit operator uint(BigInteger value)
    {
      if (value._bits == null)
        return checked ((uint) value._sign);
      if (BigInteger.Length(value._bits) > 1 || value._sign < 0)
        throw new OverflowException(SR.GetString("Overflow_UInt32"));
      else
        return value._bits[0];
    }

    [__DynamicallyInvokable]
    public static explicit operator long(BigInteger value)
    {
      if (value._bits == null)
        return (long) value._sign;
      int num1 = BigInteger.Length(value._bits);
      int num2 = 2;
      if (num1 > num2)
        throw new OverflowException(SR.GetString("Overflow_Int64"));
      int num3 = 1;
      ulong num4 = num1 <= num3 ? (ulong) value._bits[0] : NumericsHelpers.MakeUlong(value._bits[1], value._bits[0]);
      long num5 = value._sign > 0 ? (long) num4 : -(long) num4;
      if (num5 > 0L && value._sign > 0 || num5 < 0L && value._sign < 0)
        return num5;
      else
        throw new OverflowException(SR.GetString("Overflow_Int64"));
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static explicit operator ulong(BigInteger value)
    {
      if (value._bits == null)
        return checked ((ulong) value._sign);
      int num1 = BigInteger.Length(value._bits);
      int num2 = 2;
      if (num1 > num2 || value._sign < 0)
        throw new OverflowException(SR.GetString("Overflow_UInt64"));
      int num3 = 1;
      if (num1 > num3)
        return NumericsHelpers.MakeUlong(value._bits[1], value._bits[0]);
      else
        return (ulong) value._bits[0];
    }

    [__DynamicallyInvokable]
    public static explicit operator float(BigInteger value)
    {
      return (float) (double) value;
    }

    [__DynamicallyInvokable]
    public static explicit operator double(BigInteger value)
    {
      if (value._bits == null)
        return (double) value._sign;
      int sign = 1;
      int exp;
      ulong man;
      new BigIntegerBuilder(value, ref sign).GetApproxParts(out exp, out man);
      return NumericsHelpers.GetDoubleFromParts(sign, exp, man);
    }

    [__DynamicallyInvokable]
    public static explicit operator Decimal(BigInteger value)
    {
      if (value._bits == null)
        return (Decimal) value._sign;
      int num1 = BigInteger.Length(value._bits);
      int num2 = 3;
      if (num1 > num2)
        throw new OverflowException(SR.GetString("Overflow_Decimal"));
      int lo = 0;
      int mid = 0;
      int hi = 0;
      int num3 = 2;
      if (num1 > num3)
        hi = (int) value._bits[2];
      int num4 = 1;
      if (num1 > num4)
        mid = (int) value._bits[1];
      int num5 = 0;
      if (num1 > num5)
        lo = (int) value._bits[0];
      return new Decimal(lo, mid, hi, value._sign < 0, (byte) 0);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator &(BigInteger left, BigInteger right)
    {
      if (left.IsZero || right.IsZero)
        return BigInteger.Zero;
      uint[] numArray1 = left.ToUInt32Array();
      uint[] numArray2 = right.ToUInt32Array();
      uint[] numArray3 = new uint[Math.Max(numArray1.Length, numArray2.Length)];
      uint num1 = left._sign < 0 ? uint.MaxValue : 0U;
      uint num2 = right._sign < 0 ? uint.MaxValue : 0U;
      for (int index = 0; index < numArray3.Length; ++index)
      {
        uint num3 = index < numArray1.Length ? numArray1[index] : num1;
        uint num4 = index < numArray2.Length ? numArray2[index] : num2;
        numArray3[index] = num3 & num4;
      }
      return new BigInteger(numArray3);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator |(BigInteger left, BigInteger right)
    {
      if (left.IsZero)
        return right;
      if (right.IsZero)
        return left;
      uint[] numArray1 = left.ToUInt32Array();
      uint[] numArray2 = right.ToUInt32Array();
      uint[] numArray3 = new uint[Math.Max(numArray1.Length, numArray2.Length)];
      uint num1 = left._sign < 0 ? uint.MaxValue : 0U;
      uint num2 = right._sign < 0 ? uint.MaxValue : 0U;
      for (int index = 0; index < numArray3.Length; ++index)
      {
        uint num3 = index < numArray1.Length ? numArray1[index] : num1;
        uint num4 = index < numArray2.Length ? numArray2[index] : num2;
        numArray3[index] = num3 | num4;
      }
      return new BigInteger(numArray3);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator ^(BigInteger left, BigInteger right)
    {
      uint[] numArray1 = left.ToUInt32Array();
      uint[] numArray2 = right.ToUInt32Array();
      uint[] numArray3 = new uint[Math.Max(numArray1.Length, numArray2.Length)];
      uint num1 = left._sign < 0 ? uint.MaxValue : 0U;
      uint num2 = right._sign < 0 ? uint.MaxValue : 0U;
      for (int index = 0; index < numArray3.Length; ++index)
      {
        uint num3 = index < numArray1.Length ? numArray1[index] : num1;
        uint num4 = index < numArray2.Length ? numArray2[index] : num2;
        numArray3[index] = num3 ^ num4;
      }
      return new BigInteger(numArray3);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator <<(BigInteger value, int shift)
    {
      if (shift == 0)
        return value;
      if (shift == int.MinValue)
        return value >> int.MaxValue >> 1;
      if (shift < 0)
        return value >> -shift;
      int num1 = shift / 32;
      int num2 = shift - num1 * 32;
      uint[] xd;
      int xl;
      bool forBitManipulation = BigInteger.GetPartsForBitManipulation(ref value, out xd, out xl);
      uint[] numArray = new uint[xl + num1 + 1];
      if (num2 == 0)
      {
        for (int index = 0; index < xl; ++index)
          numArray[index + num1] = xd[index];
      }
      else
      {
        int num3 = 32 - num2;
        uint num4 = 0U;
        int index;
        for (index = 0; index < xl; ++index)
        {
          uint num5 = xd[index];
          numArray[index + num1] = num5 << num2 | num4;
          num4 = num5 >> num3;
        }
        numArray[index + num1] = num4;
      }
      return new BigInteger(numArray, forBitManipulation);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator >>(BigInteger value, int shift)
    {
      if (shift == 0)
        return value;
      if (shift == int.MinValue)
        return value << int.MaxValue << 1;
      if (shift < 0)
        return value << -shift;
      int num1 = shift / 32;
      int num2 = shift - num1 * 32;
      uint[] xd;
      int xl;
      bool forBitManipulation = BigInteger.GetPartsForBitManipulation(ref value, out xd, out xl);
      if (forBitManipulation)
      {
        if (shift >= 32 * xl)
          return BigInteger.MinusOne;
        uint[] numArray = new uint[xl];
        Array.Copy((Array) xd, (Array) numArray, xl);
        xd = numArray;
        NumericsHelpers.DangerousMakeTwosComplement(xd);
      }
      int length = xl - num1;
      if (length < 0)
        length = 0;
      uint[] d = new uint[length];
      if (num2 == 0)
      {
        for (int index = xl - 1; index >= num1; --index)
          d[index - num1] = xd[index];
      }
      else
      {
        int num3 = 32 - num2;
        uint num4 = 0U;
        for (int index = xl - 1; index >= num1; --index)
        {
          uint num5 = xd[index];
          d[index - num1] = !forBitManipulation || index != xl - 1 ? num5 >> num2 | num4 : num5 >> num2 | (uint) (-1 << num3);
          num4 = num5 << num3;
        }
      }
      if (forBitManipulation)
        NumericsHelpers.DangerousMakeTwosComplement(d);
      return new BigInteger(d, forBitManipulation);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator ~(BigInteger value)
    {
      return -(value + BigInteger.One);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator -(BigInteger value)
    {
      // ISSUE: explicit reference operation
      // ISSUE: variable of a reference type
      BigInteger& local = @value;
      // ISSUE: explicit reference operation
      int num = -(^local)._sign;
      // ISSUE: explicit reference operation
      (^local)._sign = num;
      return value;
    }

    [__DynamicallyInvokable]
    public static BigInteger operator +(BigInteger value)
    {
      return value;
    }

    [__DynamicallyInvokable]
    public static BigInteger operator ++(BigInteger value)
    {
      return value + BigInteger.One;
    }

    [__DynamicallyInvokable]
    public static BigInteger operator --(BigInteger value)
    {
      return value - BigInteger.One;
    }

    [__DynamicallyInvokable]
    public static BigInteger operator +(BigInteger left, BigInteger right)
    {
      if (right.IsZero)
        return left;
      if (left.IsZero)
        return right;
      int sign1 = 1;
      int sign2 = 1;
      BigIntegerBuilder bigIntegerBuilder = new BigIntegerBuilder(left, ref sign1);
      BigIntegerBuilder reg = new BigIntegerBuilder(right, ref sign2);
      if (sign1 == sign2)
        bigIntegerBuilder.Add(ref reg);
      else
        bigIntegerBuilder.Sub(ref sign1, ref reg);
      return bigIntegerBuilder.GetInteger(sign1);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator -(BigInteger left, BigInteger right)
    {
      if (right.IsZero)
        return left;
      if (left.IsZero)
        return -right;
      int sign1 = 1;
      int sign2 = -1;
      BigIntegerBuilder bigIntegerBuilder = new BigIntegerBuilder(left, ref sign1);
      BigIntegerBuilder reg = new BigIntegerBuilder(right, ref sign2);
      if (sign1 == sign2)
        bigIntegerBuilder.Add(ref reg);
      else
        bigIntegerBuilder.Sub(ref sign1, ref reg);
      return bigIntegerBuilder.GetInteger(sign1);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator *(BigInteger left, BigInteger right)
    {
      int sign = 1;
      BigIntegerBuilder bigIntegerBuilder = new BigIntegerBuilder(left, ref sign);
      BigIntegerBuilder regMul = new BigIntegerBuilder(right, ref sign);
      bigIntegerBuilder.Mul(ref regMul);
      return bigIntegerBuilder.GetInteger(sign);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator /(BigInteger dividend, BigInteger divisor)
    {
      int sign = 1;
      BigIntegerBuilder bigIntegerBuilder = new BigIntegerBuilder(dividend, ref sign);
      BigIntegerBuilder regDen = new BigIntegerBuilder(divisor, ref sign);
      bigIntegerBuilder.Div(ref regDen);
      return bigIntegerBuilder.GetInteger(sign);
    }

    [__DynamicallyInvokable]
    public static BigInteger operator %(BigInteger dividend, BigInteger divisor)
    {
      int sign1 = 1;
      int sign2 = 1;
      BigIntegerBuilder bigIntegerBuilder = new BigIntegerBuilder(dividend, ref sign1);
      BigIntegerBuilder regDen = new BigIntegerBuilder(divisor, ref sign2);
      bigIntegerBuilder.Mod(ref regDen);
      return bigIntegerBuilder.GetInteger(sign1);
    }

    [__DynamicallyInvokable]
    public static bool operator <(BigInteger left, BigInteger right)
    {
      return left.CompareTo(right) < 0;
    }

    [__DynamicallyInvokable]
    public static bool operator <=(BigInteger left, BigInteger right)
    {
      return left.CompareTo(right) <= 0;
    }

    [__DynamicallyInvokable]
    public static bool operator >(BigInteger left, BigInteger right)
    {
      return left.CompareTo(right) > 0;
    }

    [__DynamicallyInvokable]
    public static bool operator >=(BigInteger left, BigInteger right)
    {
      return left.CompareTo(right) >= 0;
    }

    [__DynamicallyInvokable]
    public static bool operator ==(BigInteger left, BigInteger right)
    {
      return left.Equals(right);
    }

    [__DynamicallyInvokable]
    public static bool operator !=(BigInteger left, BigInteger right)
    {
      return !left.Equals(right);
    }

    [__DynamicallyInvokable]
    public static bool operator <(BigInteger left, long right)
    {
      return left.CompareTo(right) < 0;
    }

    [__DynamicallyInvokable]
    public static bool operator <=(BigInteger left, long right)
    {
      return left.CompareTo(right) <= 0;
    }

    [__DynamicallyInvokable]
    public static bool operator >(BigInteger left, long right)
    {
      return left.CompareTo(right) > 0;
    }

    [__DynamicallyInvokable]
    public static bool operator >=(BigInteger left, long right)
    {
      return left.CompareTo(right) >= 0;
    }

    [__DynamicallyInvokable]
    public static bool operator ==(BigInteger left, long right)
    {
      return left.Equals(right);
    }

    [__DynamicallyInvokable]
    public static bool operator !=(BigInteger left, long right)
    {
      return !left.Equals(right);
    }

    [__DynamicallyInvokable]
    public static bool operator <(long left, BigInteger right)
    {
      return right.CompareTo(left) > 0;
    }

    [__DynamicallyInvokable]
    public static bool operator <=(long left, BigInteger right)
    {
      return right.CompareTo(left) >= 0;
    }

    [__DynamicallyInvokable]
    public static bool operator >(long left, BigInteger right)
    {
      return right.CompareTo(left) < 0;
    }

    [__DynamicallyInvokable]
    public static bool operator >=(long left, BigInteger right)
    {
      return right.CompareTo(left) <= 0;
    }

    [__DynamicallyInvokable]
    public static bool operator ==(long left, BigInteger right)
    {
      return right.Equals(left);
    }

    [__DynamicallyInvokable]
    public static bool operator !=(long left, BigInteger right)
    {
      return !right.Equals(left);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator <(BigInteger left, ulong right)
    {
      return left.CompareTo(right) < 0;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator <=(BigInteger left, ulong right)
    {
      return left.CompareTo(right) <= 0;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator >(BigInteger left, ulong right)
    {
      return left.CompareTo(right) > 0;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator >=(BigInteger left, ulong right)
    {
      return left.CompareTo(right) >= 0;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator ==(BigInteger left, ulong right)
    {
      return left.Equals(right);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator !=(BigInteger left, ulong right)
    {
      return !left.Equals(right);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator <(ulong left, BigInteger right)
    {
      return right.CompareTo(left) > 0;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator <=(ulong left, BigInteger right)
    {
      return right.CompareTo(left) >= 0;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator >(ulong left, BigInteger right)
    {
      return right.CompareTo(left) < 0;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator >=(ulong left, BigInteger right)
    {
      return right.CompareTo(left) <= 0;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator ==(ulong left, BigInteger right)
    {
      return right.Equals(left);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public static bool operator !=(ulong left, BigInteger right)
    {
      return !right.Equals(left);
    }

    [Conditional("DEBUG")]
    private void AssertValid()
    {
      if (this._bits == null)
        return;
      BigInteger.Length(this._bits);
    }

    [__DynamicallyInvokable]
    public override bool Equals(object obj)
    {
      if (!(obj is BigInteger))
        return false;
      else
        return this.Equals((BigInteger) obj);
    }

    [__DynamicallyInvokable]
    public override int GetHashCode()
    {
      if (this._bits == null)
        return this._sign;
      int n1 = this._sign;
      int index = BigInteger.Length(this._bits);
      while (--index >= 0)
        n1 = NumericsHelpers.CombineHash(n1, (int) this._bits[index]);
      return n1;
    }

    [__DynamicallyInvokable]
    public bool Equals(long other)
    {
      if (this._bits == null)
        return (long) this._sign == other;
      int num1;
      if (((long) this._sign ^ other) < 0L || (num1 = BigInteger.Length(this._bits)) > 2)
        return false;
      ulong num2 = other < 0L ? (ulong) -other : (ulong) other;
      if (num1 == 1)
        return (long) this._bits[0] == (long) num2;
      else
        return (long) NumericsHelpers.MakeUlong(this._bits[1], this._bits[0]) == (long) num2;
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public bool Equals(ulong other)
    {
      if (this._sign < 0)
        return false;
      if (this._bits == null)
        return (long) this._sign == (long) other;
      int num = BigInteger.Length(this._bits);
      if (num > 2)
        return false;
      if (num == 1)
        return (long) this._bits[0] == (long) other;
      else
        return (long) NumericsHelpers.MakeUlong(this._bits[1], this._bits[0]) == (long) other;
    }

    [__DynamicallyInvokable]
    public bool Equals(BigInteger other)
    {
      if (this._sign != other._sign)
        return false;
      if (this._bits == other._bits)
        return true;
      if (this._bits == null || other._bits == null)
        return false;
      int cu = BigInteger.Length(this._bits);
      if (cu != BigInteger.Length(other._bits))
        return false;
      else
        return BigInteger.GetDiffLength(this._bits, other._bits, cu) == 0;
    }

    [__DynamicallyInvokable]
    public int CompareTo(long other)
    {
      if (this._bits == null)
        return ((long) this._sign).CompareTo(other);
      int num1;
      if (((long) this._sign ^ other) < 0L || (num1 = BigInteger.Length(this._bits)) > 2)
        return this._sign;
      ulong num2 = other < 0L ? (ulong) -other : (ulong) other;
      return this._sign * (num1 == 2 ? NumericsHelpers.MakeUlong(this._bits[1], this._bits[0]) : (ulong) this._bits[0]).CompareTo(num2);
    }

    [CLSCompliant(false)]
    [__DynamicallyInvokable]
    public int CompareTo(ulong other)
    {
      if (this._sign < 0)
        return -1;
      if (this._bits == null)
        return ((ulong) this._sign).CompareTo(other);
      int num = BigInteger.Length(this._bits);
      if (num > 2)
        return 1;
      else
        return (num == 2 ? NumericsHelpers.MakeUlong(this._bits[1], this._bits[0]) : (ulong) this._bits[0]).CompareTo(other);
    }

    [__DynamicallyInvokable]
    public int CompareTo(BigInteger other)
    {
      if ((this._sign ^ other._sign) < 0)
        return this._sign >= 0 ? 1 : -1;
      else if (this._bits == null)
      {
        if (other._bits != null)
          return -other._sign;
        if (this._sign < other._sign)
          return -1;
        return this._sign <= other._sign ? 0 : 1;
      }
      else
      {
        int cu;
        int num;
        if (other._bits == null || (cu = BigInteger.Length(this._bits)) > (num = BigInteger.Length(other._bits)))
          return this._sign;
        if (cu < num)
          return -this._sign;
        int diffLength = BigInteger.GetDiffLength(this._bits, other._bits, cu);
        if (diffLength == 0)
          return 0;
        if (this._bits[diffLength - 1] >= other._bits[diffLength - 1])
          return this._sign;
        else
          return -this._sign;
      }
    }

    public int CompareTo(object obj)
    {
      if (obj == null)
        return 1;
      if (!(obj is BigInteger))
        throw new ArgumentException(SR.GetString("Argument_MustBeBigInt"));
      else
        return this.CompareTo((BigInteger) obj);
    }

    [__DynamicallyInvokable]
    public byte[] ToByteArray()
    {
      if (this._bits == null && this._sign == 0)
        return new byte[1];
      uint[] d;
      byte num1;
      if (this._bits == null)
      {
        uint[] numArray = new uint[1];
        int index = 0;
        int num2 = this._sign;
        numArray[index] = (uint) num2;
        d = numArray;
        num1 = this._sign < 0 ? byte.MaxValue : (byte) 0;
      }
      else if (this._sign == -1)
      {
        d = (uint[]) this._bits.Clone();
        NumericsHelpers.DangerousMakeTwosComplement(d);
        num1 = byte.MaxValue;
      }
      else
      {
        d = this._bits;
        num1 = (byte) 0;
      }
      byte[] numArray1 = new byte[checked (4 * d.Length)];
      int num3 = 0;
      for (int index1 = 0; index1 < d.Length; ++index1)
      {
        uint num2 = d[index1];
        for (int index2 = 0; index2 < 4; ++index2)
        {
          numArray1[num3++] = (byte) (num2 & (uint) byte.MaxValue);
          num2 >>= 8;
        }
      }
      int index3 = numArray1.Length - 1;
      while (index3 > 0 && (int) numArray1[index3] == (int) num1)
        --index3;
      bool flag = ((int) numArray1[index3] & 128) != ((int) num1 & 128);
      byte[] numArray2 = new byte[index3 + 1 + (flag ? 1 : 0)];
      Array.Copy((Array) numArray1, (Array) numArray2, index3 + 1);
      if (flag)
      {
        byte[] numArray3 = numArray2;
        int index1 = numArray3.Length - 1;
        int num2 = (int) num1;
        numArray3[index1] = (byte) num2;
      }
      return numArray2;
    }

    private uint[] ToUInt32Array()
    {
      if (this._bits == null && this._sign == 0)
        return new uint[1];
      uint[] d;
      uint num1;
      if (this._bits == null)
      {
        uint[] numArray = new uint[1];
        int index = 0;
        int num2 = this._sign;
        numArray[index] = (uint) num2;
        d = numArray;
        num1 = this._sign < 0 ? uint.MaxValue : 0U;
      }
      else if (this._sign == -1)
      {
        d = (uint[]) this._bits.Clone();
        NumericsHelpers.DangerousMakeTwosComplement(d);
        num1 = uint.MaxValue;
      }
      else
      {
        d = this._bits;
        num1 = 0U;
      }
      int index1 = d.Length - 1;
      while (index1 > 0 && (int) d[index1] == (int) num1)
        --index1;
      bool flag = ((int) d[index1] & int.MinValue) != ((int) num1 & int.MinValue);
      uint[] numArray1 = new uint[index1 + 1 + (flag ? 1 : 0)];
      Array.Copy((Array) d, (Array) numArray1, index1 + 1);
      if (flag)
      {
        uint[] numArray2 = numArray1;
        int index2 = numArray2.Length - 1;
        int num2 = (int) num1;
        numArray2[index2] = (uint) num2;
      }
      return numArray1;
    }

    [__DynamicallyInvokable]
    public override string ToString()
    {
      return BigNumber.FormatBigInteger(this, (string) null, NumberFormatInfo.CurrentInfo);
    }

    [__DynamicallyInvokable]
    public string ToString(IFormatProvider provider)
    {
      return BigNumber.FormatBigInteger(this, (string) null, NumberFormatInfo.GetInstance(provider));
    }

    [__DynamicallyInvokable]
    public string ToString(string format)
    {
      return BigNumber.FormatBigInteger(this, format, NumberFormatInfo.CurrentInfo);
    }

    [__DynamicallyInvokable]
    public string ToString(string format, IFormatProvider provider)
    {
      return BigNumber.FormatBigInteger(this, format, NumberFormatInfo.GetInstance(provider));
    }

    [__DynamicallyInvokable]
    public static BigInteger Parse(string value)
    {
      return BigNumber.ParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
    }

    [__DynamicallyInvokable]
    public static BigInteger Parse(string value, NumberStyles style)
    {
      return BigNumber.ParseBigInteger(value, style, NumberFormatInfo.CurrentInfo);
    }

    [__DynamicallyInvokable]
    public static BigInteger Parse(string value, IFormatProvider provider)
    {
      return BigNumber.ParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
    }

    [__DynamicallyInvokable]
    public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider)
    {
      return BigNumber.ParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider));
    }

    [__DynamicallyInvokable]
    public static bool TryParse(string value, out BigInteger result)
    {
      return BigNumber.TryParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
    }

    [__DynamicallyInvokable]
    public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigInteger result)
    {
      return BigNumber.TryParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider), out result);
    }

    [__DynamicallyInvokable]
    public static int Compare(BigInteger left, BigInteger right)
    {
      return left.CompareTo(right);
    }

    [__DynamicallyInvokable]
    public static BigInteger Abs(BigInteger value)
    {
      if (!(value >= BigInteger.Zero))
        return -value;
      else
        return value;
    }

    [__DynamicallyInvokable]
    public static BigInteger Add(BigInteger left, BigInteger right)
    {
      return left + right;
    }

    [__DynamicallyInvokable]
    public static BigInteger Subtract(BigInteger left, BigInteger right)
    {
      return left - right;
    }

    [__DynamicallyInvokable]
    public static BigInteger Multiply(BigInteger left, BigInteger right)
    {
      return left * right;
    }

    [__DynamicallyInvokable]
    public static BigInteger Divide(BigInteger dividend, BigInteger divisor)
    {
      return dividend / divisor;
    }

    [__DynamicallyInvokable]
    public static BigInteger Remainder(BigInteger dividend, BigInteger divisor)
    {
      return dividend % divisor;
    }

    [__DynamicallyInvokable]
    public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)
    {
      int sign1 = 1;
      int sign2 = 1;
      BigIntegerBuilder bigIntegerBuilder = new BigIntegerBuilder(dividend, ref sign1);
      BigIntegerBuilder regDen = new BigIntegerBuilder(divisor, ref sign2);
      BigIntegerBuilder regQuo = new BigIntegerBuilder();
      bigIntegerBuilder.ModDiv(ref regDen, ref regQuo);
      remainder = bigIntegerBuilder.GetInteger(sign1);
      return regQuo.GetInteger(sign1 * sign2);
    }

    [__DynamicallyInvokable]
    public static BigInteger Negate(BigInteger value)
    {
      return -value;
    }

    [__DynamicallyInvokable]
    public static double Log(BigInteger value)
    {
      return BigInteger.Log(value, Math.E);
    }

    [__DynamicallyInvokable]
    public static double Log(BigInteger value, double baseValue)
    {
      if (value._sign < 0 || baseValue == 1.0)
        return double.NaN;
      if (baseValue == double.PositiveInfinity)
      {
        return !value.IsOne ? double.NaN : 0.0;
      }
      else
      {
        if (baseValue == 0.0 && !value.IsOne)
          return double.NaN;
        if (value._bits == null)
          return Math.Log((double) value._sign, baseValue);
        double d = 0.0;
        double num1 = 0.5;
        int num2 = BigInteger.Length(value._bits);
        int num3 = BigInteger.BitLengthOfUInt(value._bits[num2 - 1]);
        int num4 = (num2 - 1) * 32 + num3;
        uint num5 = (uint) (1 << num3 - 1);
        for (int index = num2 - 1; index >= 0; --index)
        {
          while ((int) num5 != 0)
          {
            if (((int) value._bits[index] & (int) num5) != 0)
              d += num1;
            num1 *= 0.5;
            num5 >>= 1;
          }
          num5 = (uint) int.MinValue;
        }
        return (Math.Log(d) + 0.693147180559945 * (double) num4) / Math.Log(baseValue);
      }
    }

    [__DynamicallyInvokable]
    public static double Log10(BigInteger value)
    {
      return BigInteger.Log(value, 10.0);
    }

    [__DynamicallyInvokable]
    public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right)
    {
      if (left._sign == 0)
        return BigInteger.Abs(right);
      if (right._sign == 0)
        return BigInteger.Abs(left);
      BigIntegerBuilder reg1 = new BigIntegerBuilder(left);
      BigIntegerBuilder reg2 = new BigIntegerBuilder(right);
      BigIntegerBuilder.GCD(ref reg1, ref reg2);
      return reg1.GetInteger(1);
    }

    [__DynamicallyInvokable]
    public static BigInteger Max(BigInteger left, BigInteger right)
    {
      if (left.CompareTo(right) < 0)
        return right;
      else
        return left;
    }

    [__DynamicallyInvokable]
    public static BigInteger Min(BigInteger left, BigInteger right)
    {
      if (left.CompareTo(right) <= 0)
        return left;
      else
        return right;
    }

    private static void ModPowUpdateResult(ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
    {
      NumericsHelpers.Swap<BigIntegerBuilder>(ref regRes, ref regTmp);
      regRes.Mul(ref regTmp, ref regVal);
      regRes.Mod(ref regMod);
    }

    private static void ModPowSquareModValue(ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
    {
      NumericsHelpers.Swap<BigIntegerBuilder>(ref regVal, ref regTmp);
      // ISSUE: explicit reference operation
      // ISSUE: variable of a reference type
      BigIntegerBuilder& local1 = @regVal;
      // ISSUE: explicit reference operation
      // ISSUE: variable of a reference type
      BigIntegerBuilder& local2 = @regTmp;
      // ISSUE: explicit reference operation
      (^local1).Mul(local2, local2);
      regVal.Mod(ref regMod);
    }

    private static void ModPowInner(uint exp, ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
    {
      while ((int) exp != 0)
      {
        if (((int) exp & 1) == 1)
          BigInteger.ModPowUpdateResult(ref regRes, ref regVal, ref regMod, ref regTmp);
        if ((int) exp == 1)
          break;
        BigInteger.ModPowSquareModValue(ref regVal, ref regMod, ref regTmp);
        exp >>= 1;
      }
    }

    private static void ModPowInner32(uint exp, ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
    {
      for (int index = 0; index < 32; ++index)
      {
        if (((int) exp & 1) == 1)
          BigInteger.ModPowUpdateResult(ref regRes, ref regVal, ref regMod, ref regTmp);
        BigInteger.ModPowSquareModValue(ref regVal, ref regMod, ref regTmp);
        exp >>= 1;
      }
    }

    [__DynamicallyInvokable]
    public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
    {
      if (exponent.Sign < 0)
        throw new ArgumentOutOfRangeException("exponent", SR.GetString("ArgumentOutOfRange_MustBeNonNeg"));
      int sign1 = 1;
      int sign2 = 1;
      int sign3 = 1;
      bool isEven = exponent.IsEven;
      BigIntegerBuilder regRes = new BigIntegerBuilder(BigInteger.One, ref sign1);
      BigIntegerBuilder regVal = new BigIntegerBuilder(value, ref sign2);
      BigIntegerBuilder bigIntegerBuilder = new BigIntegerBuilder(modulus, ref sign3);
      BigIntegerBuilder regTmp = new BigIntegerBuilder(regVal.Size);
      regRes.Mod(ref bigIntegerBuilder);
      if (exponent._bits == null)
      {
        BigInteger.ModPowInner((uint) exponent._sign, ref regRes, ref regVal, ref bigIntegerBuilder, ref regTmp);
      }
      else
      {
        int num = BigInteger.Length(exponent._bits);
        for (int index = 0; index < num - 1; ++index)
          BigInteger.ModPowInner32(exponent._bits[index], ref regRes, ref regVal, ref bigIntegerBuilder, ref regTmp);
        BigInteger.ModPowInner(exponent._bits[num - 1], ref regRes, ref regVal, ref bigIntegerBuilder, ref regTmp);
      }
      return regRes.GetInteger(value._sign > 0 ? 1 : (isEven ? 1 : -1));
    }

    [__DynamicallyInvokable]
    public static BigInteger Pow(BigInteger value, int exponent)
    {
      if (exponent < 0)
        throw new ArgumentOutOfRangeException("exponent", SR.GetString("ArgumentOutOfRange_MustBeNonNeg"));
      if (exponent == 0)
        return BigInteger.One;
      if (exponent == 1)
        return value;
      if (value._bits == null)
      {
        if (value._sign == 1)
          return value;
        if (value._sign == -1)
        {
          if ((exponent & 1) == 0)
            return (BigInteger) 1;
          else
            return value;
        }
        else if (value._sign == 0)
          return value;
      }
      int sign = 1;
      BigIntegerBuilder bigIntegerBuilder1 = new BigIntegerBuilder(value, ref sign);
      int size = bigIntegerBuilder1.Size;
      int cuRes1 = size;
      uint high = bigIntegerBuilder1.High;
      uint uHiRes1 = high + 1U;
      if ((int) uHiRes1 == 0)
      {
        ++cuRes1;
        uHiRes1 = 1U;
      }
      int cuRes2 = 1;
      int cuRes3 = 1;
      uint uHiRes2 = 1U;
      uint uHiRes3 = 1U;
      int num1 = exponent;
      while (true)
      {
        if ((num1 & 1) != 0)
        {
          BigInteger.MulUpper(ref uHiRes3, ref cuRes3, uHiRes1, cuRes1);
          BigInteger.MulLower(ref uHiRes2, ref cuRes2, high, size);
        }
        if ((num1 >>= 1) != 0)
        {
          BigInteger.MulUpper(ref uHiRes1, ref cuRes1, uHiRes1, cuRes1);
          BigInteger.MulLower(ref high, ref size, high, size);
        }
        else
          break;
      }
      if (cuRes3 > 1)
        bigIntegerBuilder1.EnsureWritable(cuRes3, 0);
      BigIntegerBuilder bigIntegerBuilder2 = new BigIntegerBuilder(cuRes3);
      BigIntegerBuilder a = new BigIntegerBuilder(cuRes3);
      a.Set(1U);
      if ((exponent & 1) == 0)
        sign = 1;
      int num2 = exponent;
      while (true)
      {
        if ((num2 & 1) != 0)
        {
          NumericsHelpers.Swap<BigIntegerBuilder>(ref a, ref bigIntegerBuilder2);
          a.Mul(ref bigIntegerBuilder1, ref bigIntegerBuilder2);
        }
        if ((num2 >>= 1) != 0)
        {
          NumericsHelpers.Swap<BigIntegerBuilder>(ref bigIntegerBuilder1, ref bigIntegerBuilder2);
          // ISSUE: explicit reference operation
          // ISSUE: variable of a reference type
          BigIntegerBuilder& local1 = @bigIntegerBuilder1;
          // ISSUE: explicit reference operation
          // ISSUE: variable of a reference type
          BigIntegerBuilder& local2 = @bigIntegerBuilder2;
          // ISSUE: explicit reference operation
          (^local1).Mul(local2, local2);
        }
        else
          break;
      }
      return a.GetInteger(sign);
    }

    private void SetBitsFromDouble(double value)
    {
      int sign;
      int exp;
      ulong man;
      bool fFinite;
      NumericsHelpers.GetDoubleParts(value, out sign, out exp, out man, out fFinite);
      if ((long) man == 0L)
        this = BigInteger.Zero;
      else if (exp <= 0)
      {
        if (exp <= -64)
        {
          this = BigInteger.Zero;
        }
        else
        {
          this = (BigInteger) (man >> -exp);
          if (sign >= 0)
            return;
          this._sign = -this._sign;
        }
      }
      else if (exp <= 11)
      {
        this = (BigInteger) (man << exp);
        if (sign >= 0)
          return;
        this._sign = -this._sign;
      }
      else
      {
        ulong num1 = man << 11;
        int num2 = exp - 11;
        int index = (num2 - 1) / 32 + 1;
        int num3 = index * 32 - num2;
        this._bits = new uint[index + 2];
        this._bits[index + 1] = (uint) (num1 >> num3 + 32);
        this._bits[index] = (uint) (num1 >> num3);
        if (num3 > 0)
          this._bits[index - 1] = (uint) num1 << 32 - num3;
        this._sign = sign;
      }
    }

    internal static int Length(uint[] rgu)
    {
      int length = rgu.Length;
      if ((int) rgu[length - 1] != 0)
        return length;
      else
        return length - 1;
    }

    internal static int BitLengthOfUInt(uint x)
    {
      int num = 0;
      while (x > 0U)
      {
        x >>= 1;
        ++num;
      }
      return num;
    }

    private static bool GetPartsForBitManipulation(ref BigInteger x, out uint[] xd, out int xl)
    {
      if (x._bits == null)
      {
        if (x._sign < 0)
        {
          // ISSUE: explicit reference operation
          // ISSUE: variable of a reference type
          uint[]& local = @xd;
          uint[] numArray = new uint[1];
          int index = 0;
          int num = -x._sign;
          numArray[index] = (uint) num;
          // ISSUE: explicit reference operation
          ^local = numArray;
        }
        else
        {
          // ISSUE: explicit reference operation
          // ISSUE: variable of a reference type
          uint[]& local = @xd;
          uint[] numArray = new uint[1];
          int index = 0;
          int num = x._sign;
          numArray[index] = (uint) num;
          // ISSUE: explicit reference operation
          ^local = numArray;
        }
      }
      else
        xd = x._bits;
      xl = x._bits == null ? 1 : x._bits.Length;
      return x._sign < 0;
    }

    private static void MulUpper(ref uint uHiRes, ref int cuRes, uint uHiMul, int cuMul)
    {
      ulong uu = (ulong) uHiRes * (ulong) uHiMul;
      uint num = NumericsHelpers.GetHi(uu);
      if ((int) num != 0)
      {
        if ((int) NumericsHelpers.GetLo(uu) != 0 && (int) ++num == 0)
        {
          num = 1U;
          ++cuRes;
        }
        uHiRes = num;
        cuRes += cuMul;
      }
      else
      {
        uHiRes = NumericsHelpers.GetLo(uu);
        cuRes += cuMul - 1;
      }
    }

    private static void MulLower(ref uint uHiRes, ref int cuRes, uint uHiMul, int cuMul)
    {
      ulong uu = (ulong) uHiRes * (ulong) uHiMul;
      uint hi = NumericsHelpers.GetHi(uu);
      if ((int) hi != 0)
      {
        uHiRes = hi;
        cuRes += cuMul;
      }
      else
      {
        uHiRes = NumericsHelpers.GetLo(uu);
        cuRes += cuMul - 1;
      }
    }

    internal static int GetDiffLength(uint[] rgu1, uint[] rgu2, int cu)
    {
      int index = cu;
      while (--index >= 0)
      {
        if ((int) rgu1[index] != (int) rgu2[index])
          return index + 1;
      }
      return 0;
    }
  }
}

Source Code of System.Numerics.BigIntegerBuilder from JetBrains dotPeek 1.0 at 2018-08-05

Complete Copy:

// Type: System.Numerics.BigIntegerBuilder
// Assembly: System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Numerics.dll

using System;
using System.Diagnostics;

namespace System.Numerics
{
  internal struct BigIntegerBuilder
  {
    private static readonly double kdblLn2To32 = 32.0 * Math.Log(2.0);
    private static readonly byte[] _rgbInv = new byte[128]
    {
      (byte) 1,
      (byte) 171,
      (byte) 205,
      (byte) 183,
      (byte) 57,
      (byte) 163,
      (byte) 197,
      (byte) 239,
      (byte) 241,
      (byte) 27,
      (byte) 61,
      (byte) 167,
      (byte) 41,
      (byte) 19,
      (byte) 53,
      (byte) 223,
      (byte) 225,
      (byte) 139,
      (byte) 173,
      (byte) 151,
      (byte) 25,
      (byte) 131,
      (byte) 165,
      (byte) 207,
      (byte) 209,
      (byte) 251,
      (byte) 29,
      (byte) 135,
      (byte) 9,
      (byte) 243,
      (byte) 21,
      (byte) 191,
      (byte) 193,
      (byte) 107,
      (byte) 141,
      (byte) 119,
      (byte) 249,
      (byte) 99,
      (byte) 133,
      (byte) 175,
      (byte) 177,
      (byte) 219,
      (byte) 253,
      (byte) 103,
      (byte) 233,
      (byte) 211,
      (byte) 245,
      (byte) 159,
      (byte) 161,
      (byte) 75,
      (byte) 109,
      (byte) 87,
      (byte) 217,
      (byte) 67,
      (byte) 101,
      (byte) 143,
      (byte) 145,
      (byte) 187,
      (byte) 221,
      (byte) 71,
      (byte) 201,
      (byte) 179,
      (byte) 213,
      (byte) 127,
      (byte) 129,
      (byte) 43,
      (byte) 77,
      (byte) 55,
      (byte) 185,
      (byte) 35,
      (byte) 69,
      (byte) 111,
      (byte) 113,
      (byte) 155,
      (byte) 189,
      (byte) 39,
      (byte) 169,
      (byte) 147,
      (byte) 181,
      (byte) 95,
      (byte) 97,
      (byte) 11,
      (byte) 45,
      (byte) 23,
      (byte) 153,
      (byte) 3,
      (byte) 37,
      (byte) 79,
      (byte) 81,
      (byte) 123,
      (byte) 157,
      (byte) 7,
      (byte) 137,
      (byte) 115,
      (byte) 149,
      (byte) 63,
      (byte) 65,
      (byte) 235,
      (byte) 13,
      (byte) 247,
      (byte) 121,
      (byte) 227,
      (byte) 5,
      (byte) 47,
      (byte) 49,
      (byte) 91,
      (byte) 125,
      (byte) 231,
      (byte) 105,
      (byte) 83,
      (byte) 117,
      (byte) 31,
      (byte) 33,
      (byte) 203,
      (byte) 237,
      (byte) 215,
      (byte) 89,
      (byte) 195,
      (byte) 229,
      (byte) 15,
      (byte) 17,
      (byte) 59,
      (byte) 93,
      (byte) 199,
      (byte) 73,
      (byte) 51,
      (byte) 85,
      byte.MaxValue
    };
    private const int kcbitUint = 32;
    private int _iuLast;
    private uint _uSmall;
    private uint[] _rgu;
    private bool _fWritable;

    public int Size
    {
      get
      {
        return this._iuLast + 1;
      }
    }

    public uint High
    {
      get
      {
        if (this._iuLast != 0)
          return this._rgu[this._iuLast];
        else
          return this._uSmall;
      }
    }

    private int CuNonZero
    {
      get
      {
        int num = 0;
        for (int index = this._iuLast; index >= 0; --index)
        {
          if ((int) this._rgu[index] != 0)
            ++num;
        }
        return num;
      }
    }

    static BigIntegerBuilder()
    {
    }

    public BigIntegerBuilder(ref BigIntegerBuilder reg)
    {
      this = reg;
      if (!this._fWritable)
        return;
      this._fWritable = false;
      if (this._iuLast == 0)
        this._rgu = (uint[]) null;
      else
        reg._fWritable = false;
    }

    public BigIntegerBuilder(int cuAlloc)
    {
      this._iuLast = 0;
      this._uSmall = 0U;
      if (cuAlloc > 1)
      {
        this._rgu = new uint[cuAlloc];
        this._fWritable = true;
      }
      else
      {
        this._rgu = (uint[]) null;
        this._fWritable = false;
      }
    }

    public BigIntegerBuilder(BigInteger bn)
    {
      this._fWritable = false;
      this._rgu = bn._Bits;
      if (this._rgu == null)
      {
        this._iuLast = 0;
        this._uSmall = NumericsHelpers.Abs(bn._Sign);
      }
      else
      {
        this._iuLast = this._rgu.Length - 1;
        this._uSmall = this._rgu[0];
        while (this._iuLast > 0 && (int) this._rgu[this._iuLast] == 0)
          this._iuLast = this._iuLast - 1;
      }
    }

    public BigIntegerBuilder(BigInteger bn, ref int sign)
    {
      this._fWritable = false;
      this._rgu = bn._Bits;
      int sign1 = bn._Sign;
      int num1 = sign1 >> 31;
      // ISSUE: explicit reference operation
      // ISSUE: variable of a reference type
      int& local = @sign;
      // ISSUE: explicit reference operation
      int num2 = (^local ^ num1) - num1;
      // ISSUE: explicit reference operation
      ^local = num2;
      if (this._rgu == null)
      {
        this._iuLast = 0;
        this._uSmall = (uint) ((sign1 ^ num1) - num1);
      }
      else
      {
        this._iuLast = this._rgu.Length - 1;
        this._uSmall = this._rgu[0];
        while (this._iuLast > 0 && (int) this._rgu[this._iuLast] == 0)
          this._iuLast = this._iuLast - 1;
      }
    }

    [Conditional("DEBUG")]
    private void AssertValid(bool fTrimmed)
    {
      int num = this._iuLast;
    }

    public BigInteger GetInteger(int sign)
    {
      uint[] bits;
      this.GetIntegerParts(sign, out sign, out bits);
      return new BigInteger(sign, bits);
    }

    internal void GetIntegerParts(int signSrc, out int sign, out uint[] bits)
    {
      if (this._iuLast == 0)
      {
        if (this._uSmall <= (uint) int.MaxValue)
        {
          sign = signSrc * (int) this._uSmall;
          bits = (uint[]) null;
          return;
        }
        else if (this._rgu == null)
        {
          // ISSUE: explicit reference operation
          // ISSUE: variable of a reference type
          BigIntegerBuilder& local = @this;
          uint[] numArray = new uint[1];
          int index = 0;
          int num = (int) this._uSmall;
          numArray[index] = (uint) num;
          // ISSUE: explicit reference operation
          (^local)._rgu = numArray;
        }
        else if (this._fWritable)
          this._rgu[0] = this._uSmall;
        else if ((int) this._rgu[0] != (int) this._uSmall)
        {
          // ISSUE: explicit reference operation
          // ISSUE: variable of a reference type
          BigIntegerBuilder& local = @this;
          uint[] numArray = new uint[1];
          int index = 0;
          int num = (int) this._uSmall;
          numArray[index] = (uint) num;
          // ISSUE: explicit reference operation
          (^local)._rgu = numArray;
        }
      }
      sign = signSrc;
      int num1 = this._rgu.Length - this._iuLast - 1;
      if (num1 <= 1)
      {
        if (num1 == 0 || (int) this._rgu[this._iuLast + 1] == 0)
        {
          this._fWritable = false;
          bits = this._rgu;
          return;
        }
        else if (this._fWritable)
        {
          this._rgu[this._iuLast + 1] = 0U;
          this._fWritable = false;
          bits = this._rgu;
          return;
        }
      }
      bits = this._rgu;
      Array.Resize<uint>(ref bits, this._iuLast + 1);
      if (this._fWritable)
        return;
      this._rgu = bits;
    }

    public void Set(uint u)
    {
      this._uSmall = u;
      this._iuLast = 0;
    }

    public void Set(ulong uu)
    {
      uint hi = NumericsHelpers.GetHi(uu);
      if ((int) hi == 0)
      {
        this._uSmall = NumericsHelpers.GetLo(uu);
        this._iuLast = 0;
      }
      else
      {
        this.SetSizeLazy(2);
        this._rgu[0] = (uint) uu;
        this._rgu[1] = hi;
      }
    }

    public void GetApproxParts(out int exp, out ulong man)
    {
      if (this._iuLast == 0)
      {
        man = (ulong) this._uSmall;
        exp = 0;
      }
      else
      {
        int index = this._iuLast - 1;
        man = NumericsHelpers.MakeUlong(this._rgu[index + 1], this._rgu[index]);
        exp = index * 32;
        int num1;
        if (index <= 0 || (num1 = NumericsHelpers.CbitHighZero(this._rgu[index + 1])) <= 0)
          return;
        // ISSUE: explicit reference operation
        // ISSUE: variable of a reference type
        ulong& local = @man;
        // ISSUE: explicit reference operation
        long num2 = (long) ^local << num1 | (long) (this._rgu[index - 1] >> 32 - num1);
        // ISSUE: explicit reference operation
        ^local = (ulong) num2;
        exp -= num1;
      }
    }

    private void Trim()
    {
      if (this._iuLast <= 0 || (int) this._rgu[this._iuLast] != 0)
        return;
      this._uSmall = this._rgu[0];
      int num1;
      do
      {
        // ISSUE: explicit reference operation
        // ISSUE: variable of a reference type
        BigIntegerBuilder& local = @this;
        num1 = this._iuLast - 1;
        int num2 = num1;
        // ISSUE: explicit reference operation
        (^local)._iuLast = num2;
      }
      while (num1 > 0 && (int) this._rgu[this._iuLast] == 0);
    }

    private void SetSizeLazy(int cu)
    {
      if (cu <= 1)
      {
        this._iuLast = 0;
      }
      else
      {
        if (!this._fWritable || this._rgu.Length < cu)
        {
          this._rgu = new uint[cu];
          this._fWritable = true;
        }
        this._iuLast = cu - 1;
      }
    }

    private void SetSizeClear(int cu)
    {
      if (cu <= 1)
      {
        this._iuLast = 0;
        this._uSmall = 0U;
      }
      else
      {
        if (!this._fWritable || this._rgu.Length < cu)
        {
          this._rgu = new uint[cu];
          this._fWritable = true;
        }
        else
          Array.Clear((Array) this._rgu, 0, cu);
        this._iuLast = cu - 1;
      }
    }

    private void SetSizeKeep(int cu, int cuExtra)
    {
      if (cu <= 1)
      {
        if (this._iuLast > 0)
          this._uSmall = this._rgu[0];
        this._iuLast = 0;
      }
      else
      {
        if (!this._fWritable || this._rgu.Length < cu)
        {
          uint[] numArray = new uint[cu + cuExtra];
          if (this._iuLast == 0)
            numArray[0] = this._uSmall;
          else
            Array.Copy((Array) this._rgu, (Array) numArray, Math.Min(cu, this._iuLast + 1));
          this._rgu = numArray;
          this._fWritable = true;
        }
        else if (this._iuLast + 1 < cu)
        {
          Array.Clear((Array) this._rgu, this._iuLast + 1, cu - this._iuLast - 1);
          if (this._iuLast == 0)
            this._rgu[0] = this._uSmall;
        }
        this._iuLast = cu - 1;
      }
    }

    public void EnsureWritable(int cu, int cuExtra)
    {
      if (this._fWritable && this._rgu.Length >= cu)
        return;
      uint[] numArray = new uint[cu + cuExtra];
      if (this._iuLast > 0)
      {
        if (this._iuLast >= cu)
          this._iuLast = cu - 1;
        Array.Copy((Array) this._rgu, (Array) numArray, this._iuLast + 1);
      }
      this._rgu = numArray;
      this._fWritable = true;
    }

    public void EnsureWritable(int cuExtra)
    {
      if (this._fWritable)
        return;
      uint[] numArray = new uint[this._iuLast + 1 + cuExtra];
      Array.Copy((Array) this._rgu, (Array) numArray, this._iuLast + 1);
      this._rgu = numArray;
      this._fWritable = true;
    }

    public void EnsureWritable()
    {
      this.EnsureWritable(0);
    }

    public void Load(ref BigIntegerBuilder reg)
    {
      this.Load(ref reg, 0);
    }

    public void Load(ref BigIntegerBuilder reg, int cuExtra)
    {
      if (reg._iuLast == 0)
      {
        this._uSmall = reg._uSmall;
        this._iuLast = 0;
      }
      else
      {
        if (!this._fWritable || this._rgu.Length <= reg._iuLast)
        {
          this._rgu = new uint[reg._iuLast + 1 + cuExtra];
          this._fWritable = true;
        }
        this._iuLast = reg._iuLast;
        Array.Copy((Array) reg._rgu, (Array) this._rgu, this._iuLast + 1);
      }
    }

    public void Add(uint u)
    {
      if (this._iuLast == 0)
      {
        if ((this._uSmall = this._uSmall + u) >= u)
          return;
        this.SetSizeLazy(2);
        this._rgu[0] = this._uSmall;
        this._rgu[1] = 1U;
      }
      else
      {
        if ((int) u == 0)
          return;
        uint num = this._rgu[0] + u;
        if (num < u)
        {
          this.EnsureWritable(1);
          this.ApplyCarry(1);
        }
        else if (!this._fWritable)
          this.EnsureWritable();
        this._rgu[0] = num;
      }
    }

    public void Add(ref BigIntegerBuilder reg)
    {
      if (reg._iuLast == 0)
        this.Add(reg._uSmall);
      else if (this._iuLast == 0)
      {
        uint u = this._uSmall;
        if ((int) u == 0)
        {
          this = new BigIntegerBuilder(ref reg);
        }
        else
        {
          this.Load(ref reg, 1);
          this.Add(u);
        }
      }
      else
      {
        this.EnsureWritable(Math.Max(this._iuLast, reg._iuLast) + 1, 1);
        int iu = reg._iuLast + 1;
        if (this._iuLast < reg._iuLast)
        {
          iu = this._iuLast + 1;
          Array.Copy((Array) reg._rgu, this._iuLast + 1, (Array) this._rgu, this._iuLast + 1, reg._iuLast - this._iuLast);
          this._iuLast = reg._iuLast;
        }
        uint uCarry = 0U;
        for (int index = 0; index < iu; ++index)
          uCarry = BigIntegerBuilder.AddCarry(ref this._rgu[index], reg._rgu[index], uCarry);
        if ((int) uCarry == 0)
          return;
        this.ApplyCarry(iu);
      }
    }

    public void Sub(ref int sign, uint u)
    {
      if (this._iuLast == 0)
      {
        if (u <= this._uSmall)
        {
          this._uSmall = this._uSmall - u;
        }
        else
        {
          this._uSmall = u - this._uSmall;
          // ISSUE: explicit reference operation
          // ISSUE: variable of a reference type
          int& local = @sign;
          // ISSUE: explicit reference operation
          int num = -^local;
          // ISSUE: explicit reference operation
          ^local = num;
        }
      }
      else
      {
        if ((int) u == 0)
          return;
        this.EnsureWritable();
        uint num = this._rgu[0];
        this._rgu[0] = num - u;
        if (num >= u)
          return;
        this.ApplyBorrow(1);
        this.Trim();
      }
    }

    public void Sub(ref int sign, ref BigIntegerBuilder reg)
    {
      if (reg._iuLast == 0)
        this.Sub(ref sign, reg._uSmall);
      else if (this._iuLast == 0)
      {
        uint u = this._uSmall;
        if ((int) u == 0)
        {
          this = new BigIntegerBuilder(ref reg);
        }
        else
        {
          this.Load(ref reg);
          this.Sub(ref sign, u);
        }
        // ISSUE: explicit reference operation
        // ISSUE: variable of a reference type
        int& local = @sign;
        // ISSUE: explicit reference operation
        int num = -^local;
        // ISSUE: explicit reference operation
        ^local = num;
      }
      else if (this._iuLast < reg._iuLast)
      {
        this.SubRev(ref reg);
        // ISSUE: explicit reference operation
        // ISSUE: variable of a reference type
        int& local = @sign;
        // ISSUE: explicit reference operation
        int num = -^local;
        // ISSUE: explicit reference operation
        ^local = num;
      }
      else
      {
        int iuMin = reg._iuLast + 1;
        if (this._iuLast == reg._iuLast)
        {
          this._iuLast = BigInteger.GetDiffLength(this._rgu, reg._rgu, this._iuLast + 1) - 1;
          if (this._iuLast < 0)
          {
            this._iuLast = 0;
            this._uSmall = 0U;
            return;
          }
          else
          {
            uint num1 = this._rgu[this._iuLast];
            uint num2 = reg._rgu[this._iuLast];
            if (this._iuLast == 0)
            {
              if (num1 < num2)
              {
                this._uSmall = num2 - num1;
                // ISSUE: explicit reference operation
                // ISSUE: variable of a reference type
                int& local = @sign;
                // ISSUE: explicit reference operation
                int num3 = -^local;
                // ISSUE: explicit reference operation
                ^local = num3;
                return;
              }
              else
              {
                this._uSmall = num1 - num2;
                return;
              }
            }
            else if (num1 < num2)
            {
              reg._iuLast = this._iuLast;
              this.SubRev(ref reg);
              reg._iuLast = iuMin - 1;
              // ISSUE: explicit reference operation
              // ISSUE: variable of a reference type
              int& local = @sign;
              // ISSUE: explicit reference operation
              int num3 = -^local;
              // ISSUE: explicit reference operation
              ^local = num3;
              return;
            }
            else
              iuMin = this._iuLast + 1;
          }
        }
        this.EnsureWritable();
        uint uBorrow = 0U;
        for (int index = 0; index < iuMin; ++index)
          uBorrow = BigIntegerBuilder.SubBorrow(ref this._rgu[index], reg._rgu[index], uBorrow);
        if ((int) uBorrow != 0)
          this.ApplyBorrow(iuMin);
        this.Trim();
      }
    }

    private void SubRev(ref BigIntegerBuilder reg)
    {
      this.EnsureWritable(reg._iuLast + 1, 0);
      int iuMin = this._iuLast + 1;
      if (this._iuLast < reg._iuLast)
      {
        Array.Copy((Array) reg._rgu, this._iuLast + 1, (Array) this._rgu, this._iuLast + 1, reg._iuLast - this._iuLast);
        this._iuLast = reg._iuLast;
      }
      uint uBorrow = 0U;
      for (int index = 0; index < iuMin; ++index)
        uBorrow = BigIntegerBuilder.SubRevBorrow(ref this._rgu[index], reg._rgu[index], uBorrow);
      if ((int) uBorrow != 0)
        this.ApplyBorrow(iuMin);
      this.Trim();
    }

    public void Mul(uint u)
    {
      if ((int) u == 0)
      {
        this.Set(0U);
      }
      else
      {
        if ((int) u == 1)
          return;
        if (this._iuLast == 0)
        {
          this.Set((ulong) this._uSmall * (ulong) u);
        }
        else
        {
          this.EnsureWritable(1);
          uint uCarry = 0U;
          for (int index = 0; index <= this._iuLast; ++index)
            uCarry = BigIntegerBuilder.MulCarry(ref this._rgu[index], u, uCarry);
          if ((int) uCarry == 0)
            return;
          this.SetSizeKeep(this._iuLast + 2, 0);
          this._rgu[this._iuLast] = uCarry;
        }
      }
    }

    public void Mul(ref BigIntegerBuilder regMul)
    {
      if (regMul._iuLast == 0)
        this.Mul(regMul._uSmall);
      else if (this._iuLast == 0)
      {
        uint u = this._uSmall;
        switch (u)
        {
          case 1U:
            this = new BigIntegerBuilder(ref regMul);
            break;
          case 0U:
            break;
          default:
            this.Load(ref regMul, 1);
            this.Mul(u);
            break;
        }
      }
      else
      {
        int num = this._iuLast + 1;
        this.SetSizeKeep(num + regMul._iuLast, 1);
        int index1 = num;
        while (--index1 >= 0)
        {
          uint uMul2 = this._rgu[index1];
          this._rgu[index1] = 0U;
          uint uCarry = 0U;
          for (int index2 = 0; index2 <= regMul._iuLast; ++index2)
            uCarry = BigIntegerBuilder.AddMulCarry(ref this._rgu[index1 + index2], regMul._rgu[index2], uMul2, uCarry);
          if ((int) uCarry != 0)
          {
            for (int index2 = index1 + regMul._iuLast + 1; (int) uCarry != 0 && index2 <= this._iuLast; ++index2)
              uCarry = BigIntegerBuilder.AddCarry(ref this._rgu[index2], 0U, uCarry);
            if ((int) uCarry != 0)
            {
              this.SetSizeKeep(this._iuLast + 2, 0);
              this._rgu[this._iuLast] = uCarry;
            }
          }
        }
      }
    }

    public void Mul(ref BigIntegerBuilder reg1, ref BigIntegerBuilder reg2)
    {
      if (reg1._iuLast == 0)
      {
        if (reg2._iuLast == 0)
        {
          this.Set((ulong) reg1._uSmall * (ulong) reg2._uSmall);
        }
        else
        {
          this.Load(ref reg2, 1);
          this.Mul(reg1._uSmall);
        }
      }
      else if (reg2._iuLast == 0)
      {
        this.Load(ref reg1, 1);
        this.Mul(reg2._uSmall);
      }
      else
      {
        this.SetSizeClear(reg1._iuLast + reg2._iuLast + 2);
        uint[] numArray1;
        int num1;
        uint[] numArray2;
        int num2;
        if (reg1.CuNonZero <= reg2.CuNonZero)
        {
          numArray1 = reg1._rgu;
          num1 = reg1._iuLast + 1;
          numArray2 = reg2._rgu;
          num2 = reg2._iuLast + 1;
        }
        else
        {
          numArray1 = reg2._rgu;
          num1 = reg2._iuLast + 1;
          numArray2 = reg1._rgu;
          num2 = reg1._iuLast + 1;
        }
        for (int index1 = 0; index1 < num1; ++index1)
        {
          uint uMul1 = numArray1[index1];
          if ((int) uMul1 != 0)
          {
            uint uCarry = 0U;
            int index2 = index1;
            int index3 = 0;
            while (index3 < num2)
            {
              uCarry = BigIntegerBuilder.AddMulCarry(ref this._rgu[index2], uMul1, numArray2[index3], uCarry);
              ++index3;
              ++index2;
            }
            while ((int) uCarry != 0)
              uCarry = BigIntegerBuilder.AddCarry(ref this._rgu[index2++], 0U, uCarry);
          }
        }
        this.Trim();
      }
    }

    public uint DivMod(uint uDen)
    {
      if ((int) uDen == 1)
        return 0U;
      if (this._iuLast == 0)
      {
        uint num = this._uSmall;
        this._uSmall = num / uDen;
        return num % uDen;
      }
      else
      {
        this.EnsureWritable();
        ulong num1 = 0UL;
        for (int index = this._iuLast; index >= 0; --index)
        {
          ulong num2 = NumericsHelpers.MakeUlong((uint) num1, this._rgu[index]);
          this._rgu[index] = (uint) (num2 / (ulong) uDen);
          num1 = num2 % (ulong) uDen;
        }
        this.Trim();
        return (uint) num1;
      }
    }

    public static uint Mod(ref BigIntegerBuilder regNum, uint uDen)
    {
      if ((int) uDen == 1)
        return 0U;
      if (regNum._iuLast == 0)
        return regNum._uSmall % uDen;
      ulong num = 0UL;
      for (int index = regNum._iuLast; index >= 0; --index)
        num = NumericsHelpers.MakeUlong((uint) num, regNum._rgu[index]) % (ulong) uDen;
      return (uint) num;
    }

    public void Mod(ref BigIntegerBuilder regDen)
    {
      if (regDen._iuLast == 0)
      {
        this.Set(BigIntegerBuilder.Mod(ref this, regDen._uSmall));
      }
      else
      {
        if (this._iuLast == 0)
          return;
        BigIntegerBuilder regQuo = new BigIntegerBuilder();
        BigIntegerBuilder.ModDivCore(ref this, ref regDen, false, ref regQuo);
      }
    }

    public void Div(ref BigIntegerBuilder regDen)
    {
      if (regDen._iuLast == 0)
      {
        int num = (int) this.DivMod(regDen._uSmall);
      }
      else if (this._iuLast == 0)
      {
        this._uSmall = 0U;
      }
      else
      {
        BigIntegerBuilder bigIntegerBuilder = new BigIntegerBuilder();
        BigIntegerBuilder.ModDivCore(ref this, ref regDen, true, ref bigIntegerBuilder);
        NumericsHelpers.Swap<BigIntegerBuilder>(ref this, ref bigIntegerBuilder);
      }
    }

    public void ModDiv(ref BigIntegerBuilder regDen, ref BigIntegerBuilder regQuo)
    {
      if (regDen._iuLast == 0)
      {
        regQuo.Set(this.DivMod(regDen._uSmall));
        NumericsHelpers.Swap<BigIntegerBuilder>(ref this, ref regQuo);
      }
      else
      {
        if (this._iuLast == 0)
          return;
        BigIntegerBuilder.ModDivCore(ref this, ref regDen, true, ref regQuo);
      }
    }

    private static void ModDivCore(ref BigIntegerBuilder regNum, ref BigIntegerBuilder regDen, bool fQuo, ref BigIntegerBuilder regQuo)
    {
      regQuo.Set(0U);
      if (regNum._iuLast < regDen._iuLast)
        return;
      int num1 = regDen._iuLast + 1;
      int num2 = regNum._iuLast - regDen._iuLast;
      int cu = num2;
      for (int index = regNum._iuLast; index >= num2; --index)
      {
        if ((int) regDen._rgu[index - num2] != (int) regNum._rgu[index])
        {
          if (regDen._rgu[index - num2] < regNum._rgu[index])
          {
            ++cu;
            goto label_9;
          }
          else
            goto label_9;
        }
      }
      ++cu;
label_9:
      if (cu == 0)
        return;
      if (fQuo)
        regQuo.SetSizeLazy(cu);
      uint u = regDen._rgu[num1 - 1];
      uint num3 = regDen._rgu[num1 - 2];
      int num4 = NumericsHelpers.CbitHighZero(u);
      int num5 = 32 - num4;
      if (num4 > 0)
      {
        u = u << num4 | num3 >> num5;
        num3 <<= num4;
        if (num1 > 2)
          num3 |= regDen._rgu[num1 - 3] >> num5;
      }
      regNum.EnsureWritable();
      int index1 = cu;
      while (--index1 >= 0)
      {
        uint uHi = index1 + num1 <= regNum._iuLast ? regNum._rgu[index1 + num1] : 0U;
        ulong num6 = NumericsHelpers.MakeUlong(uHi, regNum._rgu[index1 + num1 - 1]);
        uint uLo = regNum._rgu[index1 + num1 - 2];
        if (num4 > 0)
        {
          num6 = num6 << num4 | (ulong) (uLo >> num5);
          uLo <<= num4;
          if (index1 + num1 >= 3)
            uLo |= regNum._rgu[index1 + num1 - 3] >> num5;
        }
        ulong num7 = num6 / (ulong) u;
        ulong num8 = (ulong) (uint) (num6 % (ulong) u);
        if (num7 > (ulong) uint.MaxValue)
        {
          num8 += (ulong) u * (num7 - (ulong) uint.MaxValue);
          num7 = (ulong) uint.MaxValue;
        }
        while (num8 <= (ulong) uint.MaxValue && num7 * (ulong) num3 > NumericsHelpers.MakeUlong((uint) num8, uLo))
        {
          --num7;
          num8 += (ulong) u;
        }
        if (num7 > 0UL)
        {
          ulong num9 = 0UL;
          for (int index2 = 0; index2 < num1; ++index2)
          {
            ulong num10 = num9 + (ulong) regDen._rgu[index2] * num7;
            uint num11 = (uint) num10;
            num9 = num10 >> 32;
            if (regNum._rgu[index1 + index2] < num11)
              ++num9;
            regNum._rgu[index1 + index2] -= num11;
          }
          if ((ulong) uHi < num9)
          {
            uint uCarry = 0U;
            for (int index2 = 0; index2 < num1; ++index2)
              uCarry = BigIntegerBuilder.AddCarry(ref regNum._rgu[index1 + index2], regDen._rgu[index2], uCarry);
            --num7;
          }
          regNum._iuLast = index1 + num1 - 1;
        }
        if (fQuo)
        {
          if (cu == 1)
            regQuo._uSmall = (uint) num7;
          else
            regQuo._rgu[index1] = (uint) num7;
        }
      }
      regNum._iuLast = num1 - 1;
      regNum.Trim();
    }

    public void ShiftRight(int cbit)
    {
      if (cbit <= 0)
      {
        if (cbit >= 0)
          return;
        this.ShiftLeft(-cbit);
      }
      else
        this.ShiftRight(cbit / 32, cbit % 32);
    }

    public void ShiftRight(int cuShift, int cbitShift)
    {
      if ((cuShift | cbitShift) == 0)
        return;
      if (cuShift > this._iuLast)
        this.Set(0U);
      else if (this._iuLast == 0)
      {
        this._uSmall = this._uSmall >> cbitShift;
      }
      else
      {
        uint[] numArray = this._rgu;
        int num = this._iuLast + 1;
        this._iuLast = this._iuLast - cuShift;
        if (this._iuLast == 0)
        {
          this._uSmall = numArray[cuShift] >> cbitShift;
        }
        else
        {
          if (!this._fWritable)
          {
            this._rgu = new uint[this._iuLast + 1];
            this._fWritable = true;
          }
          if (cbitShift > 0)
          {
            int index1 = cuShift + 1;
            int index2 = 0;
            while (index1 < num)
            {
              this._rgu[index2] = numArray[index1 - 1] >> cbitShift | numArray[index1] << 32 - cbitShift;
              ++index1;
              ++index2;
            }
            this._rgu[this._iuLast] = numArray[num - 1] >> cbitShift;
            this.Trim();
          }
          else
            Array.Copy((Array) numArray, cuShift, (Array) this._rgu, 0, this._iuLast + 1);
        }
      }
    }

    public void ShiftLeft(int cbit)
    {
      if (cbit <= 0)
      {
        if (cbit >= 0)
          return;
        this.ShiftRight(-cbit);
      }
      else
        this.ShiftLeft(cbit / 32, cbit % 32);
    }

    public void ShiftLeft(int cuShift, int cbitShift)
    {
      int index1 = this._iuLast + cuShift;
      uint num = 0U;
      if (cbitShift > 0)
      {
        num = this.High >> 32 - cbitShift;
        if ((int) num != 0)
          ++index1;
      }
      if (index1 == 0)
      {
        this._uSmall = this._uSmall << cbitShift;
      }
      else
      {
        uint[] numArray = this._rgu;
        bool flag = cuShift > 0;
        if (!this._fWritable || this._rgu.Length <= index1)
        {
          this._rgu = new uint[index1 + 1];
          this._fWritable = true;
          flag = false;
        }
        if (this._iuLast == 0)
        {
          if ((int) num != 0)
            this._rgu[cuShift + 1] = num;
          this._rgu[cuShift] = this._uSmall << cbitShift;
        }
        else if (cbitShift == 0)
        {
          Array.Copy((Array) numArray, 0, (Array) this._rgu, cuShift, this._iuLast + 1);
        }
        else
        {
          int index2 = this._iuLast;
          int index3 = this._iuLast + cuShift;
          if (index3 < index1)
            this._rgu[index1] = num;
          while (index2 > 0)
          {
            this._rgu[index3] = numArray[index2] << cbitShift | numArray[index2 - 1] >> 32 - cbitShift;
            --index2;
            --index3;
          }
          this._rgu[cuShift] = numArray[0] << cbitShift;
        }
        this._iuLast = index1;
        if (!flag)
          return;
        Array.Clear((Array) this._rgu, 0, cuShift);
      }
    }

    private ulong GetHigh2(int cu)
    {
      if (cu - 1 <= this._iuLast)
        return NumericsHelpers.MakeUlong(this._rgu[cu - 1], this._rgu[cu - 2]);
      if (cu - 2 == this._iuLast)
        return (ulong) this._rgu[cu - 2];
      else
        return 0UL;
    }

    private void ApplyCarry(int iu)
    {
      for (; iu <= this._iuLast; ++iu)
      {
        // ISSUE: explicit reference operation
        // ISSUE: variable of a reference type
        uint& local = @this._rgu[iu];
        // ISSUE: explicit reference operation
        uint num1 = ^local + 1U;
        int num2 = (int) num1;
        // ISSUE: explicit reference operation
        ^local = (uint) num2;
        if (num1 > 0U)
          return;
      }
      if (this._iuLast + 1 == this._rgu.Length)
        Array.Resize<uint>(ref this._rgu, this._iuLast + 2);
      uint[] numArray = this._rgu;
      // ISSUE: explicit reference operation
      // ISSUE: variable of a reference type
      BigIntegerBuilder& local1 = @this;
      int num3 = this._iuLast + 1;
      int num4 = num3;
      // ISSUE: explicit reference operation
      (^local1)._iuLast = num4;
      int index = num3;
      int num5 = 1;
      numArray[index] = (uint) num5;
    }

    private void ApplyBorrow(int iuMin)
    {
      for (int index = iuMin; index <= this._iuLast; ++index)
      {
        // ISSUE: explicit reference operation
        // ISSUE: variable of a reference type
        uint& local = @this._rgu[index];
        // ISSUE: explicit reference operation
        uint num1 = ^local;
        int num2 = (int) num1 - 1;
        // ISSUE: explicit reference operation
        ^local = (uint) num2;
        if (num1 > 0U)
          break;
      }
    }

    private static uint AddCarry(ref uint u1, uint u2, uint uCarry)
    {
      ulong num = (ulong) u1 + (ulong) u2 + (ulong) uCarry;
      u1 = (uint) num;
      return (uint) (num >> 32);
    }

    private static uint SubBorrow(ref uint u1, uint u2, uint uBorrow)
    {
      ulong num = (ulong) u1 - (ulong) u2 - (ulong) uBorrow;
      u1 = (uint) num;
      return (uint) -(int) (num >> 32);
    }

    private static uint SubRevBorrow(ref uint u1, uint u2, uint uBorrow)
    {
      ulong num = (ulong) u2 - (ulong) u1 - (ulong) uBorrow;
      u1 = (uint) num;
      return (uint) -(int) (num >> 32);
    }

    private static uint MulCarry(ref uint u1, uint u2, uint uCarry)
    {
      ulong num = (ulong) u1 * (ulong) u2 + (ulong) uCarry;
      u1 = (uint) num;
      return (uint) (num >> 32);
    }

    private static uint AddMulCarry(ref uint uAdd, uint uMul1, uint uMul2, uint uCarry)
    {
      ulong num = (ulong) uMul1 * (ulong) uMul2 + (ulong) uAdd + (ulong) uCarry;
      uAdd = (uint) num;
      return (uint) (num >> 32);
    }

    public static void GCD(ref BigIntegerBuilder reg1, ref BigIntegerBuilder reg2)
    {
      if (reg1._iuLast > 0 && (int) reg1._rgu[0] == 0 || reg2._iuLast > 0 && (int) reg2._rgu[0] == 0)
      {
        int val1 = reg1.MakeOdd();
        int num = reg2.MakeOdd();
        BigIntegerBuilder.LehmerGcd(ref reg1, ref reg2);
        int val2 = num;
        int cbit = Math.Min(val1, val2);
        if (cbit <= 0)
          return;
        reg1.ShiftLeft(cbit);
      }
      else
        BigIntegerBuilder.LehmerGcd(ref reg1, ref reg2);
    }

    private static void LehmerGcd(ref BigIntegerBuilder reg1, ref BigIntegerBuilder reg2)
    {
      int sign = 1;
      int a1;
      while (true)
      {
        a1 = reg1._iuLast + 1;
        int b1 = reg2._iuLast + 1;
        if (a1 < b1)
        {
          NumericsHelpers.Swap<BigIntegerBuilder>(ref reg1, ref reg2);
          NumericsHelpers.Swap<int>(ref a1, ref b1);
        }
        if (b1 != 1)
        {
          if (a1 != 2)
          {
            if (b1 <= a1 - 2)
            {
              reg1.Mod(ref reg2);
            }
            else
            {
              ulong a2 = reg1.GetHigh2(a1);
              ulong b2 = reg2.GetHigh2(a1);
              int num1 = NumericsHelpers.CbitHighZero(a2 | b2);
              if (num1 > 0)
              {
                a2 = a2 << num1 | (ulong) (reg1._rgu[a1 - 3] >> 32 - num1);
                b2 = b2 << num1 | (ulong) (reg2._rgu[a1 - 3] >> 32 - num1);
              }
              if (a2 < b2)
              {
                NumericsHelpers.Swap<ulong>(ref a2, ref b2);
                NumericsHelpers.Swap<BigIntegerBuilder>(ref reg1, ref reg2);
              }
              if ((long) a2 == -1L || (long) b2 == -1L)
              {
                a2 >>= 1;
                b2 >>= 1;
              }
              if ((long) a2 == (long) b2)
                reg1.Sub(ref sign, ref reg2);
              else if ((int) NumericsHelpers.GetHi(b2) == 0)
              {
                reg1.Mod(ref reg2);
              }
              else
              {
                uint num2 = 1U;
                uint num3 = 0U;
                uint num4 = 0U;
                uint num5 = 1U;
                do
                {
                  uint num6 = 1U;
                  ulong num7;
                  for (num7 = a2 - b2; num7 >= b2 && num6 < 32U; ++num6)
                    num7 -= b2;
                  if (num7 >= b2)
                  {
                    ulong num8 = a2 / b2;
                    if (num8 <= (ulong) uint.MaxValue)
                    {
                      num6 = (uint) num8;
                      num7 = a2 - (ulong) num6 * b2;
                    }
                    else
                      break;
                  }
                  ulong num9 = (ulong) num2 + (ulong) num6 * (ulong) num4;
                  ulong num10 = (ulong) num3 + (ulong) num6 * (ulong) num5;
                  if (num9 <= (ulong) int.MaxValue && num10 <= (ulong) int.MaxValue && (num7 >= num10 && num7 + num9 <= b2 - (ulong) num4))
                  {
                    num2 = (uint) num9;
                    num3 = (uint) num10;
                    a2 = num7;
                    if (a2 > (ulong) num3)
                    {
                      uint num8 = 1U;
                      ulong num11;
                      for (num11 = b2 - a2; num11 >= a2 && num8 < 32U; ++num8)
                        num11 -= a2;
                      if (num11 >= a2)
                      {
                        ulong num12 = b2 / a2;
                        if (num12 <= (ulong) uint.MaxValue)
                        {
                          num8 = (uint) num12;
                          num11 = b2 - (ulong) num8 * a2;
                        }
                        else
                          break;
                      }
                      ulong num13 = (ulong) num5 + (ulong) num8 * (ulong) num3;
                      ulong num14 = (ulong) num4 + (ulong) num8 * (ulong) num2;
                      if (num13 <= (ulong) int.MaxValue && num14 <= (ulong) int.MaxValue && (num11 >= num14 && num11 + num13 <= a2 - (ulong) num3))
                      {
                        num5 = (uint) num13;
                        num4 = (uint) num14;
                        b2 = num11;
                      }
                      else
                        break;
                    }
                    else
                      break;
                  }
                  else
                    break;
                }
                while (b2 > (ulong) num4);
                if ((int) num3 == 0)
                {
                  if (a2 / 2UL >= b2)
                    reg1.Mod(ref reg2);
                  else
                    reg1.Sub(ref sign, ref reg2);
                }
                else
                {
                  reg1.SetSizeKeep(b1, 0);
                  reg2.SetSizeKeep(b1, 0);
                  int num6 = 0;
                  int num7 = 0;
                  for (int index = 0; index < b1; ++index)
                  {
                    uint num8 = reg1._rgu[index];
                    uint num9 = reg2._rgu[index];
                    long num10 = (long) num8 * (long) num2 - (long) num9 * (long) num3 + (long) num6;
                    long num11 = (long) num9 * (long) num5 - (long) num8 * (long) num4 + (long) num7;
                    num6 = (int) (num10 >> 32);
                    num7 = (int) (num11 >> 32);
                    reg1._rgu[index] = (uint) num10;
                    reg2._rgu[index] = (uint) num11;
                  }
                  reg1.Trim();
                  reg2.Trim();
                }
              }
            }
          }
          else
            goto label_9;
        }
        else
          break;
      }
      if (a1 == 1)
      {
        reg1._uSmall = NumericsHelpers.GCD(reg1._uSmall, reg2._uSmall);
        return;
      }
      else
      {
        if ((int) reg2._uSmall == 0)
          return;
        reg1.Set(NumericsHelpers.GCD(BigIntegerBuilder.Mod(ref reg1, reg2._uSmall), reg2._uSmall));
        return;
      }
label_9:
      reg1.Set(NumericsHelpers.GCD(reg1.GetHigh2(2), reg2.GetHigh2(2)));
    }

    public int CbitLowZero()
    {
      if (this._iuLast == 0)
      {
        if (((int) this._uSmall & 1) != 0 || (int) this._uSmall == 0)
          return 0;
        else
          return NumericsHelpers.CbitLowZero(this._uSmall);
      }
      else
      {
        int index = 0;
        while ((int) this._rgu[index] == 0)
          ++index;
        return NumericsHelpers.CbitLowZero(this._rgu[index]) + index * 32;
      }
    }

    public int MakeOdd()
    {
      int cbit = this.CbitLowZero();
      if (cbit > 0)
        this.ShiftRight(cbit);
      return cbit;
    }
  }
}