diff --git a/ln.biginteger.test/UnitTest1.cs b/ln.biginteger.test/UnitTest1.cs index efcce63..31ef937 100644 --- a/ln.biginteger.test/UnitTest1.cs +++ b/ln.biginteger.test/UnitTest1.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using System; +using System.Numerics; using System.Security.Cryptography; namespace ln.biginteger.test @@ -11,266 +12,266 @@ namespace ln.biginteger.test { } - [Test] - public void Test_00_LowLevel() - { - UInt32[] a,b,c; - Int32 d; + // [Test] + // public void Test_00_LowLevel() + // { + // UInt32[] a,b,c; + // Int32 d; - a = new UInt32[]{ 0x00000000, 0x00000000 }; - d = BigInteger.big_get_bitlength( a, a.Length ); - Assert.AreEqual( 1 , d ); + // a = new UInt32[]{ 0x00000000, 0x00000000 }; + // d = BigInteger.big_get_bitlength( a, a.Length ); + // Assert.AreEqual( 1 , d ); - a = new UInt32[]{ 0x00000001, 0x00000000 }; - d = BigInteger.big_get_bitlength( a, a.Length ); - Assert.AreEqual( 2 , d ); + // a = new UInt32[]{ 0x00000001, 0x00000000 }; + // d = BigInteger.big_get_bitlength( a, a.Length ); + // Assert.AreEqual( 2 , d ); - a = new UInt32[]{ 0x00001000, 0x00000000 }; - d = BigInteger.big_get_bitlength( a, a.Length ); - Assert.AreEqual( 14 , d ); + // a = new UInt32[]{ 0x00001000, 0x00000000 }; + // d = BigInteger.big_get_bitlength( a, a.Length ); + // Assert.AreEqual( 14 , d ); - a = new UInt32[]{ 0xFFFF8000, 0x00000000 }; - d = BigInteger.big_get_bitlength( a, a.Length ); - Assert.AreEqual( 33 , d ); + // a = new UInt32[]{ 0xFFFF8000, 0x00000000 }; + // d = BigInteger.big_get_bitlength( a, a.Length ); + // Assert.AreEqual( 33 , d ); - a = new UInt32[]{ 0xFFFF8000, 0xFFFFFFFF }; - d = BigInteger.big_get_bitlength( a, a.Length ); - Assert.AreEqual( 16 , d ); + // a = new UInt32[]{ 0xFFFF8000, 0xFFFFFFFF }; + // d = BigInteger.big_get_bitlength( a, a.Length ); + // Assert.AreEqual( 16 , d ); - a = new UInt32[]{ 0xFC000000 }; - d = BigInteger.big_get_bitlength( a, a.Length ); - Assert.AreEqual( 27 , d ); + // a = new UInt32[]{ 0xFC000000 }; + // d = BigInteger.big_get_bitlength( a, a.Length ); + // Assert.AreEqual( 27 , d ); - a = new uint[]{0}; - b = new uint[]{0, 0}; - c = BigInteger.Extend(a, b.Length); - Assert.AreEqual(b, c); + // a = new uint[]{0}; + // b = new uint[]{0, 0}; + // c = BigInteger.Extend(a, b.Length); + // Assert.AreEqual(b, c); - a = new uint[]{0}; - b = new uint[]{0, 0, 0, 0}; - c = BigInteger.Extend(a, b.Length); - Assert.AreEqual(b, c); + // a = new uint[]{0}; + // b = new uint[]{0, 0, 0, 0}; + // c = BigInteger.Extend(a, b.Length); + // Assert.AreEqual(b, c); - a = new uint[]{1}; - b = new uint[]{1, 0, 0, 0}; - c = BigInteger.Extend(a, b.Length); - Assert.AreEqual(b, c); + // a = new uint[]{1}; + // b = new uint[]{1, 0, 0, 0}; + // c = BigInteger.Extend(a, b.Length); + // Assert.AreEqual(b, c); - a = new uint[]{5463782}; - b = new uint[]{5463782, 0, 0, 0}; - c = BigInteger.Extend(a, b.Length); - Assert.AreEqual(b, c); + // a = new uint[]{5463782}; + // b = new uint[]{5463782, 0, 0, 0}; + // c = BigInteger.Extend(a, b.Length); + // Assert.AreEqual(b, c); - a = new uint[]{ 0xFFFFEDCB }; - b = new uint[]{ 0xFFFFEDCB, 0xFFFFFFFF}; - c = BigInteger.Extend(a, b.Length); - Assert.AreEqual(b, c); + // a = new uint[]{ 0xFFFFEDCB }; + // b = new uint[]{ 0xFFFFEDCB, 0xFFFFFFFF}; + // c = BigInteger.Extend(a, b.Length); + // Assert.AreEqual(b, c); - a = new uint[]{ 0xFFFFEDCB }; - b = new uint[]{ 0xFFFFEDCB, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; - c = BigInteger.Extend(a, b.Length); - Assert.AreEqual(b, c); + // a = new uint[]{ 0xFFFFEDCB }; + // b = new uint[]{ 0xFFFFEDCB, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; + // c = BigInteger.Extend(a, b.Length); + // Assert.AreEqual(b, c); - a = new uint[]{ 0xFFFFEDCB, 0xFFFFFFFF }; - b = new uint[]{ 0xFFFFEDCB, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; - c = BigInteger.Extend(a, b.Length); - Assert.AreEqual(b, c); + // a = new uint[]{ 0xFFFFEDCB, 0xFFFFFFFF }; + // b = new uint[]{ 0xFFFFEDCB, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; + // c = BigInteger.Extend(a, b.Length); + // Assert.AreEqual(b, c); - a = new uint[]{ 0xFFFFFFFF }; - b = new uint[]{ 0x00000001 }; - BigInteger.big_twos( a, a.Length ); - Assert.AreEqual(b, a); + // a = new uint[]{ 0xFFFFFFFF }; + // b = new uint[]{ 0x00000001 }; + // BigInteger.big_twos( a, a.Length ); + // Assert.AreEqual(b, a); - a = new uint[]{ 0xFFFFFFFF, 0xFFFFFFFF }; - b = new uint[]{ 0x00000001, 0x00000000 }; - BigInteger.big_twos( a, a.Length ); - Assert.AreEqual(b, a); + // a = new uint[]{ 0xFFFFFFFF, 0xFFFFFFFF }; + // b = new uint[]{ 0x00000001, 0x00000000 }; + // BigInteger.big_twos( a, a.Length ); + // Assert.AreEqual(b, a); - a = new uint[]{ 0x01000020 }; - b = new uint[]{ 0x00100002 }; - BigInteger.big_shr( a, a.Length, 4); - Assert.AreEqual(b, a); + // a = new uint[]{ 0x01000020 }; + // b = new uint[]{ 0x00100002 }; + // BigInteger.big_shr( a, a.Length, 4); + // Assert.AreEqual(b, a); - a = new uint[]{ 0x10000000 }; - b = new uint[]{ 0x08000000 }; - BigInteger.big_shr( a, a.Length, 1); - Assert.AreEqual(b, a); + // a = new uint[]{ 0x10000000 }; + // b = new uint[]{ 0x08000000 }; + // BigInteger.big_shr( a, a.Length, 1); + // Assert.AreEqual(b, a); - a = new uint[]{ 0xbbccddee, 0x00000002 }; - b = new uint[]{ 0x00000000, 0x00000002 }; - Assert.IsTrue( BigInteger.big_cmp(a, b) > 0 ); + // a = new uint[]{ 0xbbccddee, 0x00000002 }; + // b = new uint[]{ 0x00000000, 0x00000002 }; + // Assert.IsTrue( BigInteger.big_cmp(a, b) > 0 ); - } + // } - [Test] - public void Test_01_LL_AddSub() - { - UInt32[] a,b,c; + // [Test] + // public void Test_01_LL_AddSub() + // { + // UInt32[] a,b,c; - a = new UInt32[]{ 0x00000000 }; - b = new UInt32[]{ 0x00000000 }; - c = new UInt32[]{ 0x00000000 }; - BigInteger.big_add( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x00000000 }; + // b = new UInt32[]{ 0x00000000 }; + // c = new UInt32[]{ 0x00000000 }; + // BigInteger.big_add( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x00000123 }; - b = new UInt32[]{ 0x00123000 }; - c = new UInt32[]{ 0x00123123 }; - BigInteger.big_add( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x00000123 }; + // b = new UInt32[]{ 0x00123000 }; + // c = new UInt32[]{ 0x00123123 }; + // BigInteger.big_add( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x00000123 }; - b = new UInt32[]{ 0x00000123 }; - c = new UInt32[]{ 0x00000246 }; - BigInteger.big_add( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x00000123 }; + // b = new UInt32[]{ 0x00000123 }; + // c = new UInt32[]{ 0x00000246 }; + // BigInteger.big_add( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x00123456 }; - b = new UInt32[]{ 0x00345678 }; - c = new UInt32[]{ 0x00468ACE }; - BigInteger.big_add( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x00123456 }; + // b = new UInt32[]{ 0x00345678 }; + // c = new UInt32[]{ 0x00468ACE }; + // BigInteger.big_add( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x70004567, 0x00000000 }; - b = new UInt32[]{ 0x10000000 }; - c = new UInt32[]{ 0x80004567, 0x00000000 }; - BigInteger.big_add( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x70004567, 0x00000000 }; + // b = new UInt32[]{ 0x10000000 }; + // c = new UInt32[]{ 0x80004567, 0x00000000 }; + // BigInteger.big_add( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x70004567, 0x00000000 }; - b = new UInt32[]{ 0x20000000 }; - c = new UInt32[]{ 0x90004567, 0x00000000 }; - BigInteger.big_add( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x70004567, 0x00000000 }; + // b = new UInt32[]{ 0x20000000 }; + // c = new UInt32[]{ 0x90004567, 0x00000000 }; + // BigInteger.big_add( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x70004567, 0x00000000 }; - b = new UInt32[]{ 0xA0000000 }; - c = new UInt32[]{ 0x10004567, 0x00000001 }; - BigInteger.big_add( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x70004567, 0x00000000 }; + // b = new UInt32[]{ 0xA0000000 }; + // c = new UInt32[]{ 0x10004567, 0x00000001 }; + // BigInteger.big_add( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x00000000 }; - b = new UInt32[]{ 0x00000001 }; - c = new UInt32[]{ 0xFFFFFFFF }; - BigInteger.big_sub( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x00000000 }; + // b = new UInt32[]{ 0x00000001 }; + // c = new UInt32[]{ 0xFFFFFFFF }; + // BigInteger.big_sub( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x00000000, 0x00000000 }; - b = new UInt32[]{ 0x00000001 }; - c = new UInt32[]{ 0xFFFFFFFF, 0xFFFFFFFF }; - BigInteger.big_sub( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x00000000, 0x00000000 }; + // b = new UInt32[]{ 0x00000001 }; + // c = new UInt32[]{ 0xFFFFFFFF, 0xFFFFFFFF }; + // BigInteger.big_sub( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x00000000, 0xF0000000 }; - b = new UInt32[]{ 0x00000001 }; - c = new UInt32[]{ 0xFFFFFFFF, 0xEFFFFFFF }; - BigInteger.big_sub( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x00000000, 0xF0000000 }; + // b = new UInt32[]{ 0x00000001 }; + // c = new UInt32[]{ 0xFFFFFFFF, 0xEFFFFFFF }; + // BigInteger.big_sub( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x54A5D32F, 0xD25AC351 }; - b = new UInt32[]{ 0xC351425A, 0x432F54A5 }; - c = new UInt32[]{ 0x915490D5, 0x8F2B6EAB }; - BigInteger.big_sub( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x54A5D32F, 0xD25AC351 }; + // b = new UInt32[]{ 0xC351425A, 0x432F54A5 }; + // c = new UInt32[]{ 0x915490D5, 0x8F2B6EAB }; + // BigInteger.big_sub( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x82345678, 0x00000013, 0x00000000 }; - b = new UInt32[]{ 0x80000000, 0x0000000c, 0x00000000 }; - c = new UInt32[]{ 0x02345678, 0x00000007, 0x00000000 }; - BigInteger.big_sub( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x82345678, 0x00000013, 0x00000000 }; + // b = new UInt32[]{ 0x80000000, 0x0000000c, 0x00000000 }; + // c = new UInt32[]{ 0x02345678, 0x00000007, 0x00000000 }; + // BigInteger.big_sub( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x12345678, 0x00000013, 0x00000000 }; - b = new UInt32[]{ 0x80000000, 0x0000000c, 0x00000000 }; - c = new UInt32[]{ 0x92345678, 0x00000006, 0x00000000 }; - BigInteger.big_sub( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x12345678, 0x00000013, 0x00000000 }; + // b = new UInt32[]{ 0x80000000, 0x0000000c, 0x00000000 }; + // c = new UInt32[]{ 0x92345678, 0x00000006, 0x00000000 }; + // BigInteger.big_sub( a, b ); + // Assert.AreEqual( c, a ); - Assert.Pass(); - } + // Assert.Pass(); + // } - [Test] - public void Test_02_LL_Mul() - { - UInt32[] a,b,c; + // [Test] + // public void Test_02_LL_Mul() + // { + // UInt32[] a,b,c; - a = new UInt32[]{ 0x00000200 }; - b = new UInt32[]{ 0x00000300 }; - c = new UInt32[]{ 0x00060000 }; - BigInteger.big_smul( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x00000200 }; + // b = new UInt32[]{ 0x00000300 }; + // c = new UInt32[]{ 0x00060000 }; + // BigInteger.big_smul( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0xD25AC351, 0x00000000 }; - b = new UInt32[]{ 0x432F54A5 }; - c = new UInt32[]{ 0x6B757735, 0x3734A555 }; - BigInteger.big_smul( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0xD25AC351, 0x00000000 }; + // b = new UInt32[]{ 0x432F54A5 }; + // c = new UInt32[]{ 0x6B757735, 0x3734A555 }; + // BigInteger.big_smul( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0xFFFFFFFF }; - b = new UInt32[]{ 0x00000001 }; - c = new UInt32[]{ 0xFFFFFFFF }; - BigInteger.big_smul( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0xFFFFFFFF }; + // b = new UInt32[]{ 0x00000001 }; + // c = new UInt32[]{ 0xFFFFFFFF }; + // BigInteger.big_smul( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0xFFFFFFFF }; - b = new UInt32[]{ 0xFFFFFFFF }; - c = new UInt32[]{ 0x00000001 }; - BigInteger.big_smul( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0xFFFFFFFF }; + // b = new UInt32[]{ 0xFFFFFFFF }; + // c = new UInt32[]{ 0x00000001 }; + // BigInteger.big_smul( a, b ); + // Assert.AreEqual( c, a ); - } + // } - [Test] - public void Test_03_LL_Div() - { - UInt32[] a,b,c; - Int32 d; + // [Test] + // public void Test_03_LL_Div() + // { + // UInt32[] a,b,c; + // Int32 d; - a = new UInt32[]{ 0x12345678 }; - b = new UInt32[]{ 0x00000001 }; - c = new UInt32[]{ 0x12345678 }; - BigInteger.big_divmod( a, b ); - Assert.AreEqual( c, a ); + // a = new UInt32[]{ 0x12345678 }; + // b = new UInt32[]{ 0x00000001 }; + // c = new UInt32[]{ 0x12345678 }; + // BigInteger.big_divmod( a, b ); + // Assert.AreEqual( c, a ); - a = new UInt32[]{ 0x12345678 }; - b = new UInt32[]{ 0x00000032 }; - c = new UInt32[]{ 0x005D34ED }; - d = 0x2E; - BigInteger.big_divmod( a, b ); - Assert.AreEqual( c, a ); - Assert.AreEqual( d, b[0] ); + // a = new UInt32[]{ 0x12345678 }; + // b = new UInt32[]{ 0x00000032 }; + // c = new UInt32[]{ 0x005D34ED }; + // d = 0x2E; + // BigInteger.big_divmod( a, b ); + // Assert.AreEqual( c, a ); + // Assert.AreEqual( d, b[0] ); - a = new UInt32[]{ 0x12345678, 0x99AABBCC, 0x00000000 }; - b = new UInt32[]{ 0x00000032 }; - c = new UInt32[]{ 0xE1A4E302, 0x0312C650, 0x00000000 }; - d = 0x14; - BigInteger.big_divmod( a, b ); - Assert.AreEqual( c, a ); - Assert.AreEqual( d, b[0] ); + // a = new UInt32[]{ 0x12345678, 0x99AABBCC, 0x00000000 }; + // b = new UInt32[]{ 0x00000032 }; + // c = new UInt32[]{ 0xE1A4E302, 0x0312C650, 0x00000000 }; + // d = 0x14; + // BigInteger.big_divmod( a, b ); + // Assert.AreEqual( c, a ); + // Assert.AreEqual( d, b[0] ); - a = new UInt32[]{ 0xBBCCDDEE, 0x778899AA }; - b = new UInt32[]{ 0x00000010 }; - c = new UInt32[]{ 0xABBCCDDE, 0x0778899A }; - d = 0x0E; - BigInteger.big_divmod( a, b ); - Assert.AreEqual( c, a ); - Assert.AreEqual( d, b[0] ); + // a = new UInt32[]{ 0xBBCCDDEE, 0x778899AA }; + // b = new UInt32[]{ 0x00000010 }; + // c = new UInt32[]{ 0xABBCCDDE, 0x0778899A }; + // d = 0x0E; + // BigInteger.big_divmod( a, b ); + // Assert.AreEqual( c, a ); + // Assert.AreEqual( d, b[0] ); - } + // } [Test] public void Test_14_HL_Pow() { BigInteger a,b,c; - a = BigInteger.FromHexString("34"); + a = BigInteger.Parse("34", 16); b = a.Pow(7); - c = BigInteger.FromHexString("0EF5DD94000"); + c = BigInteger.Parse("0EF5DD94000", 16); Assert.AreEqual(c, b); - a = BigInteger.FromHexString("34"); + a = BigInteger.Parse("34", 16); b = a.Pow(5); - c = BigInteger.FromHexString("16A97400"); + c = BigInteger.Parse("16A97400", 16); Assert.AreEqual(c, b); } @@ -318,15 +319,27 @@ namespace ln.biginteger.test { BigInteger bi = BigInteger.Parse(hexdigits, 16); string rehexed = bi.ToString(16); - Assert.AreEqual(hexdigits, rehexed); + Assert.AreEqual(hexdigits.ToLower(), rehexed.ToLower()); } [Test] - public void PerformaceTests() + public void PerformaceTest_Mul() + { + for (int n=0;n<4;n++) + { + PT_Mul(4, 100000); + PT_Mul(8, 100000); + PT_Mul(16, 100000); + PT_Mul(32, 100000); + PT_Mul(64, 100000); + } + } + + public void PT_Mul(int bytes, int repeat) { RandomNumberGenerator rnd = RandomNumberGenerator.Create(); - byte[] rand = new byte[32]; + byte[] rand = new byte[bytes]; BigInteger[] bigIntegers = new BigInteger[16]; System.Numerics.BigInteger[] dotnetIntegers = new System.Numerics.BigInteger[bigIntegers.Length]; @@ -334,33 +347,104 @@ namespace ln.biginteger.test for (int n=0;n - { - public static readonly BigInteger Zero = new BigInteger(); - public static readonly BigInteger One = new BigInteger(1); - public static readonly BigInteger MinusOne = new BigInteger(-1); + public class BigInteger : IDisposable, IComparable + { + public static readonly BigInteger One = new BigInteger(); //1); + public static readonly BigInteger Zero = new BigInteger(); + 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 }; - } + private IntPtr _mpz; - 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 = Reduce(rawbits); - } - - public BigInteger(byte[] rawbits) + public BigInteger() { - UInt32[] rints = new UInt32[(rawbits.Length + 3) >> 2]; - for (int n=0;n bits = Reduce(bits); - public static UInt32[] Reduce(UInt32[] bits) - { - Int32 rl = big_get_length(bits); - if (bits.Length > rl) - { - UInt32[] newbits = new uint[rl]; - Array.Copy(bits, newbits, rl); - bits = newbits; - } else { - bits = (UInt32[])bits.Clone(); - } - return bits; - } - - public static UInt32[] Extend(UInt32[] bits, int length) - { - UInt32[] extendedbits = new UInt32[length]; - Array.Copy(bits, extendedbits, bits.Length); - if ((bits[bits.Length-1] & 0x80000000)==0x80000000) - for (int n=bits.Length; n big_get_length(bits) << 2; - public Int32 GetBitLength() => big_get_bitlength(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) - { - int tlength = max(big_get_bitlength(bits), big_get_bitlength(bi2.bits))+1; - UInt32[] r = new uint[(tlength + 31)>>5]; - 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) - { - int tlength = max(big_get_bitlength(bits), big_get_bitlength(bi2.bits))+1; - UInt32[] r = new uint[(tlength + 31)>>5]; - 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) - { - int l = (big_get_bitlength(bits) + big_get_bitlength(bi2.bits) + 31) >> 5; - UInt32[] r = new UInt32[l]; - Array.Copy(bits, r, bits.Length); - big_smul(r, bi2.bits); - 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 2) - { - BigInteger result = One; - for (int i=31; i>=0; i--) - { - result *= result; - if ((n & (1<= 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 operator*(BigInteger bi1,BigInteger bi2) => bi1.Mul(bi2); - public static BigInteger operator/(BigInteger bi1,BigInteger bi2) => bi1.Div(bi2); - public static BigInteger operator%(BigInteger bi1,BigInteger bi2) => bi1.Mod(bi2); - //public static BigInteger operator^(BigInteger bi1,int exp) => bi1.Pow(exp); - - - - public static BigInteger Parse(string source) => Parse( source, 10 ); - public static BigInteger Parse(string source,int radix) - { - UInt32[] bits = new UInt32[ ((source.Length * 6) + 31) >> 5]; - big_parse(bits, bits.Length, source, 16); - return new BigInteger(bits); - } - - 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); - - UInt32[] bits = new UInt32[ ((hex.Length * 6) + 31) >> 5]; - big_parse(bits, bits.Length, hex, 16); - 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 override string ToString() => ToHexString(); - public string ToString(int radix) - { - if (IsZero) - return "0"; - - UInt32[] r; - UInt32[] v = (UInt32[])bits.Clone(); - - StringBuilder sb = new StringBuilder(); - if (Sign < 0) - big_twos(v, v.Length); + _mpz = BigIntegerAllocator.Pop(); + mpz_init(_mpz); + } + public BigInteger(Int64 i64) :this() => mpz_set_si(_mpz, i64); + public BigInteger(UInt64 ui64) :this() => mpz_set_ui(_mpz, ui64); + public BigInteger(Int32 i32) :this() => mpz_set_si(_mpz, i32); + public BigInteger(UInt32 ui32) :this() => mpz_set_ui(_mpz, ui32); + private BigInteger(BigInteger src) :this() => mpz_set(_mpz, src._mpz); - while (big_cmp(v, v.Length, Zero.bits, Zero.bits.Length)!=0) - { - r = new UInt32[]{ (UInt32)radix }; - big_divmod(v, v.Length, r, r.Length); - if (r[0] < 10) - sb.Append((char)('0' + r[0])); - else - sb.Append((char)(55 + r[0]) ); - } - - if (Sign < 0) - sb.Append('-'); - - char[] chs = new char[sb.Length]; - sb.CopyTo(0,chs,0,sb.Length); - Array.Reverse(chs); - return new string(chs); + + private BigInteger(string source, int b) :this() + { + if (mpz_set_str( _mpz, source, b) != 0) + throw new ArgumentOutOfRangeException(nameof(source)); + } + + public static BigInteger Parse(string src) => new BigInteger(src, 0); + public static BigInteger Parse(string src, int b) => new BigInteger(src, b); + + public static BigInteger FromByteArray(byte[] bytes) + { + BigInteger bi = new BigInteger(); + mpz_import(bi._mpz, bytes.Length, -1, 1, -1, 0, bytes); + return bi; + } + public byte[] ToByteArray() + { + int countp = 0; + IntPtr bptr = mpz_export(null, ref countp, -1, 1, -1, 0, _mpz); + byte[] bytes = new byte[countp]; + Marshal.Copy(bptr, bytes, 0, countp); + return bytes; + } + public void TryWriteBytes(Span s,out int bytesWritten) + { + byte[] sb = ToByteArray(); + for (bytesWritten = 0; bytesWritten < sb.Length; bytesWritten++) + s[bytesWritten] = sb[bytesWritten]; + } + + public static BigInteger operator+(BigInteger op1, BigInteger op2) + { + BigInteger result = new BigInteger(); + mpz_add(result._mpz, op1._mpz, op2._mpz); + return result; + } + public static BigInteger operator+(BigInteger op1, ulong ul) + { + BigInteger result = new BigInteger(); + mpz_add_ui(result._mpz, op1._mpz, ul); + return result; + } + public static BigInteger operator-(BigInteger op1, BigInteger op2) + { + BigInteger result = new BigInteger(); + mpz_sub(result._mpz, op1._mpz, op2._mpz); + return result; + } + public static BigInteger operator-(BigInteger op1, ulong ul) + { + BigInteger result = new BigInteger(); + mpz_sub_ui(result._mpz, op1._mpz, ul); + return result; + } + + public static BigInteger operator-(BigInteger op1) + { + BigInteger result = new BigInteger(); + mpz_neg(result._mpz, op1._mpz); + return result; + } + + public static BigInteger operator*(BigInteger op1, BigInteger op2) + { + BigInteger result = new BigInteger(); + mpz_mul(result._mpz, op1._mpz, op2._mpz); + return result; + } + public static BigInteger operator*(BigInteger op1, long si) + { + BigInteger result = new BigInteger(); + mpz_mul_si(result._mpz, op1._mpz, si); + return result; + } + public static BigInteger operator*(BigInteger op1, ulong ui) + { + BigInteger result = new BigInteger(); + mpz_mul_ui(result._mpz, op1._mpz, ui); + return result; + } + + public static BigInteger operator/(BigInteger n, BigInteger d) + { + BigInteger result = new BigInteger(); + mpz_tdiv_q(result._mpz, n._mpz, d._mpz); + return result; + } + public static BigInteger operator%(BigInteger n, BigInteger d) + { + BigInteger result = new BigInteger(); + mpz_tdiv_r(result._mpz, n._mpz, d._mpz); + return result; + } + + public static bool operator==(BigInteger a, BigInteger b) => mpz_cmp(a._mpz, b._mpz) == 0; + public static bool operator!=(BigInteger a, BigInteger b) => mpz_cmp(a._mpz, b._mpz) != 0; + public static bool operator<(BigInteger a, BigInteger b) => mpz_cmp(a._mpz, b._mpz) < 0; + public static bool operator>(BigInteger a, BigInteger b) => mpz_cmp(a._mpz, b._mpz) > 0; + public static bool operator<(BigInteger a, long b) => mpz_cmp_si(a._mpz, b) < 0; + public static bool operator>(BigInteger a, long b) => mpz_cmp_si(a._mpz, b) > 0; + public static bool operator<(BigInteger a, int b) => mpz_cmp_si(a._mpz, b) < 0; + public static bool operator>(BigInteger a, int b) => mpz_cmp_si(a._mpz, b) > 0; + + public static BigInteger operator<<(BigInteger n, int b) + { + BigInteger result = new BigInteger(); + mpz_mul_2exp(result._mpz, n._mpz, (ulong)b ); + return result; + } + public static BigInteger operator>>(BigInteger n, int b) + { + BigInteger result = new BigInteger(); + mpz_tdiv_q_2exp(result._mpz, n._mpz, (ulong)b ); + return result; + } + + public static implicit operator BigInteger(int i) => new BigInteger(i); + public static implicit operator BigInteger(uint i) => new BigInteger(i); + public static implicit operator BigInteger(long i) => new BigInteger(i); + public static implicit operator BigInteger(ulong i) => new BigInteger(i); + + + + + public BigInteger Abs() + { + BigInteger result = new BigInteger(); + mpz_neg(result._mpz, _mpz); + return result; + } + public BigInteger DivMod(BigInteger d, out BigInteger r) + { + BigInteger q = new BigInteger(); + r = new BigInteger(); + mpz_tdiv_qr(q._mpz, d._mpz, _mpz, d._mpz); + return q; + } + public static BigInteger ModPow(BigInteger n, BigInteger e, BigInteger m) => n.ModPow(e,m); + public BigInteger ModPow(BigInteger e, BigInteger m) + { + BigInteger r = new BigInteger(); + mpz_powm(r._mpz, _mpz, e._mpz, m._mpz); + return r; + } + public static BigInteger ModPow(BigInteger n, ulong e, BigInteger m) => n.ModPow(e,m); + public BigInteger ModPow(ulong e, BigInteger m) + { + BigInteger r = new BigInteger(); + mpz_powm_ui(r._mpz, _mpz, e, m._mpz); + return r; + } + public static BigInteger Pow(BigInteger n, ulong e) => n.Pow(e); + public BigInteger Pow(ulong e) + { + BigInteger r = new BigInteger(); + mpz_pow_ui(r._mpz, _mpz, e); + return r; + } + + public int CompareTo(BigInteger other) => mpz_cmp(_mpz, other._mpz); + public int CompareTo(long other) => mpz_cmp_si(_mpz, other); + public int CompareTo(int other) => mpz_cmp_si(_mpz, other); + + + public override string ToString() => ToString(16); + + public string ToString(int b) + { + StringBuilder sb = new StringBuilder(4096); + mpz_get_str(sb, b, _mpz); + return sb.ToString(); + } + + public string ToString(int b, int length) + { + StringBuilder sb = new StringBuilder(4096); + mpz_get_str(sb, b, _mpz); + + StringBuilder sb2 = new StringBuilder(); + for (int n=0;n> 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 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 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 void Dispose() + { + if (_mpz != IntPtr.Zero) + { + mpz_clear(_mpz); + //Marshal.FreeHGlobal(_mpz); + BigIntegerAllocator.Push(_mpz); + _mpz = IntPtr.Zero; + } + } + + public override bool Equals(object obj) => (obj is BigInteger other) && (mpz_cmp(_mpz, other._mpz) == 0); + public override int GetHashCode() => base.GetHashCode(); + + public bool IsZero => (this == 0); + public int Sign { + get { + int c = mpz_cmp_si(_mpz, 0); + return (c < 0) ? -1 : (c > 0) ? 1 : 0; + } + } + + public int GetByteLength() => mpz_sizeinbase(_mpz, 2) >> 3; + public int GetBitLength() => mpz_sizeinbase(_mpz, 2); + + + [DllImport("gmp", EntryPoint = "__gmpz_init")] + static extern void mpz_init(IntPtr mpz); - - - // 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 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 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("bigint")] - 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); - - /*** - big_get_bitlength() returns the number of bits needed to represent this value including the sign bit - ***/ - [DllImport("bigint")] - public static extern Int32 big_get_bitlength(UInt32[] bits, Int32 length); - public static Int32 big_get_bitlength(UInt32[] bits) => big_get_bitlength( bits, bits.Length ); - - [DllImport("bigint")] - public static extern Int32 big_parse(UInt32[] op, Int32 length, String source, Int32 radix); - // [DllImport("bigint")] - // public static extern Int32 big_log2(UInt32[] bits, Int32 length); - - [DllImport("bigint")] - public static extern void big_add(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); - public static void big_add(UInt32[] op_a, UInt32[] op_b) => big_add( op_a, op_a.Length, op_b, op_b.Length ); - [DllImport("bigint")] - public static extern void big_sub(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); - public static void big_sub(UInt32[] op_a, UInt32[] op_b) => big_sub( op_a, op_a.Length, op_b, op_b.Length ); - - [DllImport("bigint")] - public static extern void big_twos(UInt32[] bits, Int32 length); - [DllImport("bigint")] - public static extern void big_shl(UInt32[] bits, Int32 length, Int32 n); - [DllImport("bigint")] - public static extern void big_shr(UInt32[] bits, Int32 length, Int32 n); - - - [DllImport("bigint")] - public static extern Int32 big_cmp(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); - public static Int32 big_cmp(UInt32[] op_a, UInt32[] op_b) => big_cmp(op_a, op_a.Length, op_b, op_b.Length); - - - [DllImport("bigint")] - public static extern void big_smul(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); - public static void big_smul(UInt32[] op_a, UInt32[] op_b) => big_smul( op_a, op_a.Length, op_b, op_b.Length); - [DllImport("bigint")] - public static extern void big_divmod(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); - public static void big_divmod(UInt32[] op_a, UInt32[] op_b) => big_divmod( op_a, op_a.Length, op_b, op_b.Length); - - - private int max(int a,int b) => a > b ? a : b; + [DllImport("gmp", EntryPoint = "__gmpz_clear")] + static extern void mpz_clear(IntPtr mpz); + + [DllImport("gmp", EntryPoint = "__gmpz_set")] + static extern void mpz_set(IntPtr mpz_dst, IntPtr mpz_src); + [DllImport("gmp", EntryPoint = "__gmpz_set_ui")] + static extern void mpz_set_ui(IntPtr mpz_dst, UInt64 src); + [DllImport("gmp", EntryPoint = "__gmpz_set_si")] + static extern void mpz_set_si(IntPtr mpz_dst, Int64 src); + + [DllImport("gmp", CharSet = CharSet.Auto, EntryPoint = "__gmpz_set_str")] + static extern int mpz_set_str(IntPtr mpz_dst, string src, int b); + [DllImport("gmp", CharSet = CharSet.Auto, EntryPoint = "__gmpz_get_str")] + static extern IntPtr mpz_get_str (StringBuilder stringBuilder, int b, IntPtr mpz); + + [DllImport("gmp", EntryPoint = "__gmpz_add")] + static extern void mpz_add(IntPtr dst, IntPtr op1, IntPtr op2); + [DllImport("gmp", EntryPoint = "__gmpz_add_ui")] + static extern void mpz_add_ui(IntPtr dst, IntPtr op1, ulong op2); + + [DllImport("gmp", EntryPoint = "__gmpz_sub")] + static extern void mpz_sub(IntPtr dst, IntPtr op1, IntPtr op2); + [DllImport("gmp", EntryPoint = "__gmpz_sub_ui")] + static extern void mpz_sub_ui(IntPtr dst, IntPtr op1, ulong op2); + + [DllImport("gmp", EntryPoint = "__gmpz_neg")] + static extern void mpz_neg(IntPtr dst, IntPtr op1); + [DllImport("gmp", EntryPoint = "__gmpz_abs")] + static extern void mpz_abs(IntPtr dst, IntPtr op1); + + [DllImport("gmp", EntryPoint = "__gmpz_mul")] + static extern void mpz_mul(IntPtr dst, IntPtr op1, IntPtr op2); + [DllImport("gmp", EntryPoint = "__gmpz_mul_2exp")] + static extern void mpz_mul_2exp(IntPtr dst, IntPtr op1, ulong op2); + [DllImport("gmp", EntryPoint = "__gmpz_mul_si")] + static extern void mpz_mul_si(IntPtr dst, IntPtr op1, long sl); + [DllImport("gmp", EntryPoint = "__gmpz_mul_ui")] + static extern void mpz_mul_ui(IntPtr dst, IntPtr op1, ulong ul); + + [DllImport("gmp", EntryPoint = "__gmpz_mod")] + static extern void mpz_mod(IntPtr dst, IntPtr op1, IntPtr op2 ); + + [DllImport("gmp", EntryPoint = "__gmpz_tdiv_q")] + static extern void mpz_tdiv_q(IntPtr q, IntPtr n, IntPtr d ); + [DllImport("gmp", EntryPoint = "__gmpz_tdiv_r")] + static extern void mpz_tdiv_r(IntPtr r, IntPtr n, IntPtr d ); + [DllImport("gmp", EntryPoint = "__gmpz_tdiv_qr")] + static extern void mpz_tdiv_qr(IntPtr q, IntPtr r, IntPtr n, IntPtr d ); + [DllImport("gmp", EntryPoint = "__gmpz_tdiv_q_2exp")] + static extern void mpz_tdiv_q_2exp(IntPtr q, IntPtr n, ulong b ); + + [DllImport("gmp", EntryPoint = "__gmpz_powm")] + static extern void mpz_powm(IntPtr dst, IntPtr b, IntPtr exp, IntPtr mod ); + [DllImport("gmp", EntryPoint = "__gmpz_powm_ui")] + static extern void mpz_powm_ui(IntPtr dst, IntPtr b, ulong exp, IntPtr mod ); + + [DllImport("gmp", EntryPoint = "__gmpz_pow_ui")] + static extern void mpz_pow_ui(IntPtr dst, IntPtr b, ulong ui ); + + [DllImport("gmp", EntryPoint = "__gmpz_cmp")] + static extern Int32 mpz_cmp(IntPtr a, IntPtr b ); + [DllImport("gmp", EntryPoint = "__gmpz_cmp_ui")] + static extern Int32 mpz_cmp_ui(IntPtr a, ulong b ); + [DllImport("gmp", EntryPoint = "__gmpz_cmp_si")] + static extern Int32 mpz_cmp_si(IntPtr a, long b ); + + [DllImport("gmp", EntryPoint = "__gmpz_import")] + static extern void mpz_import(IntPtr dst, int count, int order, int size, int endian, int nails, byte[] buffer); + [DllImport("gmp", EntryPoint = "__gmpz_export")] + static extern IntPtr mpz_export(byte[] buffer, ref int countp, int order, int size, int endian, int nails, IntPtr src); + + [DllImport("gmp", EntryPoint = "__gmpz_sizeinbase")] + static extern Int32 mpz_sizeinbase(IntPtr a, int b); + + static BigInteger() + { + NativeLibrary.SetDllImportResolver(typeof(BigInteger).Assembly, ResolveLibrary); + } + + static IntPtr ResolveLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) + { + IntPtr libHandle = IntPtr.Zero; + foreach (string pat in libraryPatterns) + { + if (NativeLibrary.TryLoad(String.Format(pat, libraryName), out libHandle)) + return libHandle; + } + throw new FileNotFoundException(libraryName); + } + + static string[] libraryPatterns = new string[]{ + "x32/lib{0}.so", + "x32/lib{0}.dll", + "x32/{0}.dll", + "x32/lib{0}.dylib", + "x64/lib{0}.so", + "x64/lib{0}.dll", + "x64/{0}.dll", + "x64/lib{0}.dylib", + }; } + + + + // public class BigInteger : IComparable + // { + // public static readonly BigInteger Zero = 0; + // public static readonly BigInteger One = 1; + // public static readonly BigInteger MinusOne = -1; + + // private UInt32[] bits; + // private Int32 _length; + // private Int32 _sign; + + + // public Int32 Sign => _sign; + // public bool IsZero => (bits == null); + + + // private BigInteger(int sign, UInt32[] bits) + // { + // if (sign < 0) + // this._sign = -1; + // else if (sign > 0) + // this._sign = 1; + + // this.bits = bits; + // } + + // private void Reduce() { bits = Reduce(bits); _length = bits.Length; } + // public static UInt32[] Reduce(UInt32[] bits) + // { + // Int32 rl = managed_get_length(bits); + // if (bits.Length > rl) + // { + // UInt32[] newbits = new uint[rl]; + // Array.Copy(bits, newbits, rl); + // bits = newbits; + // } else { + // bits = (UInt32[])bits.Clone(); + // } + // return bits; + // } + + // public static UInt32[] Extend(UInt32[] bits, int length) + // { + // UInt32[] extendedbits = new UInt32[length]; + // Array.Copy(bits, extendedbits, bits.Length); + // if ((bits[bits.Length-1] & 0x80000000)==0x80000000) + // for (int n=bits.Length; n big_get_length(bits) << 2; + // public Int32 GetBitLength() => big_get_bitlength(bits) << 5; + // public Int32 GetLength() => big_get_length(bits); + + // public int CompareTo(BigInteger other) + // { + // if (_sign == other._sign) + // { + + // } else { + // return _sign - other._sign; + // } + // } + + // private bool TestZero(UInt32[] bits) + // { + // if (bits == null) + // return true; + + // foreach (uint ui in bits) + // if (ui > 0) + // return false; + // return true; + // } + + + // public BigInteger Add(BigInteger bi2) + // { + // // if ((bits.Length == 1) && (bi2.bits.Length == 1)) + // // return new BigInteger(bits[0]+bi2.bits[0]); + + // int tlength = max(_length, bi2._length) + 1; + // UInt32[] r = new uint[tlength]; + // Array.Copy(bits,r,bits.Length); + // big_add(r, bi2.bits); + // return new BigInteger(r); + // } + // public BigInteger MAdd(BigInteger bi2) + // { + // int tlength = max(_length, bi2._length) + 1; + // UInt32[] r = new uint[tlength]; + // Array.Copy(bits,r,bits.Length); + // managed_add(r, bi2.bits); + // return new BigInteger(r); + // } + + + // public BigInteger Sub(BigInteger bi2) + // { + // int tlength = max(big_get_bitlength(bits), big_get_bitlength(bi2.bits))+1; + // UInt32[] r = new uint[(tlength + 31)>>5]; + // 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) + // { + // int l = (big_get_bitlength(bits) + big_get_bitlength(bi2.bits) + 31) >> 5; + // UInt32[] r = new UInt32[l]; + // Array.Copy(bits, r, bits.Length); + // big_smul(r, bi2.bits); + // return new BigInteger(r); + // } + // public BigInteger MMul(BigInteger bi2) + // { + // int l = (big_get_bitlength(bits) + big_get_bitlength(bi2.bits) + 31) >> 5; + // UInt32[] r = new UInt32[l]; + // Array.Copy(bits, r, bits.Length); + // managed_smul(r, bi2.bits); + // 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 2) + // { + // BigInteger result = One; + // for (int i=31; i>=0; i--) + // { + // result *= result; + // if ((n & (1<= 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 implicit operator BigInteger(int i) + // { + // if (i > 0) + // return new BigInteger(1, new UInt32[]{ (uint)i} ); + // if (i < 0) + // return new BigInteger(-1, new uint[]{ (uint)-i}); + + // return new BigInteger(0, null); + // } + // public static implicit operator BigInteger(uint i) + // { + // if (i > 0) + // return new BigInteger(1, new UInt32[]{ (uint)i} ); + // return new BigInteger(0, null); + // } + + // 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 operator*(BigInteger bi1,BigInteger bi2) => bi1.Mul(bi2); + // public static BigInteger operator/(BigInteger bi1,BigInteger bi2) => bi1.Div(bi2); + // public static BigInteger operator%(BigInteger bi1,BigInteger bi2) => bi1.Mod(bi2); + // //public static BigInteger operator^(BigInteger bi1,int exp) => bi1.Pow(exp); + + + + // public static BigInteger Parse(string source) => Parse( source, 10 ); + // public static BigInteger Parse(string source,int radix) + // { + // UInt32[] bits = new UInt32[ ((source.Length * 6) + 31) >> 5]; + // big_parse(bits, bits.Length, source, 16); + // return new BigInteger(bits); + // } + + // 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); + + // UInt32[] bits = new UInt32[ ((hex.Length * 6) + 31) >> 5]; + // big_parse(bits, bits.Length, hex, 16); + // 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 override string ToString() => ToHexString(); + // public string ToString(int radix) + // { + // if (IsZero) + // return "0"; + + // UInt32[] r; + // UInt32[] v = (UInt32[])bits.Clone(); + + // StringBuilder sb = new StringBuilder(); + + // if (Sign < 0) + // big_twos(v, v.Length); + + // while (big_cmp(v, v.Length, Zero.bits, Zero.bits.Length)!=0) + // { + // r = new UInt32[]{ (UInt32)radix }; + // big_divmod(v, v.Length, r, r.Length); + // if (r[0] < 10) + // sb.Append((char)('0' + r[0])); + // else + // sb.Append((char)(55 + r[0]) ); + // } + + // if (Sign < 0) + // sb.Append('-'); + + // char[] chs = new char[sb.Length]; + // sb.CopyTo(0,chs,0,sb.Length); + // Array.Reverse(chs); + // return new string(chs); + // } + + + // // 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 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 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 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 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("bigint")] + // 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); + + // /*** + // big_get_bitlength() returns the number of bits needed to represent this value including the sign bit + // ***/ + // [DllImport("bigint")] + // public static extern Int32 big_get_bitlength(UInt32[] bits, Int32 length); + // public static Int32 big_get_bitlength(UInt32[] bits) => big_get_bitlength( bits, bits.Length ); + + // [DllImport("bigint")] + // public static extern Int32 big_parse(UInt32[] op, Int32 length, String source, Int32 radix); + // // [DllImport("bigint")] + // // public static extern Int32 big_log2(UInt32[] bits, Int32 length); + + // [DllImport("bigint")] + // public static extern void big_add(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); + // public static void big_add(UInt32[] op_a, UInt32[] op_b) => big_add( op_a, op_a.Length, op_b, op_b.Length); + // //public static unsafe extern void big_add(UInt32* op_a, Int32 length_a, UInt32* op_b, Int32 length_b); + // // public unsafe static void big_add(UInt32[] op_a, UInt32[] op_b){ + // // fixed (UInt32* a = op_a) + // // fixed (UInt32* b = op_b) + // // big_add( a, op_a.Length, b, op_b.Length ); + // // } + + // [DllImport("bigint")] + // public static extern void big_sub(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); + // public static void big_sub(UInt32[] op_a, UInt32[] op_b) => big_sub( op_a, op_a.Length, op_b, op_b.Length ); + + // [DllImport("bigint")] + // public static extern void big_twos(UInt32[] bits, Int32 length); + // [DllImport("bigint")] + // public static extern void big_shl(UInt32[] bits, Int32 length, Int32 n); + // [DllImport("bigint")] + // public static extern void big_shr(UInt32[] bits, Int32 length, Int32 n); + + + // [DllImport("bigint")] + // public static extern Int32 big_cmp(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); + // public static Int32 big_cmp(UInt32[] op_a, UInt32[] op_b) => big_cmp(op_a, op_a.Length, op_b, op_b.Length); + + + // [DllImport("bigint")] + // public static unsafe extern void big_smul(UInt32* op_a, Int32 length_a, UInt32* op_b, Int32 length_b); + // public static unsafe void big_smul(UInt32[] op_a, UInt32[] op_b) + // { + // fixed (UInt32* a = op_a) + // fixed (UInt32* b = op_b) + // big_smul( a, op_a.Length, b, op_b.Length); + // } + // [DllImport("bigint")] + // public static extern void big_divmod(UInt32[] op_a, Int32 length_a, UInt32[] op_b, Int32 length_b); + // public static void big_divmod(UInt32[] op_a, UInt32[] op_b) => big_divmod( op_a, op_a.Length, op_b, op_b.Length); + + + // private int max(int a,int b) => a > b ? a : b; + + + // public static int managed_get_length(UInt32[] op) + // { + // for (int n=op.Length-1;n>0;n--) + // { + // if ((op[n] != 0xFFFFFFFF) && ((op[n]==0) || ((op[n-1] & 0x80000000)!=0) ) ) + // return n; + // } + // return 1; + // } + + // public void managed_smul(UInt32[] op_a, UInt32[] op_b) + // { + // Int32 length_a = op_a.Length; + // Int32 length_b = op_b.Length; + // UInt32[] op_a_bak = new uint[length_a]; + // Array.Copy(op_a, op_a_bak, length_a); + + // for (int l1 = 0; l1 < length_a; l1++) + // { + // UInt64 ui64 = 0; + // int l2; + // for (l2 = 0; (l2 < length_b) && (l1 + l2 < length_a); l2++) + // { + // int target = l1 + l2; + // ui64 += op_a[target]; + // ui64 += ((UInt64)op_a_bak[l1] * op_b[l2]); + // op_a[target] = (UInt32)ui64; + // ui64 >>= 32; + // } + // for (;(l2 < length_a) && (ui64 != 0);l2++) + // { + // int target = l1 + l2; + // ui64 += op_a[target]; + // op_a[target] = (UInt32)ui64; + // ui64 >>= 32; + // } + // } + // } + + // public void managed_add(UInt32[] op_a, UInt32[] op_b) + // { + // Int64 c = 0; + // Int32 length_a = op_a.Length; + // Int32 length_b = op_b.Length; + + + // for (int n=0;n>= 32; + + // if ((c == 0) && (n > length_b)) + // break; + // } + // } + + // } } diff --git a/ln.biginteger/BigIntegerAllocator.cs b/ln.biginteger/BigIntegerAllocator.cs new file mode 100644 index 0000000..6aed25e --- /dev/null +++ b/ln.biginteger/BigIntegerAllocator.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading; + +namespace ln.biginteger +{ + public static class BigIntegerAllocator + { + static int _mpz_size = 24; + static int _allocate_count = 40960000; + + static Stack pool = new Stack(); + + public static IntPtr Pop() + { + lock (pool) + { + if (!pool.TryPop(out IntPtr ptr)) + { + ptr = Marshal.AllocHGlobal(_mpz_size * _allocate_count); + for (int n=1;n<_allocate_count;n++) + pool.Push(ptr + (n*_mpz_size)); + + } + return ptr; + } + } + + public static void Push(IntPtr ptr) + { + lock (pool) + { + pool.Push(ptr); + } + } + + + + } + +} \ No newline at end of file diff --git a/ln.biginteger/ln.biginteger.csproj b/ln.biginteger/ln.biginteger.csproj index 0cda350..80ae29e 100644 --- a/ln.biginteger/ln.biginteger.csproj +++ b/ln.biginteger/ln.biginteger.csproj @@ -2,12 +2,16 @@ netcoreapp5.0 + - - PreserveNewest - + + + + + + diff --git a/ln.biginteger/x64/libgmp.so b/ln.biginteger/x64/libgmp.so new file mode 100755 index 0000000..4b0860e Binary files /dev/null and b/ln.biginteger/x64/libgmp.so differ