// 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); }
// stP is inclusive and prime; endP is exclusive static void* CalculationThread(void *context) { PCALC_THREAD_CONTEXT tcontext = (PCALC_THREAD_CONTEXT)context; unsigned long P, setBits; unsigned int primality; char *primeStr; setBits = 0; for (;;) { // Reserve the next prime P value for us to test P = GetNextPrimeP(); // Print a message to the terminal PRINT_MSG(MSG_VERBOSE, "Thread %d: Testing P=%lu", tcontext->threadIndex, P); // Only set bits that weren't set before while (setBits < P) { mpz_setbit(tcontext->nextPrime, setBits); setBits++; } // Check the result for primality primality = mpz_probab_prime_p(tcontext->nextPrime, DIVISIONS_FOR_PRIMALITY); switch (primality) { case GMP_DEF_COMPOSITE: // Composite number is composite break; case GMP_PROB_PRIME: // Probably prime, but we need to check for sure if (PrimeTest(P, &tcontext->nextPrime) != GMP_DEF_PRIME) { // More extensive test showed it was composite break; } // Else fall through to prime case case GMP_DEF_PRIME: // Definitely prime primeStr = mpz_get_str(NULL, 10, tcontext->nextPrime); if (primeStr) { PRINT_MSG(MSG_INFO, "Thread %d --- Mersenne prime found (P=%lu): %s", tcontext->threadIndex, P, primeStr); GmpFree(primeStr, strlen(primeStr)+1); } else { PRINT_MSG(MSG_WARNING, "Unable to allocate memory to output prime!"); } break; } } // Unreachable code return NULL; }