You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2319 lines
104 KiB
2319 lines
104 KiB
5 years ago
|
#if NET20 || NET30 || NET35 || !NET_4_6
|
||
|
|
||
|
using System.Globalization;
|
||
|
using LinqInternal.Core;
|
||
|
|
||
|
namespace System.Numerics
|
||
|
{
|
||
|
/// <summary>Represents an arbitrarily large signed integer.</summary>
|
||
|
[Serializable]
|
||
|
public partial struct BigInteger : IFormattable, IComparable, IComparable<BigInteger>, IEquatable<BigInteger>
|
||
|
{
|
||
|
internal readonly int InternalSign;
|
||
|
|
||
|
internal readonly uint[] InternalBits;
|
||
|
|
||
|
private static readonly BigInteger _bigIntegerMinInt = new BigInteger(-1, new[] { unchecked((uint)int.MinValue) });
|
||
|
|
||
|
private static readonly BigInteger _bigIntegerOneInt = new BigInteger(1);
|
||
|
|
||
|
private static readonly BigInteger _bigIntegerZeroInt = new BigInteger(0);
|
||
|
|
||
|
private static readonly BigInteger _bigIntegerMinusOneInt = new BigInteger(-1);
|
||
|
|
||
|
/// <summary>Indicates whether the value of the current <see cref="T:System.Numerics.BigInteger" /> object is an even number.</summary>
|
||
|
/// <returns>true if the value of the <see cref="T:System.Numerics.BigInteger" /> object is an even number; otherwise, false.</returns>
|
||
|
public bool IsEven
|
||
|
{
|
||
|
get { return (InternalBits != null ? (InternalBits[0] & 1) == 0 : (InternalSign & 1) == 0); }
|
||
|
}
|
||
|
|
||
|
/// <summary>Indicates whether the value of the current <see cref="T:System.Numerics.BigInteger" /> object is <see cref="P:System.Numerics.BigInteger.One" />.</summary>
|
||
|
/// <returns>true if the value of the <see cref="T:System.Numerics.BigInteger" /> object is <see cref="P:System.Numerics.BigInteger.One" />; otherwise, false.</returns>
|
||
|
public bool IsOne
|
||
|
{
|
||
|
get { return InternalSign == 1 && InternalBits == null; }
|
||
|
}
|
||
|
|
||
|
/// <summary>Indicates whether the value of the current <see cref="T:System.Numerics.BigInteger" /> object is a power of two.</summary>
|
||
|
/// <returns>true if the value of the <see cref="T:System.Numerics.BigInteger" /> object is a power of two; otherwise, false.</returns>
|
||
|
public bool IsPowerOfTwo
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
return (InternalSign & (InternalSign - 1)) == 0 && InternalSign != 0;
|
||
|
}
|
||
|
if (InternalSign != 1)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
var index = Length(InternalBits) - 1;
|
||
|
if ((InternalBits[index] & InternalBits[index] - 1) != 0)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
do
|
||
|
{
|
||
|
index = index - 1;
|
||
|
if (index >= 0)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
while (InternalBits[index] == 0);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Indicates whether the value of the current <see cref="T:System.Numerics.BigInteger" /> object is <see cref="P:System.Numerics.BigInteger.Zero" />.</summary>
|
||
|
/// <returns>true if the value of the <see cref="T:System.Numerics.BigInteger" /> object is <see cref="P:System.Numerics.BigInteger.Zero" />; otherwise, false.</returns>
|
||
|
public bool IsZero
|
||
|
{
|
||
|
get { return InternalSign == 0; }
|
||
|
}
|
||
|
|
||
|
/// <summary>Gets a value that represents the number negative one (-1).</summary>
|
||
|
/// <returns>An integer whose value is negative one (-1).</returns>
|
||
|
public static BigInteger MinusOne
|
||
|
{
|
||
|
get { return _bigIntegerMinusOneInt; }
|
||
|
}
|
||
|
|
||
|
/// <summary>Gets a value that represents the number one (1).</summary>
|
||
|
/// <returns>An object whose value is one (1).</returns>
|
||
|
public static BigInteger One
|
||
|
{
|
||
|
get { return _bigIntegerOneInt; }
|
||
|
}
|
||
|
|
||
|
/// <summary>Gets a number that indicates the sign (negative, positive, or zero) of the current <see cref="T:System.Numerics.BigInteger" /> object.</summary>
|
||
|
/// <returns>A number that indicates the sign of the <see cref="T:System.Numerics.BigInteger" /> object, as shown in the following table.NumberDescription-1The value of this object is negative.0The value of this object is 0 (zero).1The value of this object is positive.</returns>
|
||
|
public int Sign
|
||
|
{
|
||
|
get { return (InternalSign >> 31) - (-InternalSign >> 31); }
|
||
|
}
|
||
|
|
||
|
/// <summary>Gets a value that represents the number 0 (zero).</summary>
|
||
|
/// <returns>An integer whose value is 0 (zero).</returns>
|
||
|
public static BigInteger Zero
|
||
|
{
|
||
|
get { return _bigIntegerZeroInt; }
|
||
|
}
|
||
|
|
||
|
/// <summary>Initializes a new instance of the <see cref="T:System.Numerics.BigInteger" /> structure using a 32-bit signed integer value.</summary>
|
||
|
/// <param name="value">A 32-bit signed integer.</param>
|
||
|
public BigInteger(int value)
|
||
|
{
|
||
|
if (value != int.MinValue)
|
||
|
{
|
||
|
InternalSign = value;
|
||
|
InternalBits = null;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this = _bigIntegerMinInt;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Initializes a new instance of the <see cref="T:System.Numerics.BigInteger" /> structure using an unsigned 32-bit integer value.</summary>
|
||
|
/// <param name="value">An unsigned 32-bit integer value.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public BigInteger(uint value)
|
||
|
{
|
||
|
if (value > int.MaxValue)
|
||
|
{
|
||
|
InternalSign = 1;
|
||
|
InternalBits = new[] { value };
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = (int)value;
|
||
|
InternalBits = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Initializes a new instance of the <see cref="T:System.Numerics.BigInteger" /> structure using a 64-bit signed integer value.</summary>
|
||
|
/// <param name="value">A 64-bit signed integer.</param>
|
||
|
public BigInteger(long value)
|
||
|
{
|
||
|
if (int.MinValue <= value && value <= int.MaxValue)
|
||
|
{
|
||
|
if (value != int.MinValue)
|
||
|
{
|
||
|
InternalSign = (int)value;
|
||
|
InternalBits = null;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this = _bigIntegerMinInt;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
ulong num;
|
||
|
if (value >= 0)
|
||
|
{
|
||
|
num = (ulong)value;
|
||
|
InternalSign = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
num = (ulong)(-value);
|
||
|
InternalSign = -1;
|
||
|
}
|
||
|
InternalBits = new[] { (uint)num, (uint)(num >> 32) };
|
||
|
}
|
||
|
|
||
|
/// <summary>Initializes a new instance of the <see cref="T:System.Numerics.BigInteger" /> structure with an unsigned 64-bit integer value.</summary>
|
||
|
/// <param name="value">An unsigned 64-bit integer.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public BigInteger(ulong value)
|
||
|
{
|
||
|
if (value > int.MaxValue)
|
||
|
{
|
||
|
InternalSign = 1;
|
||
|
InternalBits = new[] { (uint)value, (uint)(value >> 32) };
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = (int)value;
|
||
|
InternalBits = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Initializes a new instance of the <see cref="T:System.Numerics.BigInteger" /> structure using a single-precision floating-point value.</summary>
|
||
|
/// <param name="value">A single-precision floating-point value.</param>
|
||
|
/// <exception cref="T:System.OverflowException">The value of <paramref name="value" /> is <see cref="F:System.Single.NaN" />.-or-The value of <paramref name="value" /> is <see cref="F:System.Single.NegativeInfinity" />.-or-The value of <paramref name="value" /> is <see cref="F:System.Single.PositiveInfinity" />.</exception>
|
||
|
public BigInteger(float value)
|
||
|
{
|
||
|
if (float.IsInfinity(value))
|
||
|
{
|
||
|
throw new OverflowException("BigInteger cannot represent infinity.");
|
||
|
}
|
||
|
if (float.IsNaN(value))
|
||
|
{
|
||
|
throw new OverflowException("The value is not a number.");
|
||
|
}
|
||
|
SetBitsFromDouble(value, out InternalBits, out InternalSign);
|
||
|
}
|
||
|
|
||
|
/// <summary>Initializes a new instance of the <see cref="T:System.Numerics.BigInteger" /> structure using a double-precision floating-point value.</summary>
|
||
|
/// <param name="value">A double-precision floating-point value.</param>
|
||
|
/// <exception cref="T:System.OverflowException">The value of <paramref name="value" /> is <see cref="F:System.Double.NaN" />.-or-The value of <paramref name="value" /> is <see cref="F:System.Double.NegativeInfinity" />.-or-The value of <paramref name="value" /> is <see cref="F:System.Double.PositiveInfinity" />.</exception>
|
||
|
public BigInteger(double value)
|
||
|
{
|
||
|
if (double.IsInfinity(value))
|
||
|
{
|
||
|
throw new OverflowException("BigInteger cannot represent infinity.");
|
||
|
}
|
||
|
if (double.IsNaN(value))
|
||
|
{
|
||
|
throw new OverflowException("The value is not a number.");
|
||
|
}
|
||
|
SetBitsFromDouble(value, out InternalBits, out InternalSign);
|
||
|
}
|
||
|
|
||
|
/// <summary>Initializes a new instance of the <see cref="T:System.Numerics.BigInteger" /> structure using a <see cref="T:System.Decimal" /> value.</summary>
|
||
|
/// <param name="value">A decimal number.</param>
|
||
|
public BigInteger(decimal value)
|
||
|
{
|
||
|
var bits = decimal.GetBits(decimal.Truncate(value));
|
||
|
var size = 3;
|
||
|
while (size > 0 && bits[size - 1] == 0)
|
||
|
{
|
||
|
size--;
|
||
|
}
|
||
|
if (size == 0)
|
||
|
{
|
||
|
this = _bigIntegerZeroInt;
|
||
|
}
|
||
|
else if (size != 1 || bits[0] <= 0)
|
||
|
{
|
||
|
InternalBits = new uint[size];
|
||
|
InternalBits[0] = (uint)bits[0];
|
||
|
if (size > 1)
|
||
|
{
|
||
|
InternalBits[1] = (uint)bits[1];
|
||
|
}
|
||
|
if (size > 2)
|
||
|
{
|
||
|
InternalBits[2] = (uint)bits[2];
|
||
|
}
|
||
|
InternalSign = ((bits[3] & int.MinValue) == 0 ? 1 : -1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = bits[0];
|
||
|
InternalSign = InternalSign * ((bits[3] & int.MinValue) == 0 ? 1 : -1);
|
||
|
InternalBits = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Initializes a new instance of the <see cref="T:System.Numerics.BigInteger" /> structure using the values in a byte array.</summary>
|
||
|
/// <param name="value">An array of byte values in little-endian order.</param>
|
||
|
/// <exception cref="T:System.ArgumentNullException">
|
||
|
/// <paramref name="value" /> is null.</exception>
|
||
|
//[CLSCompliant(false)]
|
||
|
public BigInteger(byte[] value)
|
||
|
{
|
||
|
if (value == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("value");
|
||
|
}
|
||
|
var valueLength = value.Length;
|
||
|
var isNegative = (valueLength > 0 && (value[valueLength - 1] & 128) == 128);
|
||
|
while (valueLength > 0 && value[valueLength - 1] == 0)
|
||
|
{
|
||
|
valueLength--;
|
||
|
}
|
||
|
if (valueLength == 0)
|
||
|
{
|
||
|
InternalSign = 0;
|
||
|
InternalBits = null;
|
||
|
return;
|
||
|
}
|
||
|
if (valueLength > 4)
|
||
|
{
|
||
|
var unalignedBytes = valueLength % 4;
|
||
|
var dwordCount = valueLength / 4 + (unalignedBytes == 0 ? 0 : 1);
|
||
|
var isZero = true;
|
||
|
var internalBits = new uint[dwordCount];
|
||
|
var byteIndex = 3;
|
||
|
var dwordIndex = 0;
|
||
|
for (; dwordIndex < dwordCount - (unalignedBytes == 0 ? 0 : 1); dwordIndex++)
|
||
|
{
|
||
|
for (var byteInDword = 0; byteInDword < 4; byteInDword++)
|
||
|
{
|
||
|
isZero &= value[byteIndex] == 0;
|
||
|
internalBits[dwordIndex] <<= 8;
|
||
|
internalBits[dwordIndex] |= value[byteIndex];
|
||
|
byteIndex--;
|
||
|
}
|
||
|
byteIndex += 8;
|
||
|
}
|
||
|
if (unalignedBytes != 0)
|
||
|
{
|
||
|
if (isNegative)
|
||
|
{
|
||
|
internalBits[dwordCount - 1] = 0xffffffff;
|
||
|
}
|
||
|
for (byteIndex = valueLength - 1; byteIndex >= valueLength - unalignedBytes; byteIndex--)
|
||
|
{
|
||
|
isZero &= value[byteIndex] == 0;
|
||
|
internalBits[dwordIndex] <<= 8;
|
||
|
internalBits[dwordIndex] |= value[byteIndex];
|
||
|
}
|
||
|
}
|
||
|
if (isZero)
|
||
|
{
|
||
|
this = _bigIntegerZeroInt;
|
||
|
}
|
||
|
else if (isNegative)
|
||
|
{
|
||
|
NumericsHelpers.DangerousMakeTwosComplement(internalBits);
|
||
|
dwordCount = internalBits.Length;
|
||
|
while (dwordCount > 0 && internalBits[dwordCount - 1] == 0)
|
||
|
{
|
||
|
dwordCount--;
|
||
|
}
|
||
|
if (dwordCount == 1 && internalBits[0] > 0)
|
||
|
{
|
||
|
switch (internalBits[0])
|
||
|
{
|
||
|
case 1:
|
||
|
this = _bigIntegerMinusOneInt;
|
||
|
break;
|
||
|
|
||
|
case unchecked((uint)int.MinValue):
|
||
|
this = _bigIntegerMinInt;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
InternalSign = -1;
|
||
|
InternalBits = internalBits;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (dwordCount == internalBits.Length)
|
||
|
{
|
||
|
InternalSign = -1;
|
||
|
InternalBits = internalBits;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = -1;
|
||
|
InternalBits = new uint[dwordCount];
|
||
|
Array.Copy(internalBits, InternalBits, dwordCount);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = 1;
|
||
|
InternalBits = internalBits;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (isNegative)
|
||
|
{
|
||
|
InternalSign = -1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = 0;
|
||
|
}
|
||
|
for (var index = valueLength - 1; index >= 0; index--)
|
||
|
{
|
||
|
InternalSign <<= 8;
|
||
|
InternalSign |= value[index];
|
||
|
}
|
||
|
InternalBits = null;
|
||
|
if (InternalSign < 0 && !isNegative)
|
||
|
{
|
||
|
InternalBits = new uint[1];
|
||
|
InternalBits[0] = (uint)InternalSign;
|
||
|
InternalSign = 1;
|
||
|
}
|
||
|
if (InternalSign == int.MinValue)
|
||
|
{
|
||
|
this = _bigIntegerMinInt;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal BigInteger(int internalSign, uint[] rgu)
|
||
|
{
|
||
|
InternalSign = internalSign;
|
||
|
InternalBits = rgu;
|
||
|
}
|
||
|
|
||
|
internal BigInteger(uint[] value, bool negative)
|
||
|
{
|
||
|
if (value == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("value");
|
||
|
}
|
||
|
var length = value.Length;
|
||
|
while (length > 0 && value[length - 1] == 0)
|
||
|
{
|
||
|
length--;
|
||
|
}
|
||
|
if (length == 0)
|
||
|
{
|
||
|
this = _bigIntegerZeroInt;
|
||
|
}
|
||
|
else if (length != 1 || value[0] >= unchecked((uint)int.MinValue))
|
||
|
{
|
||
|
InternalSign = (!negative ? 1 : -1);
|
||
|
InternalBits = new uint[length];
|
||
|
Array.Copy(value, InternalBits, length);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = (!negative ? (int)value[0] : (int)(-value[0]));
|
||
|
InternalBits = null;
|
||
|
if (InternalSign == int.MinValue)
|
||
|
{
|
||
|
this = _bigIntegerMinInt;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private BigInteger(uint[] value)
|
||
|
{
|
||
|
if (value == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("value");
|
||
|
}
|
||
|
var dwordCount = value.Length;
|
||
|
var isNegative = (dwordCount > 0 && (value[dwordCount - 1] & unchecked((uint)int.MinValue)) == unchecked((uint)int.MinValue));
|
||
|
while (dwordCount > 0 && value[dwordCount - 1] == 0)
|
||
|
{
|
||
|
dwordCount--;
|
||
|
}
|
||
|
if (dwordCount == 0)
|
||
|
{
|
||
|
this = _bigIntegerZeroInt;
|
||
|
return;
|
||
|
}
|
||
|
if (dwordCount == 1)
|
||
|
{
|
||
|
if ((int)value[0] < 0 && !isNegative)
|
||
|
{
|
||
|
InternalBits = new[] { value[0] };
|
||
|
InternalSign = 1;
|
||
|
}
|
||
|
else if (value[0] != unchecked((uint)int.MinValue))
|
||
|
{
|
||
|
InternalSign = (int)value[0];
|
||
|
InternalBits = null;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this = _bigIntegerMinInt;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
if (!isNegative)
|
||
|
{
|
||
|
if (dwordCount == value.Length)
|
||
|
{
|
||
|
InternalSign = 1;
|
||
|
InternalBits = value;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = 1;
|
||
|
InternalBits = new uint[dwordCount];
|
||
|
Array.Copy(value, InternalBits, dwordCount);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
NumericsHelpers.DangerousMakeTwosComplement(value);
|
||
|
var length = value.Length;
|
||
|
while (length > 0 && value[length - 1] == 0)
|
||
|
{
|
||
|
length--;
|
||
|
}
|
||
|
if (length != 1 || value[0] <= 0)
|
||
|
{
|
||
|
if (length == value.Length)
|
||
|
{
|
||
|
InternalSign = -1;
|
||
|
InternalBits = value;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InternalSign = -1;
|
||
|
InternalBits = new uint[length];
|
||
|
Array.Copy(value, InternalBits, length);
|
||
|
}
|
||
|
}
|
||
|
else if (value[0] == 1)
|
||
|
{
|
||
|
this = _bigIntegerMinusOneInt;
|
||
|
}
|
||
|
else if (value[0] != unchecked((uint)int.MinValue))
|
||
|
{
|
||
|
InternalSign = (int)(-1 * value[0]);
|
||
|
InternalBits = null;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this = _bigIntegerMinInt;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Gets the absolute value of a <see cref="T:System.Numerics.BigInteger" /> object.</summary>
|
||
|
/// <returns>The absolute value of <paramref name="value" />.</returns>
|
||
|
/// <param name="value">A number.</param>
|
||
|
public static BigInteger Abs(BigInteger value)
|
||
|
{
|
||
|
return (value < Zero ? -value : value);
|
||
|
}
|
||
|
|
||
|
/// <summary>Adds two <see cref="T:System.Numerics.BigInteger" /> values and returns the result.</summary>
|
||
|
/// <returns>The sum of <paramref name="left" /> and <paramref name="right" />.</returns>
|
||
|
/// <param name="left">The first value to add.</param>
|
||
|
/// <param name="right">The second value to add.</param>
|
||
|
public static BigInteger Add(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left + right;
|
||
|
}
|
||
|
|
||
|
internal static int BitLengthOfUInt(uint x)
|
||
|
{
|
||
|
var numBits = 0;
|
||
|
while (x > 0)
|
||
|
{
|
||
|
x = x >> 1;
|
||
|
numBits++;
|
||
|
}
|
||
|
return numBits;
|
||
|
}
|
||
|
|
||
|
/// <summary>Compares two <see cref="T:System.Numerics.BigInteger" /> values and returns an integer that indicates whether the first value is less than, equal to, or greater than the second value.</summary>
|
||
|
/// <returns>A signed integer that indicates the relative values of <paramref name="left" /> and <paramref name="right" />, as shown in the following table.ValueConditionLess than zero<paramref name="left" /> is less than <paramref name="right" />.Zero<paramref name="left" /> equals <paramref name="right" />.Greater than zero<paramref name="left" /> is greater than <paramref name="right" />.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static int Compare(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left.CompareTo(right);
|
||
|
}
|
||
|
|
||
|
/// <summary>Compares this instance to a signed 64-bit integer and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the signed 64-bit integer.</summary>
|
||
|
/// <returns>A signed integer value that indicates the relationship of this instance to <paramref name="other" />, as shown in the following table.Return valueDescriptionLess than zeroThe current instance is less than <paramref name="other" />.ZeroThe current instance equals <paramref name="other" />.Greater than zeroThe current instance is greater than <paramref name="other" />.</returns>
|
||
|
/// <param name="other">The signed 64-bit integer to compare.</param>
|
||
|
public int CompareTo(long other)
|
||
|
{
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
return ((long)InternalSign).CompareTo(other);
|
||
|
}
|
||
|
if ((InternalSign ^ other) >= 0)
|
||
|
{
|
||
|
var length = Length(InternalBits);
|
||
|
if (length <= 2)
|
||
|
{
|
||
|
var magnitude = (other >= 0 ? (ulong)other : (ulong)(-other));
|
||
|
var unsigned = (length != 2 ? InternalBits[0] : NumericsHelpers.MakeUlong(InternalBits[1], InternalBits[0]));
|
||
|
return InternalSign * unsigned.CompareTo(magnitude);
|
||
|
}
|
||
|
}
|
||
|
return InternalSign;
|
||
|
}
|
||
|
|
||
|
/// <summary>Compares this instance to an unsigned 64-bit integer and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the unsigned 64-bit integer.</summary>
|
||
|
/// <returns>A signed integer that indicates the relative value of this instance and <paramref name="other" />, as shown in the following table.Return valueDescriptionLess than zeroThe current instance is less than <paramref name="other" />.ZeroThe current instance equals <paramref name="other" />.Greater than zeroThe current instance is greater than <paramref name="other" />.</returns>
|
||
|
/// <param name="other">The unsigned 64-bit integer to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public int CompareTo(ulong other)
|
||
|
{
|
||
|
if (InternalSign < 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
return ((ulong)InternalSign).CompareTo(other);
|
||
|
}
|
||
|
var length = Length(InternalBits);
|
||
|
if (length > 2)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
return ((length != 2 ? InternalBits[0] : NumericsHelpers.MakeUlong(InternalBits[1], InternalBits[0]))).CompareTo(other);
|
||
|
}
|
||
|
|
||
|
/// <summary>Compares this instance to a second <see cref="T:System.Numerics.BigInteger" /> and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object.</summary>
|
||
|
/// <returns>A signed integer value that indicates the relationship of this instance to <paramref name="other" />, as shown in the following table.Return valueDescriptionLess than zeroThe current instance is less than <paramref name="other" />.ZeroThe current instance equals <paramref name="other" />.Greater than zeroThe current instance is greater than <paramref name="other" />.</returns>
|
||
|
/// <param name="other">The object to compare.</param>
|
||
|
public int CompareTo(BigInteger other)
|
||
|
{
|
||
|
if ((InternalSign ^ other.InternalSign) < 0)
|
||
|
{
|
||
|
return (InternalSign >= 0 ? 1 : -1);
|
||
|
}
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
if (other.InternalBits != null)
|
||
|
{
|
||
|
return -other.InternalSign;
|
||
|
}
|
||
|
int result;
|
||
|
if (InternalSign >= other.InternalSign)
|
||
|
{
|
||
|
result = (InternalSign <= other.InternalSign ? 0 : 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result = -1;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
if (other.InternalBits != null)
|
||
|
{
|
||
|
var length = Length(InternalBits);
|
||
|
var otherLength = Length(other.InternalBits);
|
||
|
if (Length(InternalBits) <= otherLength)
|
||
|
{
|
||
|
if (length < otherLength)
|
||
|
{
|
||
|
return -InternalSign;
|
||
|
}
|
||
|
var diffLength = GetDiffLength(InternalBits, other.InternalBits, length);
|
||
|
if (diffLength == 0)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
return (InternalBits[diffLength - 1] >= other.InternalBits[diffLength - 1] ? InternalSign : -InternalSign);
|
||
|
}
|
||
|
}
|
||
|
return InternalSign;
|
||
|
}
|
||
|
|
||
|
/// <summary>Compares this instance to a specified object and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object.</summary>
|
||
|
/// <returns>A signed integer that indicates the relationship of the current instance to the <paramref name="obj" /> parameter, as shown in the following table.Return valueDescriptionLess than zeroThe current instance is less than <paramref name="obj" />.ZeroThe current instance equals <paramref name="obj" />.Greater than zeroThe current instance is greater than <paramref name="obj" />, or the <paramref name="obj" /> parameter is null. </returns>
|
||
|
/// <param name="obj">The object to compare.</param>
|
||
|
/// <exception cref="T:System.ArgumentException">
|
||
|
/// <paramref name="obj" /> is not a <see cref="T:System.Numerics.BigInteger" />. </exception>
|
||
|
public int CompareTo(object obj)
|
||
|
{
|
||
|
if (obj == null)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
if (!(obj is BigInteger))
|
||
|
{
|
||
|
throw new ArgumentException("The parameter must be a BigInteger.");
|
||
|
}
|
||
|
return CompareTo((BigInteger)obj);
|
||
|
}
|
||
|
|
||
|
/// <summary>Divides one <see cref="T:System.Numerics.BigInteger" /> value by another and returns the result.</summary>
|
||
|
/// <returns>The quotient of the division.</returns>
|
||
|
/// <param name="dividend">The value to be divided.</param>
|
||
|
/// <param name="divisor">The value to divide by.</param>
|
||
|
/// <exception cref="T:System.DivideByZeroException">
|
||
|
/// <paramref name="divisor" /> is 0 (zero).</exception>
|
||
|
public static BigInteger Divide(BigInteger dividend, BigInteger divisor)
|
||
|
{
|
||
|
return dividend / divisor;
|
||
|
}
|
||
|
|
||
|
/// <summary>Divides one <see cref="T:System.Numerics.BigInteger" /> value by another, returns the result, and returns the remainder in an output parameter.</summary>
|
||
|
/// <returns>The quotient of the division.</returns>
|
||
|
/// <param name="dividend">The value to be divided.</param>
|
||
|
/// <param name="divisor">The value to divide by.</param>
|
||
|
/// <param name="remainder">When this method returns, contains a <see cref="T:System.Numerics.BigInteger" /> value that represents the remainder from the division. This parameter is passed uninitialized.</param>
|
||
|
/// <exception cref="T:System.DivideByZeroException">
|
||
|
/// <paramref name="divisor" /> is 0 (zero).</exception>
|
||
|
public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder)
|
||
|
{
|
||
|
var signNum = 1;
|
||
|
var signDen = 1;
|
||
|
var regNum = new BigIntegerBuilder(dividend, ref signNum);
|
||
|
var regDen = new BigIntegerBuilder(divisor, ref signDen);
|
||
|
var regQuo = new BigIntegerBuilder();
|
||
|
regNum.ModDiv(ref regDen, ref regQuo);
|
||
|
remainder = regNum.GetInteger(signNum);
|
||
|
return regQuo.GetInteger(signNum * signDen);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether the current instance and a specified object have the same value.</summary>
|
||
|
/// <returns>true if the <paramref name="obj" /> parameter is a <see cref="T:System.Numerics.BigInteger" /> object or a type capable of implicit conversion to a <see cref="T:System.Numerics.BigInteger" /> value, and its value is equal to the value of the current <see cref="T:System.Numerics.BigInteger" /> object; otherwise, false.</returns>
|
||
|
/// <param name="obj">The object to compare. </param>
|
||
|
public override bool Equals(object obj)
|
||
|
{
|
||
|
if (!(obj is BigInteger))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
return Equals((BigInteger)obj);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether the current instance and a signed 64-bit integer have the same value.</summary>
|
||
|
/// <returns>true if the signed 64-bit integer and the current instance have the same value; otherwise, false.</returns>
|
||
|
/// <param name="other">The signed 64-bit integer value to compare.</param>
|
||
|
public bool Equals(long other)
|
||
|
{
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
return InternalSign == other;
|
||
|
}
|
||
|
if ((InternalSign ^ other) >= 0)
|
||
|
{
|
||
|
var length = Length(InternalBits);
|
||
|
if (length <= 2)
|
||
|
{
|
||
|
var magnitude = (other >= 0 ? (ulong)other : (ulong)(-other));
|
||
|
if (length == 1)
|
||
|
{
|
||
|
return InternalBits[0] == magnitude;
|
||
|
}
|
||
|
return NumericsHelpers.MakeUlong(InternalBits[1], InternalBits[0]) == magnitude;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether the current instance and an unsigned 64-bit integer have the same value.</summary>
|
||
|
/// <returns>true if the current instance and the unsigned 64-bit integer have the same value; otherwise, false.</returns>
|
||
|
/// <param name="other">The unsigned 64-bit integer to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public bool Equals(ulong other)
|
||
|
{
|
||
|
if (InternalSign < 0)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
return InternalSign == unchecked((long)other);
|
||
|
}
|
||
|
var length = Length(InternalBits);
|
||
|
if (length > 2)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
if (length == 1)
|
||
|
{
|
||
|
return InternalBits[0] == other;
|
||
|
}
|
||
|
return NumericsHelpers.MakeUlong(InternalBits[1], InternalBits[0]) == other;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether the current instance and a specified <see cref="T:System.Numerics.BigInteger" /> object have the same value.</summary>
|
||
|
/// <returns>true if this <see cref="T:System.Numerics.BigInteger" /> object and <paramref name="other" /> have the same value; otherwise, false.</returns>
|
||
|
/// <param name="other">The object to compare.</param>
|
||
|
public bool Equals(BigInteger other)
|
||
|
{
|
||
|
if (InternalSign != other.InternalSign)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
if (InternalBits == other.InternalBits)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if (InternalBits == null || other.InternalBits == null)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
var length = Length(InternalBits);
|
||
|
if (length != Length(other.InternalBits))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
var diffLength = GetDiffLength(InternalBits, other.InternalBits, length);
|
||
|
return diffLength == 0;
|
||
|
}
|
||
|
|
||
|
internal static int GetDiffLength(uint[] internalBits, uint[] otherInternalBits, int length)
|
||
|
{
|
||
|
var index = length;
|
||
|
do
|
||
|
{
|
||
|
index = index - 1;
|
||
|
if (index >= 0)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
while (internalBits[index] == otherInternalBits[index]);
|
||
|
return index + 1;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the hash code for the current <see cref="T:System.Numerics.BigInteger" /> object.</summary>
|
||
|
/// <returns>A 32-bit signed integer hash code.</returns>
|
||
|
public override int GetHashCode()
|
||
|
{
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
return InternalSign;
|
||
|
}
|
||
|
var sign = InternalSign;
|
||
|
var index = Length(InternalBits);
|
||
|
while (true)
|
||
|
{
|
||
|
index = index - 1;
|
||
|
if (index < 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
sign = NumericsHelpers.CombineHash(sign, (int)InternalBits[index]);
|
||
|
}
|
||
|
return sign;
|
||
|
}
|
||
|
|
||
|
private static bool GetPartsForBitManipulation(ref BigInteger x, out uint[] xd, out int xl)
|
||
|
{
|
||
|
if (x.InternalBits != null)
|
||
|
{
|
||
|
xd = x.InternalBits;
|
||
|
}
|
||
|
else if (x.InternalSign >= 0)
|
||
|
{
|
||
|
xd = new[] { unchecked((uint)x.InternalSign) };
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
xd = new[] { unchecked((uint)-x.InternalSign) };
|
||
|
}
|
||
|
xl = (x.InternalBits != null ? x.InternalBits.Length : 1);
|
||
|
return x.InternalSign < 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Finds the greatest common divisor of two <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The greatest common divisor of <paramref name="left" /> and <paramref name="right" />.</returns>
|
||
|
/// <param name="left">The first value.</param>
|
||
|
/// <param name="right">The second value.</param>
|
||
|
public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
if (left.InternalSign == 0)
|
||
|
{
|
||
|
return Abs(right);
|
||
|
}
|
||
|
if (right.InternalSign == 0)
|
||
|
{
|
||
|
return Abs(left);
|
||
|
}
|
||
|
var bigIntegerBuilder = new BigIntegerBuilder(left);
|
||
|
var bigIntegerBuilder1 = new BigIntegerBuilder(right);
|
||
|
BigIntegerBuilder.Gcd(ref bigIntegerBuilder, ref bigIntegerBuilder1);
|
||
|
return bigIntegerBuilder.GetInteger(1);
|
||
|
}
|
||
|
|
||
|
internal static int Length(uint[] internalBits)
|
||
|
{
|
||
|
var length = internalBits.Length;
|
||
|
if (internalBits[length - 1] != 0)
|
||
|
{
|
||
|
return length;
|
||
|
}
|
||
|
return length - 1;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the natural (base e) logarithm of a specified number.</summary>
|
||
|
/// <returns>The natural (base e) logarithm of <paramref name="value" />, as shown in the table in the Remarks section.</returns>
|
||
|
/// <param name="value">The number whose logarithm is to be found.</param>
|
||
|
/// <exception cref="T:System.ArgumentOutOfRangeException">The natural log of <paramref name="value" /> is out of range of the <see cref="T:System.Double" /> data type.</exception>
|
||
|
public static double Log(BigInteger value)
|
||
|
{
|
||
|
return Log(value, Math.E);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the logarithm of a specified number in a specified base.</summary>
|
||
|
/// <returns>The base <paramref name="baseValue" /> logarithm of <paramref name="value" />, as shown in the table in the Remarks section.</returns>
|
||
|
/// <param name="value">A number whose logarithm is to be found.</param>
|
||
|
/// <param name="baseValue">The base of the logarithm.</param>
|
||
|
/// <exception cref="T:System.ArgumentOutOfRangeException">The log of <paramref name="value" /> is out of range of the <see cref="T:System.Double" /> data type.</exception>
|
||
|
public static double Log(BigInteger value, double baseValue)
|
||
|
{
|
||
|
if (value.InternalSign < 0 || NumericHelper.IsOne(baseValue))
|
||
|
{
|
||
|
return double.NaN;
|
||
|
}
|
||
|
if (double.IsPositiveInfinity(baseValue))
|
||
|
{
|
||
|
return (!value.IsOne ? double.NaN : 0);
|
||
|
}
|
||
|
if (NumericHelper.IsZero(baseValue) && !value.IsOne)
|
||
|
{
|
||
|
return double.NaN;
|
||
|
}
|
||
|
if (value.InternalBits == null)
|
||
|
{
|
||
|
return Math.Log(value.InternalSign, baseValue);
|
||
|
}
|
||
|
double c = 0;
|
||
|
var d = 0.5;
|
||
|
var length = Length(value.InternalBits);
|
||
|
var topbits = BitLengthOfUInt(value.InternalBits[length - 1]);
|
||
|
var bitlen = (length - 1) * 32 + topbits;
|
||
|
var indbit = (uint)(1 << (topbits - 1 & 31));
|
||
|
for (var index = length - 1; index >= 0; index--)
|
||
|
{
|
||
|
while (indbit != 0)
|
||
|
{
|
||
|
if ((value.InternalBits[index] & indbit) != 0)
|
||
|
{
|
||
|
c = c + d;
|
||
|
}
|
||
|
d = d * 0.5;
|
||
|
indbit = indbit >> 1;
|
||
|
}
|
||
|
indbit = unchecked((uint)int.MinValue);
|
||
|
}
|
||
|
return (Math.Log(c) + 0.69314718055994529D * bitlen) / Math.Log(baseValue);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the base 10 logarithm of a specified number.</summary>
|
||
|
/// <returns>The base 10 logarithm of <paramref name="value" />, as shown in the table in the Remarks section.</returns>
|
||
|
/// <param name="value">A number whose logarithm is to be found.</param>
|
||
|
/// <exception cref="T:System.ArgumentOutOfRangeException">The base 10 log of <paramref name="value" /> is out of range of the <see cref="T:System.Double" /> data type.</exception>
|
||
|
public static double Log10(BigInteger value)
|
||
|
{
|
||
|
return Log(value, 10);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the larger of two <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The <paramref name="left" /> or <paramref name="right" /> parameter, whichever is larger.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static BigInteger Max(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
if (left.CompareTo(right) < 0)
|
||
|
{
|
||
|
return right;
|
||
|
}
|
||
|
return left;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the smaller of two <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The <paramref name="left" /> or <paramref name="right" /> parameter, whichever is smaller.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static BigInteger Min(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
if (left.CompareTo(right) <= 0)
|
||
|
{
|
||
|
return left;
|
||
|
}
|
||
|
return right;
|
||
|
}
|
||
|
|
||
|
/// <summary>Performs modulus division on a number raised to the power of another number.</summary>
|
||
|
/// <returns>The remainder after dividing <paramref name="value" />exponent by <paramref name="modulus" />.</returns>
|
||
|
/// <param name="value">The number to raise to the <paramref name="exponent" /> power.</param>
|
||
|
/// <param name="exponent">The exponent to raise <paramref name="value" /> by.</param>
|
||
|
/// <param name="modulus">The number by which to divide <paramref name="value" /> raised to the <paramref name="exponent" /> power.</param>
|
||
|
/// <exception cref="T:System.DivideByZeroException">
|
||
|
/// <paramref name="modulus" /> is zero.</exception>
|
||
|
/// <exception cref="T:System.ArgumentOutOfRangeException">
|
||
|
/// <paramref name="exponent" /> is negative.</exception>
|
||
|
public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
|
||
|
{
|
||
|
if (exponent.Sign < 0)
|
||
|
{
|
||
|
throw new ArgumentOutOfRangeException("exponent", "The number must be greater than or equal to zero.");
|
||
|
}
|
||
|
var signRes = 1;
|
||
|
var signVal = 1;
|
||
|
var signMod = 1;
|
||
|
var isEven = exponent.IsEven;
|
||
|
var regRes = new BigIntegerBuilder(One, ref signRes);
|
||
|
var regVal = new BigIntegerBuilder(value, ref signVal);
|
||
|
var regMod = new BigIntegerBuilder(modulus, ref signMod);
|
||
|
var regTmp = new BigIntegerBuilder(regVal.Size);
|
||
|
regRes.Mod(ref regMod);
|
||
|
if (exponent.InternalBits != null)
|
||
|
{
|
||
|
var length = Length(exponent.InternalBits);
|
||
|
for (var index = 0; index < length - 1; index++)
|
||
|
{
|
||
|
var num5 = exponent.InternalBits[index];
|
||
|
ModPowInner32(num5, ref regRes, ref regVal, ref regMod, ref regTmp);
|
||
|
}
|
||
|
ModPowInner(exponent.InternalBits[length - 1], ref regRes, ref regVal, ref regMod, ref regTmp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ModPowInner((uint)exponent.InternalSign, ref regRes, ref regVal, ref regMod, ref regTmp);
|
||
|
}
|
||
|
return regRes.GetInteger(value.InternalSign <= 0 ? (!isEven ? -1 : 1) : 1);
|
||
|
}
|
||
|
|
||
|
private static void ModPowInner(uint exp, ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
|
||
|
{
|
||
|
while (exp != 0)
|
||
|
{
|
||
|
if ((exp & 1) == 1)
|
||
|
{
|
||
|
ModPowUpdateResult(ref regRes, ref regVal, ref regMod, ref regTmp);
|
||
|
}
|
||
|
if (exp != 1)
|
||
|
{
|
||
|
ModPowSquareModValue(ref regVal, ref regMod, ref regTmp);
|
||
|
exp = exp >> 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void ModPowInner32(uint exp, ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
|
||
|
{
|
||
|
for (var index = 0; index < 32; index++)
|
||
|
{
|
||
|
if ((exp & 1) == 1)
|
||
|
{
|
||
|
ModPowUpdateResult(ref regRes, ref regVal, ref regMod, ref regTmp);
|
||
|
}
|
||
|
ModPowSquareModValue(ref regVal, ref regMod, ref regTmp);
|
||
|
exp = exp >> 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void ModPowSquareModValue(ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
|
||
|
{
|
||
|
NumericHelper.Swap(ref regVal, ref regTmp);
|
||
|
regVal.Mul(ref regTmp, ref regTmp);
|
||
|
regVal.Mod(ref regMod);
|
||
|
}
|
||
|
|
||
|
private static void ModPowUpdateResult(ref BigIntegerBuilder regRes, ref BigIntegerBuilder regVal, ref BigIntegerBuilder regMod, ref BigIntegerBuilder regTmp)
|
||
|
{
|
||
|
NumericHelper.Swap(ref regRes, ref regTmp);
|
||
|
regRes.Mul(ref regTmp, ref regVal);
|
||
|
regRes.Mod(ref regMod);
|
||
|
}
|
||
|
|
||
|
private static void MulLower(ref uint uHiRes, ref int cuRes, uint uHiMul, int cuMul)
|
||
|
{
|
||
|
var num = uHiRes * (ulong)uHiMul;
|
||
|
var hi = NumericHelper.GetHi(num);
|
||
|
if (hi == 0)
|
||
|
{
|
||
|
uHiRes = NumericHelper.GetLo(num);
|
||
|
cuRes = cuRes + (cuMul - 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
uHiRes = hi;
|
||
|
cuRes = cuRes + cuMul;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the product of two <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The product of the <paramref name="left" /> and <paramref name="right" /> parameters.</returns>
|
||
|
/// <param name="left">The first number to multiply.</param>
|
||
|
/// <param name="right">The second number to multiply.</param>
|
||
|
public static BigInteger Multiply(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left * right;
|
||
|
}
|
||
|
|
||
|
private static void MulUpper(ref uint uHiRes, ref int cuRes, uint uHiMul, int cuMul)
|
||
|
{
|
||
|
var num = uHiRes * (ulong)uHiMul;
|
||
|
var hi = NumericHelper.GetHi(num);
|
||
|
if (hi == 0)
|
||
|
{
|
||
|
uHiRes = NumericHelper.GetLo(num);
|
||
|
cuRes = cuRes + (cuMul - 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (NumericHelper.GetLo(num) != 0)
|
||
|
{
|
||
|
var num1 = hi + 1;
|
||
|
hi = num1;
|
||
|
if (num1 == 0)
|
||
|
{
|
||
|
hi = 1;
|
||
|
cuRes = cuRes + 1;
|
||
|
}
|
||
|
}
|
||
|
uHiRes = hi;
|
||
|
cuRes = cuRes + cuMul;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Negates a specified <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>The result of the <paramref name="value" /> parameter multiplied by negative one (-1).</returns>
|
||
|
/// <param name="value">The value to negate.</param>
|
||
|
public static BigInteger Negate(BigInteger value)
|
||
|
{
|
||
|
return -value;
|
||
|
}
|
||
|
|
||
|
/// <summary>Adds the values of two specified <see cref="T:System.Numerics.BigInteger" /> objects.</summary>
|
||
|
/// <returns>The sum of <paramref name="left" /> and <paramref name="right" />.</returns>
|
||
|
/// <param name="left">The first value to add.</param>
|
||
|
/// <param name="right">The second value to add.</param>
|
||
|
public static BigInteger operator +(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
if (right.IsZero)
|
||
|
{
|
||
|
return left;
|
||
|
}
|
||
|
if (left.IsZero)
|
||
|
{
|
||
|
return right;
|
||
|
}
|
||
|
var signLeft = 1;
|
||
|
var signRight = 1;
|
||
|
var regLeft = new BigIntegerBuilder(left, ref signLeft);
|
||
|
var regRight = new BigIntegerBuilder(right, ref signRight);
|
||
|
if (signLeft != signRight)
|
||
|
{
|
||
|
regLeft.Sub(ref signLeft, ref regRight);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
regLeft.Add(ref regRight);
|
||
|
}
|
||
|
return regLeft.GetInteger(signLeft);
|
||
|
}
|
||
|
|
||
|
/// <summary>Performs a bitwise And operation on two <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The result of the bitwise And operation.</returns>
|
||
|
/// <param name="left">The first value.</param>
|
||
|
/// <param name="right">The second value.</param>
|
||
|
public static BigInteger operator &(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
if (left.IsZero || right.IsZero)
|
||
|
{
|
||
|
return Zero;
|
||
|
}
|
||
|
var x = left.ToUInt32Array();
|
||
|
var y = right.ToUInt32Array();
|
||
|
var z = new uint[Math.Max(x.Length, y.Length)];
|
||
|
var xExtend = (uint)((left.InternalSign >= 0 ? 0 : -1));
|
||
|
var yExtend = (uint)((right.InternalSign >= 0 ? 0 : -1));
|
||
|
for (var index = 0; index < z.Length; index++)
|
||
|
{
|
||
|
var num2 = (index >= x.Length ? xExtend : x[index]);
|
||
|
z[index] = num2 & (index >= y.Length ? yExtend : y[index]);
|
||
|
}
|
||
|
return new BigInteger(z);
|
||
|
}
|
||
|
|
||
|
/// <summary>Performs a bitwise Or operation on two <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The result of the bitwise Or operation.</returns>
|
||
|
/// <param name="left">The first value.</param>
|
||
|
/// <param name="right">The second value.</param>
|
||
|
public static BigInteger operator |(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
if (left.IsZero)
|
||
|
{
|
||
|
return right;
|
||
|
}
|
||
|
if (right.IsZero)
|
||
|
{
|
||
|
return left;
|
||
|
}
|
||
|
var x = left.ToUInt32Array();
|
||
|
var y = right.ToUInt32Array();
|
||
|
var z = new uint[Math.Max(x.Length, y.Length)];
|
||
|
var xExtend = (uint)((left.InternalSign >= 0 ? 0 : -1));
|
||
|
var yExtend = (uint)((right.InternalSign >= 0 ? 0 : -1));
|
||
|
for (var index = 0; index < z.Length; index++)
|
||
|
{
|
||
|
var num2 = (index >= x.Length ? xExtend : x[index]);
|
||
|
z[index] = num2 | (index >= y.Length ? yExtend : y[index]);
|
||
|
}
|
||
|
return new BigInteger(z);
|
||
|
}
|
||
|
|
||
|
/// <summary>Decrements a <see cref="T:System.Numerics.BigInteger" /> value by 1.</summary>
|
||
|
/// <returns>The value of the <paramref name="value" /> parameter decremented by 1.</returns>
|
||
|
/// <param name="value">The value to decrement.</param>
|
||
|
public static BigInteger operator --(BigInteger value)
|
||
|
{
|
||
|
return value - One;
|
||
|
}
|
||
|
|
||
|
/// <summary>Divides a specified <see cref="T:System.Numerics.BigInteger" /> value by another specified <see cref="T:System.Numerics.BigInteger" /> value by using integer division.</summary>
|
||
|
/// <returns>The integral result of the division.</returns>
|
||
|
/// <param name="dividend">The value to be divided.</param>
|
||
|
/// <param name="divisor">The value to divide by.</param>
|
||
|
/// <exception cref="T:System.DivideByZeroException">
|
||
|
/// <paramref name="divisor" /> is 0 (zero).</exception>
|
||
|
public static BigInteger operator /(BigInteger dividend, BigInteger divisor)
|
||
|
{
|
||
|
var sign = 1;
|
||
|
var regNum = new BigIntegerBuilder(dividend, ref sign);
|
||
|
var regDen = new BigIntegerBuilder(divisor, ref sign);
|
||
|
regNum.Div(ref regDen);
|
||
|
return regNum.GetInteger(sign);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether the values of two <see cref="T:System.Numerics.BigInteger" /> objects are equal.</summary>
|
||
|
/// <returns>true if the <paramref name="left" /> and <paramref name="right" /> parameters have the same value; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator ==(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left.Equals(right);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value and a signed long integer value are equal.</summary>
|
||
|
/// <returns>true if the <paramref name="left" /> and <paramref name="right" /> parameters have the same value; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator ==(BigInteger left, long right)
|
||
|
{
|
||
|
return left.Equals(right);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a signed long integer value and a <see cref="T:System.Numerics.BigInteger" /> value are equal.</summary>
|
||
|
/// <returns>true if the <paramref name="left" /> and <paramref name="right" /> parameters have the same value; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator ==(long left, BigInteger right)
|
||
|
{
|
||
|
return right.Equals(left);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value and an unsigned long integer value are equal.</summary>
|
||
|
/// <returns>true if the <paramref name="left" /> and <paramref name="right" /> parameters have the same value; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator ==(BigInteger left, ulong right)
|
||
|
{
|
||
|
return left.Equals(right);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether an unsigned long integer value and a <see cref="T:System.Numerics.BigInteger" /> value are equal.</summary>
|
||
|
/// <returns>true if the <paramref name="left" /> and <paramref name="right" /> parameters have the same value; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator ==(ulong left, BigInteger right)
|
||
|
{
|
||
|
return right.Equals(left);
|
||
|
}
|
||
|
|
||
|
/// <summary>Performs a bitwise exclusive Or (XOr) operation on two <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The result of the bitwise Or operation.</returns>
|
||
|
/// <param name="left">The first value.</param>
|
||
|
/// <param name="right">The second value.</param>
|
||
|
public static BigInteger operator ^(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
var x = left.ToUInt32Array();
|
||
|
var y = right.ToUInt32Array();
|
||
|
var z = new uint[Math.Max(x.Length, y.Length)];
|
||
|
var xEntend = (uint)((left.InternalSign >= 0 ? 0 : -1));
|
||
|
var yExtend = (uint)((right.InternalSign >= 0 ? 0 : -1));
|
||
|
for (var index = 0; index < z.Length; index++)
|
||
|
{
|
||
|
var num2 = (index >= x.Length ? xEntend : x[index]);
|
||
|
z[index] = num2 ^ (index >= y.Length ? yExtend : y[index]);
|
||
|
}
|
||
|
return new BigInteger(z);
|
||
|
}
|
||
|
|
||
|
public static explicit operator BigInteger(float value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
public static explicit operator BigInteger(double value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
public static explicit operator BigInteger(decimal value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
public static explicit operator byte(BigInteger value)
|
||
|
{
|
||
|
return checked((byte)((int)value));
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static explicit operator sbyte(BigInteger value)
|
||
|
{
|
||
|
return checked((sbyte)((int)value));
|
||
|
}
|
||
|
|
||
|
public static explicit operator short(BigInteger value)
|
||
|
{
|
||
|
return checked((short)((int)value));
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static explicit operator ushort(BigInteger value)
|
||
|
{
|
||
|
return checked((ushort)((int)value));
|
||
|
}
|
||
|
|
||
|
public static explicit operator int(BigInteger value)
|
||
|
{
|
||
|
if (value.InternalBits == null)
|
||
|
{
|
||
|
return value.InternalSign;
|
||
|
}
|
||
|
if (Length(value.InternalBits) > 1)
|
||
|
{
|
||
|
throw new OverflowException("Value was either too large or too small for an Int32.");
|
||
|
}
|
||
|
if (value.InternalSign > 0)
|
||
|
{
|
||
|
return checked((int)value.InternalBits[0]);
|
||
|
}
|
||
|
if (value.InternalBits[0] > unchecked((uint)int.MinValue))
|
||
|
{
|
||
|
throw new OverflowException("Value was either too large or too small for an Int32.");
|
||
|
}
|
||
|
return (int)(-value.InternalBits[0]);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static explicit operator uint(BigInteger value)
|
||
|
{
|
||
|
if (value.InternalBits == null)
|
||
|
{
|
||
|
return checked((uint)value.InternalSign);
|
||
|
}
|
||
|
if (Length(value.InternalBits) > 1 || value.InternalSign < 0)
|
||
|
{
|
||
|
throw new OverflowException("Value was either too large or too small for a UInt32.");
|
||
|
}
|
||
|
return value.InternalBits[0];
|
||
|
}
|
||
|
|
||
|
public static explicit operator long(BigInteger value)
|
||
|
{
|
||
|
if (value.InternalBits == null)
|
||
|
{
|
||
|
return value.InternalSign;
|
||
|
}
|
||
|
var length = Length(value.InternalBits);
|
||
|
if (length > 2)
|
||
|
{
|
||
|
throw new OverflowException("Value was either too large or too small for an Int64.");
|
||
|
}
|
||
|
var target = (length <= 1 ? value.InternalBits[0] : NumericsHelpers.MakeUlong(value.InternalBits[1], value.InternalBits[0]));
|
||
|
var result = (value.InternalSign <= 0 ? -(long)(target) : (long)target);
|
||
|
if ((result <= 0 || value.InternalSign <= 0) && (result >= 0 || value.InternalSign >= 0))
|
||
|
{
|
||
|
throw new OverflowException("Value was either too large or too small for an Int64.");
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static explicit operator ulong(BigInteger value)
|
||
|
{
|
||
|
if (value.InternalBits == null)
|
||
|
{
|
||
|
return checked((ulong)value.InternalSign);
|
||
|
}
|
||
|
var length = Length(value.InternalBits);
|
||
|
if (length > 2 || value.InternalSign < 0)
|
||
|
{
|
||
|
throw new OverflowException("Value was either too large or too small for a UInt64.");
|
||
|
}
|
||
|
if (length <= 1)
|
||
|
{
|
||
|
return value.InternalBits[0];
|
||
|
}
|
||
|
return NumericsHelpers.MakeUlong(value.InternalBits[1], value.InternalBits[0]);
|
||
|
}
|
||
|
|
||
|
public static explicit operator float(BigInteger value)
|
||
|
{
|
||
|
return (float)((double)value);
|
||
|
}
|
||
|
|
||
|
public static explicit operator double(BigInteger value)
|
||
|
{
|
||
|
ulong man;
|
||
|
int exp;
|
||
|
if (value.InternalBits == null)
|
||
|
{
|
||
|
return value.InternalSign;
|
||
|
}
|
||
|
var sign = 1;
|
||
|
var bigIntegerBuilder = new BigIntegerBuilder(value, ref sign);
|
||
|
bigIntegerBuilder.GetApproxParts(out exp, out man);
|
||
|
return NumericsHelpers.GetDoubleFromParts(sign, exp, man);
|
||
|
}
|
||
|
|
||
|
public static explicit operator decimal(BigInteger value)
|
||
|
{
|
||
|
if (value.InternalBits == null)
|
||
|
{
|
||
|
return value.InternalSign;
|
||
|
}
|
||
|
var length = Length(value.InternalBits);
|
||
|
if (length > 3)
|
||
|
{
|
||
|
throw new OverflowException("Value was either too large or too small for a Decimal.");
|
||
|
}
|
||
|
var lo = 0;
|
||
|
var mi = 0;
|
||
|
var hi = 0;
|
||
|
if (length > 2)
|
||
|
{
|
||
|
hi = (int)value.InternalBits[2];
|
||
|
}
|
||
|
if (length > 1)
|
||
|
{
|
||
|
mi = (int)value.InternalBits[1];
|
||
|
}
|
||
|
if (length > 0)
|
||
|
{
|
||
|
lo = (int)value.InternalBits[0];
|
||
|
}
|
||
|
return new decimal(lo, mi, hi, value.InternalSign < 0, 0);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is greater than another <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator >(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left.CompareTo(right) > 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> is greater than a 64-bit signed integer value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator >(BigInteger left, long right)
|
||
|
{
|
||
|
return left.CompareTo(right) > 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit signed integer is greater than a <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator >(long left, BigInteger right)
|
||
|
{
|
||
|
return right.CompareTo(left) < 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is greater than a 64-bit unsigned integer.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator >(BigInteger left, ulong right)
|
||
|
{
|
||
|
return left.CompareTo(right) > 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is greater than a 64-bit unsigned integer.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator >(ulong left, BigInteger right)
|
||
|
{
|
||
|
return right.CompareTo(left) < 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is greater than or equal to another <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator >=(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left.CompareTo(right) >= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is greater than or equal to a 64-bit signed integer value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator >=(BigInteger left, long right)
|
||
|
{
|
||
|
return left.CompareTo(right) >= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit signed integer is greater than or equal to a <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator >=(long left, BigInteger right)
|
||
|
{
|
||
|
return right.CompareTo(left) <= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is greater than or equal to a 64-bit unsigned integer value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator >=(BigInteger left, ulong right)
|
||
|
{
|
||
|
return left.CompareTo(right) >= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit unsigned integer is greater than or equal to a <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is greater than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator >=(ulong left, BigInteger right)
|
||
|
{
|
||
|
return right.CompareTo(left) <= 0;
|
||
|
}
|
||
|
|
||
|
public static implicit operator BigInteger(byte value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static implicit operator BigInteger(sbyte value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
public static implicit operator BigInteger(short value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static implicit operator BigInteger(ushort value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
public static implicit operator BigInteger(int value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static implicit operator BigInteger(uint value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
public static implicit operator BigInteger(long value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
//[CLSCompliant(false)]
|
||
|
public static implicit operator BigInteger(ulong value)
|
||
|
{
|
||
|
return new BigInteger(value);
|
||
|
}
|
||
|
|
||
|
/// <summary>Increments a <see cref="T:System.Numerics.BigInteger" /> value by 1.</summary>
|
||
|
/// <returns>The value of the <paramref name="value" /> parameter incremented by 1.</returns>
|
||
|
/// <param name="value">The value to increment.</param>
|
||
|
public static BigInteger operator ++(BigInteger value)
|
||
|
{
|
||
|
return value + One;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether two <see cref="T:System.Numerics.BigInteger" /> objects have different values.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> and <paramref name="right" /> are not equal; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator !=(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return !left.Equals(right);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value and a 64-bit signed integer are not equal.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> and <paramref name="right" /> are not equal; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator !=(BigInteger left, long right)
|
||
|
{
|
||
|
return !left.Equals(right);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit signed integer and a <see cref="T:System.Numerics.BigInteger" /> value are not equal.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> and <paramref name="right" /> are not equal; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator !=(long left, BigInteger right)
|
||
|
{
|
||
|
return !right.Equals(left);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value and a 64-bit unsigned integer are not equal.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> and <paramref name="right" /> are not equal; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator !=(BigInteger left, ulong right)
|
||
|
{
|
||
|
return !left.Equals(right);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit unsigned integer and a <see cref="T:System.Numerics.BigInteger" /> value are not equal.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> and <paramref name="right" /> are not equal; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator !=(ulong left, BigInteger right)
|
||
|
{
|
||
|
return !right.Equals(left);
|
||
|
}
|
||
|
|
||
|
/// <summary>Shifts a <see cref="T:System.Numerics.BigInteger" /> value a specified number of bits to the left.</summary>
|
||
|
/// <returns>A value that has been shifted to the left by the specified number of bits.</returns>
|
||
|
/// <param name="value">The value whose bits are to be shifted.</param>
|
||
|
/// <param name="shift">The number of bits to shift <paramref name="value" /> to the left.</param>
|
||
|
public static BigInteger operator <<(BigInteger value, int shift)
|
||
|
{
|
||
|
uint[] xd;
|
||
|
int xl;
|
||
|
if (shift == 0)
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
if (shift == int.MinValue)
|
||
|
{
|
||
|
return (value >> int.MaxValue) >> 1;
|
||
|
}
|
||
|
if (shift < 0)
|
||
|
{
|
||
|
return value >> -shift;
|
||
|
}
|
||
|
var digitShift = shift / 32;
|
||
|
var smallShift = shift - digitShift * 32;
|
||
|
var partsForBitManipulation = GetPartsForBitManipulation(ref value, out xd, out xl);
|
||
|
var zd = new uint[xl + digitShift + 1];
|
||
|
if (smallShift != 0)
|
||
|
{
|
||
|
var carryShift = 32 - smallShift;
|
||
|
uint carry = 0;
|
||
|
int index;
|
||
|
for (index = 0; index < xl; index++)
|
||
|
{
|
||
|
var rot = xd[index];
|
||
|
zd[index + digitShift] = rot << (smallShift & 31) | carry;
|
||
|
carry = rot >> (carryShift & 31);
|
||
|
}
|
||
|
zd[index + digitShift] = carry;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (var index = 0; index < xl; index++)
|
||
|
{
|
||
|
zd[index + digitShift] = xd[index];
|
||
|
}
|
||
|
}
|
||
|
return new BigInteger(zd, partsForBitManipulation);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is less than another <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator <(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left.CompareTo(right) < 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is less than a 64-bit signed integer.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator <(BigInteger left, long right)
|
||
|
{
|
||
|
return left.CompareTo(right) < 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit signed integer is less than a <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator <(long left, BigInteger right)
|
||
|
{
|
||
|
return right.CompareTo(left) > 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is less than a 64-bit unsigned integer.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator <(BigInteger left, ulong right)
|
||
|
{
|
||
|
return left.CompareTo(right) < 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit unsigned integer is less than a <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator <(ulong left, BigInteger right)
|
||
|
{
|
||
|
return right.CompareTo(left) > 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is less than or equal to another <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than or equal to <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator <=(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left.CompareTo(right) <= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is less than or equal to a 64-bit signed integer.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than or equal to <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator <=(BigInteger left, long right)
|
||
|
{
|
||
|
return left.CompareTo(right) <= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit signed integer is less than or equal to a <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than or equal to <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
public static bool operator <=(long left, BigInteger right)
|
||
|
{
|
||
|
return right.CompareTo(left) >= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a <see cref="T:System.Numerics.BigInteger" /> value is less than or equal to a 64-bit unsigned integer.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than or equal to <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator <=(BigInteger left, ulong right)
|
||
|
{
|
||
|
return left.CompareTo(right) <= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns a value that indicates whether a 64-bit unsigned integer is less than or equal to a <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>true if <paramref name="left" /> is less than or equal to <paramref name="right" />; otherwise, false.</returns>
|
||
|
/// <param name="left">The first value to compare.</param>
|
||
|
/// <param name="right">The second value to compare.</param>
|
||
|
//[CLSCompliant(false)]
|
||
|
public static bool operator <=(ulong left, BigInteger right)
|
||
|
{
|
||
|
return right.CompareTo(left) >= 0;
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the remainder that results from division with two specified <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The remainder that results from the division.</returns>
|
||
|
/// <param name="dividend">The value to be divided.</param>
|
||
|
/// <param name="divisor">The value to divide by.</param>
|
||
|
/// <exception cref="T:System.DivideByZeroException">
|
||
|
/// <paramref name="divisor" /> is 0 (zero).</exception>
|
||
|
public static BigInteger operator %(BigInteger dividend, BigInteger divisor)
|
||
|
{
|
||
|
var signNUm = 1;
|
||
|
var signDen = 1;
|
||
|
var regNum = new BigIntegerBuilder(dividend, ref signNUm);
|
||
|
var regDen = new BigIntegerBuilder(divisor, ref signDen);
|
||
|
regNum.Mod(ref regDen);
|
||
|
return regNum.GetInteger(signNUm);
|
||
|
}
|
||
|
|
||
|
/// <summary>Multiplies two specified <see cref="T:System.Numerics.BigInteger" /> values.</summary>
|
||
|
/// <returns>The product of <paramref name="left" /> and <paramref name="right" />.</returns>
|
||
|
/// <param name="left">The first value to multiply.</param>
|
||
|
/// <param name="right">The second value to multiply.</param>
|
||
|
public static BigInteger operator *(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
var sign = 1;
|
||
|
var regLeft = new BigIntegerBuilder(left, ref sign);
|
||
|
var regRight = new BigIntegerBuilder(right, ref sign);
|
||
|
regLeft.Mul(ref regRight);
|
||
|
return regLeft.GetInteger(sign);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the bitwise one's complement of a <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>The bitwise one's complement of <paramref name="value" />.</returns>
|
||
|
/// <param name="value">An integer value.</param>
|
||
|
public static BigInteger operator ~(BigInteger value)
|
||
|
{
|
||
|
return -(value + One);
|
||
|
}
|
||
|
|
||
|
/// <summary>Shifts a <see cref="T:System.Numerics.BigInteger" /> value a specified number of bits to the right.</summary>
|
||
|
/// <returns>A value that has been shifted to the right by the specified number of bits.</returns>
|
||
|
/// <param name="value">The value whose bits are to be shifted.</param>
|
||
|
/// <param name="shift">The number of bits to shift <paramref name="value" /> to the right.</param>
|
||
|
public static BigInteger operator >>(BigInteger value, int shift)
|
||
|
{
|
||
|
uint[] xd;
|
||
|
int xl;
|
||
|
if (shift == 0)
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
if (shift == int.MinValue)
|
||
|
{
|
||
|
return (value << int.MaxValue) << 1;
|
||
|
}
|
||
|
if (shift < 0)
|
||
|
{
|
||
|
return value << -shift;
|
||
|
}
|
||
|
var digitShift = shift / 32;
|
||
|
var smallShift = shift - digitShift * 32;
|
||
|
var negx = GetPartsForBitManipulation(ref value, out xd, out xl);
|
||
|
if (negx)
|
||
|
{
|
||
|
if (shift >= 32 * xl)
|
||
|
{
|
||
|
return MinusOne;
|
||
|
}
|
||
|
var temp = new uint[xl];
|
||
|
Array.Copy(xd, temp, xl);
|
||
|
xd = temp;
|
||
|
NumericsHelpers.DangerousMakeTwosComplement(xd);
|
||
|
}
|
||
|
var zl = xl - digitShift;
|
||
|
if (zl < 0)
|
||
|
{
|
||
|
zl = 0;
|
||
|
}
|
||
|
var zd = new uint[zl];
|
||
|
if (smallShift != 0)
|
||
|
{
|
||
|
var carryShift = 32 - smallShift;
|
||
|
uint carry = 0;
|
||
|
for (var index = xl - 1; index >= digitShift; index--)
|
||
|
{
|
||
|
var rot = xd[index];
|
||
|
if (!negx || index != xl - 1)
|
||
|
{
|
||
|
zd[index - digitShift] = rot >> (smallShift & 31) | carry;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
zd[index - digitShift] = (rot >> (smallShift & 31)) | (0xFFFFFFFF << (carryShift & 31));
|
||
|
}
|
||
|
carry = rot << (carryShift & 31);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (var index = xl - 1; index >= digitShift; index--)
|
||
|
{
|
||
|
zd[index - digitShift] = xd[index];
|
||
|
}
|
||
|
}
|
||
|
if (negx)
|
||
|
{
|
||
|
NumericsHelpers.DangerousMakeTwosComplement(zd);
|
||
|
}
|
||
|
return new BigInteger(zd, negx);
|
||
|
}
|
||
|
|
||
|
/// <summary>Subtracts a <see cref="T:System.Numerics.BigInteger" /> value from another <see cref="T:System.Numerics.BigInteger" /> value.</summary>
|
||
|
/// <returns>The result of subtracting <paramref name="right" /> from <paramref name="left" />.</returns>
|
||
|
/// <param name="left">The value to subtract from (the minuend).</param>
|
||
|
/// <param name="right">The value to subtract (the subtrahend).</param>
|
||
|
public static BigInteger operator -(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
if (right.IsZero)
|
||
|
{
|
||
|
return left;
|
||
|
}
|
||
|
if (left.IsZero)
|
||
|
{
|
||
|
return -right;
|
||
|
}
|
||
|
var leftSign = 1;
|
||
|
var rightSign = -1;
|
||
|
var regLeft = new BigIntegerBuilder(left, ref leftSign);
|
||
|
var regRight = new BigIntegerBuilder(right, ref rightSign);
|
||
|
if (leftSign != rightSign)
|
||
|
{
|
||
|
regLeft.Sub(ref leftSign, ref regRight);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
regLeft.Add(ref regRight);
|
||
|
}
|
||
|
return regLeft.GetInteger(leftSign);
|
||
|
}
|
||
|
|
||
|
/// <summary>Negates a specified BigInteger value. </summary>
|
||
|
/// <returns>The result of the <paramref name="value" /> parameter multiplied by negative one (-1).</returns>
|
||
|
/// <param name="value">The value to negate.</param>
|
||
|
public static BigInteger operator -(BigInteger value)
|
||
|
{
|
||
|
return new BigInteger(-value.InternalSign, value.InternalBits);
|
||
|
}
|
||
|
|
||
|
/// <summary>Returns the value of the <see cref="T:System.Numerics.BigInteger" /> operand. (The sign of the operand is unchanged.)</summary>
|
||
|
/// <returns>The value of the <paramref name="value" /> operand.</returns>
|
||
|
/// <param name="value">An integer value.</param>
|
||
|
public static BigInteger operator +(BigInteger value)
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts the string representation of a number to its <see cref="T:System.Numerics.BigInteger" /> equivalent.</summary>
|
||
|
/// <returns>A value that is equivalent to the number specified in the <paramref name="value" /> parameter.</returns>
|
||
|
/// <param name="value">A string that contains the number to convert.</param>
|
||
|
/// <exception cref="T:System.ArgumentNullException">
|
||
|
/// <paramref name="value" /> is null.</exception>
|
||
|
/// <exception cref="T:System.FormatException">
|
||
|
/// <paramref name="value" /> is not in the correct format.</exception>
|
||
|
public static BigInteger Parse(string value)
|
||
|
{
|
||
|
return ParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts the string representation of a number in a specified style to its <see cref="T:System.Numerics.BigInteger" /> equivalent.</summary>
|
||
|
/// <returns>A value that is equivalent to the number specified in the <paramref name="value" /> parameter.</returns>
|
||
|
/// <param name="value">A string that contains a number to convert. </param>
|
||
|
/// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <paramref name="value" />.</param>
|
||
|
/// <exception cref="T:System.ArgumentException">
|
||
|
/// <paramref name="style" /> is not a <see cref="T:System.Globalization.NumberStyles" /> value.-or-<paramref name="style" /> includes the <see cref="F:System.Globalization.NumberStyles.AllowHexSpecifier" /> or <see cref="F:System.Globalization.NumberStyles.HexNumber" /> flag along with another value.</exception>
|
||
|
/// <exception cref="T:System.ArgumentNullException">
|
||
|
/// <paramref name="value" /> is null.</exception>
|
||
|
/// <exception cref="T:System.FormatException">
|
||
|
/// <paramref name="value" /> does not comply with the input pattern specified by <see cref="T:System.Globalization.NumberStyles" />.</exception>
|
||
|
public static BigInteger Parse(string value, NumberStyles style)
|
||
|
{
|
||
|
return ParseBigInteger(value, style, NumberFormatInfo.CurrentInfo);
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts the string representation of a number in a specified culture-specific format to its <see cref="T:System.Numerics.BigInteger" /> equivalent.</summary>
|
||
|
/// <returns>A value that is equivalent to the number specified in the <paramref name="value" /> parameter.</returns>
|
||
|
/// <param name="value">A string that contains a number to convert.</param>
|
||
|
/// <param name="provider">An object that provides culture-specific formatting information about <paramref name="value" />.</param>
|
||
|
/// <exception cref="T:System.ArgumentNullException">
|
||
|
/// <paramref name="value" /> is null.</exception>
|
||
|
/// <exception cref="T:System.FormatException">
|
||
|
/// <paramref name="value" /> is not in the correct format.</exception>
|
||
|
public static BigInteger Parse(string value, IFormatProvider provider)
|
||
|
{
|
||
|
return ParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts the string representation of a number in a specified style and culture-specific format to its <see cref="T:System.Numerics.BigInteger" /> equivalent.</summary>
|
||
|
/// <returns>A value that is equivalent to the number specified in the <paramref name="value" /> parameter.</returns>
|
||
|
/// <param name="value">A string that contains a number to convert.</param>
|
||
|
/// <param name="style">A bitwise combination of the enumeration values that specify the permitted format of <paramref name="value" />.</param>
|
||
|
/// <param name="provider">An object that provides culture-specific formatting information about <paramref name="value" />.</param>
|
||
|
/// <exception cref="T:System.ArgumentException">
|
||
|
/// <paramref name="style" /> is not a <see cref="T:System.Globalization.NumberStyles" /> value.-or-<paramref name="style" /> includes the <see cref="F:System.Globalization.NumberStyles.AllowHexSpecifier" /> or <see cref="F:System.Globalization.NumberStyles.HexNumber" /> flag along with another value.</exception>
|
||
|
/// <exception cref="T:System.ArgumentNullException">
|
||
|
/// <paramref name="value" /> is null.</exception>
|
||
|
/// <exception cref="T:System.FormatException">
|
||
|
/// <paramref name="value" /> does not comply with the input pattern specified by <paramref name="style" />.</exception>
|
||
|
public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider)
|
||
|
{
|
||
|
return ParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider));
|
||
|
}
|
||
|
|
||
|
/// <summary>Raises a <see cref="T:System.Numerics.BigInteger" /> value to the power of a specified value.</summary>
|
||
|
/// <returns>The result of raising <paramref name="value" /> to the <paramref name="exponent" /> power.</returns>
|
||
|
/// <param name="value">The number to raise to the <paramref name="exponent" /> power.</param>
|
||
|
/// <param name="exponent">The exponent to raise <paramref name="value" /> by.</param>
|
||
|
/// <exception cref="T:System.ArgumentOutOfRangeException">The value of the <paramref name="exponent" /> parameter is negative.</exception>
|
||
|
public static BigInteger Pow(BigInteger value, int exponent)
|
||
|
{
|
||
|
if (exponent < 0)
|
||
|
{
|
||
|
throw new ArgumentOutOfRangeException("exponent", "The number must be greater than or equal to zero.");
|
||
|
}
|
||
|
if (exponent == 0)
|
||
|
{
|
||
|
return One;
|
||
|
}
|
||
|
if (exponent == 1)
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
if (value.InternalBits == null)
|
||
|
{
|
||
|
if (value.InternalSign == 1)
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
if (value.InternalSign == -1)
|
||
|
{
|
||
|
return (exponent & 1) == 0 ? 1 : value;
|
||
|
}
|
||
|
if (value.InternalSign == 0)
|
||
|
{
|
||
|
return value;
|
||
|
}
|
||
|
}
|
||
|
var sign = 1;
|
||
|
var regSquare = new BigIntegerBuilder(value, ref sign);
|
||
|
var minSquareSize = regSquare.Size;
|
||
|
var maxSquareSize = minSquareSize;
|
||
|
var minSquare = regSquare.High;
|
||
|
var maxSquare = minSquare + 1;
|
||
|
if (maxSquare == 0)
|
||
|
{
|
||
|
maxSquareSize++;
|
||
|
maxSquare = 1;
|
||
|
}
|
||
|
var minResultSize = 1;
|
||
|
var maxResultSize = 1;
|
||
|
uint resultMin = 1;
|
||
|
uint resultMax = 1;
|
||
|
for (var expTmp = exponent; ;)
|
||
|
{
|
||
|
if ((expTmp & 1) != 0)
|
||
|
{
|
||
|
MulUpper(ref resultMax, ref maxResultSize, maxSquare, maxSquareSize);
|
||
|
MulLower(ref resultMin, ref minResultSize, minSquare, minSquareSize);
|
||
|
}
|
||
|
expTmp = expTmp >> 1;
|
||
|
if (expTmp == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
MulUpper(ref maxSquare, ref maxSquareSize, maxSquare, maxSquareSize);
|
||
|
MulLower(ref minSquare, ref minSquareSize, minSquare, minSquareSize);
|
||
|
}
|
||
|
if (maxResultSize > 1)
|
||
|
{
|
||
|
regSquare.EnsureWritable(maxResultSize, 0);
|
||
|
}
|
||
|
var regTmp = new BigIntegerBuilder(maxResultSize);
|
||
|
var regResult = new BigIntegerBuilder(maxResultSize);
|
||
|
regResult.Set(1);
|
||
|
if ((exponent & 1) == 0)
|
||
|
{
|
||
|
sign = 1;
|
||
|
}
|
||
|
for (var expTmp = exponent; ;)
|
||
|
{
|
||
|
if ((expTmp & 1) != 0)
|
||
|
{
|
||
|
NumericHelper.Swap(ref regResult, ref regTmp);
|
||
|
regResult.Mul(ref regSquare, ref regTmp);
|
||
|
}
|
||
|
expTmp = expTmp >> 1;
|
||
|
if (expTmp == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
NumericHelper.Swap(ref regSquare, ref regTmp);
|
||
|
regSquare.Mul(ref regTmp, ref regTmp);
|
||
|
}
|
||
|
return regResult.GetInteger(sign);
|
||
|
}
|
||
|
|
||
|
/// <summary>Performs integer division on two <see cref="T:System.Numerics.BigInteger" /> values and returns the remainder.</summary>
|
||
|
/// <returns>The remainder after dividing <paramref name="dividend" /> by <paramref name="divisor" />.</returns>
|
||
|
/// <param name="dividend">The value to be divided.</param>
|
||
|
/// <param name="divisor">The value to divide by.</param>
|
||
|
/// <exception cref="T:System.DivideByZeroException">
|
||
|
/// <paramref name="divisor" /> is 0 (zero).</exception>
|
||
|
public static BigInteger Remainder(BigInteger dividend, BigInteger divisor)
|
||
|
{
|
||
|
return dividend % divisor;
|
||
|
}
|
||
|
|
||
|
private static void SetBitsFromDouble(double value, out uint[] bits, out int sign)
|
||
|
{
|
||
|
int valueSign;
|
||
|
int valueExp;
|
||
|
ulong valueMan;
|
||
|
bool valueFinite;
|
||
|
sign = 0;
|
||
|
bits = null;
|
||
|
NumericsHelpers.GetDoubleParts(value, out valueSign, out valueExp, out valueMan, out valueFinite);
|
||
|
if (valueMan == 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (valueExp <= 0)
|
||
|
{
|
||
|
if (valueExp <= -64)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
var tmp = valueMan >> (-valueExp & 63);
|
||
|
if (tmp > int.MaxValue)
|
||
|
{
|
||
|
sign = 1;
|
||
|
bits = new[] { (uint)tmp, (uint)(tmp >> 32) };
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sign = (int)tmp;
|
||
|
}
|
||
|
if (valueSign < 0)
|
||
|
{
|
||
|
sign = -sign;
|
||
|
}
|
||
|
}
|
||
|
else if (valueExp > 11)
|
||
|
{
|
||
|
valueMan = valueMan << 11;
|
||
|
valueExp = valueExp - 11;
|
||
|
var significantDword = (valueExp - 1) / 32 + 1;
|
||
|
var extraDword = significantDword * 32 - valueExp;
|
||
|
bits = new uint[significantDword + 2];
|
||
|
bits[significantDword + 1] = (uint)(valueMan >> (extraDword + 32 & 63));
|
||
|
bits[significantDword] = (uint)(valueMan >> (extraDword & 63));
|
||
|
if (extraDword > 0)
|
||
|
{
|
||
|
bits[significantDword - 1] = (uint)valueMan << (32 - extraDword & 31);
|
||
|
}
|
||
|
sign = valueSign;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var tmp = valueMan << (valueExp & 63);
|
||
|
if (tmp > int.MaxValue)
|
||
|
{
|
||
|
sign = 1;
|
||
|
bits = new[] { (uint)tmp, (uint)(tmp >> 32) };
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sign = (int)tmp;
|
||
|
}
|
||
|
if (valueSign < 0)
|
||
|
{
|
||
|
sign = -sign;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>Subtracts one <see cref="T:System.Numerics.BigInteger" /> value from another and returns the result.</summary>
|
||
|
/// <returns>The result of subtracting <paramref name="right" /> from <paramref name="left" />.</returns>
|
||
|
/// <param name="left">The value to subtract from (the minuend).</param>
|
||
|
/// <param name="right">The value to subtract (the subtrahend).</param>
|
||
|
public static BigInteger Subtract(BigInteger left, BigInteger right)
|
||
|
{
|
||
|
return left - right;
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts a <see cref="T:System.Numerics.BigInteger" /> value to a byte array.</summary>
|
||
|
/// <returns>The value of the current <see cref="T:System.Numerics.BigInteger" /> object converted to an array of bytes.</returns>
|
||
|
public byte[] ToByteArray()
|
||
|
{
|
||
|
uint[] internalBits;
|
||
|
byte highByte;
|
||
|
if (InternalBits == null && InternalSign == 0)
|
||
|
{
|
||
|
return new byte[1];
|
||
|
}
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
internalBits = new[] { unchecked((uint)InternalSign) };
|
||
|
highByte = InternalSign < 0 ? (byte)0xff : (byte)0x00;
|
||
|
}
|
||
|
else if (InternalSign != -1)
|
||
|
{
|
||
|
internalBits = InternalBits;
|
||
|
highByte = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
internalBits = (uint[])InternalBits.Clone();
|
||
|
NumericsHelpers.DangerousMakeTwosComplement(internalBits);
|
||
|
highByte = 255;
|
||
|
}
|
||
|
var bytes = new byte[checked(4 * internalBits.Length)];
|
||
|
var index = 0;
|
||
|
foreach (var value in internalBits)
|
||
|
{
|
||
|
var current = value;
|
||
|
for (var j = 0; j < 4; j++)
|
||
|
{
|
||
|
bytes[index] = (byte)(current & 255);
|
||
|
current >>= 8;
|
||
|
index++;
|
||
|
}
|
||
|
}
|
||
|
var length = bytes.Length - 1;
|
||
|
while (length > 0)
|
||
|
{
|
||
|
if (bytes[length] == highByte)
|
||
|
{
|
||
|
length--;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
var extra = (bytes[length] & 128) != (highByte & 128);
|
||
|
var result = new byte[length + 1 + (extra ? 1 : 0)];
|
||
|
Array.Copy(bytes, result, length + 1);
|
||
|
if (extra)
|
||
|
{
|
||
|
result[result.Length - 1] = highByte;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts the numeric value of the current <see cref="T:System.Numerics.BigInteger" /> object to its equivalent string representation.</summary>
|
||
|
/// <returns>The string representation of the current <see cref="T:System.Numerics.BigInteger" /> value.</returns>
|
||
|
public override string ToString()
|
||
|
{
|
||
|
return FormatBigInteger(this, null, NumberFormatInfo.CurrentInfo);
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts the numeric value of the current <see cref="T:System.Numerics.BigInteger" /> object to its equivalent string representation by using the specified culture-specific formatting information.</summary>
|
||
|
/// <returns>The string representation of the current <see cref="T:System.Numerics.BigInteger" /> value in the format specified by the <paramref name="provider" /> parameter.</returns>
|
||
|
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
|
||
|
public string ToString(IFormatProvider provider)
|
||
|
{
|
||
|
return FormatBigInteger(this, null, NumberFormatInfo.GetInstance(provider));
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts the numeric value of the current <see cref="T:System.Numerics.BigInteger" /> object to its equivalent string representation by using the specified format.</summary>
|
||
|
/// <returns>The string representation of the current <see cref="T:System.Numerics.BigInteger" /> value in the format specified by the <paramref name="format" /> parameter.</returns>
|
||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||
|
/// <exception cref="T:System.FormatException">
|
||
|
/// <paramref name="format" /> is not a valid format string.</exception>
|
||
|
public string ToString(string format)
|
||
|
{
|
||
|
return FormatBigInteger(this, format, NumberFormatInfo.CurrentInfo);
|
||
|
}
|
||
|
|
||
|
/// <summary>Converts the numeric value of the current <see cref="T:System.Numerics.BigInteger" /> object to its equivalent string representation by using the specified format and culture-specific format information.</summary>
|
||
|
/// <returns>The string representation of the current <see cref="T:System.Numerics.BigInteger" /> value as specified by the <paramref name="format" /> and <paramref name="provider" /> parameters.</returns>
|
||
|
/// <param name="format">A standard or custom numeric format string.</param>
|
||
|
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
|
||
|
/// <exception cref="T:System.FormatException">
|
||
|
/// <paramref name="format" /> is not a valid format string.</exception>
|
||
|
public string ToString(string format, IFormatProvider provider)
|
||
|
{
|
||
|
return FormatBigInteger(this, format, NumberFormatInfo.GetInstance(provider));
|
||
|
}
|
||
|
|
||
|
private uint[] ToUInt32Array()
|
||
|
{
|
||
|
uint[] internalBits;
|
||
|
uint highDword;
|
||
|
if (InternalBits == null && InternalSign == 0)
|
||
|
{
|
||
|
return new uint[1];
|
||
|
}
|
||
|
if (InternalBits == null)
|
||
|
{
|
||
|
internalBits = new[] { unchecked((uint)InternalSign) };
|
||
|
highDword = (uint)((InternalSign >= 0 ? 0 : -1));
|
||
|
}
|
||
|
else if (InternalSign != -1)
|
||
|
{
|
||
|
internalBits = InternalBits;
|
||
|
highDword = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
internalBits = (uint[])InternalBits.Clone();
|
||
|
NumericsHelpers.DangerousMakeTwosComplement(internalBits);
|
||
|
highDword = unchecked((uint)-1);
|
||
|
}
|
||
|
var length = internalBits.Length - 1;
|
||
|
while (length > 0)
|
||
|
{
|
||
|
if (internalBits[length] == highDword)
|
||
|
{
|
||
|
length--;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
var needExtraByte = (internalBits[length] & int.MinValue) != (highDword & int.MinValue);
|
||
|
var trimmed = new uint[length + 1 + (!needExtraByte ? 0 : 1)];
|
||
|
Array.Copy(internalBits, trimmed, length + 1);
|
||
|
if (needExtraByte)
|
||
|
{
|
||
|
trimmed[trimmed.Length - 1] = highDword;
|
||
|
}
|
||
|
return trimmed;
|
||
|
}
|
||
|
|
||
|
/// <summary>Tries to convert the string representation of a number to its <see cref="T:System.Numerics.BigInteger" /> equivalent, and returns a value that indicates whether the conversion succeeded.</summary>
|
||
|
/// <returns>true if <paramref name="value" /> was converted successfully; otherwise, false.</returns>
|
||
|
/// <param name="value">The string representation of a number.</param>
|
||
|
/// <param name="result">When this method returns, contains the <see cref="T:System.Numerics.BigInteger" /> equivalent to the number that is contained in <paramref name="value" />, or zero (0) if the conversion fails. The conversion fails if the <paramref name="value" /> parameter is null or is not of the correct format. This parameter is passed uninitialized.</param>
|
||
|
/// <exception cref="T:System.ArgumentNullException">
|
||
|
/// <paramref name="value" /> is null.</exception>
|
||
|
public static bool TryParse(string value, out BigInteger result)
|
||
|
{
|
||
|
return TryParseBigInteger(value, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
|
||
|
}
|
||
|
|
||
|
/// <summary>Tries to convert the string representation of a number in a specified style and culture-specific format to its <see cref="T:System.Numerics.BigInteger" /> equivalent, and returns a value that indicates whether the conversion succeeded.</summary>
|
||
|
/// <returns>true if the <paramref name="value" /> parameter was converted successfully; otherwise, false.</returns>
|
||
|
/// <param name="value">The string representation of a number. The string is interpreted using the style specified by <paramref name="style" />.</param>
|
||
|
/// <param name="style">A bitwise combination of enumeration values that indicates the style elements that can be present in <paramref name="value" />. A typical value to specify is <see cref="F:System.Globalization.NumberStyles.Integer" />.</param>
|
||
|
/// <param name="provider">An object that supplies culture-specific formatting information about <paramref name="value" />.</param>
|
||
|
/// <param name="result">When this method returns, contains the <see cref="T:System.Numerics.BigInteger" /> equivalent to the number that is contained in <paramref name="value" />, or <see cref="P:System.Numerics.BigInteger.Zero" /> if the conversion failed. The conversion fails if the <paramref name="value" /> parameter is null or is not in a format that is compliant with <paramref name="style" />. This parameter is passed uninitialized.</param>
|
||
|
/// <exception cref="T:System.ArgumentException">
|
||
|
/// <paramref name="style" /> is not a <see cref="T:System.Globalization.NumberStyles" /> value.-or-<paramref name="style" /> includes the <see cref="F:System.Globalization.NumberStyles.AllowHexSpecifier" /> or <see cref="F:System.Globalization.NumberStyles.HexNumber" /> flag along with another value. </exception>
|
||
|
public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigInteger result)
|
||
|
{
|
||
|
return TryParseBigInteger(value, style, NumberFormatInfo.GetInstance(provider), out result);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|