commit a54b28ed97590dc562b71c503c79e2533f0df4f1 Author: Harald Wolff Date: Tue Oct 17 21:49:51 2017 +0200 Initial Commit 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; + } + } +}