// Test Probable BiTwin Chain for: mpzOrigin // Test the numbers in the optimal order for any given chain length // Gives the correct length of a BiTwin chain even for short chains static void ProbableBiTwinChainTestFast(const mpz_class& mpzOrigin, unsigned int& nProbableChainLength, CPrimalityTestParams& testParams) { mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; nProbableChainLength = 0; // Fermat test for origin-1 first mpzOriginMinusOne = mpzOrigin - 1; if (!FermatProbablePrimalityTestFast(mpzOriginMinusOne, nProbableChainLength, testParams, true)) return; TargetIncrementLength(nProbableChainLength); // Fermat test for origin+1 mpzOriginPlusOne = mpzOrigin + 1; if (!FermatProbablePrimalityTestFast(mpzOriginPlusOne, nProbableChainLength, testParams, true)) return; TargetIncrementLength(nProbableChainLength); // Euler-Lagrange-Lifchitz test for the following numbers in chain for (unsigned int nChainSeq = 2; true; nChainSeq += 2) { mpzOriginMinusOne <<= 1; mpzOriginMinusOne++; bool fFastFail = nChainSeq < 4; if (!EulerLagrangeLifchitzPrimalityTestFast(mpzOriginMinusOne, true, nProbableChainLength, testParams, fFastFail)) break; TargetIncrementLength(nProbableChainLength); mpzOriginPlusOne <<= 1; mpzOriginPlusOne--; if (!EulerLagrangeLifchitzPrimalityTestFast(mpzOriginPlusOne, false, nProbableChainLength, testParams, fFastFail)) break; TargetIncrementLength(nProbableChainLength); } }
// Test Probable Cunningham Chain for: n // fSophieGermain: // true - Test for Cunningham Chain of first kind (n, 2n+1, 4n+3, ...) // false - Test for Cunningham Chain of second kind (n, 2n-1, 4n-3, ...) // Return value: // true - Probable Cunningham Chain found (length at least 2) // false - Not Cunningham Chain static bool ProbableCunninghamChainTestFast(const mpz_class& n, bool fSophieGermain, bool fFermatTest, unsigned int& nProbableChainLength, CPrimalityTestParams& testParams, bool use_gpu_fermat_test) { nProbableChainLength = 0; mpz_class &N = testParams.N; N = n; if (!use_gpu_fermat_test && !FermatProbablePrimalityTestFast(N, nProbableChainLength, testParams, true)) { return false; } // Euler-Lagrange-Lifchitz test for the following numbers in chain while (true) { TargetIncrementLength(nProbableChainLength); N = N + N + (fSophieGermain? 1 : (-1)); if (fFermatTest) { if (!FermatProbablePrimalityTestFast(N, nProbableChainLength, testParams, true)) break; } else { if (!EulerLagrangeLifchitzPrimalityTestFast(N, fSophieGermain, nProbableChainLength, testParams, true)) break; } } return (TargetGetLength(nProbableChainLength) >= 2); }
// Test Probable Cunningham Chain for: n // fSophieGermain: // true - Test for Cunningham Chain of first kind (n, 2n+1, 4n+3, ...) // false - Test for Cunningham Chain of second kind (n, 2n-1, 4n-3, ...) // Return value: // true - Probable Cunningham Chain found (length at least 2) // false - Not Cunningham Chain static bool CunnChainTest(mpz_t *n, bool fSophieGermain, bool fFermatTest, unsigned int *pnProbableChainLength) { *pnProbableChainLength = 0; mpz_t N; mpz_init_set(N, *n); // Fermat test for n first if (!PrimeTest(&N, pnProbableChainLength)) { mpz_clear(N); return false; } // Euler-Lagrange-Lifchitz test for the following numbers in chain while (true) { TargetIncrementLength(pnProbableChainLength); mpz_add(N, N, N); if (fSophieGermain) mpz_add_ui(N, N, 1); else mpz_sub_ui(N, N, 1); //disabled, see SpecialPrimeTest() comments for further information /*if (fFermatTest) { if (!PrimeTest(&N, pnProbableChainLength)) break; } else { if (!SpecialPrimeTest(&N, fSophieGermain, pnProbableChainLength)) break; }*/ if (!PrimeTest(&N, pnProbableChainLength)) break; } mpz_clear(N); #ifdef SUPERDEBUG printf("PCCT => %u (%u)\n", TargetGetLength(*pnProbableChainLength), *pnProbableChainLength); #endif return (TargetGetLength(*pnProbableChainLength) >= 2); }
// Test Probable Cunningham Chain for: n // fSophieGermain: // true - Test for Cunningham Chain of first kind (n, 2n+1, 4n+3, ...) // false - Test for Cunningham Chain of second kind (n, 2n-1, 4n-3, ...) static void ProbableCunninghamChainTestFast(const mpz_class& n, bool fSophieGermain, unsigned int& nProbableChainLength, CPrimalityTestParams& testParams) { nProbableChainLength = 0; // Fermat test for n first if (!FermatProbablePrimalityTestFast(n, nProbableChainLength, testParams, true)) return; // Euler-Lagrange-Lifchitz test for the following numbers in chain mpz_class &N = testParams.mpzN; N = n; for (unsigned int nChainSeq = 1; true; nChainSeq++) { TargetIncrementLength(nProbableChainLength); N <<= 1; N += (fSophieGermain? 1 : (-1)); bool fFastFail = nChainSeq < 4; if (!EulerLagrangeLifchitzPrimalityTestFast(N, fSophieGermain, nProbableChainLength, testParams, fFastFail)) break; } }