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;
}
Beispiel #2
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);
}
Beispiel #3
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;
}
Beispiel #4
0
/**
 *  @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;
}
Beispiel #5
0
/**
 *  @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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
}
Beispiel #9
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);
}
Beispiel #10
0
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
}
Beispiel #11
0
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);
}
Beispiel #12
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
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);
	}
}
Beispiel #18
0
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;
}
Beispiel #19
0
/**
 * 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);

}
Beispiel #20
0
/*------------------------------------------------------------------------*/
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;
}
Beispiel #21
0
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;
}
Beispiel #22
0
/**
 *  @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);
	}
}