int checkBl(mpz_t n, uint32 *qli, fb_list *fb, mpz_t *Bl, int s) { //check that Bl^2 == N mod ql and Bl == 0 mod qj for 1<=j<=s, j != l int i,j,p,q; mpz_t t1,t2; mpz_init(t1); mpz_init(t2); for (i=0;i<s;i++) { p = fb->list->prime[qli[i]]; mpz_tdiv_q_2exp(t2, Bl[i], 1); //zShiftRight(&t2,&Bl[i],1); mpz_mul(t1, t2, t2); //zSqr(&t2,&t1); if (mpz_tdiv_ui(t1,p) % mpz_tdiv_ui(n,p) != 0) printf("%s^2 mod %u != N mod %u\n",mpz_conv2str(&gstr1.s, 10, Bl[i]),p,p); for (j=0;j<s;j++) { if (j==i) continue; q = fb->list->prime[qli[j]]; mpz_tdiv_q_2exp(t2, Bl[i], 1); //zShiftRight(&t2,&Bl[i],1); if (mpz_tdiv_ui(t2,q) != 0) printf("%s mod %u != 0\n",mpz_conv2str(&gstr1.s, 10, Bl[i]),q); } } mpz_clear(t1); mpz_clear(t2); return 0; }
/*------------------------------------------------------------------------*/ static uint32 get_prime_roots(poly_search_t *poly, uint32 which_poly, uint32 p, uint32 *roots) { mp_poly_t tmp_poly; mp_t *low_coeff; uint32 high_coeff; uint32 degree = poly->degree; curr_poly_t *c = poly->batch + which_poly; memset(&tmp_poly, 0, sizeof(mp_poly_t)); tmp_poly.degree = degree; tmp_poly.coeff[degree].num.nwords = 1; tmp_poly.coeff[degree].num.val[0] = p - 1; if (mp_gcd_1(p, (uint32)mpz_tdiv_ui( c->high_coeff, (mp_limb_t)p)) > 1) return 0; low_coeff = &tmp_poly.coeff[0].num; low_coeff->val[0] = mpz_tdiv_ui(c->trans_N, (mp_limb_t)p); if (low_coeff->val[0]) low_coeff->nwords = 1; return poly_get_zeros(roots, &tmp_poly, p, &high_coeff, 0); }
/** * @brief Check if an node contains a enpassant move * @param[in] id The identifier used * @return 1 If the node contains enpassant * @return 0 Otherwise * * This function check if a given node contains a enpassant move * or not, given its Identifier * */ int identifier_is_passant(Identifier id) { Identifier tmp; int ret; mpz_init(tmp); mpz_tdiv_q_ui(tmp, id, 10000); ret = mpz_tdiv_ui(tmp, 10); mpz_clear(tmp); return ret; }
/** * @brief Get the castling state * @param[in] id The identifier used * @return [|0;15|] Meaning a state of castling * * This function check the castling state of an node, given its * Identifier * */ int identifier_get_cast(Identifier id) { Identifier tmp; int ret; mpz_init(tmp); mpz_tdiv_q_ui(tmp, id, 100); ret = mpz_tdiv_ui(tmp, 100); mpz_clear(tmp); return ret; }
/** * @brief Check if an node is a white move * @param[in] id The identifier used * @return 1 If the node is a white move * @return 0 Otherwise * * This function check if a given node is a white move * or not, given its Identifier * */ int identifier_is_white(Identifier id) { Identifier tmp; int ret; mpz_init(tmp); mpz_tdiv_q_ui(tmp, id, 100000); ret = (mpz_tdiv_ui(tmp, 10) % 2); mpz_clear(tmp); return ret; }
bool trialDivisionChainTest(const PrimeSource &primeSource, mpz_class &N, bool fSophieGermain, unsigned chainLength, unsigned depth) { N += (fSophieGermain ? -1 : 1); for (unsigned i = 0; i < chainLength; i++) { for (unsigned divIdx = 0; divIdx < depth; divIdx++) { if (mpz_tdiv_ui(N.get_mpz_t(), primeSource[divIdx]) == 0) { fprintf(stderr, " * divisor: [%u]%u\n", divIdx, primeSource[divIdx]); return false; } } N <<= 1; N += (fSophieGermain ? 1 : -1); } return true; }
int main(int argc, char **argv) { mpz_t year, tmp1, tmp2, tmp3, tmp4; unsigned long day_of_week = 0; uintmax_t month_min = 1, month_max = 12; int_fast8_t month_days = 0; const int_fast8_t months_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; time_t t = time(NULL); char weekday[13] = {0}, weekdays[92] = {0}, month_name[13] = {0}; struct tm *time_struct = localtime(&t); setlocale(LC_ALL, ""); mpz_init(year); switch(argc) { case 1: mpz_set_ui(year, time_struct->tm_year + 1900); month_min = month_max = time_struct->tm_mon + 1; break; case 2: mpz_set_str(year, argv[1], 10); break; default: month_min = month_max = strtoumax(argv[1], NULL, 10); mpz_set_str(year, argv[2], 10); } if(mpz_sgn(year) < 1 || !month_min || month_min > 12) { fputs("http://opengroup.org/onlinepubs/9699919799/utilities/cal.html\n", stderr); exit(1); } for(int_fast8_t i = 0; i < 7; ++i) { time_struct->tm_wday = i; strftime(weekday, 13, "%a", time_struct); strcat(weekdays, weekday); strcat(weekdays, " "); } strcat(weekdays, "\n"); for(uintmax_t month = month_min; month <= month_max; ++month) { time_struct->tm_mon = month - 1; strftime(month_name, 13, "%b", time_struct); if(month > month_min) putchar('\n'); for(int_fast8_t i = (23 - strlen(mpz_get_str(NULL, 10, year))) / 2; i > 0; --i) putchar(' '); fputs(month_name, stdout); putchar(' '); printf("%s\n", mpz_get_str(NULL, 10, year)); fputs(weekdays, stdout); if(!mpz_cmp_ui(year, 1752) && month == 9) { fputs(" 1 2 14 15 16", stdout); fputs("17 18 19 20 21 22 23", stdout); fputs("24 25 26 27 28 29 30", stdout); } else { month_days = months_days[month - 1]; mpz_init(tmp1); mpz_init(tmp2); mpz_init(tmp3); mpz_init(tmp4); if(mpz_cmp_ui(year, 1752) > 0 || (!mpz_cmp_ui(year, 1752) && month > 9)) { /* Gregorian */ if(month == 2 && mpz_divisible_ui_p(year, 4) && (!mpz_divisible_ui_p(year, 100) || mpz_divisible_ui_p(year, 400))) month_days = 29; mpz_add_ui(tmp4, year, 4800 - (14 - month) / 12); mpz_tdiv_q_ui(tmp1, tmp4, 4); mpz_tdiv_q_ui(tmp2, tmp4, 100); mpz_tdiv_q_ui(tmp3, tmp4, 400); mpz_mul_ui(tmp4, tmp4, 365); mpz_add(tmp4, tmp4, tmp1); mpz_sub(tmp4, tmp4, tmp2); mpz_add(tmp4, tmp4, tmp3); mpz_add_ui(tmp4, tmp4, (153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5); mpz_sub_ui(tmp4, tmp4, 32043); day_of_week = mpz_tdiv_ui(tmp4, 7); } else { /* Julian */ if(month == 2 && mpz_divisible_ui_p(year, 4)) month_days = 29; mpz_add_ui(tmp2, year, 4800 - (14 - month) / 12); mpz_tdiv_q_ui(tmp1, tmp2, 4); mpz_mul_ui(tmp2, tmp2, 365); mpz_add(tmp2, tmp2, tmp1); mpz_add_ui(tmp2, tmp2, (153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5); mpz_sub_ui(tmp2, tmp2, 32081); day_of_week = mpz_tdiv_ui(tmp2, 7); } mpz_clear(tmp1); mpz_clear(tmp2); mpz_clear(tmp3); mpz_clear(tmp4); for(uint_fast8_t i = 0; i < day_of_week; ++i) fputs(" ", stdout); for(int_fast8_t i = 1; i <= month_days; ++i) { printf("%2u", i); ++day_of_week; if(i < month_days) fputs((day_of_week %= 7) ? " " : "\n", stdout); } } putchar('\n'); } mpz_clear(year); return 0; }
int main (int argc, char **argv) { mpz_t dividend; mpz_t quotient, remainder; mpz_t quotient2, remainder2; mpz_t temp; mp_size_t dividend_size; unsigned long divisor; int i; int reps = 10000; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; unsigned long r_rq, r_q, r_r, r; tests_start (); rands = RANDS; mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (dividend); mpz_init (quotient); mpz_init (remainder); mpz_init (quotient2); mpz_init (remainder2); mpz_init (temp); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 10 + 2; /* 0..2047 bit operands */ do { mpz_rrandomb (bs, rands, 64); divisor = mpz_get_ui (bs); } while (divisor == 0); mpz_urandomb (bs, rands, size_range); dividend_size = mpz_get_ui (bs); mpz_rrandomb (dividend, rands, dividend_size); mpz_urandomb (bs, rands, 2); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (dividend, dividend); /* printf ("%ld\n", SIZ (dividend)); */ r_rq = mpz_tdiv_qr_ui (quotient, remainder, dividend, divisor); r_q = mpz_tdiv_q_ui (quotient2, dividend, divisor); r_r = mpz_tdiv_r_ui (remainder2, dividend, divisor); r = mpz_tdiv_ui (dividend, divisor); /* First determine that the quotients and remainders computed with different functions are equal. */ if (mpz_cmp (quotient, quotient2) != 0) dump_abort ("quotients from mpz_tdiv_qr_ui and mpz_tdiv_q_ui differ", dividend, divisor); if (mpz_cmp (remainder, remainder2) != 0) dump_abort ("remainders from mpz_tdiv_qr_ui and mpz_tdiv_r_ui differ", dividend, divisor); /* Check if the sign of the quotient is correct. */ if (mpz_cmp_ui (quotient, 0) != 0) if ((mpz_cmp_ui (quotient, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0)) dump_abort ("quotient sign wrong", dividend, divisor); /* Check if the remainder has the same sign as the dividend (quotient rounded towards 0). */ if (mpz_cmp_ui (remainder, 0) != 0) if ((mpz_cmp_ui (remainder, 0) < 0) != (mpz_cmp_ui (dividend, 0) < 0)) dump_abort ("remainder sign wrong", dividend, divisor); mpz_mul_ui (temp, quotient, divisor); mpz_add (temp, temp, remainder); if (mpz_cmp (temp, dividend) != 0) dump_abort ("n mod d != n - [n/d]*d", dividend, divisor); mpz_abs (remainder, remainder); if (mpz_cmp_ui (remainder, divisor) >= 0) dump_abort ("remainder greater than divisor", dividend, divisor); if (mpz_cmp_ui (remainder, r_rq) != 0) dump_abort ("remainder returned from mpz_tdiv_qr_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r_q) != 0) dump_abort ("remainder returned from mpz_tdiv_q_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r_r) != 0) dump_abort ("remainder returned from mpz_tdiv_r_ui is wrong", dividend, divisor); if (mpz_cmp_ui (remainder, r) != 0) dump_abort ("remainder returned from mpz_tdiv_ui is wrong", dividend, divisor); } mpz_clear (bs); mpz_clear (dividend); mpz_clear (quotient); mpz_clear (remainder); mpz_clear (quotient2); mpz_clear (remainder2); mpz_clear (temp); tests_end (); exit (0); }
/* Find primes in region [fr,fr+rsize). Requires that fr is odd and that rsize is even. The sieving array s should be aligned for "long int" and have rsize/2 entries, rounded up to the nearest multiple of "long int". */ void sieve_region (unsigned char *s, mpz_t fr, unsigned long rsize) { unsigned long ssize = rsize / 2; unsigned long start, start2, prime; unsigned long i; mpz_t tmp; mpz_init (tmp); #if 0 /* initialize sieving array */ for (ii = 0; ii < (ssize + sizeof (long) - 1) / sizeof (long); ii++) ((long *) s) [ii] = ~0L; #else { long k; long *se = (long *) (s + ((ssize + sizeof (long) - 1) & -sizeof (long))); for (k = -((ssize + sizeof (long) - 1) / sizeof (long)); k < 0; k++) se[k] = ~0L; } #endif for (i = 0; i < n_primes; i++) { prime = primes[i].prime; if (primes[i].rem >= 0) { start2 = primes[i].rem; } else { mpz_set_ui (tmp, prime); mpz_mul_ui (tmp, tmp, prime); if (mpz_cmp (fr, tmp) <= 0) { mpz_sub (tmp, tmp, fr); if (mpz_cmp_ui (tmp, 2 * ssize) > 0) break; /* avoid overflow at next line, also speedup */ start = mpz_get_ui (tmp); } else { start = (prime - mpz_tdiv_ui (fr, prime)) % prime; if (start % 2 != 0) start += prime; /* adjust if even divisible */ } start2 = start / 2; } #if 0 for (ii = start2; ii < ssize; ii += prime) s[ii] = 0; primes[i].rem = ii - ssize; #else { long k; unsigned char *se = s + ssize; /* point just beyond sieving range */ for (k = start2 - ssize; k < 0; k += prime) se[k] = 0; primes[i].rem = k; } #endif } mpz_clear (tmp); }
DWORD WINAPI soe_worker_thread_main(LPVOID thread_data) { #else void *soe_worker_thread_main(void *thread_data) { #endif thread_soedata_t *t = (thread_soedata_t *)thread_data; while(1) { uint32 i; /* wait forever for work to do */ #if defined(WIN32) || defined(_WIN64) WaitForSingleObject(t->run_event, INFINITE); #else pthread_mutex_lock(&t->run_lock); while (t->command == SOE_COMMAND_WAIT) { pthread_cond_wait(&t->run_cond, &t->run_lock); } #endif /* do work */ if (t->command == SOE_COMMAND_SIEVE_AND_COUNT) { t->sdata.lines[t->current_line] = (uint8 *)malloc(t->sdata.numlinebytes * sizeof(uint8)); sieve_line(t); t->linecount = count_line(&t->sdata, t->current_line); free(t->sdata.lines[t->current_line]); } else if (t->command == SOE_COMMAND_SIEVE_AND_COMPUTE) { sieve_line(t); } else if (t->command == SOE_COMPUTE_ROOTS) { if (VFLAG > 2) printf("starting root computation over %u to %u\n", t->startid, t->stopid); if (t->sdata.sieve_range == 0) { for (i = t->startid; i < t->stopid; i++) { uint32 inv; uint32 prime = t->sdata.sieve_p[i]; inv = modinv_1(t->sdata.prodN, prime); t->sdata.root[i] = prime - inv; t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = (t->sdata.lowlimit + 1) % prime; } } else { mpz_t tmpz; //mpz_t t1, t2; mpz_init(tmpz); //experiment for custom ranges that can be expressed as base^exp + range //mpz_init(t1); //mpz_init(t2); mpz_add_ui(tmpz, *t->sdata.offset, t->sdata.lowlimit + 1); for (i = t->startid; i < t->stopid; i++) { uint32 inv; uint32 prime = t->sdata.sieve_p[i]; inv = modinv_1(t->sdata.prodN, prime); t->sdata.root[i] = prime - inv; t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = mpz_tdiv_ui(tmpz, prime); //mpz_set_ui(t2,prime); //mpz_set_ui(t1, 10); //mpz_powm_ui(t1, t1, 999999, t2); //t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = mpz_get_ui(t1); } //mpz_clear(t1); //mpz_clear(t2); } } else if (t->command == SOE_COMPUTE_PRIMES) { t->linecount = 0; for (i = t->startid; i < t->stopid; i+=8) { t->linecount = compute_8_bytes(&t->sdata, t->linecount, t->ddata.primes, i, NULL); } } else if (t->command == SOE_COMPUTE_PRPS) { t->linecount = 0; for (i = t->startid; i < t->stopid; i++) { mpz_add_ui(t->tmpz, t->offset, t->ddata.primes[i - t->startid]); if ((mpz_cmp(t->tmpz, t->lowlimit) >= 0) && (mpz_cmp(t->highlimit, t->tmpz) >= 0)) { if (mpz_probab_prime_p(t->tmpz, t->current_line)) t->ddata.primes[t->linecount++] = t->ddata.primes[i - t->startid]; } } } else if (t->command == SOE_COMMAND_END) break; /* signal completion */ t->command = SOE_COMMAND_WAIT; #if defined(WIN32) || defined(_WIN64) SetEvent(t->finish_event); #else pthread_cond_signal(&t->run_cond); pthread_mutex_unlock(&t->run_lock); #endif } #if defined(WIN32) || defined(_WIN64) return 0; #else return NULL; #endif }
void zTrial(fact_obj_t *fobj) { //trial divide n using primes below limit. optionally, print factors found. //input expected in the gmp_n field of div_obj. uint32 r,k=0; uint32 limit = fobj->div_obj.limit; int print = fobj->div_obj.print; FILE *flog; fp_digit q; mpz_t tmp; mpz_init(tmp); flog = fopen(fobj->flogname,"a"); if (flog == NULL) { printf("fopen error: %s\n", strerror(errno)); printf("could not open %s for writing\n",fobj->flogname); return; } if (P_MAX < limit) { free(PRIMES); PRIMES = soe_wrapper(spSOEprimes, szSOEp, 0, limit, 0, &NUM_P); P_MIN = PRIMES[0]; P_MAX = PRIMES[NUM_P-1]; } while ((mpz_cmp_ui(fobj->div_obj.gmp_n, 1) > 0) && (PRIMES[k] < limit) && (k < (uint32)NUM_P)) { q = (fp_digit)PRIMES[k]; r = mpz_tdiv_ui(fobj->div_obj.gmp_n, q); if (r != 0) k++; else { mpz_tdiv_q_ui(fobj->div_obj.gmp_n, fobj->div_obj.gmp_n, q); mpz_set_64(tmp, q); add_to_factor_list(fobj, tmp); #if BITS_PER_DIGIT == 64 logprint(flog,"div: found prime factor = %" PRIu64 "\n",q); #else logprint(flog,"div: found prime factor = %u\n",q); #endif if (print && (VFLAG > 0)) #if BITS_PER_DIGIT == 64 printf("div: found prime factor = %" PRIu64 "\n",q); #else printf("div: found prime factor = %u\n",q); #endif } } fclose(flog); mpz_clear(tmp); }
void getRoots(soe_staticdata_t *sdata, thread_soedata_t *thread_data) { int prime, prodN; uint64 startprime; uint64 i; int j; uint32 range, lastid; //timing double t; struct timeval tstart, tstop; TIME_DIFF * difference; prodN = (int)sdata->prodN; startprime = sdata->startprime; gettimeofday(&tstart, NULL); for (i=startprime; i<sdata->bucket_start_id; i++) { uint32 inv; prime = sdata->sieve_p[i]; //sieving requires that we find the offset of each sieve prime in each block //that we sieve. We are more restricted in choice of offset because we //sieve residue classes. A good way to find the offset is the extended //euclidean algorithm, which reads ax + by = gcd(a,b), //where a = prime, b = prodN, and therefore gcd = 1. //since a and b are coprime, y is the multiplicative inverse of prodN modulo prime. //This value is a constant, so compute it here in order to facilitate //finding offsets later. //solve prodN ^ -1 % p inv = modinv_1(prodN,prime); sdata->root[i] = prime - inv; } gettimeofday(&tstop, NULL); difference = my_difftime(&tstart, &tstop); t = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG > 2) printf("time to compute linear sieve roots = %1.2f\n", t); gettimeofday(&tstart, NULL); // start the threads for (i = 0; i < THREADS - 1; i++) start_soe_worker_thread(thread_data + i, 0); start_soe_worker_thread(thread_data + i, 1); range = (sdata->pboundi - sdata->bucket_start_id) / THREADS; lastid = sdata->bucket_start_id; // divvy up the primes for (j = 0; j < THREADS; j++) { thread_soedata_t *t = thread_data + j; t->sdata = *sdata; t->startid = lastid; t->stopid = t->startid + range; lastid = t->stopid; } // the last one gets any leftover if (thread_data[THREADS-1].stopid != sdata->pboundi) thread_data[THREADS-1].stopid = sdata->pboundi; // now run with the threads for (j = 0; j < THREADS; j++) { thread_soedata_t *t = thread_data + j; if (j == (THREADS - 1)) { if (VFLAG > 2) printf("starting root computation over %u to %u\n", t->startid, t->stopid); // run in the current thread // bucket sieved primes need more data if (sdata->sieve_range == 0) { for (i = t->startid; i < t->stopid; i++) { uint32 inv; prime = t->sdata.sieve_p[i]; //sieving requires that we find the offset of each sieve prime in each block //that we sieve. We are more restricted in choice of offset because we //sieve residue classes. A good way to find the offset is the extended //euclidean algorithm, which reads ax + by = gcd(a,b), //where a = prime, b = prodN, and therefore gcd = 1. //since a and b are coprime, y is the multiplicative inverse of prodN modulo prime. //This value is a constant, so compute it here in order to facilitate //finding offsets later. //solve prodN ^ -1 % p inv = modinv_1(prodN, prime); t->sdata.root[i] = prime - inv; //we can also speed things up by computing and storing the residue //mod p of the first sieve location in the first residue class. This provides //a speedup by pulling this constant (involving a division) out of a critical loop //when finding offsets of bucket sieved primes. //these are only used by bucket sieved primes. t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = (t->sdata.lowlimit + 1) % prime; } } else { mpz_t tmpz; //mpz_t t1, t2; mpz_init(tmpz); //uint64 res; //experiment for custom ranges that can be expressed as base^exp + range //mpz_init(t1); //mpz_init(t2); mpz_add_ui(tmpz, *t->sdata.offset, t->sdata.lowlimit + 1); for (i = t->startid; i < t->stopid; i++) { uint32 inv; prime = t->sdata.sieve_p[i]; //sieving requires that we find the offset of each sieve prime in each block //that we sieve. We are more restricted in choice of offset because we //sieve residue classes. A good way to find the offset is the extended //euclidean algorithm, which reads ax + by = gcd(a,b), //where a = prime, b = prodN, and therefore gcd = 1. //since a and b are coprime, y is the multiplicative inverse of prodN modulo prime. //This value is a constant, so compute it here in order to facilitate //finding offsets later. //solve prodN ^ -1 % p inv = modinv_1(prodN,prime); t->sdata.root[i] = prime - inv; //we can also speed things up by computing and storing the residue //mod p of the first sieve location in the first residue class. This provides //a speedup by pulling this constant (involving a division) out of a critical loop //when finding offsets of bucket sieved primes. //these are only used by bucket sieved primes. t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = mpz_tdiv_ui(tmpz, prime); //mpz_set_ui(t2,prime); //mpz_set_ui(t1, 1000000000); //mpz_powm_ui(t1, t1, 111111, t2); //res = mpz_get_64(t1); //t->sdata.lower_mod_prime[i - t->sdata.bucket_start_id] = (uint32)res; } //mpz_clear(t1); //mpz_clear(t2); } } else { t->command = SOE_COMPUTE_ROOTS; #if defined(WIN32) || defined(_WIN64) SetEvent(t->run_event); #else pthread_cond_signal(&t->run_cond); pthread_mutex_unlock(&t->run_lock); #endif } } //wait for each thread to finish for (i = 0; i < THREADS; i++) { thread_soedata_t *t = thread_data + i; if (i < (THREADS - 1)) { #if defined(WIN32) || defined(_WIN64) WaitForSingleObject(t->finish_event, INFINITE); #else pthread_mutex_lock(&t->run_lock); while (t->command != SOE_COMMAND_WAIT) pthread_cond_wait(&t->run_cond, &t->run_lock); #endif } } //stop the worker threads for (i=0; i<THREADS - 1; i++) stop_soe_worker_thread(thread_data + i, 0); gettimeofday(&tstop, NULL); difference = my_difftime(&tstart, &tstop); t = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG > 2) printf("time to compute bucket sieve roots = %1.2f\n", t); #ifdef INPLACE_BUCKET gettimeofday(&tstart, NULL); // inplace primes have special requirements because they operate on // the normal number line, and not in residue space for (; i < sdata->pboundi; i++) { uint64 starthit; uint32 startclass; uint64 startbit; uint32 rclass, bnum, rclassid; uint32 index = i - sdata->inplace_start_id; int a; // copy the prime into the special data structure //sdata->inplace_data[index].prime = sdata->sieve_p[i]; // pull some computations involving a division out of the inner loop. // we need to know what prime/prodN and prime%prodN are. sdata->inplace_data[index].p_div = sdata->sieve_p[i] / prodN; rclass = sdata->sieve_p[i] % prodN; rclassid = resID_mod30[rclass]; sdata->inplace_data[index].p_mod = rclass; // now compute the starting hit in our sieve interval... starthit = (sdata->lowlimit / sdata->sieve_p[i] + 1) * sdata->sieve_p[i]; // ... that is in one of our residue classes startclass = starthit % prodN; // using a lookup table startclass = next_mod30[rclassid][startclass]; starthit += ((uint64)sdata->sieve_p[i] * (uint64)(startclass >> 8)); startclass = startclass & 0xff; // the starting accumulated error is equal to the starting class sdata->inplace_data[index].eacc = startclass; // now compute the starting bit and block location for this starting hit startbit = (starthit - sdata->lowlimit - (uint64)startclass) / (uint64)prodN; // sanity check if (((starthit - sdata->lowlimit - (uint64)startclass) % (uint64)prodN) != 0) printf("starting bit is invalid!\n"); sdata->inplace_data[index].bitloc = startbit & FLAGSIZEm1; bnum = startbit >> FLAGBITS; // finally, add the prime to a linked list // if the next hit is within our interval if (bnum < sdata->blocks) { //then reassign this prime to its next hit if (sdata->inplace_ptrs[bnum][resID_mod30[startclass]] == -1) { // this is the first hit in this block and rclass, so set the pointer // to this prime, and set next_pid = 0 so that we know to stop here // when we sieve sdata->inplace_ptrs[bnum][resID_mod30[startclass]] = index; sdata->inplace_data[index].next_pid = 0; } else { // add this prime to a listed list within the inplace sieve array. // this is done by first setting the next id to the current prime // at the end of the list sdata->inplace_data[index].next_pid = sdata->inplace_ptrs[bnum][resID_mod30[startclass]]; // and then setting the end of the list to this prime sdata->inplace_ptrs[bnum][resID_mod30[startclass]] = index; } } } gettimeofday(&tstop, NULL); difference = my_difftime(&tstart, &tstop); t = ((double)difference->secs + (double)difference->usecs / 1000000); free(difference); if (VFLAG > 2) printf("time to compute inplace sieve roots = %1.2f\n", t); #endif return; }
// Test probable primality of n = 2p +/- 1 based on Euler, Lagrange and Lifchitz // fSophieGermain: // true: n = 2p+1, p prime, aka Cunningham Chain of first kind // false: n = 2p-1, p prime, aka Cunningham Chain of second kind // Return values // true: n is probable prime // false: n is composite; set fractional length in the nLength output static bool EulerLagrangeLifchitzPrimalityTestFast(const mpz_class& n, bool fSophieGermain, unsigned int& nLength, CPrimalityTestParams& testParams, bool fFastDiv = false) { // Faster GMP version mpz_t& mpzN = testParams.mpzN; mpz_t& mpzE = testParams.mpzE; mpz_t& mpzR = testParams.mpzR; mpz_t& mpzRplusOne = testParams.mpzRplusOne; const unsigned int nPrimorialSeq = testParams.nPrimorialSeq; mpz_set(mpzN, n.get_mpz_t()); if (fFastDiv) { // Fast divisibility tests // Starting from the first prime not included in the round primorial const unsigned int nBeginSeq = nPrimorialSeq + 1; const unsigned int nEndSeq = nBeginSeq + nFastDivPrimes; for (unsigned int nPrimeSeq = nBeginSeq; nPrimeSeq < nEndSeq; nPrimeSeq++) { if (mpz_divisible_ui_p(mpzN, vPrimes[nPrimeSeq])) { return false; } } } ++gandalfs; mpz_sub_ui(mpzE, mpzN, 1); mpz_tdiv_q_2exp(mpzE, mpzE, 1); mpz_powm(mpzR, mpzTwo.get_mpz_t(), mpzE, mpzN); unsigned int nMod8 = mpz_tdiv_ui(mpzN, 8); bool fPassedTest = false; if (fSophieGermain && (nMod8 == 7)) // Euler & Lagrange fPassedTest = !mpz_cmp_ui(mpzR, 1); else if (fSophieGermain && (nMod8 == 3)) // Lifchitz { mpz_add_ui(mpzRplusOne, mpzR, 1); fPassedTest = !mpz_cmp(mpzRplusOne, mpzN); } else if ((!fSophieGermain) && (nMod8 == 5)) // Lifchitz { mpz_add_ui(mpzRplusOne, mpzR, 1); fPassedTest = !mpz_cmp(mpzRplusOne, mpzN); } else if ((!fSophieGermain) && (nMod8 == 1)) // LifChitz fPassedTest = !mpz_cmp_ui(mpzR, 1); else { cout << "EulerLagrangeLifchitzPrimalityTest() : invalid n %% 8 = " << nMod8 << ", " << (fSophieGermain? "first kind" : "second kind") << endl; return false; //return error("EulerLagrangeLifchitzPrimalityTest() : invalid n %% 8 = %d, %s", nMod8, (fSophieGermain? "first kind" : "second kind")); } if (fPassedTest) { return true; } // Failed test, calculate fractional length mpz_mul(mpzE, mpzR, mpzR); mpz_tdiv_r(mpzR, mpzE, mpzN); // derive Fermat test remainder mpz_sub(mpzE, mpzN, mpzR); mpz_mul_2exp(mpzR, mpzE, nFractionalBits); mpz_tdiv_q(mpzE, mpzR, mpzN); unsigned int nFractionalLength = mpz_get_ui(mpzE); if (nFractionalLength >= (1 << nFractionalBits)) { cout << "EulerLagrangeLifchitzPrimalityTest() : fractional assert" << endl; return false; } nLength = (nLength & TARGET_LENGTH_MASK) | nFractionalLength; return false; }
void firstRoots(static_conf_t *sconf, dynamic_conf_t *dconf) { //the roots are computed using a and b as follows: //(+/-t - b)(a)^-1 mod p //where the t values are the roots to t^2 = N mod p, found by shanks_tonelli //when constructing the factor base. //assume b > t //unpack stuff from the job data structures siqs_poly *poly = dconf->curr_poly; fb_list *fb = sconf->factor_base; uint32 start_prime = 2; int *rootupdates = dconf->rootupdates; update_t update_data = dconf->update_data; sieve_fb_compressed *fb_p = dconf->comp_sieve_p; sieve_fb_compressed *fb_n = dconf->comp_sieve_n; lp_bucket *lp_bucket_p = dconf->buckets; uint32 *modsqrt = sconf->modsqrt_array; //locals uint32 i, interval; uint8 logp; int root1, root2, prime, amodp, bmodp, inv, x, bnum,j,numblocks; int s = poly->s; int bound_index = 0, k; uint32 bound_val = fb->med_B; uint32 *bptr, *sliceptr_p, *sliceptr_n; uint32 *numptr_p, *numptr_n; int check_bound = BUCKET_ALLOC/2 - 1, room; numblocks = sconf->num_blocks; interval = numblocks << BLOCKBITS; if (lp_bucket_p->list != NULL) { lp_bucket_p->fb_bounds[0] = fb->med_B; sliceptr_p = lp_bucket_p->list; sliceptr_n = lp_bucket_p->list + (numblocks << BUCKET_BITS); numptr_p = lp_bucket_p->num; numptr_n = lp_bucket_p->num + numblocks; //reset lp_buckets for (i=0;i< (2*numblocks*lp_bucket_p->alloc_slices) ;i++) numptr_p[i] = 0; lp_bucket_p->num_slices = 0; } else { sliceptr_p = NULL; sliceptr_n = NULL; numptr_p = NULL; numptr_n = NULL; } for (i=start_prime;i<sconf->sieve_small_fb_start;i++) { uint64 q64, tmp, t2; prime = fb->tinylist->prime[i]; root1 = modsqrt[i]; root2 = prime - root1; amodp = (int)mpz_tdiv_ui(poly->mpz_poly_a,prime); bmodp = (int)mpz_tdiv_ui(poly->mpz_poly_b,prime); //find a^-1 mod p = inv(a mod p) mod p inv = modinv_1(amodp,prime); COMPUTE_FIRST_ROOTS // reuse integer inverse of prime that we've calculated for use // in trial division stage // inv * root1 % prime t2 = (uint64)inv * (uint64)root1; tmp = t2 + (uint64)fb->tinylist->correction[i]; q64 = tmp * (uint64)fb->tinylist->small_inv[i]; tmp = q64 >> 32; root1 = t2 - tmp * prime; // inv * root2 % prime t2 = (uint64)inv * (uint64)root2; tmp = t2 + (uint64)fb->tinylist->correction[i]; q64 = tmp * (uint64)fb->tinylist->small_inv[i]; tmp = q64 >> 32; root2 = t2 - tmp * prime; //we don't sieve these primes, so ordering doesn't matter update_data.firstroots1[i] = root1; update_data.firstroots2[i] = root2; fb_p->root1[i] = (uint16)root1; fb_p->root2[i] = (uint16)root2; fb_n->root1[i] = (uint16)(prime - root2); fb_n->root2[i] = (uint16)(prime - root1); //if we were sieving, this would double count the location on the //positive side. but since we're not, its easier to check for inclusion //on the progression if we reset the negative root to zero if it is == prime if (fb_n->root1[i] == prime) fb_n->root1[i] = 0; if (fb_n->root2[i] == prime) fb_n->root2[i] = 0; //for this factor base prime, compute the rootupdate value for all s //Bl values. amodp holds a^-1 mod p //the rootupdate value is given by 2*Bj*amodp //Bl[j] now holds 2*Bl for (j=0;j<s;j++) { x = (int)mpz_tdiv_ui(dconf->Bl[j],prime); // x * inv % prime t2 = (uint64)inv * (uint64)x; tmp = t2 + (uint64)fb->tinylist->correction[i]; q64 = tmp * (uint64)fb->tinylist->small_inv[i]; tmp = q64 >> 32; x = t2 - tmp * prime; rootupdates[(j)*fb->B+i] = x; } } for (i=sconf->sieve_small_fb_start;i<fb->fb_15bit_B;i++) { uint64 small_inv, correction; uint64 q64, tmp, t2; prime = fb->list->prime[i]; root1 = modsqrt[i]; root2 = prime - root1; // compute integer inverse of prime for use in mod operations in this // function. small_inv = ((uint64)1 << 48) / (uint64)prime; if (floor((double)((uint64)1 << 48) / (double)prime + 0.5) == (double)small_inv) { correction = 1; } else { correction = 0; small_inv++; } amodp = (int)mpz_tdiv_ui(poly->mpz_poly_a,prime); bmodp = (int)mpz_tdiv_ui(poly->mpz_poly_b,prime); //find a^-1 mod p = inv(a mod p) mod p inv = modinv_1(amodp,prime); COMPUTE_FIRST_ROOTS // inv * root1 % prime t2 = (uint64)inv * (uint64)root1; tmp = t2 + correction; q64 = tmp * small_inv; tmp = q64 >> 48; root1 = t2 - tmp * prime; // inv * root2 % prime t2 = (uint64)inv * (uint64)root2; tmp = t2 + correction; q64 = tmp * small_inv; tmp = q64 >> 48; root2 = t2 - tmp * prime; if (root2 < root1) { update_data.sm_firstroots1[i] = (uint16)root2; update_data.sm_firstroots2[i] = (uint16)root1; fb_p->root1[i] = (uint16)root2; fb_p->root2[i] = (uint16)root1; fb_n->root1[i] = (uint16)(prime - root1); fb_n->root2[i] = (uint16)(prime - root2); } else { update_data.sm_firstroots1[i] = (uint16)root1; update_data.sm_firstroots2[i] = (uint16)root2; fb_p->root1[i] = (uint16)root1; fb_p->root2[i] = (uint16)root2; fb_n->root1[i] = (uint16)(prime - root2); fb_n->root2[i] = (uint16)(prime - root1); } //for this factor base prime, compute the rootupdate value for all s //Bl values. amodp holds a^-1 mod p //the rootupdate value is given by 2*Bj*amodp //Bl[j] now holds 2*Bl for (j=0;j<s;j++) { x = (int)mpz_tdiv_ui(dconf->Bl[j],prime); // x * inv % prime t2 = (uint64)inv * (uint64)x; tmp = t2 + correction; q64 = tmp * small_inv; tmp = q64 >> 48; x = t2 - tmp * prime; rootupdates[(j)*fb->B+i] = x; dconf->sm_rootupdates[(j)*fb->B+i] = (uint16)x; } } //printf("prime[15bit-1] = %u\n", fb_p->prime[fb->fb_15bit_B-1]); for (i=fb->fb_15bit_B;i<fb->med_B;i++) { uint64 small_inv, correction; uint64 q64, tmp, t2; prime = fb->list->prime[i]; root1 = modsqrt[i]; root2 = prime - root1; // compute integer inverse of prime for use in mod operations in this // function. small_inv = ((uint64)1 << 48) / (uint64)prime; if (floor((double)((uint64)1 << 48) / (double)prime + 0.5) == (double)small_inv) { correction = 1; } else { correction = 0; small_inv++; } amodp = (int)mpz_tdiv_ui(poly->mpz_poly_a,prime); bmodp = (int)mpz_tdiv_ui(poly->mpz_poly_b,prime); //find a^-1 mod p = inv(a mod p) mod p inv = modinv_1(amodp,prime); COMPUTE_FIRST_ROOTS // inv * root1 % prime t2 = (uint64)inv * (uint64)root1; tmp = t2 + correction; q64 = tmp * small_inv; tmp = q64 >> 48; root1 = t2 - tmp * prime; // inv * root2 % prime t2 = (uint64)inv * (uint64)root2; tmp = t2 + correction; q64 = tmp * small_inv; tmp = q64 >> 48; root2 = t2 - tmp * prime; if (root2 < root1) { update_data.firstroots1[i] = root2; update_data.firstroots2[i] = root1; fb_p->root1[i] = (uint16)root2; fb_p->root2[i] = (uint16)root1; fb_n->root1[i] = (uint16)(prime - root1); fb_n->root2[i] = (uint16)(prime - root2); } else { update_data.firstroots1[i] = root1; update_data.firstroots2[i] = root2; fb_p->root1[i] = (uint16)root1; fb_p->root2[i] = (uint16)root2; fb_n->root1[i] = (uint16)(prime - root2); fb_n->root2[i] = (uint16)(prime - root1); } //for this factor base prime, compute the rootupdate value for all s //Bl values. amodp holds a^-1 mod p //the rootupdate value is given by 2*Bj*amodp //Bl[j] now holds 2*Bl for (j=0;j<s;j++) { x = (int)mpz_tdiv_ui(dconf->Bl[j],prime); // x * inv % prime t2 = (uint64)inv * (uint64)x; tmp = t2 + correction; q64 = tmp * small_inv; tmp = q64 >> 48; x = t2 - tmp * prime; rootupdates[(j)*fb->B+i] = x; } } check_bound = fb->med_B + BUCKET_ALLOC/2; logp = fb->list->logprime[fb->med_B-1]; for (i=fb->med_B;i<fb->large_B;i++) { //uint64 small_inv, correction; //uint64 q64, tmp, t2; CHECK_NEW_SLICE(i); prime = fb->list->prime[i]; root1 = modsqrt[i]; root2 = prime - root1; amodp = (int)mpz_tdiv_ui(poly->mpz_poly_a,prime); bmodp = (int)mpz_tdiv_ui(poly->mpz_poly_b,prime); //find a^-1 mod p = inv(a mod p) mod p inv = modinv_1(amodp,prime); COMPUTE_FIRST_ROOTS root1 = (uint32)((uint64)inv * (uint64)root1 % (uint64)prime); root2 = (uint32)((uint64)inv * (uint64)root2 % (uint64)prime); update_data.firstroots1[i] = root1; update_data.firstroots2[i] = root2; FILL_ONE_PRIME_LOOP_P(i); root1 = (prime - update_data.firstroots1[i]); root2 = (prime - update_data.firstroots2[i]); FILL_ONE_PRIME_LOOP_N(i); //for this factor base prime, compute the rootupdate value for all s //Bl values. amodp holds a^-1 mod p //the rootupdate value is given by 2*Bj*amodp //Bl[j] now holds 2*Bl for (j=0;j<s;j++) { x = (int)mpz_tdiv_ui(dconf->Bl[j], prime); x = (int)((int64)x * (int64)inv % (int64)prime); rootupdates[(j)*fb->B+i] = x; } } logp = fb->list->logprime[fb->large_B-1]; for (i=fb->large_B;i<fb->B;i++) { CHECK_NEW_SLICE(i); prime = fb->list->prime[i]; root1 = modsqrt[i]; root2 = prime - root1; amodp = (int)mpz_tdiv_ui(poly->mpz_poly_a,prime); bmodp = (int)mpz_tdiv_ui(poly->mpz_poly_b,prime); //find a^-1 mod p = inv(a mod p) mod p inv = modinv_1(amodp,prime); COMPUTE_FIRST_ROOTS root1 = (uint32)((uint64)inv * (uint64)root1 % (uint64)prime); root2 = (uint32)((uint64)inv * (uint64)root2 % (uint64)prime); update_data.firstroots1[i] = root1; update_data.firstroots2[i] = root2; FILL_ONE_PRIME_P(i); root1 = (prime - root1); root2 = (prime - root2); FILL_ONE_PRIME_N(i); //for this factor base prime, compute the rootupdate value for all s //Bl values. amodp holds a^-1 mod p //the rootupdate value is given by 2*Bj*amodp //Bl[j] now holds 2*Bl //s is the number of primes in 'a' for (j=0;j<s;j++) { x = (int)mpz_tdiv_ui(dconf->Bl[j], prime); x = (int)((int64)x * (int64)inv % (int64)prime); rootupdates[(j)*fb->B+i] = x; } } if (lp_bucket_p->list != NULL) lp_bucket_p->num_slices = bound_index + 1; return; }
void testfirstRoots(static_conf_t *sconf, dynamic_conf_t *dconf) { //the roots are computed using a and b as follows: //(+/-t - b)(a)^-1 mod p //where the t values are the roots to t^2 = N mod p, found by shanks_tonelli //when constructing the factor base. //assume b > t //compute the roots as if we were actually going to use this, but don't save //anything. We are just trying to determine the size needed for each large //prime bucket by sieving over just the first bucket uint32 i,logp; int root1, root2, prime, amodp, bmodp, inv, bnum,numblocks; int lpnum,last_bound; //unpack stuff from the job data siqs_poly *poly = dconf->curr_poly; fb_list *fb = sconf->factor_base; lp_bucket *lp_bucket_p = dconf->buckets; uint32 *modsqrt = sconf->modsqrt_array; numblocks = sconf->num_blocks; lpnum = 0; dconf->buckets->alloc_slices = 1; //extreme estimate for number of slices i = (sconf->factor_base->B - sconf->factor_base->med_B) / 512; last_bound = fb->med_B; for (i=fb->med_B;i<fb->B;i++) { prime = fb->list->prime[i]; root1 = modsqrt[i]; root2 = prime - root1; logp = fb->list->logprime[i]; amodp = (int)mpz_tdiv_ui(poly->mpz_poly_a,prime); bmodp = (int)mpz_tdiv_ui(poly->mpz_poly_b,prime); //find a^-1 mod p = inv(a mod p) mod p inv = modinv_1(amodp,prime); root1 = (int)root1 - bmodp; if (root1 < 0) root1 += prime; root2 = (int)root2 - bmodp; if (root2 < 0) root2 += prime; root1 = (uint32)((uint64)inv * (uint64)root1 % (uint64)prime); root2 = (uint32)((uint64)inv * (uint64)root2 % (uint64)prime); //just need to do this once, because the next step of prime will be //into a different bucket bnum = root1 >> BLOCKBITS; if (bnum == 0) lpnum++; //repeat for the other root bnum = root2 >> BLOCKBITS; if (bnum == 0) lpnum++; if ((uint32)lpnum > (double)BUCKET_ALLOC * 0.75) { //we want to allocate more slices than we will probably need //assume alloc/2 is a safe amount of slack lp_bucket_p->alloc_slices++; lpnum = 0; } if (i - last_bound == 65536) { //when prime are really big, we may cross this boundary //before the buckets fill up lp_bucket_p->alloc_slices++; lpnum = 0; last_bound = i; } } // extra cushion - may increase the memory usage a bit, but in very // rare circumstances not enough slices allocated causes crashes. lp_bucket_p->alloc_slices++; return; }
int check_specialcase(FILE *sieve_log, fact_obj_t *fobj) { //check for some special cases of input number //sieve_log is passed in already open, and should return open if (mpz_even_p(fobj->qs_obj.gmp_n)) { printf("input must be odd\n"); return 1; } if (mpz_probab_prime_p(fobj->qs_obj.gmp_n, NUM_WITNESSES)) { add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n", gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); mpz_set_ui(fobj->qs_obj.gmp_n,1); return 1; } if (mpz_perfect_square_p(fobj->qs_obj.gmp_n)) { mpz_sqrt(fobj->qs_obj.gmp_n,fobj->qs_obj.gmp_n); add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); add_to_factor_list(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->qs_obj.gmp_n), mpz_conv2str(&gstr1.s, 10, fobj->qs_obj.gmp_n)); mpz_set_ui(fobj->qs_obj.gmp_n,1); return 1; } if (mpz_perfect_power_p(fobj->qs_obj.gmp_n)) { if (VFLAG > 0) printf("input is a perfect power\n"); factor_perfect_power(fobj, fobj->qs_obj.gmp_n); if (sieve_log != NULL) { uint32 j; logprint(sieve_log,"input is a perfect power\n"); for (j=0; j<fobj->num_factors; j++) { uint32 k; for (k=0; k<fobj->fobj_factors[j].count; k++) { logprint(sieve_log,"prp%d = %s\n",gmp_base10(fobj->fobj_factors[j].factor), mpz_conv2str(&gstr1.s, 10, fobj->fobj_factors[j].factor)); } } } return 1; } if (mpz_sizeinbase(fobj->qs_obj.gmp_n,2) < 115) { //run MPQS, as SIQS doesn't work for smaller inputs //MPQS will take over the log file, so close it now. int i; // we've verified that the input is not odd or prime. also // do some very quick trial division before calling smallmpqs, which // does none of these things. for (i=1; i<25; i++) { if (mpz_tdiv_ui(fobj->qs_obj.gmp_n, spSOEprimes[i]) == 0) mpz_tdiv_q_ui(fobj->qs_obj.gmp_n, fobj->qs_obj.gmp_n, spSOEprimes[i]); } smallmpqs(fobj); return 1; //tells SIQS to not try to close the logfile } if (gmp_base10(fobj->qs_obj.gmp_n) > 140) { printf("input too big for SIQS\n"); return 1; } return 0; }
void riecoin_process(minerRiecoinBlock_t* block) { uint32 searchBits = block->targetCompact; if( riecoin_sieve ) memset(riecoin_sieve, 0x00, riecoin_sieveSize/8); else { riecoin_sieve = (uint8*)malloc(riecoin_sieveSize/8); memset(riecoin_sieve, 0x00, riecoin_sieveSize/8); } uint8* sieve = riecoin_sieve; // test data // getblock 16ee31c116b75d0299dc03cab2b6cbcb885aa29adf292b2697625bc9d28b2b64 //debug_parseHexStringLE("c59ba5357285de73b878fed43039a37f85887c8960e66bcb6e86bdad565924bd", 64, block->merkleRoot); //block->version = 2; //debug_parseHexStringLE("c64673c670fb327c2e009b3b626d2def01d51ad4131a7a1040e9cef7bfa34838", 64, block->prevBlockHash); //block->nTime = 1392151955; //block->nBits = 0x02013000; //debug_parseHexStringLE("0000000000000000000000000000000000000000000000000000000070b67515", 64, block->nOffset); // generate PoW hash (version to nBits) uint8 powHash[32]; sha256_ctx ctx; sha256_init(&ctx); sha256_update(&ctx, (uint8*)block, 80); sha256_final(&ctx, powHash); sha256_init(&ctx); sha256_update(&ctx, powHash, 32); sha256_final(&ctx, powHash); // generatePrimeBase uint32* powHashU32 = (uint32*)powHash; mpz_t z_target; mpz_t z_temp; mpz_init(z_temp); mpz_init_set_ui(z_target, 1); mpz_mul_2exp(z_target, z_target, zeroesBeforeHashInPrime); for(uint32 i=0; i<256; i++) { mpz_mul_2exp(z_target, z_target, 1); if( (powHashU32[i/32]>>(i))&1 ) z_target->_mp_d[0]++; } unsigned int trailingZeros = searchBits - 1 - zeroesBeforeHashInPrime - 256; mpz_mul_2exp(z_target, z_target, trailingZeros); // find first offset where x%2310 = 97 uint64 remainder2310 = mpz_tdiv_ui(z_target, 2310); remainder2310 = (2310-remainder2310)%2310; remainder2310 += 97; mpz_add_ui(z_temp, z_target, remainder2310); mpz_t z_temp2; mpz_init(z_temp2); mpz_t z_ft_r; mpz_init(z_ft_r); mpz_t z_ft_b; mpz_init_set_ui(z_ft_b, 2); mpz_t z_ft_n; mpz_init(z_ft_n); static uint32 primeTupleBias[6] = {0,4,6,10,12,16}; for(uint32 i=5; i<riecoin_primeTestSize; i++) { for(uint32 f=0; f<6; f++) { uint32 p = riecoin_primeTestTable[i]; uint32 remainder = mpz_tdiv_ui(z_temp, p);//; remainder += primeTupleBias[f]; remainder %= p; uint32 index; // a+b*x=0 (mod p) => b*x=p-a => x = (p-a)*modinv(b) sint32 pa = (p<remainder)?(p-remainder+p):(p-remainder); sint32 b = 2310; index = (pa%p)*int_invert(b, p); index %= p; while(index < riecoin_sieveSize) { sieve[(index)>>3] |= (1<<((index)&7)); index += p; } } } uint32 countCandidates = 0; uint32 countPrimes = 0; uint32 countPrimes2 = 0; // scan for candidates for(uint32 i=1; i<riecoin_sieveSize; i++) { if( sieve[(i)>>3] & (1<<((i)&7)) ) continue; countCandidates++; // test the first 4 numbers for being prime (5th and 6th is checked server side) // we use fermat test as it is slightly faster for virtually the same accuracy // p1 mpz_add_ui(z_temp, z_target, (uint64)remainder2310 + 2310ULL*(uint64)i); mpz_sub_ui(z_ft_n, z_temp, 1); mpz_powm(z_ft_r, z_ft_b, z_ft_n, z_temp); if (mpz_cmp_ui(z_ft_r, 1) != 0) continue; else countPrimes++; // p2 mpz_add_ui(z_temp, z_temp, 4); mpz_sub_ui(z_ft_n, z_temp, 1); mpz_powm(z_ft_r, z_ft_b, z_ft_n, z_temp); if (mpz_cmp_ui(z_ft_r, 1) != 0) continue; else countPrimes2++; total2ChainCount++; // p3 mpz_add_ui(z_temp, z_temp, 2); if( mpz_probab_prime_p(z_temp, 1) == 0 ) continue; total3ChainCount++; // p4 mpz_add_ui(z_temp, z_temp, 4); if( mpz_probab_prime_p(z_temp, 1) == 0 ) continue; total4ChainCount++; // calculate offset mpz_add_ui(z_temp, z_target, (uint64)remainder2310 + 2310ULL*(uint64)i); mpz_sub(z_temp2, z_temp, z_target); // submit share uint8 nOffset[32]; memset(nOffset, 0x00, 32); #ifdef _WIN64 for(uint32 d=0; d<min(32/8, z_temp2->_mp_size); d++) { *(uint64*)(nOffset+d*8) = z_temp2->_mp_d[d]; } #else for(uint32 d=0; d<min(32/4, z_temp2->_mp_size); d++) { *(uint32*)(nOffset+d*4) = z_temp2->_mp_d[d]; } #endif totalShareCount++; xptMiner_submitShare(block, nOffset); } }
int mpz_perfect_power_p (mpz_srcptr u) { unsigned long int prime; unsigned long int n, n2; int i; unsigned long int rem; mpz_t u2, q; int exact; mp_size_t uns; mp_size_t usize = SIZ (u); TMP_DECL (marker); if (usize == 0) return 1; /* consider 0 a perfect power */ n2 = mpz_scan1 (u, 0); if (n2 == 1) return 0; /* 2 divides exactly once. */ if (n2 != 0 && (n2 & 1) == 0 && usize < 0) return 0; /* 2 has even multiplicity with negative U */ TMP_MARK (marker); uns = ABS (usize) - n2 / BITS_PER_MP_LIMB; MPZ_TMP_INIT (q, uns); MPZ_TMP_INIT (u2, uns); mpz_tdiv_q_2exp (u2, u, n2); if (isprime (n2)) goto n2prime; for (i = 1; primes[i] != 0; i++) { prime = primes[i]; rem = mpz_tdiv_ui (u2, prime); if (rem == 0) /* divisable by this prime? */ { rem = mpz_tdiv_q_ui (q, u2, prime * prime); if (rem != 0) { TMP_FREE (marker); return 0; /* prime divides exactly once, reject */ } mpz_swap (q, u2); for (n = 2;;) { rem = mpz_tdiv_q_ui (q, u2, prime); if (rem != 0) break; mpz_swap (q, u2); n++; } if ((n & 1) == 0 && usize < 0) { TMP_FREE (marker); return 0; /* even multiplicity with negative U, reject */ } n2 = gcd (n2, n); if (n2 == 1) { TMP_FREE (marker); return 0; /* we have multiplicity 1 of some factor */ } if (mpz_cmpabs_ui (u2, 1) == 0) { TMP_FREE (marker); return 1; /* factoring completed; consistent power */ } /* As soon as n2 becomes a prime number, stop factoring. Either we have u=x^n2 or u is not a perfect power. */ if (isprime (n2)) goto n2prime; } } if (n2 == 0) { /* We found no factors above; have to check all values of n. */ unsigned long int nth; for (nth = usize < 0 ? 3 : 2;; nth++) { if (! isprime (nth)) continue; #if 0 exact = mpz_padic_root (q, u2, nth, PTH); if (exact) #endif exact = mpz_root (q, u2, nth); if (exact) { TMP_FREE (marker); return 1; } if (mpz_cmp_ui (q, SMALLEST_OMITTED_PRIME) < 0) { TMP_FREE (marker); return 0; } } } else { unsigned long int nth; /* We found some factors above. We just need to consider values of n that divides n2. */ for (nth = 2; nth <= n2; nth++) { if (! isprime (nth)) continue; if (n2 % nth != 0) continue; #if 0 exact = mpz_padic_root (q, u2, nth, PTH); if (exact) #endif exact = mpz_root (q, u2, nth); if (exact) { TMP_FREE (marker); return 1; } if (mpz_cmp_ui (q, SMALLEST_OMITTED_PRIME) < 0) { TMP_FREE (marker); return 0; } } TMP_FREE (marker); return 0; } n2prime: exact = mpz_root (NULL, u2, n2); TMP_FREE (marker); return exact; }
/** * calculates the multipliers for sieving * a multiplier or sieve factor i is * the inverse of H % p, so that ((i + n * p) * H) % p == 1 or * i = p - (in verse of H % p) so that ((i + n * p) * H) % p == p - i == -1 % p */ static inline void calc_multipliers(Sieve *const sieve, const mpz_t mpz_primorial) { #ifdef PRINT_TIME uint64_t start_time = gettime_usec(); #endif uint32_t *const cc1_muls = sieve->cc1_muls; uint32_t *const cc2_muls = sieve->cc2_muls; /* generate the multiplicators for the first layer first */ uint32_t i; for (i = min_prime_index; sieve->active && i < max_prime_index; i++) { /* current prime */ const uint32_t prime = primes[i]; /* modulo = primorial % prime */ const uint32_t modulo = (uint32_t) mpz_tdiv_ui(mpz_primorial, prime); /* nothing in the sieve is divisible by this prime */ if (modulo == 0) continue; uint32_t factor = invert(modulo, prime); const uint32_t two_inverse = two_inverses[i]; const uint32_t offset = layers * i; uint32_t l; if (i < int64_arithmetic) { for (l = 0; l < layers; l++) { cc1_muls[offset + l] = factor; cc2_muls[offset + l] = prime - factor; /* calc factor for the next number in chain */ factor = (factor * two_inverse) % prime; } } else { for (l = 0; l < layers; l++) { cc1_muls[offset + l] = factor; cc2_muls[offset + l] = prime - factor; /* calc factor for the next number in chain */ factor = (uint32_t) ((((uint64_t) factor) * ((uint64_t) two_inverse)) % ((uint64_t) prime)); } } } #ifdef PRINT_TIME error_msg("[DD] calulating mulls: %" PRIu64 "\n", gettime_usec() - start_time); #endif /* run test if DEBUG is enabeld */ check_mulltiplier(mpz_primorial, cc1_muls, cc2_muls, sieve_size, layers, primes, min_prime_index, max_prime_index); }
/*------------------------------------------------------------------------*/ static uint32 get_composite_roots(sieve_fb_t *s, curr_poly_t *c, uint32 which_poly, uint64 p, uint32 num_factors, uint32 *factors, uint32 num_roots_min, uint32 num_roots_max) { uint32 i, j, k, i0, i1, i2, i3, i4, i5, i6; uint32 crt_p[MAX_P_FACTORS]; uint32 num_roots[MAX_P_FACTORS]; uint64 prod[MAX_P_FACTORS]; uint32 roots[MAX_P_FACTORS][MAX_POLYSELECT_DEGREE]; aprog_t *aprogs = s->aprog_data.aprogs; uint32 degree = s->degree; for (i = 0, j = 1; i < num_factors; i++) { aprog_t *a; if (i > 0 && factors[i] == factors[i-1]) continue; a = aprogs + factors[i]; if (a->num_roots[which_poly] == 0) return 0; j *= a->num_roots[which_poly]; } if (j < num_roots_min || j > num_roots_max) return INVALID_NUM_ROOTS; for (i = j = 0; j < MAX_P_FACTORS && i < num_factors; i++, j++) { aprog_t *a = aprogs + factors[i]; uint32 power_limit; num_roots[j] = a->num_roots[which_poly]; crt_p[j] = a->p; power_limit = (uint32)(-1) / a->p; for (k = 0; k < num_roots[j]; k++) { roots[j][k] = a->roots[which_poly][k]; } while (i < num_factors - 1 && factors[i] == factors[i+1]) { uint32 nmodp, new_power; if (crt_p[j] > power_limit) return 0; new_power = crt_p[j] * a->p; nmodp = mpz_tdiv_ui(c->trans_N, (mp_limb_t)new_power); for (k = 0; k < num_roots[j]; k++) { roots[j][k] = lift_root_32(nmodp, roots[j][k], crt_p[j], a->p, degree); } crt_p[j] = new_power; i++; } } if (i < num_factors) return 0; num_factors = j; if (num_factors == 1) { for (i = 0; i < num_roots[0]; i++) mpz_set_ui(s->roots[i], (mp_limb_t)roots[0][i]); return num_roots[0]; } for (i = 0; i < num_factors; i++) { prod[i] = p / crt_p[i]; prod[i] = prod[i] * mp_modinv_1((uint32)(prod[i] % crt_p[i]), crt_p[i]); } mpz_set_ui(s->accum[i], (mp_limb_t)0); uint64_2gmp(p, s->p); i0 = i1 = i2 = i3 = i4 = i5 = i6 = i = 0; switch (num_factors) { case 7: for (i6 = num_roots[6] - 1; (int32)i6 >= 0; i6--) { uint64_2gmp(prod[6], s->accum[6]); mpz_mul_ui(s->accum[6], s->accum[6], (mp_limb_t)roots[6][i6]); mpz_add(s->accum[6], s->accum[6], s->accum[7]); case 6: for (i5 = num_roots[5] - 1; (int32)i5 >= 0; i5--) { uint64_2gmp(prod[5], s->accum[5]); mpz_mul_ui(s->accum[5], s->accum[5], (mp_limb_t)roots[5][i5]); mpz_add(s->accum[5], s->accum[5], s->accum[6]); case 5: for (i4 = num_roots[4] - 1; (int32)i4 >= 0; i4--) { uint64_2gmp(prod[4], s->accum[4]); mpz_mul_ui(s->accum[4], s->accum[4], (mp_limb_t)roots[4][i4]); mpz_add(s->accum[4], s->accum[4], s->accum[5]); case 4: for (i3 = num_roots[3] - 1; (int32)i3 >= 0; i3--) { uint64_2gmp(prod[3], s->accum[3]); mpz_mul_ui(s->accum[3], s->accum[3], (mp_limb_t)roots[3][i3]); mpz_add(s->accum[3], s->accum[3], s->accum[4]); case 3: for (i2 = num_roots[2] - 1; (int32)i2 >= 0; i2--) { uint64_2gmp(prod[2], s->accum[2]); mpz_mul_ui(s->accum[2], s->accum[2], (mp_limb_t)roots[2][i2]); mpz_add(s->accum[2], s->accum[2], s->accum[3]); case 2: for (i1 = num_roots[1] - 1; (int32)i1 >= 0; i1--) { uint64_2gmp(prod[1], s->accum[1]); mpz_mul_ui(s->accum[1], s->accum[1], (mp_limb_t)roots[1][i1]); mpz_add(s->accum[1], s->accum[1], s->accum[2]); for (i0 = num_roots[0] - 1; (int32)i0 >= 0; i0--) { uint64_2gmp(prod[0], s->accum[0]); mpz_mul_ui(s->accum[0], s->accum[0], (mp_limb_t)roots[0][i0]); mpz_add(s->accum[0], s->accum[0], s->accum[1]); mpz_tdiv_r(s->accum[0], s->accum[0], s->p); mpz_set(s->roots[i++], s->accum[0]); }}}}}}} } return i; }
void trial_divide_Q_siqs(uint32 report_num, uint8 parity, uint32 poly_id, uint32 bnum, static_conf_t *sconf, dynamic_conf_t *dconf) { //we have flagged this sieve offset as likely to produce a relation //nothing left to do now but check and see. uint64 q64, f64; int j,it; uint32 prime; int smooth_num; uint32 *fb_offsets; uint32 polya_factors[20]; sieve_fb *fb; uint32 offset, block_loc; fb_offsets = &dconf->fb_offsets[report_num][0]; smooth_num = dconf->smooth_num[report_num]; block_loc = dconf->reports[report_num]; #ifdef QS_TIMING gettimeofday(&qs_timing_start, NULL); #endif offset = (bnum << sconf->qs_blockbits) + block_loc; if (parity) fb = dconf->fb_sieve_n; else fb = dconf->fb_sieve_p; #ifdef USE_YAFU_TDIV z32_to_mpz(&dconf->Qvals32[report_num], dconf->Qvals[report_num]); #endif //check for additional factors of the a-poly factors //make a separate list then merge it with fb_offsets it=0; //max 20 factors allocated for - should be overkill for (j = 0; (j < dconf->curr_poly->s) && (it < 20); j++) { //fbptr = fb + dconf->curr_poly->qlisort[j]; //prime = fbptr->prime; prime = fb[dconf->curr_poly->qlisort[j]].prime; while ((mpz_tdiv_ui(dconf->Qvals[report_num],prime) == 0) && (it < 20)) { mpz_tdiv_q_ui(dconf->Qvals[report_num], dconf->Qvals[report_num], prime); polya_factors[it++] = dconf->curr_poly->qlisort[j]; } } //check if it completely factored by looking at the unfactored portion in tmp //if ((mpz_size(dconf->Qvals[report_num]) == 1) && //(mpz_get_64(dconf->Qvals[report_num]) < (uint64)sconf->large_prime_max)) if ((mpz_size(dconf->Qvals[report_num]) == 1) && (mpz_cmp_ui(dconf->Qvals[report_num], sconf->large_prime_max) < 0)) { uint32 large_prime[2]; large_prime[0] = (uint32)mpz_get_ui(dconf->Qvals[report_num]); //Q->val[0]; large_prime[1] = 1; //add this one if (sconf->is_tiny) { // we need to encode both the a_poly and b_poly index // in poly_id poly_id |= (sconf->total_poly_a << 16); buffer_relation(offset,large_prime,smooth_num+1, fb_offsets,poly_id,parity,dconf,polya_factors,it); } else buffer_relation(offset,large_prime,smooth_num+1, fb_offsets,poly_id,parity,dconf,polya_factors,it); #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); #endif return; } if (sconf->use_dlp == 0) return; //quick check if Q is way too big for DLP (more than 64 bits) if (mpz_sizeinbase(dconf->Qvals[report_num], 2) >= 64) return; q64 = mpz_get_64(dconf->Qvals[report_num]); if ((q64 > sconf->max_fb2) && (q64 < sconf->large_prime_max2)) { //quick prime check: compute 2^(residue-1) mod residue. uint64 res; //printf("%llu\n",q64); #if BITS_PER_DIGIT == 32 mpz_set_64(dconf->gmptmp1, q64); mpz_set_64(dconf->gmptmp2, 2); mpz_set_64(dconf->gmptmp3, q64-1); mpz_powm(dconf->gmptmp1, dconf->gmptmp2, dconf->gmptmp3, dconf->gmptmp1); res = mpz_get_64(dconf->gmptmp1); #else spModExp(2, q64 - 1, q64, &res); #endif //if equal to 1, assume it is prime. this may be wrong sometimes, but we don't care. //more important to quickly weed out probable primes than to spend more time to be //more sure. if (res == 1) { #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); #endif dconf->dlp_prp++; return; } //try to find a double large prime #ifdef HAVE_CUDA { uint32 large_prime[2] = {1,1}; // remember the residue and the relation it is associated with dconf->buf_id[dconf->num_squfof_cand] = dconf->buffered_rels; dconf->squfof_candidates[dconf->num_squfof_cand++] = q64; // buffer the relation buffer_relation(offset,large_prime,smooth_num+1, fb_offsets,poly_id,parity,dconf,polya_factors,it); } #else dconf->attempted_squfof++; mpz_set_64(dconf->gmptmp1, q64); f64 = sp_shanks_loop(dconf->gmptmp1, sconf->obj); if (f64 > 1 && f64 != q64) { uint32 large_prime[2]; large_prime[0] = (uint32)f64; large_prime[1] = (uint32)(q64 / f64); if (large_prime[0] < sconf->large_prime_max && large_prime[1] < sconf->large_prime_max) { //add this one dconf->dlp_useful++; buffer_relation(offset,large_prime,smooth_num+1, fb_offsets,poly_id,parity,dconf,polya_factors,it); } } else { dconf->failed_squfof++; //printf("squfof failure: %" PRIu64 "\n", q64); } #endif } else dconf->dlp_outside_range++; #ifdef QS_TIMING gettimeofday (&qs_timing_stop, NULL); qs_timing_diff = my_difftime (&qs_timing_start, &qs_timing_stop); TF_STG6 += ((double)qs_timing_diff->secs + (double)qs_timing_diff->usecs / 1000000); free(qs_timing_diff); #endif return; }
/** * @brief Get the number of "half move clock" * @param[in] id The identifier used * @return [|0;51|] the number of half moves * * This function returns the number of half moves done * since the last pawn move or capture, it is used for * the fifty-move rule. * */ int identifier_get_halfmove(Identifier id) { int ret; ret = mpz_tdiv_ui(id, 100); return ret; }
/*------------------------------------------------------------------------*/ static void sieve_add_aprog(sieve_fb_t *s, poly_coeff_t *c, uint32 p, uint32 fb_roots_min, uint32 fb_roots_max) { uint32 i, j, nmodp, num_roots; uint32 degree = c->degree; uint32 power, power_limit; uint32 roots[MAX_POLYSELECT_DEGREE]; aprog_list_t *list = &s->aprog_data; aprog_t *a; /* p will be able to generate arithmetic progressions; add it to our list of them... */ if (list->num_aprogs == list->num_aprogs_alloc) { list->num_aprogs_alloc *= 2; list->aprogs = (aprog_t *)xrealloc(list->aprogs, list->num_aprogs_alloc * sizeof(aprog_t)); } /* ...if trans_N has any degree_th roots mod p */ a = list->aprogs + list->num_aprogs; a->p = p; num_roots = get_prime_roots(c, p, roots, &s->tmp_poly); if (num_roots == 0 || num_roots < fb_roots_min || num_roots > fb_roots_max) return; list->num_aprogs++; a->num_roots = num_roots; power = p; power_limit = (uint32)(-1) / p; for (i = 1; i < MAX_POWERS && power < power_limit; i++) power *= p; a->max_power = i; a->powers[0].power = p; for (i = 0; i < num_roots; i++) a->powers[0].roots[i] = roots[i]; /* add powers of p as well */ power = p; for (i = 1; i < a->max_power; i++) { power *= p; a->powers[i].power = power; nmodp = mpz_tdiv_ui(c->trans_N, (mp_limb_t)power); for (j = 0; j < num_roots; j++) a->powers[i].roots[j] = lift_root_32(nmodp, a->powers[i - 1].roots[j], a->powers[i - 1].power, p, degree); } }