void cSieve_prepare(mpz_class& mpzFixedMultiplier, uint32 chainLength) { uint32 sieveSize = (nMaxSieveSize+7)&~7; // align to 8 // todo: Make sure the sieve doesnt crash when the difficulty changes if( cSieve == NULL || cSieve->chainLength != chainLength ) { if( cSieve == NULL ) { cSieve = (continuousSieve_t*)malloc(sizeof(continuousSieve_t)); memset(cSieve, 0x00, sizeof(continuousSieve_t)); } // free bitmasks if the size changed if( cSieve->chainLength != chainLength ) { if( cSieve->layerMaskC1 ) { free(cSieve->layerMaskC1); free(cSieve->layerMaskC2); //free(cSieve->layerMaskBT); cSieve->layerMaskC1 = NULL; cSieve->layerMaskC2 = NULL; //cSieve->layerMaskBT = NULL; } } // alloc sieve mask cSieve->sieveSize = sieveSize; cSieve->chainLength = chainLength; cSieve->maskBytes = (sieveSize+7)/8; uint32 chainMaskSize = cSieve->maskBytes * chainLength; if( cSieve->layerMaskC1 == NULL ) { cSieve->layerMaskC1 = (uint8*)malloc(chainMaskSize); cSieve->layerMaskC2 = (uint8*)malloc(chainMaskSize); //cSieve->layerMaskBT = (uint8*)malloc(chainMaskSize); } // reset sieve memset(cSieve->layerMaskC1, 0x00, chainMaskSize); memset(cSieve->layerMaskC2, 0x00, chainMaskSize); //memset(cSieve->layerMaskBT, 0x00, chainMaskSize); } // alloc prime factor base table if( cSieve->primeFactorBase == NULL ) { unsigned int nPrimes = 0; if( nSievePercentage <= 100 ) nPrimes = (uint64)vPrimes.size() * (uint64)nSievePercentage / 100ULL; else nPrimes = vPrimes.size(); // use the whole array to avoid rounding problems and out-of-bounds access cSieve->numPrimeFactors = nPrimes;//50000; cSieve->primeFactorBase = (cPrimeFactor_t*)malloc(sizeof(cPrimeFactor_t)*cSieve->numPrimeFactors); for(uint32 i=0; i<cSieve->numPrimeFactors; i++) { cSieve->primeFactorBase[i].twoInverse = single_modinv(2, vPrimes[i]); } } // calculate fixed inverse mpz_class mpzF, mpzTemp; for(uint32 i=0; i<cSieve->numPrimeFactors; i++) { uint32 p = vPrimes[i]; uint32 fixedFactorMod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzFixedMultiplier.get_mpz_t(), p); cSieve->primeFactorBase[i].mod = fixedFactorMod; cSieve->primeFactorBase[i].base = single_modinv(fixedFactorMod, p); } // do sieving for the first nChainLength layers //for(uint32 t=0; t<cSieve->chainLength; t++) //for(uint32 t=0; t<cSieve->chainLength; t++) cSieve->mpzFixedMultiplier = mpzFixedMultiplier; for(uint32 t=0; t<cSieve->chainLength; t++) { mpzF = mpzFixedMultiplier; uint8* maskC1 = cSieve->layerMaskC1+t*cSieve->maskBytes; uint8* maskC2 = cSieve->layerMaskC2+t*cSieve->maskBytes; for(uint32 i=0; i<cSieve->numPrimeFactors; i++) { if( cSieve->primeFactorBase[i].mod == 0 ) continue; uint32 p = vPrimes[i]; /*uint32 fixedFactorMod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzF.get_mpz_t(), p); uint32 fixedInverseU32 = single_modinv(fixedFactorMod, p); *///uint32 fixedInverseTwo = single_modinv(2, p); // mark all cunningham chains of first kind uint32 nSolvedMultiplier = cSieve->primeFactorBase[i].base; while( nSolvedMultiplier < cSieve->sieveSize ) { maskC1[nSolvedMultiplier>>3] |= (1<<(nSolvedMultiplier&7)); nSolvedMultiplier += p; } // mark all cunningham chains of second kind uint64 nSolvedMultiplier64 = (uint64)cSieve->primeFactorBase[i].base * (uint64)(p-1); // tested and correct nSolvedMultiplier64 %= (uint64)p; nSolvedMultiplier = (uint32)nSolvedMultiplier64; while( nSolvedMultiplier < cSieve->sieveSize ) { maskC2[nSolvedMultiplier>>3] |= (1<<(nSolvedMultiplier&7)); nSolvedMultiplier += p; } // apply *2 factor to prime base //cSieve->primeFactorBase[i].base = (cSieve->primeFactorBase[i].base*cSieve->primeFactorBase[i].twoInverse)%p; cSieve->primeFactorBase[i].base = (uint32)(((uint64)cSieve->primeFactorBase[i].base*(uint64)cSieve->primeFactorBase[i].twoInverse)%(uint64)p); } } // reset multiplier scan cSieve->currentSieveLayerIdx = 0; cSieve->currentMultiplierScanIndex = 1; }
void cSieve_prepare(mpz_class& mpzFixedMultiplier, uint32 chainLength, uint32 overwritePrimeFactors=0, uint32 overwriteSieveSize=0) { uint32 sieveSize = (minerSettings.nSieveSize+31)&~31; // align to 32 (4 bytes) if( overwriteSieveSize ) sieveSize = (overwriteSieveSize+31)&~31; // todo: Make sure the sieve doesnt crash when the difficulty changes if( cSieve == NULL || cSieve->chainLength != chainLength || cSieve->sieveSize != sieveSize || cSieve->nPrimeFactors != minerSettings.nPrimesToSieve ) { if( cSieve == NULL ) { cSieve = (continuousSieve_t*)malloc(sizeof(continuousSieve_t)); memset(cSieve, 0x00, sizeof(continuousSieve_t)); } // start setting up sieve properties early (to avoid threading issues) cSieve->sieveSize = sieveSize; cSieve->chainLength = chainLength; if( cSieve->sieveSize & 7 ) __debugbreak(); // must not happen cSieve->maskBytes = cSieve->sieveSize/8; if( overwritePrimeFactors == 0 ) cSieve->nPrimeFactors = minerSettings.nPrimesToSieve; else cSieve->nPrimeFactors = overwritePrimeFactors; // free everything that has been allocated before if( cSieve->layerMaskC1 ) { free(cSieve->layerMaskC1); free(cSieve->layerMaskC2); cSieve->layerMaskC1 = NULL; cSieve->layerMaskC2 = NULL; } if( cSieve->primeFactorBase ) { free(cSieve->primeFactorBase); cSieve->primeFactorBase = NULL; } // alloc sieve mask uint32 chainMaskSize = cSieve->maskBytes * chainLength; if( cSieve->layerMaskC1 == NULL ) { cSieve->layerMaskC1 = (uint8*)malloc(chainMaskSize); cSieve->layerMaskC2 = (uint8*)malloc(chainMaskSize); } // alloc prime factor base table if( cSieve->primeFactorBase == NULL ) { cSieve->primeFactorBase = (cPrimeFactor_t*)malloc(sizeof(cPrimeFactor_t)*cSieve->nPrimeFactors); for(uint32 i=0; i<cSieve->nPrimeFactors; i++) { cSieve->primeFactorBase[i].twoInverse = single_modinv(2, vPrimes[i]); } } } // calculate fixed inverse mpz_class mpzF, mpzTemp; for(uint32 i=0; i<cSieve->nPrimeFactors; i++) { uint32 p = vPrimes[i]; uint32 fixedFactorMod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzFixedMultiplier.get_mpz_t(), p); cSieve->primeFactorBase[i].mod = fixedFactorMod; cSieve->primeFactorBase[i].base = single_modinv(fixedFactorMod, p); } // reset sieve memset(cSieve->layerMaskC1, 0x00, cSieve->maskBytes * chainLength); memset(cSieve->layerMaskC2, 0x00, cSieve->maskBytes * chainLength); cSieve->mpzFixedMultiplier = mpzFixedMultiplier; for(uint32 t=0; t<cSieve->chainLength; t++) { mpzF = mpzFixedMultiplier; uint8* maskC1 = cSieve->layerMaskC1+t*cSieve->maskBytes; uint8* maskC2 = cSieve->layerMaskC2+t*cSieve->maskBytes; for(uint32 i=0; i<cSieve->nPrimeFactors; i++) { if( cSieve->primeFactorBase[i].mod == 0 ) continue; uint32 p = vPrimes[i]; /*uint32 fixedFactorMod = mpz_mod_ui(mpzTemp.get_mpz_t(), mpzF.get_mpz_t(), p); uint32 fixedInverseU32 = single_modinv(fixedFactorMod, p); *///uint32 fixedInverseTwo = single_modinv(2, p); // mark all cunningham chains of first kind uint32 nSolvedMultiplier = cSieve->primeFactorBase[i].base; while( nSolvedMultiplier < cSieve->sieveSize ) { maskC1[nSolvedMultiplier>>3] |= (1<<(nSolvedMultiplier&7)); nSolvedMultiplier += p; } // mark all cunningham chains of second kind nSolvedMultiplier = -cSieve->primeFactorBase[i].base + p; // tested and correct nSolvedMultiplier %= (uint64)p; while( nSolvedMultiplier < cSieve->sieveSize ) { maskC2[nSolvedMultiplier>>3] |= (1<<(nSolvedMultiplier&7)); nSolvedMultiplier += p; } // apply *2 factor to prime base //cSieve->primeFactorBase[i].base = (cSieve->primeFactorBase[i].base*cSieve->primeFactorBase[i].twoInverse)%p; cSieve->primeFactorBase[i].base = (uint32)(((uint64)cSieve->primeFactorBase[i].base*(uint64)cSieve->primeFactorBase[i].twoInverse)%(uint64)p); } } // reset multiplier scan cSieve->currentSieveLayerIdx = 0; cSieve->currentMultiplierScanIndex = 1; }