// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) bool ProbablePrimeChainTestFast(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams) { const unsigned int nBits = testParams.nBits; const unsigned int nCandidateType = testParams.nCandidateType; mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; unsigned int& nChainLength = testParams.nChainLength; nChainLength = 0; // Test for Cunningham Chain of first kind if (nCandidateType == 0) { mpzOriginMinusOne = mpzPrimeChainOrigin - 1; ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, nChainLength, testParams); } else if (nCandidateType == 1) { // Test for Cunningham Chain of second kind mpzOriginPlusOne = mpzPrimeChainOrigin + 1; ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, nChainLength, testParams); } else if (nCandidateType == 2) { ProbableBiTwinChainTestFast(mpzPrimeChainOrigin, nChainLength, testParams); } return (nChainLength >= nBits); }
// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) bool ProbablePrimeChainTestFast2(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams, uint32 sieveFlags, uint32 multiplier) { const unsigned int nBits = testParams.nBits; unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1; unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2; unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin; const bool fFermatTest = testParams.fFermatTest; mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; nChainLengthCunningham1 = 0; nChainLengthCunningham2 = 0; nChainLengthBiTwin = 0; bool testCFirstKind = ((sieveFlags&SIEVE_FLAG_BT_COMPOSITE)!=0) || ((sieveFlags&SIEVE_FLAG_C2_COMPOSITE)!=0); // yes, C1 and C2 is switched bool testCSecondKind = ((sieveFlags&SIEVE_FLAG_BT_COMPOSITE)!=0) || ((sieveFlags&SIEVE_FLAG_C1_COMPOSITE)!=0); // Test for Cunningham Chain of first kind mpzOriginMinusOne = mpzPrimeChainOrigin - 1; if( testCFirstKind ) ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, fFermatTest, nChainLengthCunningham1, testParams); else nChainLengthCunningham1 = 0; // Test for Cunningham Chain of second kind mpzOriginPlusOne = mpzPrimeChainOrigin + 1; if( testCSecondKind ) ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, fFermatTest, nChainLengthCunningham2, testParams); else nChainLengthCunningham2 = 0; //// do we need to flag some bits as composite to avoid redundant chain checks? //uint32 redundancyCheckLength = min(nChainLengthCunningham1, nChainLengthCunningham2); //redundancyCheckLength >>= 24; //if( redundancyCheckLength >= 2 ) //{ // printf("."); // uint32 mask = 1<<(multiplier&7); // uint32 maskIdx = multiplier>>3; // for(uint32 r=0; r<redundancyCheckLength; r++) // { // uint8* maskC1 = cSieve->layerMaskC1+((cSieve->currentSieveLayerIdx+r)%cSieve->chainLength)*cSieve->maskBytes; // uint8* maskC2 = cSieve->layerMaskC1+((cSieve->currentSieveLayerIdx+r)%cSieve->chainLength)*cSieve->maskBytes; // maskC1[maskIdx] |= mask; // maskC2[maskIdx] |= mask; // } //} // verify if there is any chance to find a biTwin that worth calculation if (nChainLengthCunningham1 < 0x2000000 || nChainLengthCunningham2 < 0x2000000) return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits); // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain nChainLengthBiTwin = (TargetGetLength(nChainLengthCunningham1) > TargetGetLength(nChainLengthCunningham2))? (nChainLengthCunningham2 + TargetFromInt(TargetGetLength(nChainLengthCunningham2)+1)) : (nChainLengthCunningham1 + TargetFromInt(TargetGetLength(nChainLengthCunningham1))); return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits || nChainLengthBiTwin >= nBits); }
// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) bool ProbablePrimeChainTestFast(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams) { const unsigned int nBits = testParams.bits; const unsigned int nCandidateType = testParams.candidateType; unsigned int& nChainLength = testParams.chainLength; mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; nChainLength = 0; // Test for Cunningham Chain of first kind if (nCandidateType == PRIME_CHAIN_CUNNINGHAM1) { mpzOriginMinusOne = mpzPrimeChainOrigin - 1; ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, false, nChainLength, testParams); } else if (nCandidateType == PRIME_CHAIN_CUNNINGHAM2) { // Test for Cunningham Chain of second kind mpzOriginPlusOne = mpzPrimeChainOrigin + 1; ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, false, nChainLength, testParams); } else { unsigned int nChainLengthCunningham1 = 0; unsigned int nChainLengthCunningham2 = 0; mpzOriginMinusOne = mpzPrimeChainOrigin - 1; if (ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, false, nChainLengthCunningham1, testParams)) { mpzOriginPlusOne = mpzPrimeChainOrigin + 1; ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, false, nChainLengthCunningham2, testParams); // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain nChainLength = (chainLengthFromBits(nChainLengthCunningham1) > chainLengthFromBits(nChainLengthCunningham2))? (nChainLengthCunningham2 + bitsFromChainLengthWithoutFractional(chainLengthFromBits(nChainLengthCunningham2)+1)) : (nChainLengthCunningham1 + bitsFromChainLengthWithoutFractional(chainLengthFromBits(nChainLengthCunningham1))); } } return (nChainLength >= nBits); }
// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) bool ProbablePrimeChainTestFast2(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams, uint32 sieveFlags, uint32 multiplier) { const unsigned int nBits = testParams.nBits; unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1; unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2; unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin; const bool fFermatTest = testParams.fFermatTest; mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; nChainLengthCunningham1 = 0; nChainLengthCunningham2 = 0; nChainLengthBiTwin = 0; //sieveFlags = 0; // note: enabling the sieve optimization seems to decrease the rate of shares (remove this line to enable this future for non-gpu mode) bool testCFirstKind = ((sieveFlags&SIEVE_FLAG_BT_COMPOSITE)==0) || ((sieveFlags&SIEVE_FLAG_C1_COMPOSITE)==0); // yes, C1 and C2 are switched bool testCSecondKind = ((sieveFlags&SIEVE_FLAG_BT_COMPOSITE)==0) || ((sieveFlags&SIEVE_FLAG_C2_COMPOSITE)==0); bool testCFirstFast = (sieveFlags&SIEVE_FLAG_C1_COMPOSITE)!=0; // should be !=0? bool testCSecondFast = (sieveFlags&SIEVE_FLAG_C2_COMPOSITE)!=0; mpzOriginMinusOne = mpzPrimeChainOrigin - 1; // first kind origin mpzOriginPlusOne = mpzPrimeChainOrigin + 1; // second kind origin // detailed test //if( testCFirstKind && testCFirstFast == true ) //(sieveFlags&SIEVE_FLAG_C1_COMPOSITE)==0 ) //{ // for(uint32 i=0; i<5000; i++) // { // if( mpz_tdiv_ui(mpzOriginMinusOne.get_mpz_t(), vPrimes[i]) == 0 ) // __debugbreak(); // } //} //if( testCSecondKind && testCSecondFast == true )//(sieveFlags&SIEVE_FLAG_C2_COMPOSITE)==0 ) //{ // for(uint32 i=0; i<5000; i++) // { // if( mpz_tdiv_ui(mpzOriginPlusOne.get_mpz_t(), vPrimes[i]) == 0 ) // __debugbreak(); // } //} //printf("%d\n", fFermatTest?1:0); // Test for Cunningham Chain of first kind if( testCFirstKind ) { ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, fFermatTest, nChainLengthCunningham1, testParams, testCFirstFast); //if( nChainLengthCunningham1 >= 0x04000000 ) //{ // //__debugbreak(); // mpz_class mpz_r; // mpz_class mpz_n1 = mpzPrimeChainOrigin - 1; // mpz_class mpz_n2 = mpzPrimeChainOrigin*2 - 1; // mpz_class mpz_n3 = mpzPrimeChainOrigin*4 - 1; // mpz_class mpz_n4 = mpzPrimeChainOrigin*8 - 1; // mpz_class mpz_e = mpz_n3 - 1; // mpz_class mpz_m = mpz_n1 * mpz_n2 * mpz_n3 * mpz_n4; // mpz_powm(mpz_r.get_mpz_t(), mpzTwo.get_mpz_t(), mpz_e.get_mpz_t(), mpz_m.get_mpz_t()); // bool isPrime = (mpz_r.get_mpz_t()->_mp_d[0]&0xFF)==0xFF; // printf("%08X isPrime: %s D: %016X\n", nChainLengthCunningham1, isPrime?"yes":"no", mpz_r.get_mpz_t()->_mp_d[0]); // if( isPrime == false ) // __debugbreak(); // //__debugbreak(); //} } else nChainLengthCunningham1 = 0; // Test for Cunningham Chain of second kind if( testCSecondKind ) ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, fFermatTest, nChainLengthCunningham2, testParams, testCSecondFast); else nChainLengthCunningham2 = 0; //// do we need to flag some bits as composite to avoid redundant chain checks? //uint32 redundancyCheckLength = min(nChainLengthCunningham1, nChainLengthCunningham2); //redundancyCheckLength >>= 24; //if( redundancyCheckLength >= 2 ) //{ // printf("."); // uint32 mask = 1<<(multiplier&7); // uint32 maskIdx = multiplier>>3; // for(uint32 r=0; r<redundancyCheckLength; r++) // { // uint8* maskC1 = cSieve->layerMaskC1+((cSieve->currentSieveLayerIdx+r)%cSieve->chainLength)*cSieve->maskBytes; // uint8* maskC2 = cSieve->layerMaskC1+((cSieve->currentSieveLayerIdx+r)%cSieve->chainLength)*cSieve->maskBytes; // maskC1[maskIdx] |= mask; // maskC2[maskIdx] |= mask; // } //} // verify if there is any chance to find a biTwin that worth calculation if (nChainLengthCunningham1 < 0x2000000 || nChainLengthCunningham2 < 0x2000000) return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits); // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain nChainLengthBiTwin = (TargetGetLength(nChainLengthCunningham1) > TargetGetLength(nChainLengthCunningham2))? (nChainLengthCunningham2 + TargetFromInt(TargetGetLength(nChainLengthCunningham2)+1)) : (nChainLengthCunningham1 + TargetFromInt(TargetGetLength(nChainLengthCunningham1))); return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits || nChainLengthBiTwin >= nBits); }
// Test probable prime chain for: nOrigin // Return value: // true - Probable prime chain found (one of nChainLength meeting target) // false - prime chain too short (none of nChainLength meeting target) static bool ProbablePrimeChainTestFast(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams, uint sievenumber, bool use_gpu_fermat_test) { const unsigned int nBits = testParams.nBits; const unsigned int nBits_masked = nBits&TARGET_LENGTH_MASK; unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1; unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2; unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin; const bool fFermatTest = testParams.fFermatTest; mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne; mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne; nChainLengthCunningham1 = 0; nChainLengthCunningham2 = 0; nChainLengthBiTwin = 0; // Test for Cunningham Chain of first kind if (sievenumber&1) { mpzOriginMinusOne = mpzPrimeChainOrigin - 1; ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, fFermatTest, nChainLengthCunningham1, testParams, use_gpu_fermat_test); if ((nChainLengthCunningham1&TARGET_FRACTIONAL_MASK) == 0) nChainLengthCunningham1 |= TARGET_FRACTIONAL_MASK; } // Test for Cunningham Chain of second kind if (sievenumber&2) { mpzOriginPlusOne = mpzPrimeChainOrigin + 1; ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, fFermatTest, nChainLengthCunningham2, testParams, use_gpu_fermat_test); if ((nChainLengthCunningham2&TARGET_FRACTIONAL_MASK) == 0) nChainLengthCunningham2 |= TARGET_FRACTIONAL_MASK; } // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain nChainLengthBiTwin = (TargetGetLength(nChainLengthCunningham1) > TargetGetLength(nChainLengthCunningham2))? (nChainLengthCunningham2 + TargetFromInt(TargetGetLength(nChainLengthCunningham2)+1)) : (nChainLengthCunningham1 + TargetFromInt(TargetGetLength(nChainLengthCunningham1))); uint c1 = TargetGetLength(nChainLengthCunningham1); uint c2 = TargetGetLength(nChainLengthCunningham2); uint tw = TargetGetLength(nChainLengthBiTwin); if (c1 >= 6) { cout << "C1 " << nChainLengthCunningham1 << " --> " << TargetToString(nChainLengthCunningham1) << " found!" << endl; } if (c2 >= 6) { cout << "C2 " << nChainLengthCunningham2 << " --> " << TargetToString(nChainLengthCunningham2) << " found!" << endl; } if (tw >= 6) { cout << "TW " << nChainLengthBiTwin << " --> " << TargetToString(nChainLengthBiTwin) << " found!" << endl; } ++chainspersec[c1]; ++chainspersec[c2]; ++chainspersec[tw]; ++totalpersec; return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits || nChainLengthBiTwin >= nBits); }