public static ULongIntB BinaryOr(ULongIntB a, ULongIntB b) { ULongIntB c = new ULongIntB(a.CoefLength); for (int i = 0; i < a.Size; ++i) c[i] = (ushort)(a[i] | b[i]); c.Size = System.Math.Max(a.Size, b.Size); return c; }
public static ULongIntB BinaryXor(ULongIntB a, ULongIntB b) { ULongIntB c = new ULongIntB(a.CoefLength); for (int i = 0; i < a.Size; ++i) c[i] = (ushort)(a[i] ^ b[i]); c.Size = System.Math.Max(a.Size, b.Size); int s = c.Size - 1; if (s > 0) while (c[s] == 0) { --s; if (s == 0) break; } c.Size = s + 1; return c; }
internal static int TestSmallPrimes(ULongIntB n, uint ladgestSmallPrime) { if (ladgestSmallPrime > LIntConstant.smallPrimes[LIntConstant.smallPrimes.Length - 1]) ladgestSmallPrime = LIntConstant.smallPrimes[LIntConstant.smallPrimes.Length - 1]; // by testing small numbers // we can avoid testing on 85% other natural numbers for (int i = 0; LIntConstant.smallPrimes[i] < ladgestSmallPrime; ++i) { ushort r = n % LIntConstant.smallPrimes[i]; if (r == 0) return r; } return 0; }
public static void TwoFact(ULongIntB A, out ULongIntB u, out int k) { k = 0; u = new ULongIntB(A); if (A == 0) return; while (LongMath.IsEven(u)) { ++k; u.Shr(); } }
/// <summary> /// Test if input number is prime /// </summary> /// <param name="n">Input number</param> /// <param name="rounds">Number of times to provide test</param> /// <returns>Exact answer if input number is composite, and /// a probable answer if input number can be prime. Probability of mistake /// answer is (0.25)^(Rounds number)</returns> public static PrimeTestResult TestPrimeMillerRabin(ULongIntB n, RoundsNumber rounds) { int r = TestSmallPrimes(n, 2000); if (r != 0) return PrimeTestResult.Composite; ULongIntB Nm1 = new ULongIntB(n); --Nm1; int t = 0; ULongIntB q = null; TwoFact(Nm1, out q, out t); RandomLong rand = new RandomLong((ulong)DateTime.Now.Millisecond); for (int i = 0; i < (int)rounds; ++i) { ULongIntB a = new ULongIntB(rand.NextNotOne(Nm1), ConstructorMode.Assign); ULongIntB b = ExpMod5(a, q, n); if ((b == 1) || b == Nm1) continue; bool next = false; for (int j = 0; j < t - 1; ++j) { b = SquareMod(b, n); if (b == 1) return PrimeTestResult.Composite; if (b == Nm1) { next = true; break; } } if (!next) return PrimeTestResult.Composite; } return PrimeTestResult.DontKnow; }
//// <summary> /// Calculates square of input unsigned number by modulo /// </summary> /// <param name="a">Input number</param> /// <param name="m">Modulo</param> /// <returns>(a*a) % m</returns> public static ULongIntB SquareMod(ULongIntB a, ULongIntB m) { return LongMath.Sqr(a) % m; }
/// <summary> /// Calculates square of input unsigned number N times by modulo /// </summary> /// <param name="a">Input number</param> /// <param name="n">Number of times to calculate square</param> /// <param name="m">Modulo</param> /// <returns>[ a ^ (2*n) ] % m</returns> public static ULongIntB NSquareMod(ULongIntB a, uint n, ULongIntB m) { ULongIntB res = a % m; for (int i = 0; i < n; ++i) res = LongMath.Sqr(res) % m; return res; }
/// <summary> /// Calculates binary logarithm of input number /// </summary> /// <param name="a">Input number</param> /// <returns>Binary logarithm</returns> public static uint Log2(ULongIntB a) { if (a.Size <= 0) return 0; int temp = a[a.Size - 1]; int bitsCount = 0; while (temp != 0) { ++bitsCount; temp >>= 1; } return (uint)(bitsCount + (a.Size - 1)*LIntConstant.BitsPerDigit - 1); }
public static ULongIntB ExpMod5(ULongIntB a, ULongIntB n, ULongIntB m) { if (a == 0) return (ULongIntB)0; if (a == 1) return (ULongIntB)1; if (n == 0) return (ULongIntB)1; if (m == 1) return (ULongIntB)0; int k = 5; int M = (1 << k); ULongIntB[] mods = new ULongIntB[(M >> 1) + 1]; ULongIntB tempSquare = SquareMod(a, m); mods[0] = a % m; // generate table of numbers [ (a ^ k) mod m, where k == (2*j + 1) ] int index = 1; int i = 3; while (i <= M - 1) { mods[index] = (mods[index - 1] * tempSquare) % m; ++index; i += 2; } int bitsCount = LIntConstant.BitsPerDigit; int log = (int)Log2((ULongIntB)n) + 1; // length of power in 2^k number system int N = log / k; if ((log % k) != 0) ++N; i = N - 1; int s = (k*i) / bitsCount; int d = (k*i) % bitsCount; int eN = (((int)n[s] | ((int)n[s + 1] << bitsCount)) >> d) & (M - 1); int t, u; ULongIntB p = null; if (eN == 0) p = (ULongIntB)1; else { LongIntHelper.TwoFact(eN, out t, out u); index = ((u - 1) / 2); p = new ULongIntB(mods[index]); p = NSquareMod(p, (uint)t, m); } i = N - 2; while (i >= 0) { s = (k*i) / bitsCount; d = (k*i) % bitsCount; int e = (((int)n[s] | ((int)n[s + 1] << bitsCount)) >> d) & (M - 1); if (e == 0) p = NSquareMod(p, (uint)k, m); else { LongIntHelper.TwoFact(e, out t, out u); p = NSquareMod(p, (uint)(k - t), m); index = ((u - 1) / 2); p = (p * mods[index]) % m; p = NSquareMod(p, (uint)t, m); } --i; } return p; }
/// <summary> /// Calculates A*A /// </summary> /// <param name="A">Long Number</param> /// <returns>Long number that is result of self-product of A</returns> public static ULongIntB Sqr(ULongIntB A) { return new ULongIntB(LongMath.InnerSqr(A), ConstructorMode.Assign); }
public static ULongIntB Exp(ULongIntB A, ulong n) { return new ULongIntB(InnerPower(A, n), ConstructorMode.Assign); }
public static void Divide(ULongIntB A, ULongIntB B, out ULongIntB Q, out ULongIntB R) { LongIntBase QNumber = new LongIntBase(A.Base); LongIntBase RNumber = new LongIntBase(B.Base); LongMath.Divide(A, B, out QNumber, out RNumber, true, true); Q = new ULongIntB(QNumber, ConstructorMode.Assign); R = new ULongIntB(RNumber, ConstructorMode.Assign); }