Files
SuperVPN/output/Libraries/BouncyCastle.Crypto/Org/BouncyCastle/Math/BigInteger.cs
2025-10-09 09:57:24 +09:00

2899 lines
59 KiB
C#

using System;
using System.Collections;
using System.Globalization;
using System.Text;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Math;
[Serializable]
public class BigInteger
{
private const long IMASK = 4294967295L;
private const ulong UIMASK = 4294967295uL;
private const int chunk2 = 1;
private const int chunk8 = 1;
private const int chunk10 = 19;
private const int chunk16 = 16;
private const int BitsPerByte = 8;
private const int BitsPerInt = 32;
private const int BytesPerInt = 4;
internal static readonly int[][] primeLists;
internal static readonly int[] primeProducts;
private static readonly int[] ZeroMagnitude;
private static readonly byte[] ZeroEncoding;
private static readonly BigInteger[] SMALL_CONSTANTS;
public static readonly BigInteger Zero;
public static readonly BigInteger One;
public static readonly BigInteger Two;
public static readonly BigInteger Three;
public static readonly BigInteger Ten;
private static readonly byte[] BitLengthTable;
private static readonly BigInteger radix2;
private static readonly BigInteger radix2E;
private static readonly BigInteger radix8;
private static readonly BigInteger radix8E;
private static readonly BigInteger radix10;
private static readonly BigInteger radix10E;
private static readonly BigInteger radix16;
private static readonly BigInteger radix16E;
private static readonly SecureRandom RandomSource;
private static readonly int[] ExpWindowThresholds;
private int[] magnitude;
private int sign;
private int nBits = -1;
private int nBitLength = -1;
private int mQuote = 0;
public int BitCount
{
get
{
if (nBits == -1)
{
if (sign < 0)
{
nBits = Not().BitCount;
}
else
{
int num = 0;
for (int i = 0; i < magnitude.Length; i++)
{
num += BitCnt(magnitude[i]);
}
nBits = num;
}
}
return nBits;
}
}
public int BitLength
{
get
{
if (nBitLength == -1)
{
nBitLength = ((sign != 0) ? CalcBitLength(sign, 0, magnitude) : 0);
}
return nBitLength;
}
}
public int IntValue
{
get
{
if (sign == 0)
{
return 0;
}
int num = magnitude.Length;
int num2 = magnitude[num - 1];
if (sign >= 0)
{
return num2;
}
return -num2;
}
}
public long LongValue
{
get
{
if (sign == 0)
{
return 0L;
}
int num = magnitude.Length;
long num2 = magnitude[num - 1] & 0xFFFFFFFFu;
if (num > 1)
{
num2 |= (magnitude[num - 2] & 0xFFFFFFFFu) << 32;
}
if (sign >= 0)
{
return num2;
}
return -num2;
}
}
public int SignValue => sign;
static BigInteger()
{
primeLists = new int[64][]
{
new int[8] { 3, 5, 7, 11, 13, 17, 19, 23 },
new int[5] { 29, 31, 37, 41, 43 },
new int[5] { 47, 53, 59, 61, 67 },
new int[4] { 71, 73, 79, 83 },
new int[4] { 89, 97, 101, 103 },
new int[4] { 107, 109, 113, 127 },
new int[4] { 131, 137, 139, 149 },
new int[4] { 151, 157, 163, 167 },
new int[4] { 173, 179, 181, 191 },
new int[4] { 193, 197, 199, 211 },
new int[3] { 223, 227, 229 },
new int[3] { 233, 239, 241 },
new int[3] { 251, 257, 263 },
new int[3] { 269, 271, 277 },
new int[3] { 281, 283, 293 },
new int[3] { 307, 311, 313 },
new int[3] { 317, 331, 337 },
new int[3] { 347, 349, 353 },
new int[3] { 359, 367, 373 },
new int[3] { 379, 383, 389 },
new int[3] { 397, 401, 409 },
new int[3] { 419, 421, 431 },
new int[3] { 433, 439, 443 },
new int[3] { 449, 457, 461 },
new int[3] { 463, 467, 479 },
new int[3] { 487, 491, 499 },
new int[3] { 503, 509, 521 },
new int[3] { 523, 541, 547 },
new int[3] { 557, 563, 569 },
new int[3] { 571, 577, 587 },
new int[3] { 593, 599, 601 },
new int[3] { 607, 613, 617 },
new int[3] { 619, 631, 641 },
new int[3] { 643, 647, 653 },
new int[3] { 659, 661, 673 },
new int[3] { 677, 683, 691 },
new int[3] { 701, 709, 719 },
new int[3] { 727, 733, 739 },
new int[3] { 743, 751, 757 },
new int[3] { 761, 769, 773 },
new int[3] { 787, 797, 809 },
new int[3] { 811, 821, 823 },
new int[3] { 827, 829, 839 },
new int[3] { 853, 857, 859 },
new int[3] { 863, 877, 881 },
new int[3] { 883, 887, 907 },
new int[3] { 911, 919, 929 },
new int[3] { 937, 941, 947 },
new int[3] { 953, 967, 971 },
new int[3] { 977, 983, 991 },
new int[3] { 997, 1009, 1013 },
new int[3] { 1019, 1021, 1031 },
new int[3] { 1033, 1039, 1049 },
new int[3] { 1051, 1061, 1063 },
new int[3] { 1069, 1087, 1091 },
new int[3] { 1093, 1097, 1103 },
new int[3] { 1109, 1117, 1123 },
new int[3] { 1129, 1151, 1153 },
new int[3] { 1163, 1171, 1181 },
new int[3] { 1187, 1193, 1201 },
new int[3] { 1213, 1217, 1223 },
new int[3] { 1229, 1231, 1237 },
new int[3] { 1249, 1259, 1277 },
new int[3] { 1279, 1283, 1289 }
};
ZeroMagnitude = new int[0];
ZeroEncoding = new byte[0];
SMALL_CONSTANTS = new BigInteger[17];
BitLengthTable = new byte[256]
{
0, 1, 2, 2, 3, 3, 3, 3, 4, 4,
4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8
};
RandomSource = new SecureRandom();
ExpWindowThresholds = new int[8] { 7, 25, 81, 241, 673, 1793, 4609, 2147483647 };
Zero = new BigInteger(0, ZeroMagnitude, checkMag: false);
Zero.nBits = 0;
Zero.nBitLength = 0;
SMALL_CONSTANTS[0] = Zero;
for (uint num = 1u; num < SMALL_CONSTANTS.Length; num++)
{
SMALL_CONSTANTS[num] = CreateUValueOf(num);
}
One = SMALL_CONSTANTS[1];
Two = SMALL_CONSTANTS[2];
Three = SMALL_CONSTANTS[3];
Ten = SMALL_CONSTANTS[10];
radix2 = ValueOf(2L);
radix2E = radix2.Pow(1);
radix8 = ValueOf(8L);
radix8E = radix8.Pow(1);
radix10 = ValueOf(10L);
radix10E = radix10.Pow(19);
radix16 = ValueOf(16L);
radix16E = radix16.Pow(16);
primeProducts = new int[primeLists.Length];
for (int i = 0; i < primeLists.Length; i++)
{
int[] array = primeLists[i];
int num2 = array[0];
for (int j = 1; j < array.Length; j++)
{
num2 *= array[j];
}
primeProducts[i] = num2;
}
}
private static int GetByteLength(int nBits)
{
return (nBits + 8 - 1) / 8;
}
internal static BigInteger Arbitrary(int sizeInBits)
{
return new BigInteger(sizeInBits, RandomSource);
}
private BigInteger(int signum, int[] mag, bool checkMag)
{
if (checkMag)
{
int i;
for (i = 0; i < mag.Length && mag[i] == 0; i++)
{
}
if (i == mag.Length)
{
sign = 0;
magnitude = ZeroMagnitude;
return;
}
sign = signum;
if (i == 0)
{
magnitude = mag;
return;
}
magnitude = new int[mag.Length - i];
Array.Copy(mag, i, magnitude, 0, magnitude.Length);
}
else
{
sign = signum;
magnitude = mag;
}
}
public BigInteger(string value)
: this(value, 10)
{
}
public BigInteger(string str, int radix)
{
if (str.Length == 0)
{
throw new FormatException("Zero length BigInteger");
}
NumberStyles style;
int num;
BigInteger bigInteger;
BigInteger val;
switch (radix)
{
case 2:
style = NumberStyles.Integer;
num = 1;
bigInteger = radix2;
val = radix2E;
break;
case 8:
style = NumberStyles.Integer;
num = 1;
bigInteger = radix8;
val = radix8E;
break;
case 10:
style = NumberStyles.Integer;
num = 19;
bigInteger = radix10;
val = radix10E;
break;
case 16:
style = NumberStyles.AllowHexSpecifier;
num = 16;
bigInteger = radix16;
val = radix16E;
break;
default:
throw new FormatException("Only bases 2, 8, 10, or 16 allowed");
}
int i = 0;
sign = 1;
if (str[0] == '-')
{
if (str.Length == 1)
{
throw new FormatException("Zero length BigInteger");
}
sign = -1;
i = 1;
}
for (; i < str.Length && int.Parse(str[i].ToString(), style) == 0; i++)
{
}
if (i >= str.Length)
{
sign = 0;
magnitude = ZeroMagnitude;
return;
}
BigInteger bigInteger2 = Zero;
int num2 = i + num;
if (num2 <= str.Length)
{
do
{
string text = str.Substring(i, num);
ulong num3 = ulong.Parse(text, style);
BigInteger value = CreateUValueOf(num3);
switch (radix)
{
case 2:
if (num3 >= 2)
{
throw new FormatException("Bad character in radix 2 string: " + text);
}
bigInteger2 = bigInteger2.ShiftLeft(1);
break;
case 8:
if (num3 >= 8)
{
throw new FormatException("Bad character in radix 8 string: " + text);
}
bigInteger2 = bigInteger2.ShiftLeft(3);
break;
case 16:
bigInteger2 = bigInteger2.ShiftLeft(64);
break;
default:
bigInteger2 = bigInteger2.Multiply(val);
break;
}
bigInteger2 = bigInteger2.Add(value);
i = num2;
num2 += num;
}
while (num2 <= str.Length);
}
if (i < str.Length)
{
string text2 = str.Substring(i);
ulong value2 = ulong.Parse(text2, style);
BigInteger bigInteger3 = CreateUValueOf(value2);
if (bigInteger2.sign > 0)
{
switch (radix)
{
case 16:
bigInteger2 = bigInteger2.ShiftLeft(text2.Length << 2);
break;
default:
bigInteger2 = bigInteger2.Multiply(bigInteger.Pow(text2.Length));
break;
case 2:
case 8:
break;
}
bigInteger2 = bigInteger2.Add(bigInteger3);
}
else
{
bigInteger2 = bigInteger3;
}
}
magnitude = bigInteger2.magnitude;
}
public BigInteger(byte[] bytes)
: this(bytes, 0, bytes.Length)
{
}
public BigInteger(byte[] bytes, int offset, int length)
{
if (length == 0)
{
throw new FormatException("Zero length BigInteger");
}
if ((sbyte)bytes[offset] < 0)
{
sign = -1;
int num = offset + length;
int i;
for (i = offset; i < num && (sbyte)bytes[i] == -1; i++)
{
}
if (i >= num)
{
magnitude = One.magnitude;
return;
}
int num2 = num - i;
byte[] array = new byte[num2];
int num3 = 0;
while (num3 < num2)
{
array[num3++] = (byte)(~bytes[i++]);
}
while (array[--num3] == byte.MaxValue)
{
array[num3] = 0;
}
byte[] array3;
byte[] array2 = (array3 = array);
int num4 = num3;
nint num5 = num4;
array2[num4] = (byte)(array3[num5] + 1);
magnitude = MakeMagnitude(array, 0, array.Length);
}
else
{
magnitude = MakeMagnitude(bytes, offset, length);
sign = ((magnitude.Length > 0) ? 1 : 0);
}
}
private static int[] MakeMagnitude(byte[] bytes, int offset, int length)
{
int num = offset + length;
int i;
for (i = offset; i < num && bytes[i] == 0; i++)
{
}
if (i >= num)
{
return ZeroMagnitude;
}
int num2 = (num - i + 3) / 4;
int num3 = (num - i) % 4;
if (num3 == 0)
{
num3 = 4;
}
if (num2 < 1)
{
return ZeroMagnitude;
}
int[] array = new int[num2];
int num4 = 0;
int num5 = 0;
for (int j = i; j < num; j++)
{
num4 <<= 8;
num4 |= bytes[j] & 0xFF;
num3--;
if (num3 <= 0)
{
array[num5] = num4;
num5++;
num3 = 4;
num4 = 0;
}
}
if (num5 < array.Length)
{
array[num5] = num4;
}
return array;
}
public BigInteger(int sign, byte[] bytes)
: this(sign, bytes, 0, bytes.Length)
{
}
public BigInteger(int sign, byte[] bytes, int offset, int length)
{
switch (sign)
{
default:
throw new FormatException("Invalid sign value");
case 0:
this.sign = 0;
magnitude = ZeroMagnitude;
break;
case -1:
case 1:
magnitude = MakeMagnitude(bytes, offset, length);
this.sign = ((magnitude.Length >= 1) ? sign : 0);
break;
}
}
public BigInteger(int sizeInBits, Random random)
{
if (sizeInBits < 0)
{
throw new ArgumentException("sizeInBits must be non-negative");
}
nBits = -1;
nBitLength = -1;
if (sizeInBits == 0)
{
sign = 0;
magnitude = ZeroMagnitude;
return;
}
int byteLength = GetByteLength(sizeInBits);
byte[] array = new byte[byteLength];
random.NextBytes(array);
int num = 8 * byteLength - sizeInBits;
byte[] array2;
(array2 = array)[0] = (byte)(array2[0] & (byte)(255 >>> num));
magnitude = MakeMagnitude(array, 0, array.Length);
sign = ((magnitude.Length >= 1) ? 1 : 0);
}
public BigInteger(int bitLength, int certainty, Random random)
{
if (bitLength < 2)
{
throw new ArithmeticException("bitLength < 2");
}
sign = 1;
nBitLength = bitLength;
if (bitLength == 2)
{
magnitude = ((random.Next(2) == 0) ? Two.magnitude : Three.magnitude);
return;
}
int byteLength = GetByteLength(bitLength);
byte[] array = new byte[byteLength];
int num = 8 * byteLength - bitLength;
byte b = (byte)(255u >> num);
byte b2 = (byte)(1 << 7 - num);
while (true)
{
random.NextBytes(array);
byte[] array2;
(array2 = array)[0] = (byte)(array2[0] & b);
(array2 = array)[0] = (byte)(array2[0] | b2);
byte[] array3 = (array2 = array);
int num2 = byteLength - 1;
nint num3 = num2;
array3[num2] = (byte)(array2[num3] | 1);
magnitude = MakeMagnitude(array, 0, array.Length);
nBits = -1;
mQuote = 0;
if (certainty < 1 || CheckProbablePrime(certainty, random, randomlySelected: true))
{
break;
}
for (int i = 1; i < magnitude.Length - 1; i++)
{
int[] array5;
int[] array4 = (array5 = magnitude);
int num4 = i;
num3 = num4;
array4[num4] = array5[num3] ^ random.Next();
if (CheckProbablePrime(certainty, random, randomlySelected: true))
{
return;
}
}
}
}
public BigInteger Abs()
{
if (sign < 0)
{
return Negate();
}
return this;
}
private static int[] AddMagnitudes(int[] a, int[] b)
{
int num = a.Length - 1;
int num2 = b.Length - 1;
long num3 = 0L;
while (num2 >= 0)
{
num3 += (long)(uint)a[num] + (long)(uint)b[num2--];
a[num--] = (int)num3;
num3 >>>= 32;
}
if (num3 != 0)
{
while (num >= 0)
{
int[] array2;
int[] array = (array2 = a);
int num4 = num--;
nint num5 = num4;
if ((array[num4] = array2[num5] + 1) != 0)
{
break;
}
}
}
return a;
}
public BigInteger Add(BigInteger value)
{
if (sign == 0)
{
return value;
}
if (sign != value.sign)
{
if (value.sign == 0)
{
return this;
}
if (value.sign < 0)
{
return Subtract(value.Negate());
}
return value.Subtract(Negate());
}
return AddToMagnitude(value.magnitude);
}
private BigInteger AddToMagnitude(int[] magToAdd)
{
int[] array;
int[] array2;
if (magnitude.Length < magToAdd.Length)
{
array = magToAdd;
array2 = magnitude;
}
else
{
array = magnitude;
array2 = magToAdd;
}
uint num = uint.MaxValue;
if (array.Length == array2.Length)
{
num -= (uint)array2[0];
}
bool flag = (uint)array[0] >= num;
int[] array3;
if (flag)
{
array3 = new int[array.Length + 1];
array.CopyTo(array3, 1);
}
else
{
array3 = (int[])array.Clone();
}
array3 = AddMagnitudes(array3, array2);
return new BigInteger(sign, array3, flag);
}
public BigInteger And(BigInteger value)
{
if (sign == 0 || value.sign == 0)
{
return Zero;
}
int[] array = ((sign > 0) ? magnitude : Add(One).magnitude);
int[] array2 = ((value.sign > 0) ? value.magnitude : value.Add(One).magnitude);
bool flag = sign < 0 && value.sign < 0;
int num = System.Math.Max(array.Length, array2.Length);
int[] array3 = new int[num];
int num2 = array3.Length - array.Length;
int num3 = array3.Length - array2.Length;
for (int i = 0; i < array3.Length; i++)
{
int num4 = ((i >= num2) ? array[i - num2] : 0);
int num5 = ((i >= num3) ? array2[i - num3] : 0);
if (sign < 0)
{
num4 = ~num4;
}
if (value.sign < 0)
{
num5 = ~num5;
}
array3[i] = num4 & num5;
if (flag)
{
array3[i] = ~array3[i];
}
}
BigInteger bigInteger = new BigInteger(1, array3, checkMag: true);
if (flag)
{
bigInteger = bigInteger.Not();
}
return bigInteger;
}
public BigInteger AndNot(BigInteger val)
{
return And(val.Not());
}
public static int BitCnt(int i)
{
uint num = (uint)i;
num -= (num >> 1) & 0x55555555;
num = (num & 0x33333333) + ((num >> 2) & 0x33333333);
num = (num + (num >> 4)) & 0xF0F0F0F;
num += num >> 8;
num += num >> 16;
return (int)(num & 0x3F);
}
private static int CalcBitLength(int sign, int indx, int[] mag)
{
while (true)
{
if (indx >= mag.Length)
{
return 0;
}
if (mag[indx] != 0)
{
break;
}
indx++;
}
int num = 32 * (mag.Length - indx - 1);
int num2 = mag[indx];
num += BitLen(num2);
if (sign < 0 && (num2 & -num2) == num2)
{
do
{
if (++indx >= mag.Length)
{
num--;
break;
}
}
while (mag[indx] == 0);
}
return num;
}
internal static int BitLen(int w)
{
uint num = (uint)w >> 24;
if (num != 0)
{
return 24 + BitLengthTable[num];
}
num = (uint)w >> 16;
if (num != 0)
{
return 16 + BitLengthTable[num];
}
num = (uint)w >> 8;
if (num != 0)
{
return 8 + BitLengthTable[num];
}
return BitLengthTable[w];
}
private bool QuickPow2Check()
{
if (sign > 0)
{
return nBits == 1;
}
return false;
}
public int CompareTo(object obj)
{
return CompareTo((BigInteger)obj);
}
private static int CompareTo(int xIndx, int[] x, int yIndx, int[] y)
{
while (xIndx != x.Length && x[xIndx] == 0)
{
xIndx++;
}
while (yIndx != y.Length && y[yIndx] == 0)
{
yIndx++;
}
return CompareNoLeadingZeroes(xIndx, x, yIndx, y);
}
private static int CompareNoLeadingZeroes(int xIndx, int[] x, int yIndx, int[] y)
{
int num = x.Length - y.Length - (xIndx - yIndx);
if (num != 0)
{
if (num >= 0)
{
return 1;
}
return -1;
}
while (xIndx < x.Length)
{
uint num2 = (uint)x[xIndx++];
uint num3 = (uint)y[yIndx++];
if (num2 != num3)
{
if (num2 >= num3)
{
return 1;
}
return -1;
}
}
return 0;
}
public int CompareTo(BigInteger value)
{
if (sign >= value.sign)
{
if (sign <= value.sign)
{
if (sign != 0)
{
return sign * CompareNoLeadingZeroes(0, magnitude, 0, value.magnitude);
}
return 0;
}
return 1;
}
return -1;
}
private int[] Divide(int[] x, int[] y)
{
int i;
for (i = 0; i < x.Length && x[i] == 0; i++)
{
}
int j;
for (j = 0; j < y.Length && y[j] == 0; j++)
{
}
int num = CompareNoLeadingZeroes(i, x, j, y);
int[] array3;
if (num > 0)
{
int num2 = CalcBitLength(1, j, y);
int num3 = CalcBitLength(1, i, x);
int num4 = num3 - num2;
int k = 0;
int l = 0;
int num5 = num2;
int[] array;
int[] array2;
if (num4 > 0)
{
array = new int[(num4 >> 5) + 1];
array[0] = 1 << num4 % 32;
array2 = ShiftLeft(y, num4);
num5 += num4;
}
else
{
array = new int[1] { 1 };
int num6 = y.Length - j;
array2 = new int[num6];
Array.Copy(y, j, array2, 0, num6);
}
array3 = new int[array.Length];
while (true)
{
if (num5 < num3 || CompareNoLeadingZeroes(i, x, l, array2) >= 0)
{
Subtract(i, x, l, array2);
AddMagnitudes(array3, array);
while (x[i] == 0)
{
if (++i == x.Length)
{
return array3;
}
}
num3 = 32 * (x.Length - i - 1) + BitLen(x[i]);
if (num3 <= num2)
{
if (num3 < num2)
{
return array3;
}
num = CompareNoLeadingZeroes(i, x, j, y);
if (num <= 0)
{
break;
}
}
}
num4 = num5 - num3;
if (num4 == 1)
{
uint num7 = (uint)array2[l] >> 1;
uint num8 = (uint)x[i];
if (num7 > num8)
{
num4++;
}
}
if (num4 < 2)
{
ShiftRightOneInPlace(l, array2);
num5--;
ShiftRightOneInPlace(k, array);
}
else
{
ShiftRightInPlace(l, array2, num4);
num5 -= num4;
ShiftRightInPlace(k, array, num4);
}
for (; array2[l] == 0; l++)
{
}
for (; array[k] == 0; k++)
{
}
}
}
else
{
array3 = new int[1];
}
if (num == 0)
{
AddMagnitudes(array3, One.magnitude);
Array.Clear(x, i, x.Length - i);
}
return array3;
}
public BigInteger Divide(BigInteger val)
{
if (val.sign == 0)
{
throw new ArithmeticException("Division by zero error");
}
if (sign == 0)
{
return Zero;
}
if (val.QuickPow2Check())
{
BigInteger bigInteger = Abs().ShiftRight(val.Abs().BitLength - 1);
if (val.sign != sign)
{
return bigInteger.Negate();
}
return bigInteger;
}
int[] x = (int[])magnitude.Clone();
return new BigInteger(sign * val.sign, Divide(x, val.magnitude), checkMag: true);
}
public BigInteger[] DivideAndRemainder(BigInteger val)
{
if (val.sign == 0)
{
throw new ArithmeticException("Division by zero error");
}
BigInteger[] array = new BigInteger[2];
if (sign == 0)
{
array[0] = Zero;
array[1] = Zero;
}
else if (val.QuickPow2Check())
{
int n = val.Abs().BitLength - 1;
BigInteger bigInteger = Abs().ShiftRight(n);
int[] mag = LastNBits(n);
array[0] = ((val.sign == sign) ? bigInteger : bigInteger.Negate());
array[1] = new BigInteger(sign, mag, checkMag: true);
}
else
{
int[] array2 = (int[])magnitude.Clone();
int[] mag2 = Divide(array2, val.magnitude);
array[0] = new BigInteger(sign * val.sign, mag2, checkMag: true);
array[1] = new BigInteger(sign, array2, checkMag: true);
}
return array;
}
public override bool Equals(object obj)
{
if (obj == this)
{
return true;
}
if (!(obj is BigInteger bigInteger))
{
return false;
}
if (sign == bigInteger.sign)
{
return IsEqualMagnitude(bigInteger);
}
return false;
}
private bool IsEqualMagnitude(BigInteger x)
{
_ = x.magnitude;
if (magnitude.Length != x.magnitude.Length)
{
return false;
}
for (int i = 0; i < magnitude.Length; i++)
{
if (magnitude[i] != x.magnitude[i])
{
return false;
}
}
return true;
}
public BigInteger Gcd(BigInteger value)
{
if (value.sign == 0)
{
return Abs();
}
if (sign == 0)
{
return value.Abs();
}
BigInteger bigInteger = this;
BigInteger bigInteger2 = value;
while (bigInteger2.sign != 0)
{
BigInteger bigInteger3 = bigInteger.Mod(bigInteger2);
bigInteger = bigInteger2;
bigInteger2 = bigInteger3;
}
return bigInteger;
}
public override int GetHashCode()
{
int num = magnitude.Length;
if (magnitude.Length > 0)
{
num ^= magnitude[0];
if (magnitude.Length > 1)
{
num ^= magnitude[magnitude.Length - 1];
}
}
if (sign >= 0)
{
return num;
}
return ~num;
}
private BigInteger Inc()
{
if (sign == 0)
{
return One;
}
if (sign < 0)
{
return new BigInteger(-1, doSubBigLil(magnitude, One.magnitude), checkMag: true);
}
return AddToMagnitude(One.magnitude);
}
public bool IsProbablePrime(int certainty)
{
return IsProbablePrime(certainty, randomlySelected: false);
}
internal bool IsProbablePrime(int certainty, bool randomlySelected)
{
if (certainty <= 0)
{
return true;
}
BigInteger bigInteger = Abs();
if (!bigInteger.TestBit(0))
{
return bigInteger.Equals(Two);
}
if (bigInteger.Equals(One))
{
return false;
}
return bigInteger.CheckProbablePrime(certainty, RandomSource, randomlySelected);
}
private bool CheckProbablePrime(int certainty, Random random, bool randomlySelected)
{
int num = System.Math.Min(BitLength - 1, primeLists.Length);
for (int i = 0; i < num; i++)
{
int num2 = Remainder(primeProducts[i]);
int[] array = primeLists[i];
foreach (int num3 in array)
{
if (num2 % num3 == 0)
{
if (BitLength < 16)
{
return IntValue == num3;
}
return false;
}
}
}
return RabinMillerTest(certainty, random, randomlySelected);
}
public bool RabinMillerTest(int certainty, Random random)
{
return RabinMillerTest(certainty, random, randomlySelected: false);
}
internal bool RabinMillerTest(int certainty, Random random, bool randomlySelected)
{
int bitLength = BitLength;
int num = (certainty - 1) / 2 + 1;
if (randomlySelected)
{
int num2 = ((bitLength >= 1024) ? 4 : ((bitLength >= 512) ? 8 : ((bitLength >= 256) ? 16 : 50)));
if (certainty < 100)
{
num = System.Math.Min(num2, num);
}
else
{
num -= 50;
num += num2;
}
}
int lowestSetBitMaskFirst = GetLowestSetBitMaskFirst(-2);
BigInteger e = ShiftRight(lowestSetBitMaskFirst);
BigInteger bigInteger = One.ShiftLeft(32 * magnitude.Length).Remainder(this);
BigInteger bigInteger2 = Subtract(bigInteger);
while (true)
{
BigInteger bigInteger3 = new BigInteger(BitLength, random);
if (bigInteger3.sign == 0 || bigInteger3.CompareTo(this) >= 0 || bigInteger3.IsEqualMagnitude(bigInteger) || bigInteger3.IsEqualMagnitude(bigInteger2))
{
continue;
}
BigInteger bigInteger4 = ModPowMonty(bigInteger3, e, this, convert: false);
if (!bigInteger4.Equals(bigInteger))
{
int num3 = 0;
while (!bigInteger4.Equals(bigInteger2))
{
if (++num3 == lowestSetBitMaskFirst)
{
return false;
}
bigInteger4 = ModPowMonty(bigInteger4, Two, this, convert: false);
if (bigInteger4.Equals(bigInteger))
{
return false;
}
}
}
if (--num <= 0)
{
break;
}
}
return true;
}
public BigInteger Max(BigInteger value)
{
if (CompareTo(value) <= 0)
{
return value;
}
return this;
}
public BigInteger Min(BigInteger value)
{
if (CompareTo(value) >= 0)
{
return value;
}
return this;
}
public BigInteger Mod(BigInteger m)
{
if (m.sign < 1)
{
throw new ArithmeticException("Modulus must be positive");
}
BigInteger bigInteger = Remainder(m);
if (bigInteger.sign < 0)
{
return bigInteger.Add(m);
}
return bigInteger;
}
public BigInteger ModInverse(BigInteger m)
{
if (m.sign < 1)
{
throw new ArithmeticException("Modulus must be positive");
}
if (m.QuickPow2Check())
{
return ModInversePow2(m);
}
BigInteger a = Remainder(m);
BigInteger u1Out;
BigInteger bigInteger = ExtEuclid(a, m, out u1Out);
if (!bigInteger.Equals(One))
{
throw new ArithmeticException("Numbers not relatively prime.");
}
if (u1Out.sign < 0)
{
return u1Out.Add(m);
}
return u1Out;
}
private BigInteger ModInversePow2(BigInteger m)
{
if (!TestBit(0))
{
throw new ArithmeticException("Numbers not relatively prime.");
}
int num = m.BitLength - 1;
long num2 = ModInverse64(LongValue);
if (num < 64)
{
num2 &= (1L << num) - 1;
}
BigInteger bigInteger = ValueOf(num2);
if (num > 64)
{
BigInteger val = Remainder(m);
int num3 = 64;
do
{
BigInteger n = bigInteger.Multiply(val).Remainder(m);
bigInteger = bigInteger.Multiply(Two.Subtract(n)).Remainder(m);
num3 <<= 1;
}
while (num3 < num);
}
if (bigInteger.sign < 0)
{
bigInteger = bigInteger.Add(m);
}
return bigInteger;
}
private static int ModInverse32(int d)
{
int num = d + (((d + 1) & 4) << 1);
num *= 2 - d * num;
num *= 2 - d * num;
return num * (2 - d * num);
}
private static long ModInverse64(long d)
{
long num = d + (((d + 1) & 4) << 1);
num *= 2 - d * num;
num *= 2 - d * num;
num *= 2 - d * num;
return num * (2 - d * num);
}
private static BigInteger ExtEuclid(BigInteger a, BigInteger b, out BigInteger u1Out)
{
BigInteger bigInteger = One;
BigInteger bigInteger2 = Zero;
BigInteger bigInteger3 = a;
BigInteger bigInteger4 = b;
if (bigInteger4.sign > 0)
{
while (true)
{
BigInteger[] array = bigInteger3.DivideAndRemainder(bigInteger4);
bigInteger3 = bigInteger4;
bigInteger4 = array[1];
BigInteger bigInteger5 = bigInteger;
bigInteger = bigInteger2;
if (bigInteger4.sign <= 0)
{
break;
}
bigInteger2 = bigInteger5.Subtract(bigInteger2.Multiply(array[0]));
}
}
u1Out = bigInteger;
return bigInteger3;
}
private static void ZeroOut(int[] x)
{
Array.Clear(x, 0, x.Length);
}
public BigInteger ModPow(BigInteger e, BigInteger m)
{
if (m.sign < 1)
{
throw new ArithmeticException("Modulus must be positive");
}
if (m.Equals(One))
{
return Zero;
}
if (e.sign == 0)
{
return One;
}
if (sign == 0)
{
return Zero;
}
bool flag = e.sign < 0;
if (flag)
{
e = e.Negate();
}
BigInteger bigInteger = Mod(m);
if (!e.Equals(One))
{
bigInteger = (((m.magnitude[m.magnitude.Length - 1] & 1) != 0) ? ModPowMonty(bigInteger, e, m, convert: true) : ModPowBarrett(bigInteger, e, m));
}
if (flag)
{
bigInteger = bigInteger.ModInverse(m);
}
return bigInteger;
}
private static BigInteger ModPowBarrett(BigInteger b, BigInteger e, BigInteger m)
{
int num = m.magnitude.Length;
BigInteger mr = One.ShiftLeft(num + 1 << 5);
BigInteger yu = One.ShiftLeft(num << 6).Divide(m);
int i = 0;
for (int bitLength = e.BitLength; bitLength > ExpWindowThresholds[i]; i++)
{
}
int num2 = 1 << i;
BigInteger[] array = new BigInteger[num2];
array[0] = b;
BigInteger bigInteger = ReduceBarrett(b.Square(), m, mr, yu);
for (int j = 1; j < num2; j++)
{
array[j] = ReduceBarrett(array[j - 1].Multiply(bigInteger), m, mr, yu);
}
int[] windowList = GetWindowList(e.magnitude, i);
int num3 = windowList[0];
int num4 = num3 & 0xFF;
int num5 = num3 >> 8;
BigInteger bigInteger2;
if (num4 == 1)
{
bigInteger2 = bigInteger;
num5--;
}
else
{
bigInteger2 = array[num4 >> 1];
}
int num6 = 1;
while ((num3 = windowList[num6++]) != -1)
{
num4 = num3 & 0xFF;
int num7 = num5 + BitLengthTable[num4];
for (int k = 0; k < num7; k++)
{
bigInteger2 = ReduceBarrett(bigInteger2.Square(), m, mr, yu);
}
bigInteger2 = ReduceBarrett(bigInteger2.Multiply(array[num4 >> 1]), m, mr, yu);
num5 = num3 >> 8;
}
for (int l = 0; l < num5; l++)
{
bigInteger2 = ReduceBarrett(bigInteger2.Square(), m, mr, yu);
}
return bigInteger2;
}
private static BigInteger ReduceBarrett(BigInteger x, BigInteger m, BigInteger mr, BigInteger yu)
{
int bitLength = x.BitLength;
int bitLength2 = m.BitLength;
if (bitLength < bitLength2)
{
return x;
}
if (bitLength - bitLength2 > 1)
{
int num = m.magnitude.Length;
BigInteger bigInteger = x.DivideWords(num - 1);
BigInteger bigInteger2 = bigInteger.Multiply(yu);
BigInteger bigInteger3 = bigInteger2.DivideWords(num + 1);
BigInteger bigInteger4 = x.RemainderWords(num + 1);
BigInteger bigInteger5 = bigInteger3.Multiply(m);
BigInteger n = bigInteger5.RemainderWords(num + 1);
x = bigInteger4.Subtract(n);
if (x.sign < 0)
{
x = x.Add(mr);
}
}
while (x.CompareTo(m) >= 0)
{
x = x.Subtract(m);
}
return x;
}
private static BigInteger ModPowMonty(BigInteger b, BigInteger e, BigInteger m, bool convert)
{
int num = m.magnitude.Length;
int num2 = 32 * num;
bool flag = m.BitLength + 2 <= num2;
uint mDash = (uint)m.GetMQuote();
if (convert)
{
b = b.ShiftLeft(num2).Remainder(m);
}
int[] a = new int[num + 1];
int[] array = b.magnitude;
if (array.Length < num)
{
int[] array2 = new int[num];
array.CopyTo(array2, num - array.Length);
array = array2;
}
int i = 0;
if (e.magnitude.Length > 1 || e.BitCount > 2)
{
for (int bitLength = e.BitLength; bitLength > ExpWindowThresholds[i]; i++)
{
}
}
int num3 = 1 << i;
int[][] array3 = new int[num3][];
array3[0] = array;
int[] array4 = Arrays.Clone(array);
SquareMonty(a, array4, m.magnitude, mDash, flag);
for (int j = 1; j < num3; j++)
{
array3[j] = Arrays.Clone(array3[j - 1]);
MultiplyMonty(a, array3[j], array4, m.magnitude, mDash, flag);
}
int[] windowList = GetWindowList(e.magnitude, i);
int num4 = windowList[0];
int num5 = num4 & 0xFF;
int num6 = num4 >> 8;
int[] array5;
if (num5 == 1)
{
array5 = array4;
num6--;
}
else
{
array5 = Arrays.Clone(array3[num5 >> 1]);
}
int num7 = 1;
while ((num4 = windowList[num7++]) != -1)
{
num5 = num4 & 0xFF;
int num8 = num6 + BitLengthTable[num5];
for (int k = 0; k < num8; k++)
{
SquareMonty(a, array5, m.magnitude, mDash, flag);
}
MultiplyMonty(a, array5, array3[num5 >> 1], m.magnitude, mDash, flag);
num6 = num4 >> 8;
}
for (int l = 0; l < num6; l++)
{
SquareMonty(a, array5, m.magnitude, mDash, flag);
}
if (convert)
{
MontgomeryReduce(array5, m.magnitude, mDash);
}
else if (flag && CompareTo(0, array5, 0, m.magnitude) >= 0)
{
Subtract(0, array5, 0, m.magnitude);
}
return new BigInteger(1, array5, checkMag: true);
}
private static int[] GetWindowList(int[] mag, int extraBits)
{
int num = mag[0];
int num2 = BitLen(num);
int num3 = ((mag.Length - 1 << 5) + num2) / (1 + extraBits) + 2;
int[] array = new int[num3];
int num4 = 0;
int num5 = 33 - num2;
num <<= num5;
int num6 = 1;
int num7 = 1 << extraBits;
int num8 = 0;
int num9 = 0;
while (true)
{
if (num5 < 32)
{
if (num6 < num7)
{
num6 = (num6 << 1) | (num >>> 31);
}
else if (num < 0)
{
array[num4++] = CreateWindowEntry(num6, num8);
num6 = 1;
num8 = 0;
}
else
{
num8++;
}
num <<= 1;
num5++;
}
else
{
if (++num9 == mag.Length)
{
break;
}
num = mag[num9];
num5 = 0;
}
}
array[num4++] = CreateWindowEntry(num6, num8);
array[num4] = -1;
return array;
}
private static int CreateWindowEntry(int mult, int zeroes)
{
while ((mult & 1) == 0)
{
mult >>= 1;
zeroes++;
}
return mult | (zeroes << 8);
}
private static int[] Square(int[] w, int[] x)
{
int num = w.Length - 1;
ulong num4;
for (int num2 = x.Length - 1; num2 > 0; num2--)
{
ulong num3 = (uint)x[num2];
num4 = num3 * num3 + (uint)w[num];
w[num] = (int)num4;
num4 >>= 32;
for (int num5 = num2 - 1; num5 >= 0; num5--)
{
ulong num6 = num3 * (uint)x[num5];
num4 += ((ulong)(uint)w[--num] & 0xFFFFFFFFuL) + (uint)((int)num6 << 1);
w[num] = (int)num4;
num4 = (num4 >> 32) + (num6 >> 31);
}
num4 += (uint)w[--num];
w[num] = (int)num4;
if (--num >= 0)
{
w[num] = (int)(num4 >> 32);
}
num += num2;
}
num4 = (uint)x[0];
num4 = num4 * num4 + (uint)w[num];
w[num] = (int)num4;
if (--num >= 0)
{
int[] array2;
int[] array = (array2 = w);
int num7 = num;
nint num8 = num7;
array[num7] = array2[num8] + (int)(num4 >> 32);
}
return w;
}
private static int[] Multiply(int[] x, int[] y, int[] z)
{
int num = z.Length;
if (num < 1)
{
return x;
}
int num2 = x.Length - y.Length;
do
{
long num3 = z[--num] & 0xFFFFFFFFu;
long num4 = 0L;
if (num3 != 0)
{
for (int num5 = y.Length - 1; num5 >= 0; num5--)
{
num4 += num3 * (y[num5] & 0xFFFFFFFFu) + (x[num2 + num5] & 0xFFFFFFFFu);
x[num2 + num5] = (int)num4;
num4 >>>= 32;
}
}
num2--;
if (num2 >= 0)
{
x[num2] = (int)num4;
}
}
while (num > 0);
return x;
}
private int GetMQuote()
{
if (mQuote != 0)
{
return mQuote;
}
int d = -magnitude[magnitude.Length - 1];
return mQuote = ModInverse32(d);
}
private static void MontgomeryReduce(int[] x, int[] m, uint mDash)
{
int num = m.Length;
for (int num2 = num - 1; num2 >= 0; num2--)
{
uint num3 = (uint)x[num - 1];
ulong num4 = num3 * mDash;
ulong num5 = num4 * (uint)m[num - 1] + num3;
num5 >>= 32;
for (int num6 = num - 2; num6 >= 0; num6--)
{
num5 += num4 * (uint)m[num6] + (uint)x[num6];
x[num6 + 1] = (int)num5;
num5 >>= 32;
}
x[0] = (int)num5;
}
if (CompareTo(0, x, 0, m) >= 0)
{
Subtract(0, x, 0, m);
}
}
private static void MultiplyMonty(int[] a, int[] x, int[] y, int[] m, uint mDash, bool smallMontyModulus)
{
int num = m.Length;
if (num == 1)
{
x[0] = (int)MultiplyMontyNIsOne((uint)x[0], (uint)y[0], (uint)m[0], mDash);
return;
}
uint num2 = (uint)y[num - 1];
ulong num3 = (uint)x[num - 1];
ulong num4 = num3 * num2;
ulong num5 = (uint)(int)num4 * mDash;
ulong num6 = num5 * (uint)m[num - 1];
num4 += (uint)num6;
num4 = (num4 >> 32) + (num6 >> 32);
for (int num7 = num - 2; num7 >= 0; num7--)
{
ulong num8 = num3 * (uint)y[num7];
num6 = num5 * (uint)m[num7];
num4 += (num8 & 0xFFFFFFFFu) + (uint)num6;
a[num7 + 2] = (int)num4;
num4 = (num4 >> 32) + (num8 >> 32) + (num6 >> 32);
}
a[1] = (int)num4;
int num9 = (int)(num4 >> 32);
for (int num10 = num - 2; num10 >= 0; num10--)
{
uint num11 = (uint)a[num];
ulong num12 = (uint)x[num10];
ulong num13 = num12 * num2;
ulong num14 = (num13 & 0xFFFFFFFFu) + num11;
ulong num15 = (uint)(int)num14 * mDash;
ulong num16 = num15 * (uint)m[num - 1];
num14 += (uint)num16;
num14 = (num14 >> 32) + (num13 >> 32) + (num16 >> 32);
for (int num17 = num - 2; num17 >= 0; num17--)
{
num13 = num12 * (uint)y[num17];
num16 = num15 * (uint)m[num17];
num14 += (num13 & 0xFFFFFFFFu) + (uint)num16 + (uint)a[num17 + 1];
a[num17 + 2] = (int)num14;
num14 = (num14 >> 32) + (num13 >> 32) + (num16 >> 32);
}
num14 += (uint)num9;
a[1] = (int)num14;
num9 = (int)(num14 >> 32);
}
a[0] = num9;
if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0)
{
Subtract(0, a, 0, m);
}
Array.Copy(a, 1, x, 0, num);
}
private static void SquareMonty(int[] a, int[] x, int[] m, uint mDash, bool smallMontyModulus)
{
int num = m.Length;
if (num == 1)
{
uint num2 = (uint)x[0];
x[0] = (int)MultiplyMontyNIsOne(num2, num2, (uint)m[0], mDash);
return;
}
ulong num3 = (uint)x[num - 1];
ulong num4 = num3 * num3;
ulong num5 = (uint)(int)num4 * mDash;
ulong num6 = num5 * (uint)m[num - 1];
num4 += (uint)num6;
num4 = (num4 >> 32) + (num6 >> 32);
for (int num7 = num - 2; num7 >= 0; num7--)
{
ulong num8 = num3 * (uint)x[num7];
num6 = num5 * (uint)m[num7];
num4 += (num6 & 0xFFFFFFFFu) + (uint)((int)num8 << 1);
a[num7 + 2] = (int)num4;
num4 = (num4 >> 32) + (num8 >> 31) + (num6 >> 32);
}
a[1] = (int)num4;
int num9 = (int)(num4 >> 32);
for (int num10 = num - 2; num10 >= 0; num10--)
{
uint num11 = (uint)a[num];
ulong num12 = num11 * mDash;
ulong num13 = num12 * (uint)m[num - 1] + num11;
num13 >>= 32;
for (int num14 = num - 2; num14 > num10; num14--)
{
num13 += num12 * (uint)m[num14] + (uint)a[num14 + 1];
a[num14 + 2] = (int)num13;
num13 >>= 32;
}
ulong num15 = (uint)x[num10];
ulong num16 = num15 * num15;
ulong num17 = num12 * (uint)m[num10];
num13 += (num16 & 0xFFFFFFFFu) + (uint)num17 + (uint)a[num10 + 1];
a[num10 + 2] = (int)num13;
num13 = (num13 >> 32) + (num16 >> 32) + (num17 >> 32);
for (int num18 = num10 - 1; num18 >= 0; num18--)
{
ulong num19 = num15 * (uint)x[num18];
ulong num20 = num12 * (uint)m[num18];
num13 += (num20 & 0xFFFFFFFFu) + (uint)((int)num19 << 1) + (uint)a[num18 + 1];
a[num18 + 2] = (int)num13;
num13 = (num13 >> 32) + (num19 >> 31) + (num20 >> 32);
}
num13 += (uint)num9;
a[1] = (int)num13;
num9 = (int)(num13 >> 32);
}
a[0] = num9;
if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0)
{
Subtract(0, a, 0, m);
}
Array.Copy(a, 1, x, 0, num);
}
private static uint MultiplyMontyNIsOne(uint x, uint y, uint m, uint mDash)
{
ulong num = (ulong)x * (ulong)y;
uint num2 = (uint)(int)num * mDash;
ulong num3 = m;
ulong num4 = num3 * num2;
num += (uint)num4;
num = (num >> 32) + (num4 >> 32);
if (num > num3)
{
num -= num3;
}
return (uint)num;
}
public BigInteger Multiply(BigInteger val)
{
if (val == this)
{
return Square();
}
if ((sign & val.sign) == 0)
{
return Zero;
}
if (val.QuickPow2Check())
{
BigInteger bigInteger = ShiftLeft(val.Abs().BitLength - 1);
if (val.sign <= 0)
{
return bigInteger.Negate();
}
return bigInteger;
}
if (QuickPow2Check())
{
BigInteger bigInteger2 = val.ShiftLeft(Abs().BitLength - 1);
if (sign <= 0)
{
return bigInteger2.Negate();
}
return bigInteger2;
}
int num = magnitude.Length + val.magnitude.Length;
int[] array = new int[num];
Multiply(array, magnitude, val.magnitude);
int signum = sign ^ val.sign ^ 1;
return new BigInteger(signum, array, checkMag: true);
}
public BigInteger Square()
{
if (sign == 0)
{
return Zero;
}
if (QuickPow2Check())
{
return ShiftLeft(Abs().BitLength - 1);
}
int num = magnitude.Length << 1;
if (magnitude[0] >>> 16 == 0)
{
num--;
}
int[] array = new int[num];
Square(array, magnitude);
return new BigInteger(1, array, checkMag: false);
}
public BigInteger Negate()
{
if (sign == 0)
{
return this;
}
return new BigInteger(-sign, magnitude, checkMag: false);
}
public BigInteger NextProbablePrime()
{
if (sign < 0)
{
throw new ArithmeticException("Cannot be called on value < 0");
}
if (CompareTo(Two) < 0)
{
return Two;
}
BigInteger bigInteger = Inc().SetBit(0);
while (!bigInteger.CheckProbablePrime(100, RandomSource, randomlySelected: false))
{
bigInteger = bigInteger.Add(Two);
}
return bigInteger;
}
public BigInteger Not()
{
return Inc().Negate();
}
public BigInteger Pow(int exp)
{
if (exp <= 0)
{
if (exp < 0)
{
throw new ArithmeticException("Negative exponent");
}
return One;
}
if (sign == 0)
{
return this;
}
if (QuickPow2Check())
{
long num = (long)exp * (long)(BitLength - 1);
if (num > int.MaxValue)
{
throw new ArithmeticException("Result too large");
}
return One.ShiftLeft((int)num);
}
BigInteger bigInteger = One;
BigInteger bigInteger2 = this;
while (true)
{
if ((exp & 1) == 1)
{
bigInteger = bigInteger.Multiply(bigInteger2);
}
exp >>= 1;
if (exp == 0)
{
break;
}
bigInteger2 = bigInteger2.Multiply(bigInteger2);
}
return bigInteger;
}
public static BigInteger ProbablePrime(int bitLength, Random random)
{
return new BigInteger(bitLength, 100, random);
}
private int Remainder(int m)
{
long num = 0L;
for (int i = 0; i < magnitude.Length; i++)
{
long num2 = (uint)magnitude[i];
num = ((num << 32) | num2) % m;
}
return (int)num;
}
private static int[] Remainder(int[] x, int[] y)
{
int i;
for (i = 0; i < x.Length && x[i] == 0; i++)
{
}
int j;
for (j = 0; j < y.Length && y[j] == 0; j++)
{
}
int num = CompareNoLeadingZeroes(i, x, j, y);
if (num > 0)
{
int num2 = CalcBitLength(1, j, y);
int num3 = CalcBitLength(1, i, x);
int num4 = num3 - num2;
int k = 0;
int num5 = num2;
int[] array;
if (num4 > 0)
{
array = ShiftLeft(y, num4);
num5 += num4;
}
else
{
int num6 = y.Length - j;
array = new int[num6];
Array.Copy(y, j, array, 0, num6);
}
while (true)
{
if (num5 < num3 || CompareNoLeadingZeroes(i, x, k, array) >= 0)
{
Subtract(i, x, k, array);
while (x[i] == 0)
{
if (++i == x.Length)
{
return x;
}
}
num3 = 32 * (x.Length - i - 1) + BitLen(x[i]);
if (num3 <= num2)
{
if (num3 < num2)
{
return x;
}
num = CompareNoLeadingZeroes(i, x, j, y);
if (num <= 0)
{
break;
}
}
}
num4 = num5 - num3;
if (num4 == 1)
{
uint num7 = (uint)array[k] >> 1;
uint num8 = (uint)x[i];
if (num7 > num8)
{
num4++;
}
}
if (num4 < 2)
{
ShiftRightOneInPlace(k, array);
num5--;
}
else
{
ShiftRightInPlace(k, array, num4);
num5 -= num4;
}
for (; array[k] == 0; k++)
{
}
}
}
if (num == 0)
{
Array.Clear(x, i, x.Length - i);
}
return x;
}
public BigInteger Remainder(BigInteger n)
{
if (n.sign == 0)
{
throw new ArithmeticException("Division by zero error");
}
if (sign == 0)
{
return Zero;
}
if (n.magnitude.Length == 1)
{
int num = n.magnitude[0];
if (num > 0)
{
if (num == 1)
{
return Zero;
}
int num2 = Remainder(num);
if (num2 != 0)
{
return new BigInteger(sign, new int[1] { num2 }, checkMag: false);
}
return Zero;
}
}
if (CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude) < 0)
{
return this;
}
int[] mag;
if (n.QuickPow2Check())
{
mag = LastNBits(n.Abs().BitLength - 1);
}
else
{
mag = (int[])magnitude.Clone();
mag = Remainder(mag, n.magnitude);
}
return new BigInteger(sign, mag, checkMag: true);
}
private int[] LastNBits(int n)
{
if (n < 1)
{
return ZeroMagnitude;
}
int val = (n + 32 - 1) / 32;
val = System.Math.Min(val, magnitude.Length);
int[] array = new int[val];
Array.Copy(magnitude, magnitude.Length - val, array, 0, val);
int num = (val << 5) - n;
if (num > 0)
{
int[] array2;
(array2 = array)[0] = array2[0] & (-1 >>> num);
}
return array;
}
private BigInteger DivideWords(int w)
{
int num = magnitude.Length;
if (w >= num)
{
return Zero;
}
int[] array = new int[num - w];
Array.Copy(magnitude, 0, array, 0, num - w);
return new BigInteger(sign, array, checkMag: false);
}
private BigInteger RemainderWords(int w)
{
int num = magnitude.Length;
if (w >= num)
{
return this;
}
int[] array = new int[w];
Array.Copy(magnitude, num - w, array, 0, w);
return new BigInteger(sign, array, checkMag: false);
}
private static int[] ShiftLeft(int[] mag, int n)
{
int num = n >>> 5;
int num2 = n & 0x1F;
int num3 = mag.Length;
int[] array;
if (num2 == 0)
{
array = new int[num3 + num];
mag.CopyTo(array, 0);
}
else
{
int num4 = 0;
int num5 = 32 - num2;
int num6 = mag[0] >>> num5;
if (num6 != 0)
{
array = new int[num3 + num + 1];
array[num4++] = num6;
}
else
{
array = new int[num3 + num];
}
int num7 = mag[0];
for (int i = 0; i < num3 - 1; i++)
{
int num8 = mag[i + 1];
array[num4++] = (num7 << num2) | (num8 >>> num5);
num7 = num8;
}
array[num4] = mag[num3 - 1] << num2;
}
return array;
}
private static int ShiftLeftOneInPlace(int[] x, int carry)
{
int num = x.Length;
while (--num >= 0)
{
uint num2 = (uint)x[num];
x[num] = (int)(num2 << 1) | carry;
carry = (int)(num2 >> 31);
}
return carry;
}
public BigInteger ShiftLeft(int n)
{
if (sign == 0 || magnitude.Length == 0)
{
return Zero;
}
if (n == 0)
{
return this;
}
if (n < 0)
{
return ShiftRight(-n);
}
BigInteger bigInteger = new BigInteger(sign, ShiftLeft(magnitude, n), checkMag: true);
if (nBits != -1)
{
bigInteger.nBits = ((sign > 0) ? nBits : (nBits + n));
}
if (nBitLength != -1)
{
bigInteger.nBitLength = nBitLength + n;
}
return bigInteger;
}
private static void ShiftRightInPlace(int start, int[] mag, int n)
{
int num = (n >>> 5) + start;
int num2 = n & 0x1F;
int num3 = mag.Length - 1;
if (num != start)
{
int num4 = num - start;
for (int num5 = num3; num5 >= num; num5--)
{
mag[num5] = mag[num5 - num4];
}
for (int num6 = num - 1; num6 >= start; num6--)
{
mag[num6] = 0;
}
}
if (num2 != 0)
{
int num7 = 32 - num2;
int num8 = mag[num3];
for (int num9 = num3; num9 > num; num9--)
{
int num10 = mag[num9 - 1];
mag[num9] = (num8 >>> num2) | (num10 << num7);
num8 = num10;
}
mag[num] >>>= num2;
}
}
private static void ShiftRightOneInPlace(int start, int[] mag)
{
int num = mag.Length;
int num2 = mag[num - 1];
while (--num > start)
{
int num3 = mag[num - 1];
mag[num] = (num2 >>> 1) | (num3 << 31);
num2 = num3;
}
mag[start] >>>= 1;
}
public BigInteger ShiftRight(int n)
{
if (n == 0)
{
return this;
}
if (n < 0)
{
return ShiftLeft(-n);
}
if (n >= BitLength)
{
if (sign >= 0)
{
return Zero;
}
return One.Negate();
}
int num = BitLength - n + 31 >> 5;
int[] array = new int[num];
int num2 = n >> 5;
int num3 = n & 0x1F;
if (num3 == 0)
{
Array.Copy(magnitude, 0, array, 0, array.Length);
}
else
{
int num4 = 32 - num3;
int num5 = magnitude.Length - 1 - num2;
for (int num6 = num - 1; num6 >= 0; num6--)
{
array[num6] = magnitude[num5--] >>> num3;
if (num5 >= 0)
{
int[] array3;
int[] array2 = (array3 = array);
int num7 = num6;
nint num8 = num7;
array2[num7] = array3[num8] | (magnitude[num5] << num4);
}
}
}
return new BigInteger(sign, array, checkMag: false);
}
private static int[] Subtract(int xStart, int[] x, int yStart, int[] y)
{
int num = x.Length;
int num2 = y.Length;
int num3 = 0;
do
{
long num4 = (x[--num] & 0xFFFFFFFFu) - (y[--num2] & 0xFFFFFFFFu) + num3;
x[num] = (int)num4;
num3 = (int)(num4 >> 63);
}
while (num2 > yStart);
if (num3 != 0)
{
int[] array;
int[] array2;
int num5;
nint num6;
do
{
array = (array2 = x);
num5 = --num;
num6 = num5;
}
while ((array[num5] = array2[num6] - 1) == -1);
}
return x;
}
public BigInteger Subtract(BigInteger n)
{
if (n.sign == 0)
{
return this;
}
if (sign == 0)
{
return n.Negate();
}
if (sign != n.sign)
{
return Add(n.Negate());
}
int num = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude);
if (num == 0)
{
return Zero;
}
BigInteger bigInteger;
BigInteger bigInteger2;
if (num < 0)
{
bigInteger = n;
bigInteger2 = this;
}
else
{
bigInteger = this;
bigInteger2 = n;
}
return new BigInteger(sign * num, doSubBigLil(bigInteger.magnitude, bigInteger2.magnitude), checkMag: true);
}
private static int[] doSubBigLil(int[] bigMag, int[] lilMag)
{
int[] x = (int[])bigMag.Clone();
return Subtract(0, x, 0, lilMag);
}
public byte[] ToByteArray()
{
return ToByteArray(unsigned: false);
}
public byte[] ToByteArrayUnsigned()
{
return ToByteArray(unsigned: true);
}
private byte[] ToByteArray(bool unsigned)
{
if (sign == 0)
{
if (!unsigned)
{
return new byte[1];
}
return ZeroEncoding;
}
int num = ((unsigned && sign > 0) ? BitLength : (BitLength + 1));
int byteLength = GetByteLength(num);
byte[] array = new byte[byteLength];
int num2 = magnitude.Length;
int num3 = array.Length;
if (sign > 0)
{
while (num2 > 1)
{
uint num4 = (uint)magnitude[--num2];
array[--num3] = (byte)num4;
array[--num3] = (byte)(num4 >> 8);
array[--num3] = (byte)(num4 >> 16);
array[--num3] = (byte)(num4 >> 24);
}
uint num5;
for (num5 = (uint)magnitude[0]; num5 > 255; num5 >>= 8)
{
array[--num3] = (byte)num5;
}
array[--num3] = (byte)num5;
}
else
{
bool flag = true;
while (num2 > 1)
{
uint num6 = (uint)(~magnitude[--num2]);
if (flag)
{
flag = ++num6 == 0;
}
array[--num3] = (byte)num6;
array[--num3] = (byte)(num6 >> 8);
array[--num3] = (byte)(num6 >> 16);
array[--num3] = (byte)(num6 >> 24);
}
uint num7 = (uint)magnitude[0];
if (flag)
{
num7--;
}
while (num7 > 255)
{
array[--num3] = (byte)(~num7);
num7 >>= 8;
}
array[--num3] = (byte)(~num7);
if (num3 > 0)
{
array[--num3] = byte.MaxValue;
}
}
return array;
}
public override string ToString()
{
return ToString(10);
}
public string ToString(int radix)
{
switch (radix)
{
default:
throw new FormatException("Only bases 2, 8, 10, 16 are allowed");
case 2:
case 8:
case 10:
case 16:
{
if (magnitude == null)
{
return "null";
}
if (sign == 0)
{
return "0";
}
int i;
for (i = 0; i < magnitude.Length && magnitude[i] == 0; i++)
{
}
if (i == magnitude.Length)
{
return "0";
}
StringBuilder stringBuilder = new StringBuilder();
if (sign == -1)
{
stringBuilder.Append('-');
}
switch (radix)
{
case 2:
{
int num5 = i;
stringBuilder.Append(Convert.ToString(magnitude[num5], 2));
while (++num5 < magnitude.Length)
{
AppendZeroExtendedString(stringBuilder, Convert.ToString(magnitude[num5], 2), 32);
}
break;
}
case 8:
{
int num = 1073741823;
BigInteger bigInteger3 = Abs();
int num2 = bigInteger3.BitLength;
IList list2 = Platform.CreateArrayList();
while (num2 > 30)
{
list2.Add(Convert.ToString(bigInteger3.IntValue & num, 8));
bigInteger3 = bigInteger3.ShiftRight(30);
num2 -= 30;
}
stringBuilder.Append(Convert.ToString(bigInteger3.IntValue, 8));
for (int num3 = list2.Count - 1; num3 >= 0; num3--)
{
AppendZeroExtendedString(stringBuilder, (string)list2[num3], 10);
}
break;
}
case 16:
{
int num4 = i;
stringBuilder.Append(Convert.ToString(magnitude[num4], 16));
while (++num4 < magnitude.Length)
{
AppendZeroExtendedString(stringBuilder, Convert.ToString(magnitude[num4], 16), 8);
}
break;
}
case 10:
{
BigInteger bigInteger = Abs();
if (bigInteger.BitLength < 64)
{
stringBuilder.Append(Convert.ToString(bigInteger.LongValue, radix));
break;
}
IList list = Platform.CreateArrayList();
BigInteger bigInteger2 = ValueOf(radix);
while (bigInteger2.CompareTo(bigInteger) <= 0)
{
list.Add(bigInteger2);
bigInteger2 = bigInteger2.Square();
}
int count = list.Count;
stringBuilder.EnsureCapacity(stringBuilder.Length + (1 << count));
ToString(stringBuilder, radix, list, count, bigInteger);
break;
}
}
return stringBuilder.ToString();
}
}
}
private static void ToString(StringBuilder sb, int radix, IList moduli, int scale, BigInteger pos)
{
if (pos.BitLength < 64)
{
string text = Convert.ToString(pos.LongValue, radix);
if (sb.Length > 1 || (sb.Length == 1 && sb[0] != '-'))
{
AppendZeroExtendedString(sb, text, 1 << scale);
}
else if (pos.SignValue != 0)
{
sb.Append(text);
}
}
else
{
BigInteger[] array = pos.DivideAndRemainder((BigInteger)moduli[--scale]);
ToString(sb, radix, moduli, scale, array[0]);
ToString(sb, radix, moduli, scale, array[1]);
}
}
private static void AppendZeroExtendedString(StringBuilder sb, string s, int minLength)
{
for (int i = s.Length; i < minLength; i++)
{
sb.Append('0');
}
sb.Append(s);
}
private static BigInteger CreateUValueOf(ulong value)
{
int num = (int)(value >> 32);
int num2 = (int)value;
if (num != 0)
{
return new BigInteger(1, new int[2] { num, num2 }, checkMag: false);
}
if (num2 != 0)
{
BigInteger bigInteger = new BigInteger(1, new int[1] { num2 }, checkMag: false);
if ((num2 & -num2) == num2)
{
bigInteger.nBits = 1;
}
return bigInteger;
}
return Zero;
}
private static BigInteger CreateValueOf(long value)
{
if (value < 0)
{
if (value == long.MinValue)
{
return CreateValueOf(~value).Not();
}
return CreateValueOf(-value).Negate();
}
return CreateUValueOf((ulong)value);
}
public static BigInteger ValueOf(long value)
{
if (value >= 0 && value < SMALL_CONSTANTS.Length)
{
return SMALL_CONSTANTS[value];
}
return CreateValueOf(value);
}
public int GetLowestSetBit()
{
if (sign == 0)
{
return -1;
}
return GetLowestSetBitMaskFirst(-1);
}
private int GetLowestSetBitMaskFirst(int firstWordMask)
{
int num = magnitude.Length;
int num2 = 0;
uint num3 = (uint)(magnitude[--num] & firstWordMask);
while (num3 == 0)
{
num3 = (uint)magnitude[--num];
num2 += 32;
}
while ((num3 & 0xFF) == 0)
{
num3 >>= 8;
num2 += 8;
}
while ((num3 & 1) == 0)
{
num3 >>= 1;
num2++;
}
return num2;
}
public bool TestBit(int n)
{
if (n < 0)
{
throw new ArithmeticException("Bit position must not be negative");
}
if (sign < 0)
{
return !Not().TestBit(n);
}
int num = n / 32;
if (num >= magnitude.Length)
{
return false;
}
int num2 = magnitude[magnitude.Length - 1 - num];
return ((num2 >> n % 32) & 1) > 0;
}
public BigInteger Or(BigInteger value)
{
if (sign == 0)
{
return value;
}
if (value.sign == 0)
{
return this;
}
int[] array = ((sign > 0) ? magnitude : Add(One).magnitude);
int[] array2 = ((value.sign > 0) ? value.magnitude : value.Add(One).magnitude);
bool flag = sign < 0 || value.sign < 0;
int num = System.Math.Max(array.Length, array2.Length);
int[] array3 = new int[num];
int num2 = array3.Length - array.Length;
int num3 = array3.Length - array2.Length;
for (int i = 0; i < array3.Length; i++)
{
int num4 = ((i >= num2) ? array[i - num2] : 0);
int num5 = ((i >= num3) ? array2[i - num3] : 0);
if (sign < 0)
{
num4 = ~num4;
}
if (value.sign < 0)
{
num5 = ~num5;
}
array3[i] = num4 | num5;
if (flag)
{
array3[i] = ~array3[i];
}
}
BigInteger bigInteger = new BigInteger(1, array3, checkMag: true);
if (flag)
{
bigInteger = bigInteger.Not();
}
return bigInteger;
}
public BigInteger Xor(BigInteger value)
{
if (sign == 0)
{
return value;
}
if (value.sign == 0)
{
return this;
}
int[] array = ((sign > 0) ? magnitude : Add(One).magnitude);
int[] array2 = ((value.sign > 0) ? value.magnitude : value.Add(One).magnitude);
bool flag = (sign < 0 && value.sign >= 0) || (sign >= 0 && value.sign < 0);
int num = System.Math.Max(array.Length, array2.Length);
int[] array3 = new int[num];
int num2 = array3.Length - array.Length;
int num3 = array3.Length - array2.Length;
for (int i = 0; i < array3.Length; i++)
{
int num4 = ((i >= num2) ? array[i - num2] : 0);
int num5 = ((i >= num3) ? array2[i - num3] : 0);
if (sign < 0)
{
num4 = ~num4;
}
if (value.sign < 0)
{
num5 = ~num5;
}
array3[i] = num4 ^ num5;
if (flag)
{
array3[i] = ~array3[i];
}
}
BigInteger bigInteger = new BigInteger(1, array3, checkMag: true);
if (flag)
{
bigInteger = bigInteger.Not();
}
return bigInteger;
}
public BigInteger SetBit(int n)
{
if (n < 0)
{
throw new ArithmeticException("Bit address less than zero");
}
if (TestBit(n))
{
return this;
}
if (sign > 0 && n < BitLength - 1)
{
return FlipExistingBit(n);
}
return Or(One.ShiftLeft(n));
}
public BigInteger ClearBit(int n)
{
if (n < 0)
{
throw new ArithmeticException("Bit address less than zero");
}
if (!TestBit(n))
{
return this;
}
if (sign > 0 && n < BitLength - 1)
{
return FlipExistingBit(n);
}
return AndNot(One.ShiftLeft(n));
}
public BigInteger FlipBit(int n)
{
if (n < 0)
{
throw new ArithmeticException("Bit address less than zero");
}
if (sign > 0 && n < BitLength - 1)
{
return FlipExistingBit(n);
}
return Xor(One.ShiftLeft(n));
}
private BigInteger FlipExistingBit(int n)
{
int[] array = (int[])magnitude.Clone();
int[] array3;
int[] array2 = (array3 = array);
int num = array.Length - 1 - (n >> 5);
nint num2 = num;
array2[num] = array3[num2] ^ (1 << (n & 0x1F));
return new BigInteger(sign, array, checkMag: false);
}
}