From a54b28ed97590dc562b71c503c79e2533f0df4f1 Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Tue, 17 Oct 2017 21:49:51 +0200 Subject: [PATCH] Initial Commit --- .gitignore | 40 ++++ BigInt.csproj | 55 +++++ BigIntMath.cs | 456 +++++++++++++++++++++++++++++++++++++ BigIntegerWrapper.cs | 297 ++++++++++++++++++++++++ BigUIntMath.cs | 233 +++++++++++++++++++ Euclid.cs | 72 ++++++ IntBase.cs | 51 +++++ IntField.cs | 30 +++ Integer.cs | 226 ++++++++++++++++++ NumericsExtensions.cs | 36 +++ Properties/AssemblyInfo.cs | 26 +++ UInteger.cs | 236 +++++++++++++++++++ 12 files changed, 1758 insertions(+) create mode 100644 .gitignore create mode 100644 BigInt.csproj create mode 100644 BigIntMath.cs create mode 100644 BigIntegerWrapper.cs create mode 100644 BigUIntMath.cs create mode 100644 Euclid.cs create mode 100644 IntBase.cs create mode 100644 IntField.cs create mode 100644 Integer.cs create mode 100644 NumericsExtensions.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 UInteger.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4e82d27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Autosave files +*~ + +# build +[Oo]bj/ +[Bb]in/ +packages/ +TestResults/ + +# globs +Makefile.in +*.DS_Store +*.sln.cache +*.suo +*.cache +*.pidb +*.userprefs +*.usertasks +config.log +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.user +*.tar.gz +tarballs/ +test-results/ +Thumbs.db + +# Mac bundle stuff +*.dmg +*.app + +# resharper +*_Resharper.* +*.Resharper + +# dotCover +*.dotCover diff --git a/BigInt.csproj b/BigInt.csproj new file mode 100644 index 0000000..1cd2810 --- /dev/null +++ b/BigInt.csproj @@ -0,0 +1,55 @@ + + + + Debug + AnyCPU + {E745E261-9E3E-4401-B3BA-78B38753A82E} + Library + BigInt + BigInteger + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + + + + + + + + + + + + + + + {97CA3CA9-98B3-4492-B072-D7A5995B68E9} + sharp.extensions + + + + \ No newline at end of file diff --git a/BigIntMath.cs b/BigIntMath.cs new file mode 100644 index 0000000..13a0e52 --- /dev/null +++ b/BigIntMath.cs @@ -0,0 +1,456 @@ +using System; +using sharp.extensions; +namespace BigInt +{ + public static class BigIntMath + { + /* Public Interface */ + + public static bool sign(UInt32[] value){ + return (value[value.Length - 1] & (1 << 31)) != 0; + } + + public static int log2(UInt32[] value) + { + switch (sign(value)){ + case false: + for (int n = value.Length << 5; n > 0; n--) + { + if ((value[(n - 1) >> 5] & (1 << ((n - 1) & 0x1F))) != 0) + { + return n - 1; + } + } + return 0; + case true: + for (int n = (value.Length << 5)-1; n > 0; n--) + { + if ((value[(n - 1) >> 5] & (1 << ((n - 1) & 0x1F))) == 0) + { + return 1 - n; + } + } + return 0; + } + return 0; + } + + public static bool isZero(UInt32[] value){ + foreach (UInt32 v in value){ + if (v != 0){ + return false; + } + } + return true; + } + + public static UInt32[] ones(UInt32[] value){ + UInt32[] result = value.Segment(0); + for (int n = 0; n < result.Length;n++){ + result[n] ^= 0xffffffff; + } + return result; + } + + public static UInt32[] twos(UInt32[] value){ + UInt32[] result = ones(value); + UInt32[] one = new UInt32[]{1}; + result = add(result, one); + return result; + } + + /** + * Extend signed integer to higher width + **/ + public static UInt32[] extendSigned(UInt32[] value,int width){ + UInt32[] result = value.Segment(0).Extend(width); + if (sign(value)) + { + for (int n = value.Length; n < width; n++) + { + result[n] = 0xFFFFFFFF; + } + } + return result; + } + + public static void extendEqualSigned(ref UInt32[] a, ref UInt32[] b){ + int width = a.Length > b.Length ? a.Length : b.Length; + + a = extendSigned(a, width); + b = extendSigned(b, width); + } + + public static UInt32[] signedFromUnsigned(UInt32[] value){ + int lg2 = log2(value); + int vlen = value.Length; + + if (lg2 < 0){ + lg2 = 34 - lg2; + if ((lg2 % 32)==0){ + vlen++; + } + } + return value.Extend(vlen); + } + + /** + * Reduce signed integer to smallest width, needed to represent its value + **/ + public static UInt32[] reduceSigned(UInt32[] value){ + int lg2 = log2(value); + if (lg2 < 0){ + lg2 = 0 - lg2; + } + lg2 >>= 5; + lg2++; + if (value.Length != lg2){ + return value.Segment(0, lg2); + } + return value; + } + + /** + * Reduce unsigned integer to smallest width, needed to represent its value + **/ + public static UInt32[] reduceUnsigned(UInt32[] value) + { + int lg2 = log2(value); + if (lg2 < 0){ + lg2 = value.Length; + } else { + lg2 >>= 5; + lg2++; + } + + if (lg2 < 1) + { + lg2 = 1; + } + if (value.Length != lg2) + { + return value.Segment(0, lg2); + } + return value; + } + + public static UInt32[] add(UInt32[] a, UInt32[] b) + { + UInt32 c = 0; + + a = a.Segment(0); + extendEqualSigned(ref a, ref b); + + for (int n = 0; n < a.Length; n++) + { + a[n] = add(a[n], b[n], ref c); + } + return a; + } + + public static UInt32[] sub(UInt32[] a, UInt32[] b) + { + UInt32 c = 0; + a = a.Segment(0); + + extendEqualSigned(ref a, ref b); + + for (int n = 0; n < a.Length; n++) + { + a[n] = sub(a[n], b[n], ref c); + } + return a; + } + + public static UInt32[] umul(UInt32[] a, UInt32[] b) + { + UInt32[] result = new UInt32[a.Length + b.Length]; + + for (int l1 = 0; l1 < a.Length; l1++) + { + for (int l2 = 0; l2 < (b.Length); l2++) + { + int target = l1 + l2; + UInt64 ui64 = ((UInt64)a[l1] * b[l2]); + for (int ct = target; (ct < result.Length) && (ui64 != 0); ct++){ + ui64 += result[ct]; + result[ct] = (UInt32)ui64; + ui64 >>= 32; + } + } + } + + return result; + } + + public static UInt32[] smul(UInt32[] a, UInt32[] b) + { + a = extendSigned(a, a.Length << 1); + b = extendSigned(b, b.Length << 1); + + UInt32[] result = new UInt32[(a.Length + b.Length)>>1]; + + for (int l1 = 0; l1 < a.Length; l1++) + { + for (int l2 = 0; l2 < (b.Length); l2++) + { + int target = l1 + l2; + UInt64 ui64 = ((UInt64)a[l1] * b[l2]); + for (int ct = target; (ct < result.Length) && (ui64 != 0); ct++) + { + ui64 += result[ct]; + result[ct] = (UInt32)ui64; + ui64 >>= 32; + } + } + } + return result; + } + + /** + * @brief Calulate a / b. (unsigned values) + * @returns Result of division. + **/ + public static UInt32[] udiv(UInt32[] a,UInt32[] b){ + return udivmod(ref a, b); + } + public static UInt32[] umod(UInt32[] a,UInt32[] b){ + UInt32[] m = a.Segment(0); + udivmod(ref m,b); + return m; + } + + public static UInt32[] udivmod(ref UInt32[] _a, UInt32[] b) + { + UInt32[] a = _a; + + if (cmp(a, b) < 0) + { + return new UInt32[a.Length]; + } + + UInt32[] result = new UInt32[a.Length]; + UInt32[] d = b.Segment(0).Extend(a.Length); + + int lg2a, lg2b, shift; + + lg2a = log2(a); + lg2b = log2(d); + shift = lg2a - lg2b; + + if (shift > 0) + { + shl(d, shift); + } + + for (int n = 0; n <= (shift); n++) + { + shl(result, 1); + + if (cmp(d, a) <= 0) + { + result[0] |= 1; + a = sub(a, d); + } + + shr(d, 1); + } + _a = a; + return result; + } + + /** + * @brief Calulate a / b. (unsigned values) + * @returns Result of division. a[] will contain reminder. + **/ + public static UInt32[] sdiv(UInt32[] a, UInt32[] b) + { + return sdivmod(ref a, b); + } + public static UInt32[] smod(UInt32[] a, UInt32[] b) + { + UInt32[] m = a.Segment(0); + sdivmod(ref m, b); + return m; + } + + /** + * sdivmod ( a , b ) + * + * Calculate Quotient and Reminder of a / b using signed integer arithmetics + * returns quotient + * leaves reminder in + * + **/ + public static UInt32[] sdivmod(ref UInt32[] a, UInt32[] b) + { + bool sgna, sgnb; + + sgna = sign(a); + sgnb = sign(b); + + Console.WriteLine("sdivmod(): a = {0}",a.getBytes().Reverse().toHexString()); + Console.WriteLine("sdivmod(): b = {0}",b.getBytes().Reverse().toHexString()); + + if (sgna){ + a = twos(a); + } + if (sgnb){ + b = twos(b); + } + + UInt32[] result = udivmod(ref a, b); + + if (sgna != sgnb){ + result = twos(result); + } + if (sgna){ + a = twos(a); + } + + Console.WriteLine("sdivmod(): result = {0}",result.getBytes().Reverse().toHexString()); + Console.WriteLine("sdivmod(): reminder = {0}",a.getBytes().Reverse().toHexString()); + + return result; + } + + /** + * @brief Logical Shift Left + **/ + public static void shl(UInt32[] a, int n) + { + if (n > 0) + { + int step = n >> 5; + n &= 0x1F; + + for (int i = a.Length; i > 0; i--) + { + int b1 = i - 1 - step; + int b2 = b1 - 1; + + if (b1 >= 0){ + a[i - 1] = (a[b1] << n); + if ((n != 0)&&(b2 >= 0)) + { + a[i - 1] |= ((a[b2] >> (32 - n))); + } + } else { + a[i - 1] = 0; + } + } + } + } + /** + * @brief Logical Shift Right + **/ + public static void shr(UInt32[] a, int n) + { + if (n > 0) + { + bool s = sign(a); + int step = n >> 5; + n &= 0x1F; + + for (int i = 0; i < a.Length; i++) + { + int b1 = i + step; + int b2 = b1 + 1; + + if (b1 < a.Length) + { + a[i] = (a[b1] >> n); + if ((b2 == a.Length) && (s)){ + a[i] |= ((0xffffffff << (32 - n))); + } else if ((n != 0) && (b2 < a.Length)) + { + a[i] |= ((a[b2] << (32 - n))); + } + + } else { + a[i] = s ? 0xFFFFFFFF : 0; + } + } + } + } + + /** + * @brief Compare + * @returns Negative Value if ab,0 if equal + **/ + public static int cmp(UInt32[] a, UInt32[] b) + { + a = a.Segment(0); + b = b.Segment(0); + extendEqualSigned(ref a, ref b); + + UInt32[] result = sub(a, b); + + if (isZero(result)) + { + return 0; + } + else if (sign(result)) + { + return -1; + } + else + { + return 1; + } + } + + + + + + + /* Helper Functions */ + + private static UInt32 add(UInt32 a, UInt32 b, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)carry + (UInt64)a + (UInt64)b; + carry = (UInt32)(ui64 >> 32); + return (UInt32)(ui64 & 0xffffffff); + } + private static UInt32 add(UInt32 a, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)carry + (UInt64)a; + carry = (UInt32)(ui64 >> 32); + return (UInt32)(ui64 & 0xffffffff); + } + + private static UInt32 sub(UInt32 a, UInt32 b, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)a - (UInt64)b - (UInt64)carry; + carry = (ui64 & (1UL << 63)) != 0 ? (UInt32)1 : (UInt32)0; + return (UInt32)(ui64 & 0xffffffff); + } + private static UInt32 sub(UInt32 a, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)a - (UInt64)carry; + carry = (ui64 & (1UL << 63)) != 0 ? (UInt32)1 : (UInt32)0; + return (UInt32)(ui64 & 0xffffffff); + } + + private static UInt32 shl(UInt32 a, int n, ref UInt32 carry) + { + UInt64 result = (UInt64)((UInt64)a << n) | carry; + carry = (UInt32)(result >> 32); + return (UInt32)result; + } + private static UInt32 shr(UInt32 a, int n, ref UInt32 carry) + { + UInt64 result = (UInt64)((UInt64)a << (32 - n)) | ((UInt64)carry << 32); + carry = (UInt32)result; + return (UInt32)(result >> 32); + } + + + + + + + + } +} diff --git a/BigIntegerWrapper.cs b/BigIntegerWrapper.cs new file mode 100644 index 0000000..7fd1a0c --- /dev/null +++ b/BigIntegerWrapper.cs @@ -0,0 +1,297 @@ +using System; +using sharp.extensions; +using System.Text; +using System.Numerics; + +namespace BigInt +{ + public class BigIntegerWrapper + { + /** Value for Calculations **/ + private System.Numerics.BigInteger value; + /** + * Size of BigInteger in bytes that this Number is represented externally + **/ + private int size; + + + public BigIntegerWrapper(int size) + { + this.size = size; + this.value = new System.Numerics.BigInteger(); + } + public BigIntegerWrapper(int size, Int64 v) + { + this.size = size; + this.value = v; + } + public BigIntegerWrapper(int size, Int32 v) + { + this.size = size; + this.value = v; + } + public BigIntegerWrapper(int size,System.Numerics.BigInteger value){ + this.size = size; + this.value = value; + } + public BigIntegerWrapper(byte[] value) + { + this.size = value.Length; + this.value = new System.Numerics.BigInteger(value); + } + + public BigIntegerWrapper Pow3(){ + return new BigIntegerWrapper(this.size,this.value * this.value * this.value); + } + + public BigIntegerWrapper Sqrt(){ + return new BigIntegerWrapper(this.size, this.value.Sqrt()); + } + + + public byte[] getBytes() + { + byte[] va = this.value.ToByteArray(); + byte[] r = new byte[this.size]; + int lcopy = va.Length < r.Length ? va.Length : r.Length; + + Array.Copy( va,r, lcopy ); + r.Fill(value < 0 ? (byte)0xff : (byte)0,lcopy); + + return r; + } + + public byte[] getBytes(Endianess endianess){ + byte[] bytes = getBytes(); + if (endianess != 0.CurrentEndianess()){ + return bytes.Reverse(); + } + return bytes; + } + + public string toHexString() + { + return getBytes().toHexString(); + } + public string toHexString(Endianess endianess) + { + return getBytes(endianess).toHexString(); + } + + public static BigIntegerWrapper fromHexString(string hex){ + return new BigIntegerWrapper(HexString.toBytes(hex)); + } + + public static BigIntegerWrapper operator +(BigIntegerWrapper a, BigIntegerWrapper b) + { + return new BigIntegerWrapper(a.size, a.value + b.value); + } + public static BigIntegerWrapper operator -(BigIntegerWrapper a, BigIntegerWrapper b) + { + return new BigIntegerWrapper(a.size, a.value - b.value); + } + public static BigIntegerWrapper operator /(BigIntegerWrapper a, BigIntegerWrapper b) + { + return new BigIntegerWrapper(a.size, a.value / b.value); + } + public static BigIntegerWrapper operator *(BigIntegerWrapper a, BigIntegerWrapper b) + { + return new BigIntegerWrapper(a.size, a.value * b.value); + } + public static BigIntegerWrapper operator %(BigIntegerWrapper a, BigIntegerWrapper b) + { + return new BigIntegerWrapper(a.size, a.value % b.value); + } + + public static BigIntegerWrapper operator <<(BigIntegerWrapper a,int n) + { + return new BigIntegerWrapper(a.size, a.value << n); + } + public static BigIntegerWrapper operator >>(BigIntegerWrapper a, int n) + { + return new BigIntegerWrapper(a.size, a.value >> n); + } + + + public static implicit operator BigIntegerWrapper(Int32 v) + { + return new BigIntegerWrapper(v.GetBytes()); + } + public static implicit operator BigIntegerWrapper(UInt32 v) + { + return new BigIntegerWrapper(v.GetBytes()); + } + public static implicit operator BigIntegerWrapper(Int64 v) + { + return new BigIntegerWrapper(v.GetBytes()); + } + public static implicit operator BigIntegerWrapper(UInt64 v) + { + return new BigIntegerWrapper(v.GetBytes()); + } + + + } +} + +/* + UInt32[] value; + + public BigInteger(int bits) + { + this.value = new UInt32[(bits + 0x1F) >> 5]; + } + public BigInteger(UInt32[] initialValue) + { + this.value = initialValue.Segment(0); + } + public BigInteger(BigInteger initialValue) + { + this.value = initialValue.value.Segment(0); + } + + public UInt32 this[int n] { + get { return (this.value.Length > n) ? this.value[n] : 0; } + } + + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + foreach (UInt32 seg in this.value.Reverse()){ + sb.Append(seg.GetBytes(Endianess.BigEndian).toHexString()); + } + return sb.ToString(); + } + + + public static BigInteger operator +(BigInteger a, UInt32 b) + { + UInt32[] result = new UInt32[a.value.Length]; + UInt32 c = 0; + + result[0] = add(a[0], b, ref c); + for (int n = 1; n < result.Length; n++) + { + result[n] = add(a[n], ref c); + } + + return new BigInteger(result); + } + public static BigInteger operator +(BigInteger a,BigInteger b){ + UInt32[] result = new UInt32[ getBufferSize(a,b) ]; + UInt32 c = 0; + + for (int n = 0; n < result.Length; n++){ + result[n] = add(a[n], b[n], ref c); + } + + return new BigInteger(result); + } + + public static BigInteger operator -(BigInteger a, UInt32 b) + { + UInt32[] result = new UInt32[a.value.Length]; + UInt32 c = 0; + + result[0] = sub(a[0], b, ref c); + for (int n = 1; n < result.Length; n++) + { + result[n] = sub(a[n], ref c); + } + + return new BigInteger(result); + } + public static BigInteger operator -(BigInteger a, BigInteger b) + { + UInt32[] result = new UInt32[getBufferSize(a, b)]; + UInt32 c = 0; + + for (int n = 0; n < result.Length; n++) + { + result[n] = add(a[n], b[n], ref c); + } + + return new BigInteger(result); + } + + public static BigInteger operator <<(BigInteger a,int n){ + BigInteger b = new BigInteger(a); + UInt32 c = 0; + int step = n >> 5; + n &= 0x1F; + + for (int i = step; i < (b.value.Length); i++){ + b.value[i] = shl(b.value[i - step], n, ref c); + } + for (int i = 0; i < (step); i++) + { + b.value[i] = 0; + } + return b; + } + + public static BigInteger operator >>(BigInteger a, int n) + { + BigInteger b = new BigInteger(a); + UInt32 c = 0; + + for (int i = b.value.Length; i > 0; i--) + { + b.value[i-1] = shr(b.value[i-1], n, ref c); + } + + return b; + } + + private static UInt32 add(UInt32 a, UInt32 b, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)carry + (UInt64)a + (UInt64)b; + carry = (UInt32)(ui64 >> 32); + return (UInt32)(ui64 & 0xffffffff); + } + private static UInt32 add(UInt32 a, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)carry + (UInt64)a; + carry = (UInt32)(ui64 >> 32); + return (UInt32)(ui64 & 0xffffffff); + } + + private static UInt32 sub(UInt32 a, UInt32 b, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)a - (UInt64)b - (UInt64)carry; + carry = (ui64 & (1UL << 63)) != 0 ? (UInt32)1 : (UInt32)0; + return (UInt32)(ui64 & 0xffffffff); + } + private static UInt32 sub(UInt32 a, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)a - (UInt64)carry; + carry = (ui64 & (1UL << 63)) != 0 ? (UInt32)1 : (UInt32)0; + return (UInt32)(ui64 & 0xffffffff); + } + + private static UInt32 shl(UInt32 a, int n, ref UInt32 carry) + { + UInt64 result = (UInt64)((UInt64)a << n) | carry; + carry = (UInt32)(result >> 32); + return (UInt32)result; + } + private static UInt32 shr(UInt32 a, int n, ref UInt32 carry) + { + UInt64 result = (UInt64)((UInt64)a << (32 - n)) | ((UInt64)carry << 32); + carry = (UInt32)result; + return (UInt32)(result >> 32); + } + + + private static int getBufferSize(BigInteger a){ + return a.value.Length; + } + private static int getBufferSize(BigInteger a,BigInteger b) + { + return a.value.Length > b.value.Length ? a.value.Length : b.value.Length; + } + } +} +*/ + diff --git a/BigUIntMath.cs b/BigUIntMath.cs new file mode 100644 index 0000000..7cb6eb2 --- /dev/null +++ b/BigUIntMath.cs @@ -0,0 +1,233 @@ +using System; +using sharp.extensions; +namespace BigInt +{ + public static class BigUIntMath + { + /* Public Interface */ + + + public static void add(UInt32[] a, UInt32[] b) + { + UInt32 c = 0; + + for (int n = 0; n < a.Length; n++) + { + a[n] = add(a[n], (n < b.Length) ? b[n] : 0, ref c); + } + } + + public static void sub(UInt32[] a, UInt32[] b) + { + UInt32 c = 0; + + for (int n = 0; n < a.Length; n++) + { + a[n] = sub(a[n], (n < b.Length) ? b[n] : 0, ref c); + } + } + + public static UInt32[] mul(UInt32[] a, UInt32[] b) + { + UInt32[] result = new UInt32[a.Length + b.Length]; + + for (int l1 = 0; l1 < a.Length; l1++) + { + for (int l2 = 0; l2 < (b.Length); l2++) + { + int target = l1 + l2; + UInt64 ui64 = ((UInt64)a[l1] * b[l2]); + for (int ct = target; (ct < result.Length) && (ui64 != 0); ct++){ + ui64 += result[ct]; + result[ct] = (UInt32)ui64; + ui64 >>= 32; + } + } + } + + return result; + } + + /** + * @brief Calulate a / b. + * @returns Result of division. a[] will contain reminder. + **/ + public static UInt32[] div(UInt32[] a, UInt32[] b) + { + if (cmp(a, b) < 0) + { + return new UInt32[a.Length]; + } + + UInt32[] result = new UInt32[a.Length]; + UInt32[] d = b.Segment(0).Extend(a.Length); + + int lg2a, lg2b, shift; + + lg2a = log2(a); + lg2b = log2(d); + shift = lg2a - lg2b; + + if (shift > 0) + { + shl(d, shift); + } + + for (int n = 0; n <= (shift); n++) + { + shl(result, 1); + + if (cmp(d, a) <= 0) + { + result[0] |= 1; + sub(a, d); + } + + shr(d, 1); + } + return result; + } + + public static int log2(UInt32[] a) + { + for (int n = a.Length << 5; n > 0; n--) + { + if ((a[(n - 1) >> 5] & (1 << ((n - 1) & 0x1F))) != 0) + { + return n - 1; + } + } + return 0; + } + + /** + * @brief Logical Shift Left + **/ + public static void shl(UInt32[] a, int n) + { + if (n > 0) + { + int step = n >> 5; + n &= 0x1F; + + for (int i = a.Length; i > 0; i--) + { + int b1 = i - 1 - step; + int b2 = b1 - 1; + + if (b1 >= 0){ + a[i - 1] = (a[b1] << n); + if ((n != 0)&&(b2 >= 0)) + { + a[i - 1] |= ((a[b2] >> (32 - n))); + } + } else { + a[i - 1] = 0; + } + } + } + } + /** + * @brief Logical Shift Right + **/ + public static void shr(UInt32[] a, int n) + { + if (n > 0) + { + int step = n >> 5; + n &= 0x1F; + + for (int i = 0; i < a.Length; i++) + { + int b1 = i + step; + int b2 = b1 + 1; + + if (b1 < a.Length) + { + a[i] = (a[b1] >> n); + if ((n != 0) && (b2 < a.Length)) + { + a[i] |= ((a[b2] << (32 - n))); + } + } + else + { + a[i] = 0; + } + } + } + } + + /** + * @brief Compare + * @returns Negative Value if ab,0 if equal + **/ + public static int cmp(UInt32[] a, UInt32[] b) + { + int start = a.Length > b.Length ? a.Length : b.Length; + + for (int n = start; n > 0; n--) + { + Int64 diff = (n <= a.Length ? (Int64)a[n - 1] : 0) - (n <= b.Length ? (Int64)b[n - 1] : 0); + if (diff != 0) + { + return (diff < 0) ? -1 : 1; + } + } + return 0; + } + + + + + + + /* Helper Functions */ + + private static UInt32 add(UInt32 a, UInt32 b, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)carry + (UInt64)a + (UInt64)b; + carry = (UInt32)(ui64 >> 32); + return (UInt32)(ui64 & 0xffffffff); + } + private static UInt32 add(UInt32 a, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)carry + (UInt64)a; + carry = (UInt32)(ui64 >> 32); + return (UInt32)(ui64 & 0xffffffff); + } + + private static UInt32 sub(UInt32 a, UInt32 b, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)a - (UInt64)b - (UInt64)carry; + carry = (ui64 & (1UL << 63)) != 0 ? (UInt32)1 : (UInt32)0; + return (UInt32)(ui64 & 0xffffffff); + } + private static UInt32 sub(UInt32 a, ref UInt32 carry) + { + UInt64 ui64 = (UInt64)a - (UInt64)carry; + carry = (ui64 & (1UL << 63)) != 0 ? (UInt32)1 : (UInt32)0; + return (UInt32)(ui64 & 0xffffffff); + } + + private static UInt32 shl(UInt32 a, int n, ref UInt32 carry) + { + UInt64 result = (UInt64)((UInt64)a << n) | carry; + carry = (UInt32)(result >> 32); + return (UInt32)result; + } + private static UInt32 shr(UInt32 a, int n, ref UInt32 carry) + { + UInt64 result = (UInt64)((UInt64)a << (32 - n)) | ((UInt64)carry << 32); + carry = (UInt32)result; + return (UInt32)(result >> 32); + } + + + + + + + + } +} diff --git a/Euclid.cs b/Euclid.cs new file mode 100644 index 0000000..85b96b9 --- /dev/null +++ b/Euclid.cs @@ -0,0 +1,72 @@ +using System; +using sharp.extensions; + +namespace BigInt +{ + public static class Euclid + { + + public static Tripple extended(Integer a, Integer b) + { + if (b.isZero()){ + if (a != Integer.ONE){ + throw new ArgumentException("Euclid found GCD>1!"); + } + return new Tripple(a, Integer.ONE, Integer.ZERO); + } + Tripple r = extended(b, a % b); + return new Tripple(r.X,r.Z,r.Y - ((a / b) * r.Z) ); + } + + /** + * Implementation of inverse() like found at + * https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm (14 Oct 2017) + **/ + public static Integer inverse(Integer a,Integer m){ + Integer one, zero; + + rt act, next, future; + + one = Integer.ONE; + zero = Integer.ZERO; + + act = new rt(m, zero); + next = new rt(a, one); + + while (!next.r.isZero()) + { + Integer q = act.r / next.r; + future = new rt( + act.r - (q * next.r), + act.t - (q * next.t) + ); + Console.WriteLine("EUCLID: q = {0}",q); + Console.WriteLine("EUCLID: act: r = {0} / t = {1}",act.r,act.t); + Console.WriteLine("EUCLID: next: r = {0} / t = {1}",next.r,next.t); + Console.WriteLine("EUCLID: future: r = {0} / t = {1}",future.r,future.t); + + act = next; + next = future; + } + + if (act.r > one){ + return null; + } + if (act.t < 0){ + act.t += m; + } + + return act.t; + } + + private struct rt { + public Integer r, t; + + public rt(Integer r,Integer t){ + this.r = r; + this.t = t; + } + } + + } +} diff --git a/IntBase.cs b/IntBase.cs new file mode 100644 index 0000000..c7797d9 --- /dev/null +++ b/IntBase.cs @@ -0,0 +1,51 @@ +using System; +using System.CodeDom; +using System.Dynamic; +using sharp.extensions; +namespace BigInt +{ + public abstract class IntBase + { + protected UInt32[] rawValue; + + public UInt32[] RawValue + { + get { return this.rawValue; } + protected set + { + this.rawValue = value; + } + } + + public byte[] getBytes() + { + byte[] b = new byte[this.RawValue.Length << 2]; + for (int n = 0; n < this.RawValue.Length; n++) + { + b.Insert(this.RawValue[n].GetBytes(), n << 2); + } + return b; + } + + public bool this[int bit] + { + get { return ((this.RawValue[bit >> 5] & (1 << (bit & 0x1F))) != 0); } + } + + public bool isZero(){ + return BigIntMath.isZero(rawValue); + } + + public string toHexString() + { + return getBytes().Reverse().toHexString(); + } + + public override string ToString() + { + return String.Format("[{0}: {1}]",this.GetType().Name,toHexString()); + } + + } + +} diff --git a/IntField.cs b/IntField.cs new file mode 100644 index 0000000..e679e69 --- /dev/null +++ b/IntField.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq.Expressions; +namespace BigInt +{ + public class IntField + { + public static IntField Default { get; set; } = null; // new IntField(UBigInteger.ZERO.Resize(256) - 1); + + public UInteger FieldModulo { get; private set; } + public int FieldWidth { get; private set; } + + public IntField(UInteger p,int width){ + this.FieldWidth = width; + this.FieldModulo = p; + } + public IntField(UInteger p){ + this.FieldModulo = p; + this.FieldWidth = p.RawValue.Length << 5; + } + + public UInteger Fit(UInteger value){ + return value % FieldModulo; + } + + public override string ToString(){ + return String.Format("[IntField p={0}]",this.FieldModulo); + } + + } +} diff --git a/Integer.cs b/Integer.cs new file mode 100644 index 0000000..ca8d892 --- /dev/null +++ b/Integer.cs @@ -0,0 +1,226 @@ +using System; +using sharp.extensions; +namespace BigInt +{ + public class Integer: IntBase + { + public static readonly Integer ZERO = new Integer(); + public static readonly Integer ONE = new Integer(new UInt32[] { 1 }); + + public Integer() + { + this.RawValue = new UInt32[1]; + } + + public Integer(UInt32[] value) + { + this.RawValue = BigIntMath.reduceSigned(value); + } + public Integer(byte[] ivalue) + { + UInt32[] v = new UInt32[(ivalue.Length + 3) >> 2]; + ivalue = ivalue.Extend(v.Length << 2); + + for (int n = 0; n < v.Length; n++) + { + v[n] = BitConverter.ToUInt32(ivalue, n << 2); + } + this.RawValue = BigIntMath.reduceSigned(v); + } + public Integer(UInt32[] value, IntField field) + { + this.RawValue = BigIntMath.reduceSigned(value); + } + public Integer(Integer src) + { + this.RawValue = src.RawValue; + } + + public bool Sign(){ + return BigIntMath.sign(rawValue); + } + + public int Log2(){ + return BigIntMath.log2(rawValue); + } + + public Integer Pow(int n) + { + if (n == 0) + { + return ONE; + } + else if (n == 1) + { + return this; + } + else if (n > 1) + { + Integer result = this; + n--; + while ((n--) > 0) + { + result = (result * this); + } + return result; + } + throw new ArgumentException("Integer.Pow(n): not implemented for negative exponent"); + } + + public Integer Ones() + { + UInt32[] result = BigIntMath.ones(rawValue); + return new Integer(result); + } + + public Integer Twos() + { + UInt32[] result = BigIntMath.twos(rawValue); + return new Integer(result); + } + + + public static Integer fromHexString(string hex) + { + return new Integer(HexString.toBytes(hex).Reverse()); + } + + public override string ToString() + { + return String.Format("[{0}: Sign: {2,5} / {1}]", this.GetType().Name, toHexString(), Sign() ); + } + + + + private Integer __op_add(Integer b) + { + int width = (rawValue.Length > b.RawValue.Length ? rawValue.Length : b.RawValue.Length) + 1; + UInt32[] v = BigIntMath.extendSigned(rawValue, width); + UInt32[] vb = BigIntMath.extendSigned(b.RawValue, width); + return new Integer(BigIntMath.reduceSigned(BigIntMath.add(v,vb))); + } + private Integer __op_sub(Integer b) + { + int width = (rawValue.Length > b.RawValue.Length ? rawValue.Length : b.RawValue.Length) + 1; + UInt32[] v = BigIntMath.extendSigned(rawValue, width); + UInt32[] vb = BigIntMath.extendSigned(b.RawValue, width); + return new Integer(BigIntMath.reduceSigned(BigIntMath.sub(v,vb))); + } + + private int __op_cmp(Integer b) + { + return BigIntMath.cmp(rawValue, b.RawValue); + } + + private Integer __op_div(Integer b) + { + UInt32[] result = BigIntMath.sdiv(rawValue, b.RawValue); + return new Integer(result); + } + + private Integer __op_mod(Integer b) + { + return null; + } + + private Integer __op_mul(Integer b) + { + UInt32[] value = BigIntMath.smul(rawValue, b.RawValue); + return new Integer(value); + } + + private Integer __op_new(uint[] value) + { + return new Integer(value); + } + + private Integer __op_shl(int b) + { + UInt32[] value = BigIntMath.extendSigned(rawValue, RawValue.Length + ((b + 31) >> 5)); + BigIntMath.shl(value,b); + return new Integer(value); + } + + private Integer __op_shr(int b) + { + UInt32[] value = rawValue.Segment(0); + BigIntMath.shr(value, b); + return new Integer(value); + } + + public static implicit operator Integer(UInteger ui) + { + return new Integer( BigIntMath.signedFromUnsigned( ui.RawValue )); + } + public static implicit operator Integer(int i) + { + return new Integer(new UInt32[]{(UInt32)i}); + } + + + + public static Integer operator +(Integer a, Integer b) + { + return a.__op_add(b); + } + public static Integer operator -(Integer a, Integer b) + { + return a.__op_sub(b); + } + public static Integer operator *(Integer a, Integer b) + { + return a.__op_mul(b); + } + public static Integer operator *(Integer a, UInt32 b) + { + Integer bb = new Integer(new UInt32[] { b }); + return a.__op_mul(bb); + } + + public static Integer operator /(Integer a, Integer b) + { + return a.__op_div(b); + } + public static Integer operator %(Integer a, Integer b) + { + return a.__op_mod(b); + } + + public static bool operator <(Integer a, Integer b) + { + return a.__op_cmp(b) < 0; + } + public static bool operator >(Integer a, Integer b) + { + return a.__op_cmp(b) > 0; + } + public static bool operator ==(Integer a, Integer 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 !=(Integer a, Integer b) + { + return a.__op_cmp(b) != 0; + } + + public static Integer operator <<(Integer a, int b) + { + return a.__op_shl(b); + } + public static Integer operator >>(Integer a, int b) + { + return a.__op_shr(b); + } + + + + } +} diff --git a/NumericsExtensions.cs b/NumericsExtensions.cs new file mode 100644 index 0000000..503db67 --- /dev/null +++ b/NumericsExtensions.cs @@ -0,0 +1,36 @@ +using System; +using System.Numerics; + +namespace BigInt +{ + public static class NumericsExtensions + { + public static System.Numerics.BigInteger Sqrt(this System.Numerics.BigInteger n) + { + if (n == 0) return 0; + if (n > 0) + { + int bitLength = Convert.ToInt32(Math.Ceiling(System.Numerics.BigInteger.Log(n, 2))); + System.Numerics.BigInteger root = System.Numerics.BigInteger.One << (bitLength / 2); + + while (!isSqrt(n, root)) + { + root += n / root; + root /= 2; + } + + return root; + } + + throw new ArithmeticException("NaN"); + } + + private static Boolean isSqrt(System.Numerics.BigInteger n, System.Numerics.BigInteger root) + { + System.Numerics.BigInteger lowerBound = root * root; + System.Numerics.BigInteger upperBound = (root + 1) * (root + 1); + + return (n >= lowerBound && n < upperBound); + } + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..42e3346 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("BigInteger")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/UInteger.cs b/UInteger.cs new file mode 100644 index 0000000..38c9e48 --- /dev/null +++ b/UInteger.cs @@ -0,0 +1,236 @@ +using System; +using sharp.extensions; +using System.Text; +using System.CodeDom; +namespace BigInt +{ + public class UInteger: IntBase + { + public static readonly UInteger ZERO = new UInteger(); + public static readonly UInteger ONE = new UInteger(new UInt32[] { 1 }); + + public UInteger() + { + this.RawValue = new UInt32[1]; + } + + public UInteger(UInt32[] value) + { + this.RawValue = BigIntMath.reduceUnsigned(value); + + } + public UInteger(byte[] ivalue) + { + UInt32[] v = new UInt32[(ivalue.Length + 3) >> 2]; + ivalue = ivalue.Extend(v.Length << 2); + + for (int n = 0; n < v.Length; n++) + { + v[n] = BitConverter.ToUInt32(ivalue, n << 2); + } + this.RawValue = BigIntMath.reduceUnsigned(v); + } + public UInteger(UInt32[] value, IntField field) + { + this.RawValue = BigIntMath.reduceUnsigned(value); + } + public UInteger(UInteger src) + { + this.RawValue = src.RawValue; + } + + public int Log2() + { + int lg2 = BigIntMath.log2(rawValue); + return lg2 < 0 ? rawValue.Length << 32 : lg2; + } + public UInteger Pow(int n) + { + if (n == 0) + { + return ONE; + } + else if (n == 1) + { + return this; + } + else if (n > 1) + { + UInteger result = this; + n--; + while ((n--) > 0) + { + result = (result * this); + } + return result; + } + throw new ArgumentException("Integer.Pow(n): not implemented for negative exponent"); + } + + public UInteger Ones() + { + UInt32[] result = BigIntMath.ones(rawValue); + return new UInteger(result); + } + + public UInteger Twos() + { + UInt32[] result = BigIntMath.twos(rawValue); + return new UInteger(result); + } + + + + public static UInteger fromHexString(string hex) + { + return new UInteger(HexString.toBytes(hex).Reverse()); + } + + private UInteger __op_new(uint[] value) + { + return new UInteger(value); + } + + private UInteger __op_add(UInteger b) + { + UInt32[] result = RawValue.Segment(0).Extend(b.RawValue.Length); + BigUIntMath.add(result,b.RawValue); + return new UInteger(result); + } + + private UInteger __op_sub(UInteger b) + { + UInt32[] result = RawValue.Segment(0).Extend(b.RawValue.Length); + BigUIntMath.sub(result,b.RawValue); + return new UInteger(result); + } + + private UInteger __op_mul(UInteger b) + { + return new UInteger(BigUIntMath.mul(this.RawValue,b.RawValue)); + } + + private UInteger __op_div(UInteger b) + { + return new UInteger(BigUIntMath.div(this.RawValue.Segment(0), b.RawValue)); + } + + private UInteger __op_mod(UInteger b) + { + UInt32[] result = RawValue.Segment(0); + BigUIntMath.div(result,b.RawValue); + return new UInteger(result); + } + + private UInteger __op_shl(int b) + { + UInt32[] v = this.RawValue.Segment(0); + v = v.Extend(v.Length + ((b + 31) >> 5)); + BigUIntMath.shl(v, b); + UInteger r = new UInteger(v); + return r; + } + + private UInteger __op_shr(int b) + { + UInteger result = new UInteger(this); + BigUIntMath.shr(result.RawValue,b); + return result; + } + + private int __op_cmp(UInteger b) + { + return BigUIntMath.cmp(this.RawValue,b.RawValue); + } + + + public static implicit operator UInteger(int n) + { + return new UInteger(new UInt32[] { (UInt32)n }); + } + public static implicit operator UInteger(uint n) + { + return new UInteger(new UInt32[] { n }); + } + public static implicit operator UInteger(UInt64 n) + { + return new UInteger(new UInt32[] { (UInt32)n, (UInt32)(n >> 32) }); + } + + public static implicit operator UInteger(Integer ui) + { + return new UInteger(ui.RawValue); + } + + + public static UInteger operator +(UInteger a, UInteger b) + { + return a.__op_add(b); + } + public static UInteger operator -(UInteger a, UInteger b) + { + return a.__op_sub(b); + } + public static UInteger operator *(UInteger a, UInteger b) + { + return a.__op_mul(b); + } + public static UInteger operator *(UInteger a, UInt32 b) + { + UInteger bb = a.__op_new(new UInt32[] { b }); + return a.__op_mul(bb); + } + + public static UInteger operator /(UInteger a, UInteger b) + { + return a.__op_div(b); + } + public static UInteger operator %(UInteger a, UInteger b) + { + return a.__op_mod(b); + } + + public static bool operator <(UInteger a, UInteger b) + { + return a.__op_cmp(b) < 0; + } + public static bool operator >(UInteger a, UInteger b) + { + return a.__op_cmp(b) > 0; + } + public static bool operator ==(UInteger a, UInteger 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 !=(UInteger a, UInteger b) + { + return a.__op_cmp(b) != 0; + } + + public static UInteger operator <<(UInteger a, int b) + { + return a.__op_shl(b); + } + public static UInteger operator >>(UInteger a, int b) + { + return a.__op_shr(b); + } + + public override bool Equals(object obj) + { + if (typeof(IntBase).IsInstanceOfType(obj)){ + IntBase ib = (IntBase)obj; + return BigIntMath.cmp(rawValue, ib.RawValue) == 0; + } + return false; + } + } +}