private ulong Rho(ulong n, ulong xInit, ulong c, IReducer <ulong> reducer) { if ((n & 1) == 0) { return(2); } var x = reducer.ToResidue(xInit); var y = x.Copy(); var ys = x.Copy(); var r = 1; var m = batchSize; var cPrime = reducer.ToResidue(c); var one = reducer.ToResidue(1); var diff = one.Copy(); var q = one.Copy(); var g = (ulong)1; do { x.Set(y); for (int i = 0; i < r; i++) { AdvanceF(y, cPrime); } var k = 0; while (k < r && g == 1) { ys.Set(y); var limit = Math.Min(m, r - k); q.Set(one); for (int i = 0; i < limit; i++) { AdvanceF(y, cPrime); q.Multiply(diff.Set(x).Subtract(y)); } g = IntegerMath.GreatestCommonDivisor(q.Value, n); k += limit; } r <<= 1; }while (g == 1); if (g.CompareTo(n) == 0) { // Backtrack. do { AdvanceF(ys, cPrime); g = IntegerMath.GreatestCommonDivisor(diff.Set(x).Subtract(ys).Value, n); }while (g == 1); } if (g.CompareTo(n) == 0) { return(0); } return(g); }
private long Rho(long n, long xInit, long c) { if ((n & 1) == 0) { return(2); } var x = xInit; var y = xInit; var ys = y; var r = 1; var m = batchSize; var g = (long)1; do { x = y; for (int i = 0; i < r; i++) { y = F(y, c, n); } var k = 0; while (k < r && g == 1) { ys = y; var limit = Math.Min(m, r - k); var q = (long)1; for (int i = 0; i < limit; i++) { y = F(y, c, n); q = IntegerMath.ModularProduct(q, x - y, n); } g = IntegerMath.GreatestCommonDivisor(q, n); k += limit; } r <<= 1; }while (g == 1); if (g == n) { do { ys = F(ys, c, n); g = IntegerMath.GreatestCommonDivisor(x - ys, n); }while (g == 1); } return(g); }
public MertensFunctionWheel64(int threads) { this.threads = threads; wheelSubtotal = new int[wheelSize]; wheelInclude = new bool[wheelSize >> 1]; wheelNext = new int[wheelSize >> 1]; var total = 0; var first = -1; for (var i = 0; i < wheelSize; i++) { var include = IntegerMath.GreatestCommonDivisor(i, wheelSize) == 1; if (include) { if (first == -1) { first = i; } ++total; } wheelSubtotal[i] = total; wheelInclude[i >> 1] = include; } Debug.Assert(total == wheelCount); var next = first - 1; for (var i = (wheelSize >> 1) - 1; i >= 0; i--) { next += 2; wheelNext[i] = next; if (wheelInclude[i]) { next = 0; } } }
public override Rational GreatestCommonDivisor(Rational a, Rational b) { return(IntegerMath.GreatestCommonDivisor((BigInteger)a, (BigInteger)b)); }
public override uint GreatestCommonDivisor(uint a, uint b) { return(IntegerMath.GreatestCommonDivisor(a, b)); }
public MertensFunctionWheel(int threads) { this.threads = threads; wheelSubtotal = new int[wheelSize]; wheelInclude = new bool[wheelSize >> 1]; wheelNext = new byte[wheelSize >> 1]; wheelPrev = new byte[wheelSize >> 1]; var total = 0; for (var i = 0; i < wheelSize; i++) { var include = IntegerMath.GreatestCommonDivisor(i, wheelSize) == 1; if (include) { ++total; } wheelSubtotal[i] = total; wheelInclude[i >> 1] = include; } Debug.Assert(total == wheelCount); var next = 0; for (var i = (wheelSize >> 1) - 1; i >= 0; i--) { next += 2; wheelNext[i] = (byte)next; if (wheelInclude[i]) { next = 0; } } var prev = 0; for (var i = 0; i < (wheelSize >> 1); i++) { prev += 2; wheelPrev[i] = (byte)prev; if (wheelInclude[i]) { prev = 0; } } #if DEBUG for (var i = 1; i < wheelSize; i += 2) { var skip = wheelNext[i >> 1]; for (var j = 2; j < skip; j += 2) { if (wheelInclude[((i + j) % wheelSize) >> 1]) { Debugger.Break(); } } if (!wheelInclude[((i + skip) % wheelSize) >> 1]) { Debugger.Break(); } } for (var i = 1; i < wheelSize; i += 2) { var skip = wheelPrev[i >> 1]; for (var j = 2; j < skip; j += 2) { if (wheelInclude[((i - j + wheelSize) % wheelSize) >> 1]) { Debugger.Break(); } } if (!wheelInclude[((i - skip + wheelSize) % wheelSize) >> 1]) { Debugger.Break(); } } #endif wheelFactors = IntegerMath.Factors(wheelSize).ToArray(); wheelMobius = wheelFactors.Select(factor => IntegerMath.Mobius(factor)).ToArray(); }
/*-----------------------------------------------------------------------*/ uint squfof_one_cycle(squfof_data_t data, uint mult_idx, uint num_iter, out uint factor) { /* Perform one unit of work for SQUFOF with one multiplier */ uint sqrtn = data.sqrtn[mult_idx]; uint cutoff = data.cutoff[mult_idx]; uint num_saved = data.num_saved[mult_idx]; uint multiplier = 2 * multipliers[mult_idx]; uint coarse_cutoff = cutoff * multiplier; ushort[] saved = data.saved[mult_idx]; uint q0 = data.q0[mult_idx]; uint p1 = data.p1[mult_idx]; uint q1 = data.q1[mult_idx]; uint i, j; uint p0 = 0; uint sqrtq = 0; ulong scaledn; factor = 0; for (i = 0; i < num_iter; i++) { uint q, bits, tmp; /* compute (sqrtn+p1)/q1; since this is unity * more than half the time, special case the * division to save some effort */ tmp = sqrtn + p1 - q1; q = 1; if (tmp >= q1) { q += tmp / q1; } /* compute the next numerator and denominator */ p0 = q * q1 - p1; q0 = q0 + (p1 - p0) * q; /* In order to avoid trivial factorizations, * save q1 values that are small in a list. Only * values that do not contain factors of the * multiplier must be saved; however, the GCD * is 5x more expensive than all the rest of the * work performed in the loop. To avoid most GCDs, * only attempt one if q1 is less than the cutoff * times the full multiplier * * If the queue overflows (very rare), signal that * this multiplier failed and move on to another one */ if (q1 < coarse_cutoff) { tmp = q1 / IntegerMath.GreatestCommonDivisor(q1, multiplier); if (tmp < cutoff) { if (num_saved >= QSIZE) { data.failed[mult_idx] = true; return(i); } saved[num_saved++] = (ushort)tmp; } } /* if q0 is a perfect square, then the factorization * has probably succeeded. Most of the squareness * tests out there require multiple divisions and * complicated loops. We can approximate these tests * by doing two things: testing that the number of * trailing zeros in q0 is even, and then testing * if q0 shifted right this many places is 1 mod 8. */ bits = 0; tmp = q0; while ((tmp & 1) == 0) { bits++; tmp >>= 1; } if ((bits & 1) == 0 && ((tmp & 7) == 1)) { /* q0 is probably a perfect square. Take the * square root by cheating */ sqrtq = (uint)(Math.Sqrt((double)q0)); if (sqrtq * sqrtq == q0) { /* it *is* a perfect square. If it has * not appeared previously in the list * for this multiplier, then we're almost * finished */ for (j = 0; j < num_saved; j++) { if (saved[j] == sqrtq) { break; } } if (j == num_saved) { break; } } } /* perform the odd half of the SQUFOF cycle */ tmp = sqrtn + p0 - q0; q = 1; if (tmp >= q0) { q += tmp / q0; } p1 = q * q0 - p0; q1 = q1 + (p0 - p1) * q; if (q0 < coarse_cutoff) { tmp = q0 / IntegerMath.GreatestCommonDivisor(q0, multiplier); if (tmp < cutoff) { if (num_saved >= QSIZE) { data.failed[mult_idx] = true; return(i); } saved[num_saved++] = (ushort)tmp; } } } if (sqrtq == 1) { /* the above found a trivial factor, so this * multiplier has failed */ data.failed[mult_idx] = true; return(i); } else if (i == num_iter) { /* no square root found; save the parameters * and go on to the next multiplier */ data.q0[mult_idx] = q0; data.p1[mult_idx] = p1; data.q1[mult_idx] = q1; data.num_saved[mult_idx] = num_saved; return(i); } /* square root found; the algorithm cannot fail now. * Compute the inverse quadratic form and iterate */ q0 = sqrtq; p1 = p0 + sqrtq * ((sqrtn - p0) / sqrtq); scaledn = data.n * (ulong)multipliers[mult_idx]; q1 = (uint)((scaledn - (ulong)p1 * (ulong)p1) / (ulong)q0); while (true) { uint q, tmp; tmp = sqrtn + p1 - q1; q = 1; if (tmp >= q1) { q += tmp / q1; } p0 = q * q1 - p1; q0 = q0 + (p1 - p0) * q; if (p0 == p1) { q0 = q1; break; } tmp = sqrtn + p0 - q0; q = 1; if (tmp >= q0) { q += tmp / q0; } p1 = q * q0 - p0; q1 = q1 + (p0 - p1) * q; if (p0 == p1) { break; } } /* q0 is the factor of n. Remove factors that exist * in the multiplier and save whatever's left */ q0 = q0 / IntegerMath.GreatestCommonDivisor(q0, multiplier); factor = q0; return(i); }
public override ulong GreatestCommonDivisor(ulong a, ulong b) { return(IntegerMath.GreatestCommonDivisor(a, b)); }
public override double GreatestCommonDivisor(double a, double b) { return((double)IntegerMath.GreatestCommonDivisor(ToBigInteger(a), ToBigInteger(b))); }
public override Complex GreatestCommonDivisor(Complex a, Complex b) { return((Complex)IntegerMath.GreatestCommonDivisor(ToBigInteger(a), ToBigInteger(b))); }
public override BigInteger GreatestCommonDivisor(BigInteger a, BigInteger b) { return(IntegerMath.GreatestCommonDivisor(a, b)); }