900 lines
22 KiB
C#
900 lines
22 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace ln.biginteger
|
|
{
|
|
public class BigInteger : IComparable<BigInteger>
|
|
{
|
|
public static readonly BigInteger Zero = new BigInteger();
|
|
public static readonly BigInteger One = new BigInteger(1);
|
|
public static readonly BigInteger MinusOne = new BigInteger(-1);
|
|
|
|
UInt32[] bits;
|
|
|
|
public BigInteger()
|
|
{
|
|
this.bits = new UInt32[1];
|
|
}
|
|
public BigInteger(UInt32 ui)
|
|
{
|
|
this.bits = new uint[]{ ui };
|
|
}
|
|
public BigInteger(Int32 i)
|
|
{
|
|
this.bits = new uint[]{ (uint)i };
|
|
}
|
|
|
|
public BigInteger(UInt64 i)
|
|
{
|
|
this.bits = new uint[]{
|
|
(uint)(i & 0xFFFFFFFF),
|
|
(uint)(i >> 32),
|
|
0
|
|
};
|
|
Reduce();
|
|
}
|
|
public BigInteger(Int64 i)
|
|
{
|
|
this.bits = new uint[]{
|
|
(uint)(i & 0xFFFFFFFF),
|
|
(uint)(i >> 32)
|
|
};
|
|
Reduce();
|
|
}
|
|
|
|
public BigInteger(UInt32[] rawbits)
|
|
{
|
|
bits = rawbits;
|
|
if (!Reduce())
|
|
bits = (UInt32[])bits.Clone();
|
|
}
|
|
|
|
private bool Reduce()
|
|
{
|
|
Int32 rl = GetLength();
|
|
if (bits.Length > rl)
|
|
{
|
|
UInt32[] newbits = new uint[rl];
|
|
Array.Copy(bits, newbits, rl);
|
|
bits = newbits;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public Int32 GetByteCount() => big_get_length(bits) << 2;
|
|
public Int32 GetBitLength() => big_get_length(bits) << 5;
|
|
public Int32 GetLength() => big_get_length(bits);
|
|
|
|
public int CompareTo(BigInteger other) => big_cmp(bits, bits.Length, other.bits, other.bits.Length);
|
|
|
|
|
|
public Int32 Sign {
|
|
get {
|
|
if ((bits.Length == 1) && (bits[0] == 0))
|
|
return 0;
|
|
else if ((bits[bits.Length-1] & 0x80000000) != 0)
|
|
return -1;
|
|
else
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
public bool IsZero => ((bits.Length == 1) && (bits[0] == 0));
|
|
|
|
|
|
public BigInteger Add(BigInteger bi2)
|
|
{
|
|
UInt32[] r = new uint[max(bits.Length, bi2.bits.Length)+1];
|
|
Array.Copy(bits,r,bits.Length);
|
|
big_add(r, r.Length, bi2.bits, bi2.bits.Length);
|
|
return new BigInteger(r);
|
|
}
|
|
public BigInteger Sub(BigInteger bi2)
|
|
{
|
|
UInt32[] r = new uint[max(bits.Length, bi2.bits.Length)+1];
|
|
Array.Copy(bits,r,bits.Length);
|
|
big_sub(r, r.Length, bi2.bits, bi2.bits.Length);
|
|
return new BigInteger(r);
|
|
}
|
|
// public BigInteger Sub(BigInteger bi2)
|
|
// {
|
|
// UInt32[] r = new uint[max(bits.Length, bi2.bits.Length)+1];
|
|
// Array.Copy(bits,r,bits.Length);
|
|
|
|
// UInt32[] r2 = (uint[])bi2.bits.Clone();
|
|
// big_twos(r2, r2.Length);
|
|
|
|
// big_add(r, r.Length, r2, r2.Length);
|
|
// return new BigInteger(r);
|
|
// }
|
|
|
|
public BigInteger Mul(BigInteger bi2)
|
|
{
|
|
UInt32[] r = new uint[bits.Length + bi2.bits.Length];
|
|
big_smul(bits, bits.Length, bi2.bits, bi2.bits.Length, r);
|
|
return new BigInteger(r);
|
|
}
|
|
|
|
public BigInteger DivMod(BigInteger divisor,out BigInteger remainder)
|
|
{
|
|
UInt32[] quotient = (uint[])bits.Clone();
|
|
UInt32[] d = (uint[])divisor.bits.Clone();
|
|
|
|
big_divmod( quotient, quotient.Length, d, d.Length);
|
|
|
|
remainder = new BigInteger(d);
|
|
return new BigInteger(quotient);
|
|
}
|
|
public BigInteger Div(BigInteger divisor)
|
|
{
|
|
UInt32[] quotient = (uint[])bits.Clone();
|
|
UInt32[] d = (uint[])divisor.bits.Clone();
|
|
|
|
big_divmod( quotient, quotient.Length, d, d.Length);
|
|
|
|
return new BigInteger(quotient);
|
|
}
|
|
public BigInteger Mod(BigInteger divisor)
|
|
{
|
|
UInt32[] quotient = (uint[])bits.Clone();
|
|
UInt32[] d = (uint[])divisor.bits.Clone();
|
|
|
|
big_divmod( quotient, quotient.Length, d, d.Length);
|
|
|
|
return new BigInteger(d);
|
|
}
|
|
|
|
|
|
|
|
public BigInteger Ones()
|
|
{
|
|
UInt32[] r = (UInt32[])bits.Clone();
|
|
for (int n=0;n<r.Length;n++)
|
|
r[n] = ~r[n];
|
|
return new BigInteger(r);
|
|
}
|
|
|
|
public BigInteger Twos()
|
|
{
|
|
UInt32[] r = (UInt32[])bits.Clone();
|
|
big_twos(r, r.Length);
|
|
return new BigInteger(r);
|
|
}
|
|
|
|
public BigInteger ShiftLeft(int n)
|
|
{
|
|
UInt32[] r = (UInt32[])bits.Clone();
|
|
big_shl(r, r.Length, n);
|
|
return new BigInteger(r);
|
|
}
|
|
public BigInteger ShiftRight(int n)
|
|
{
|
|
UInt32[] r = (UInt32[])bits.Clone();
|
|
big_shr(r, r.Length, n);
|
|
return new BigInteger(r);
|
|
}
|
|
|
|
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (obj is BigInteger bi2)
|
|
{
|
|
if (bits.Length == bi2.bits.Length)
|
|
{
|
|
for (int n=0;n<bits.Length;n++)
|
|
{
|
|
if (bits[n] != bi2.bits[n])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
public byte[] ToByteArray()
|
|
{
|
|
bool nonzero = false;
|
|
MemoryStream ms = new MemoryStream();
|
|
|
|
// if (Sign < 0)
|
|
// ms.WriteByte(0);
|
|
|
|
for (int n=bits.Length-1; n >= 0; n--)
|
|
{
|
|
for (int m=3; m>=0; m--)
|
|
{
|
|
byte tb = (byte)((bits[n] >> (m*8)) & 0xff);
|
|
if (nonzero || (tb!=0))
|
|
{
|
|
nonzero = true;
|
|
ms.WriteByte(tb);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ms.ToArray();
|
|
}
|
|
|
|
|
|
public static BigInteger operator+(BigInteger bi1,BigInteger bi2) => bi1.Add(bi2);
|
|
public static BigInteger operator-(BigInteger bi1,BigInteger bi2) => bi1.Sub(bi2);
|
|
|
|
public static BigInteger operator<<(BigInteger bi, int n) => bi.ShiftLeft(n);
|
|
public static BigInteger operator>>(BigInteger bi, int n) => bi.ShiftRight(n);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static BigInteger FromHexString(string hex)
|
|
{
|
|
hex = hex.ToUpper();
|
|
int length = (hex.Length+7) >> 3;
|
|
UInt32[] bits = new uint[length];
|
|
int n;
|
|
|
|
for (n=hex.Length-8; n>=0; n -= 8)
|
|
bits[length - 1 - (n >> 3)] = uint.Parse(hex.Substring(n,8), NumberStyles.HexNumber);
|
|
if (n > -8)
|
|
bits[length - 1] = uint.Parse(hex.Substring(0, 8 + n), NumberStyles.HexNumber);
|
|
|
|
return new BigInteger(bits);
|
|
}
|
|
|
|
public string ToHexString()
|
|
{
|
|
byte[] bytes = ToByteArray();
|
|
StringBuilder sb = new StringBuilder();
|
|
foreach (byte by in bytes)
|
|
sb.AppendFormat("{0:X2}", by);
|
|
return sb.ToString();
|
|
}
|
|
|
|
|
|
|
|
// public BigInteger(UInt32[] value)
|
|
// {
|
|
// this.bits = value;
|
|
// }
|
|
|
|
|
|
|
|
|
|
// public BigInteger(byte[] ivalue)
|
|
// {
|
|
// UInt32[] v = new UInt32[(ivalue.Length + 3) >> 2];
|
|
// ivalue = ivalue.Segment(0, v.Length << 2);
|
|
|
|
// for (int n = 0; n < v.Length; n++)
|
|
// {
|
|
// v[n] = BitConverter.ToUInt32(ivalue, n << 2);
|
|
// }
|
|
// this.bits = BigIntMath.reduceSigned(v);
|
|
// }
|
|
// public BigInteger(BigInteger src)
|
|
// {
|
|
// this.bits = src.bits;
|
|
// }
|
|
|
|
// public bool IsZero => BigIntMath.isZero(bits);
|
|
// public int Sign => BigIntMath.isZero(bits) ? 0 : BigIntMath.sign(bits) ? -1 : 1;
|
|
|
|
// public int GetByteCount() => bits.Length * 4;
|
|
// public int GetBitLength() => BigIntMath.log2(bits);
|
|
|
|
// public byte[] ToByteArray() => bits.GetBytes();
|
|
|
|
// public void TryWriteBytes(Span<byte> s,out int bytesWritten)
|
|
// {
|
|
// byte[] sb = ToByteArray();
|
|
// for (bytesWritten = 0; bytesWritten < sb.Length; bytesWritten++)
|
|
// s[bytesWritten] = sb[bytesWritten];
|
|
// }
|
|
|
|
// public int Log2(){
|
|
// return BigIntMath.log2(bits);
|
|
// }
|
|
|
|
// public static BigInteger ModPow(BigInteger i,int n,BigInteger modulus)
|
|
// {
|
|
// BigInteger r = BigInteger.One;
|
|
// while (n-- > 0)
|
|
// {
|
|
// r *= i;
|
|
// r %= modulus;
|
|
// }
|
|
// return r;
|
|
// }
|
|
|
|
// public BigInteger Pow(int n)
|
|
// {
|
|
// if (n == 0)
|
|
// {
|
|
// return One;
|
|
// }
|
|
// else if (n == 1)
|
|
// {
|
|
// return this;
|
|
// }
|
|
// else if (n > 1)
|
|
// {
|
|
// BigInteger result = this;
|
|
// n--;
|
|
// while ((n--) > 0)
|
|
// {
|
|
// result = (result * this);
|
|
// }
|
|
// return result;
|
|
// }
|
|
// throw new ArgumentException("Integer.Pow(n): not implemented for negative exponent");
|
|
// }
|
|
|
|
// public BigInteger Ones()
|
|
// {
|
|
// UInt32[] result = BigIntMath.ones(bits);
|
|
// return new BigInteger(result);
|
|
// }
|
|
|
|
// public BigInteger Twos()
|
|
// {
|
|
// UInt32[] result = BigIntMath.twos(bits);
|
|
// return new BigInteger(result);
|
|
// }
|
|
|
|
|
|
// public static BigInteger fromHexString(string hex) => Parse(hex, 16);
|
|
|
|
// public override string ToString()
|
|
// {
|
|
// return String.Format("[{0}: Sign: {2,5} / {1}]", this.GetType().Name, ToString(16), Sign );
|
|
// }
|
|
|
|
// public string ToString(string format)
|
|
// {
|
|
// if (format.Equals("X"))
|
|
// return ToString(16);
|
|
// return ToString(10);
|
|
// }
|
|
|
|
// public string ToString(int radix) => ToString(radix, -1);
|
|
// public string ToString(int radix, int length)
|
|
// {
|
|
// if ((radix < 2) || (radix > 36))
|
|
// throw new ArgumentOutOfRangeException(nameof(radix));
|
|
|
|
// uint[] v = bits.Segment(0);
|
|
// uint[] r = new uint[]{ (uint)radix };
|
|
|
|
// StringBuilder sb = new StringBuilder();
|
|
|
|
// while ((!BigIntMath.isZero(v)) && ((length-- )!=0))
|
|
// {
|
|
// uint[] x = BigIntMath.sdivmod(ref v, r);
|
|
// if (v[0] < 10)
|
|
// sb.Append((char)('0' + v[0]));
|
|
// else
|
|
// sb.Append((char)(55 + v[0]));
|
|
// v = x;
|
|
// }
|
|
|
|
// char[] result = new char[sb.Length];
|
|
// sb.CopyTo(0, result, 0, sb.Length);
|
|
// Array.Reverse(result);
|
|
// return new string(result);
|
|
// }
|
|
|
|
// public static BigInteger Parse(string input) => Parse(input, 10);
|
|
|
|
// public static BigInteger Parse(string input, NumberStyles numberStyles)
|
|
// {
|
|
// if ((numberStyles & (NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier)) != 0)
|
|
// return Parse(input, 16);
|
|
// return Parse(input, 10);
|
|
// }
|
|
|
|
// public static BigInteger Parse(string input, int radix)
|
|
// {
|
|
// BigInteger v = 0;
|
|
// bool sign = false;
|
|
|
|
// if (input[0] == '-')
|
|
// {
|
|
// sign = true;
|
|
// input = input.Substring(1);
|
|
// }
|
|
|
|
// foreach (char d in input)
|
|
// {
|
|
// int n = d - '0';
|
|
// if (n > 9)
|
|
// n = d - 55;
|
|
|
|
// v *= radix;
|
|
// v += n;
|
|
// }
|
|
|
|
// if (sign)
|
|
// v = v.Twos();
|
|
|
|
// return v;
|
|
// }
|
|
|
|
|
|
|
|
// private BigInteger __op_add(BigInteger b)
|
|
// {
|
|
// int width = (bits.Length > b.bits.Length ? bits.Length : b.bits.Length) + 1;
|
|
// UInt32[] v = BigIntMath.extendSigned(bits, width);
|
|
// UInt32[] vb = BigIntMath.extendSigned(b.bits, width);
|
|
// return new BigInteger(BigIntMath.reduceSigned(BigIntMath.add(v,vb)));
|
|
// }
|
|
// private BigInteger __op_sub(BigInteger b)
|
|
// {
|
|
// int width = (bits.Length > b.bits.Length ? bits.Length : b.bits.Length) + 1;
|
|
// UInt32[] v = BigIntMath.extendSigned(bits, width);
|
|
// UInt32[] vb = BigIntMath.extendSigned(b.bits, width);
|
|
// return new BigInteger(BigIntMath.reduceSigned(BigIntMath.sub(v,vb)));
|
|
// }
|
|
|
|
// private int __op_cmp(BigInteger b)
|
|
// {
|
|
// return BigIntMath.cmp(bits, b.bits);
|
|
// }
|
|
|
|
// private BigInteger __op_div(BigInteger b)
|
|
// {
|
|
// UInt32[] result = BigIntMath.sdiv(bits, b.bits);
|
|
// return new BigInteger(result);
|
|
// }
|
|
|
|
// private BigInteger __op_mod(BigInteger b)
|
|
// {
|
|
// UInt32[] result = BigIntMath.smod(bits, b.bits);
|
|
// return new BigInteger(result);
|
|
// }
|
|
|
|
// private BigInteger __op_mul(BigInteger b)
|
|
// {
|
|
// UInt32[] value = BigIntMath.smul(bits, b.bits);
|
|
// return new BigInteger(value);
|
|
// }
|
|
|
|
// private BigInteger __op_new(uint[] value)
|
|
// {
|
|
// return new BigInteger(value);
|
|
// }
|
|
|
|
// private BigInteger __op_shl(int b)
|
|
// {
|
|
// UInt32[] value = BigIntMath.extendSigned(bits, bits.Length + ((b + 31) >> 5));
|
|
// BigIntMath.shl(value,b);
|
|
// return new BigInteger(value);
|
|
// }
|
|
|
|
// private BigInteger __op_shr(int b)
|
|
// {
|
|
// UInt32[] value = bits.Segment(0);
|
|
// BigIntMath.shr(value, b);
|
|
// return new BigInteger(value);
|
|
// }
|
|
|
|
// public static implicit operator BigInteger(int i)
|
|
// {
|
|
// return new BigInteger(new UInt32[]{(UInt32)i});
|
|
// }
|
|
|
|
|
|
|
|
// public static BigInteger operator +(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_add(b);
|
|
// }
|
|
// public static BigInteger operator -(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_sub(b);
|
|
// }
|
|
// public static BigInteger operator *(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_mul(b);
|
|
// }
|
|
|
|
// public static BigInteger operator /(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_div(b);
|
|
// }
|
|
// public static BigInteger operator %(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_mod(b);
|
|
// }
|
|
|
|
// public static bool operator <(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_cmp(b) < 0;
|
|
// }
|
|
// public static bool operator >(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_cmp(b) > 0;
|
|
// }
|
|
// public static bool operator ==(BigInteger a, BigInteger b)
|
|
// {
|
|
// if ((object)a == (object)b)
|
|
// {
|
|
// return true;
|
|
// }
|
|
// if (((object)a == null) || ((object)b == null))
|
|
// {
|
|
// return false;
|
|
// }
|
|
// return a.__op_cmp(b) == 0;
|
|
// }
|
|
// public static bool operator !=(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_cmp(b) != 0;
|
|
// }
|
|
|
|
// public static BigInteger operator <<(BigInteger a, int b)
|
|
// {
|
|
// return a.__op_shl(b);
|
|
// }
|
|
// public static BigInteger operator >>(BigInteger a, int b)
|
|
// {
|
|
// return a.__op_shr(b);
|
|
// }
|
|
|
|
// public override bool Equals(object obj) => (obj is BigInteger other) && (this == other);
|
|
// public override int GetHashCode() => ToByteArray().CreateHashCode();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*** Native Implementations ***/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// public BigInteger(UInt32[] value)
|
|
// {
|
|
// this.bits = value;
|
|
// }
|
|
|
|
|
|
|
|
|
|
// public BigInteger(byte[] ivalue)
|
|
// {
|
|
// UInt32[] v = new UInt32[(ivalue.Length + 3) >> 2];
|
|
// ivalue = ivalue.Segment(0, v.Length << 2);
|
|
|
|
// for (int n = 0; n < v.Length; n++)
|
|
// {
|
|
// v[n] = BitConverter.ToUInt32(ivalue, n << 2);
|
|
// }
|
|
// this.bits = BigIntMath.reduceSigned(v);
|
|
// }
|
|
// public BigInteger(BigInteger src)
|
|
// {
|
|
// this.bits = src.bits;
|
|
// }
|
|
|
|
// public bool IsZero => BigIntMath.isZero(bits);
|
|
// public int Sign => BigIntMath.isZero(bits) ? 0 : BigIntMath.sign(bits) ? -1 : 1;
|
|
|
|
// public int GetByteCount() => bits.Length * 4;
|
|
// public int GetBitLength() => BigIntMath.log2(bits);
|
|
|
|
// public byte[] ToByteArray() => bits.GetBytes();
|
|
|
|
// public void TryWriteBytes(Span<byte> s,out int bytesWritten)
|
|
// {
|
|
// byte[] sb = ToByteArray();
|
|
// for (bytesWritten = 0; bytesWritten < sb.Length; bytesWritten++)
|
|
// s[bytesWritten] = sb[bytesWritten];
|
|
// }
|
|
|
|
// public int Log2(){
|
|
// return BigIntMath.log2(bits);
|
|
// }
|
|
|
|
// public static BigInteger ModPow(BigInteger i,int n,BigInteger modulus)
|
|
// {
|
|
// BigInteger r = BigInteger.One;
|
|
// while (n-- > 0)
|
|
// {
|
|
// r *= i;
|
|
// r %= modulus;
|
|
// }
|
|
// return r;
|
|
// }
|
|
|
|
// public BigInteger Pow(int n)
|
|
// {
|
|
// if (n == 0)
|
|
// {
|
|
// return One;
|
|
// }
|
|
// else if (n == 1)
|
|
// {
|
|
// return this;
|
|
// }
|
|
// else if (n > 1)
|
|
// {
|
|
// BigInteger result = this;
|
|
// n--;
|
|
// while ((n--) > 0)
|
|
// {
|
|
// result = (result * this);
|
|
// }
|
|
// return result;
|
|
// }
|
|
// throw new ArgumentException("Integer.Pow(n): not implemented for negative exponent");
|
|
// }
|
|
|
|
// public BigInteger Ones()
|
|
// {
|
|
// UInt32[] result = BigIntMath.ones(bits);
|
|
// return new BigInteger(result);
|
|
// }
|
|
|
|
// public BigInteger Twos()
|
|
// {
|
|
// UInt32[] result = BigIntMath.twos(bits);
|
|
// return new BigInteger(result);
|
|
// }
|
|
|
|
|
|
// public static BigInteger fromHexString(string hex) => Parse(hex, 16);
|
|
|
|
// public override string ToString()
|
|
// {
|
|
// return String.Format("[{0}: Sign: {2,5} / {1}]", this.GetType().Name, ToString(16), Sign );
|
|
// }
|
|
|
|
// public string ToString(string format)
|
|
// {
|
|
// if (format.Equals("X"))
|
|
// return ToString(16);
|
|
// return ToString(10);
|
|
// }
|
|
|
|
// public string ToString(int radix) => ToString(radix, -1);
|
|
// public string ToString(int radix, int length)
|
|
// {
|
|
// if ((radix < 2) || (radix > 36))
|
|
// throw new ArgumentOutOfRangeException(nameof(radix));
|
|
|
|
// uint[] v = bits.Segment(0);
|
|
// uint[] r = new uint[]{ (uint)radix };
|
|
|
|
// StringBuilder sb = new StringBuilder();
|
|
|
|
// while ((!BigIntMath.isZero(v)) && ((length-- )!=0))
|
|
// {
|
|
// uint[] x = BigIntMath.sdivmod(ref v, r);
|
|
// if (v[0] < 10)
|
|
// sb.Append((char)('0' + v[0]));
|
|
// else
|
|
// sb.Append((char)(55 + v[0]));
|
|
// v = x;
|
|
// }
|
|
|
|
// char[] result = new char[sb.Length];
|
|
// sb.CopyTo(0, result, 0, sb.Length);
|
|
// Array.Reverse(result);
|
|
// return new string(result);
|
|
// }
|
|
|
|
// public static BigInteger Parse(string input) => Parse(input, 10);
|
|
|
|
// public static BigInteger Parse(string input, NumberStyles numberStyles)
|
|
// {
|
|
// if ((numberStyles & (NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier)) != 0)
|
|
// return Parse(input, 16);
|
|
// return Parse(input, 10);
|
|
// }
|
|
|
|
// public static BigInteger Parse(string input, int radix)
|
|
// {
|
|
// BigInteger v = 0;
|
|
// bool sign = false;
|
|
|
|
// if (input[0] == '-')
|
|
// {
|
|
// sign = true;
|
|
// input = input.Substring(1);
|
|
// }
|
|
|
|
// foreach (char d in input)
|
|
// {
|
|
// int n = d - '0';
|
|
// if (n > 9)
|
|
// n = d - 55;
|
|
|
|
// v *= radix;
|
|
// v += n;
|
|
// }
|
|
|
|
// if (sign)
|
|
// v = v.Twos();
|
|
|
|
// return v;
|
|
// }
|
|
|
|
|
|
|
|
// private BigInteger __op_add(BigInteger b)
|
|
// {
|
|
// int width = (bits.Length > b.bits.Length ? bits.Length : b.bits.Length) + 1;
|
|
// UInt32[] v = BigIntMath.extendSigned(bits, width);
|
|
// UInt32[] vb = BigIntMath.extendSigned(b.bits, width);
|
|
// return new BigInteger(BigIntMath.reduceSigned(BigIntMath.add(v,vb)));
|
|
// }
|
|
// private BigInteger __op_sub(BigInteger b)
|
|
// {
|
|
// int width = (bits.Length > b.bits.Length ? bits.Length : b.bits.Length) + 1;
|
|
// UInt32[] v = BigIntMath.extendSigned(bits, width);
|
|
// UInt32[] vb = BigIntMath.extendSigned(b.bits, width);
|
|
// return new BigInteger(BigIntMath.reduceSigned(BigIntMath.sub(v,vb)));
|
|
// }
|
|
|
|
// private int __op_cmp(BigInteger b)
|
|
// {
|
|
// return BigIntMath.cmp(bits, b.bits);
|
|
// }
|
|
|
|
// private BigInteger __op_div(BigInteger b)
|
|
// {
|
|
// UInt32[] result = BigIntMath.sdiv(bits, b.bits);
|
|
// return new BigInteger(result);
|
|
// }
|
|
|
|
// private BigInteger __op_mod(BigInteger b)
|
|
// {
|
|
// UInt32[] result = BigIntMath.smod(bits, b.bits);
|
|
// return new BigInteger(result);
|
|
// }
|
|
|
|
// private BigInteger __op_mul(BigInteger b)
|
|
// {
|
|
// UInt32[] value = BigIntMath.smul(bits, b.bits);
|
|
// return new BigInteger(value);
|
|
// }
|
|
|
|
// private BigInteger __op_new(uint[] value)
|
|
// {
|
|
// return new BigInteger(value);
|
|
// }
|
|
|
|
// private BigInteger __op_shl(int b)
|
|
// {
|
|
// UInt32[] value = BigIntMath.extendSigned(bits, bits.Length + ((b + 31) >> 5));
|
|
// BigIntMath.shl(value,b);
|
|
// return new BigInteger(value);
|
|
// }
|
|
|
|
// private BigInteger __op_shr(int b)
|
|
// {
|
|
// UInt32[] value = bits.Segment(0);
|
|
// BigIntMath.shr(value, b);
|
|
// return new BigInteger(value);
|
|
// }
|
|
|
|
// public static implicit operator BigInteger(int i)
|
|
// {
|
|
// return new BigInteger(new UInt32[]{(UInt32)i});
|
|
// }
|
|
|
|
|
|
|
|
// public static BigInteger operator +(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_add(b);
|
|
// }
|
|
// public static BigInteger operator -(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_sub(b);
|
|
// }
|
|
// public static BigInteger operator *(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_mul(b);
|
|
// }
|
|
|
|
// public static BigInteger operator /(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_div(b);
|
|
// }
|
|
// public static BigInteger operator %(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_mod(b);
|
|
// }
|
|
|
|
// public static bool operator <(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_cmp(b) < 0;
|
|
// }
|
|
// public static bool operator >(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_cmp(b) > 0;
|
|
// }
|
|
// public static bool operator ==(BigInteger a, BigInteger b)
|
|
// {
|
|
// if ((object)a == (object)b)
|
|
// {
|
|
// return true;
|
|
// }
|
|
// if (((object)a == null) || ((object)b == null))
|
|
// {
|
|
// return false;
|
|
// }
|
|
// return a.__op_cmp(b) == 0;
|
|
// }
|
|
// public static bool operator !=(BigInteger a, BigInteger b)
|
|
// {
|
|
// return a.__op_cmp(b) != 0;
|
|
// }
|
|
|
|
// public static BigInteger operator <<(BigInteger a, int b)
|
|
// {
|
|
// return a.__op_shl(b);
|
|
// }
|
|
// public static BigInteger operator >>(BigInteger a, int b)
|
|
// {
|
|
// return a.__op_shr(b);
|
|
// }
|
|
|
|
// public override bool Equals(object obj) => (obj is BigInteger other) && (this == other);
|
|
// public override int GetHashCode() => ToByteArray().CreateHashCode();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*** Native Implementations ***/
|
|
[DllImport("libbigint")]
|
|
public static extern Int32 big_get_length(UInt32[] bits, Int32 length);
|
|
public static Int32 big_get_length(UInt32[] bits) => big_get_length(bits, bits.Length);
|
|
|
|
[DllImport("libbigint")]
|
|
public static extern void big_add(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b);
|
|
[DllImport("libbigint")]
|
|
public static extern void big_sub(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b);
|
|
|
|
[DllImport("libbigint")]
|
|
public static extern void big_twos(UInt32[] bits, Int32 length);
|
|
[DllImport("libbigint")]
|
|
public static extern void big_shl(UInt32[] bits, Int32 length, Int32 n);
|
|
[DllImport("libbigint")]
|
|
public static extern void big_shr(UInt32[] bits, Int32 length, Int32 n);
|
|
|
|
|
|
[DllImport("libbigint")]
|
|
public static extern Int32 big_cmp(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b);
|
|
|
|
|
|
[DllImport("libbigint")]
|
|
public static extern void big_smul(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b, UInt32[] result);
|
|
[DllImport("libbigint")]
|
|
public static extern void big_divmod(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b);
|
|
|
|
|
|
private int max(int a,int b) => a > b ? a : b;
|
|
|
|
}
|
|
}
|