// 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) static bool AllChainTest(mpz_t *bnPrimeChainOrigin, unsigned int nBits, bool fFermatTest, unsigned int *pnChainLengthCunningham1, unsigned int *pnChainLengthCunningham2, unsigned int *pnChainLengthBiTwin, unsigned int sievenumber) { *pnChainLengthCunningham1 = 0; *pnChainLengthCunningham2 = 0; *pnChainLengthBiTwin = 0; mpz_t mp; mpz_init(mp); // Test for Cunningham Chain of first kind if (sievenumber&1) { mpz_sub_ui(mp, *bnPrimeChainOrigin, 1); CunnChainTest(&mp, true, fFermatTest, pnChainLengthCunningham1); } // Test for Cunningham Chain of second kind if (sievenumber&2) { mpz_add_ui(mp, *bnPrimeChainOrigin, 1); CunnChainTest(&mp, false, fFermatTest, pnChainLengthCunningham2); } mpz_clear(mp); // Figure out BiTwin Chain length // BiTwin Chain allows a single prime at the end for odd length chain *pnChainLengthBiTwin = (TargetGetLength(*pnChainLengthCunningham1) > TargetGetLength(*pnChainLengthCunningham2)) ? (*pnChainLengthCunningham2 + TargetFromInt(TargetGetLength(*pnChainLengthCunningham2)+1)) : (*pnChainLengthCunningham1 + TargetFromInt(TargetGetLength(*pnChainLengthCunningham1))); return (*pnChainLengthCunningham1 >= nBits || *pnChainLengthCunningham2 >= nBits || *pnChainLengthBiTwin >= 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); }