Ejemplo n.º 1
0
static PyObject *
GMPy_MPZ_Function_Remove(PyObject *self, PyObject *args)
{
    MPZ_Object *result = NULL, *tempx = NULL, *tempf = NULL;
    PyObject *x, *f;
    size_t multiplicity;

    if (PyTuple_GET_SIZE(args) != 2) {
        TYPE_ERROR("remove() requires 'mpz','mpz' arguments");
        return NULL;
    }

    if (!(result = GMPy_MPZ_New(NULL))) {
        /* LCOV_EXCL_START */
        return NULL;
        /* LCOV_EXCL_STOP */
    }

    x = PyTuple_GET_ITEM(args, 0);
    f = PyTuple_GET_ITEM(args, 1);

    if (MPZ_Check(x) && MPZ_Check(f)) {
        if (mpz_cmp_si(MPZ(f), 2) < 0) {
            VALUE_ERROR("factor must be > 1");
            Py_DECREF((PyObject*)result);
            return NULL;
        }
        multiplicity = mpz_remove(result->z, MPZ(x), MPZ(f));
        return Py_BuildValue("(Nk)", result, multiplicity);
    }
    else {


        if (!(tempx = GMPy_MPZ_From_Integer(x, NULL)) ||
            !(tempf = GMPy_MPZ_From_Integer(f, NULL))) {

            TYPE_ERROR("remove() requires 'mpz','mpz' arguments");
            Py_XDECREF((PyObject*)tempx);
            Py_XDECREF((PyObject*)tempf);
            Py_DECREF((PyObject*)result);
            return NULL;
        }
        if (mpz_cmp_si(MPZ(tempf), 2) < 0) {
            VALUE_ERROR("factor must be > 1");
            Py_DECREF((PyObject*)tempx);
            Py_DECREF((PyObject*)tempf);
            Py_DECREF((PyObject*)result);
            return NULL;
        }
        multiplicity = mpz_remove(result->z, tempx->z, tempf->z);
        return Py_BuildValue("(Nk)", result, multiplicity);
    }
}
Ejemplo n.º 2
0
int
main (int argc, char **argv)
{
  gmp_randstate_ptr rands;
  long count = COUNT;
  mp_ptr mp;
  mp_ptr ap;
  mp_ptr tp;
  mp_ptr scratch;
  mpz_t m, a, r, g;
  int test;
  mp_limb_t ran;
  mp_size_t itch;
  TMP_DECL;

  tests_start ();
  rands = RANDS;


  TMP_MARK;
  mpz_init (m);
  mpz_init (a);
  mpz_init (r);
  mpz_init (g);

  if (argc > 1)
    {
      char *end;
      count = strtol (argv[1], &end, 0);
      if (*end || count <= 0)
	{
	  fprintf (stderr, "Invalid test count: %s.\n", argv[1]);
	  return 1;
	}
    }

  mp = TMP_ALLOC_LIMBS (MAX_SIZE);
  ap = TMP_ALLOC_LIMBS (MAX_SIZE);
  tp = TMP_ALLOC_LIMBS (MAX_SIZE);
  scratch = TMP_ALLOC_LIMBS (mpn_sec_invert_itch (MAX_SIZE) + 1);

  for (test = 0; test < count; test++)
    {
      mp_bitcnt_t bits;
      int rres, tres;
      mp_size_t n;

      bits = urandom () % (GMP_NUMB_BITS * MAX_SIZE) + 1;

      if (test & 1)
	mpz_rrandomb (m, rands, bits);
      else
	mpz_urandomb (m, rands, bits);
      if (test & 2)
	mpz_rrandomb (a, rands, bits);
      else
	mpz_urandomb (a, rands, bits);

      mpz_setbit (m, 0);
      if (test & 4)
	{
	  /* Ensure it really is invertible */
	  if (mpz_sgn (a) == 0)
	    mpz_set_ui (a, 1);
	  else
	    for (;;)
	      {
		mpz_gcd (g, a, m);
		if (mpz_cmp_ui (g, 1) == 0)
		  break;
		mpz_remove (a, a, g);
	      }
	}

      rres = mpz_invert (r, a, m);
      if ( (test & 4) && !rres)
	{
	  gmp_fprintf (stderr, "test %d: Not invertible!\n"
		       "m = %Zd\n"
		       "a = %Zd\n", test, m, a);
	  abort ();
	}
      ASSERT_ALWAYS (! (test & 4) || rres);

      n = (bits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
      ASSERT_ALWAYS (n <= MAX_SIZE);
      itch = mpn_sec_invert_itch (n);
      scratch[itch] = ran = urandom ();

      mpz_to_mpn (ap, n, a);
      mpz_to_mpn (mp, n, m);
      tres = mpn_sec_invert (tp, ap, mp, n,
			     bit_size (ap, n) + bit_size (mp, n),
			     scratch);

      if (rres != tres || (rres == 1 && !mpz_eq_mpn (tp, n, r)) || ran != scratch[itch])
	{
	  gmp_fprintf (stderr, "Test %d failed.\n"
		       "m = %Zd\n"
		       "a = %Zd\n", test, m, a);
	  fprintf (stderr, "ref ret: %d\n"
		  "got ret: %d\n", rres, tres);
	  if (rres)
	    gmp_fprintf (stderr, "ref: %Zd\n", r);
	  if (tres)
	    gmp_fprintf (stderr, "got: %Nd\n", tp, n);
	  if (ran != scratch[itch])
	    fprintf (stderr, "scratch[itch] changed.\n");
	  abort ();
	}
    }

  TMP_FREE;

  mpz_clear (m);
  mpz_clear (a);
  mpz_clear (r);
  mpz_clear (g);

  tests_end ();
  return 0;
}
Ejemplo n.º 3
0
int main(int argc, char **argv) {
	gettimeofday(&start_global, NULL);
	print_lib_version();

	mpz_init(N);
	mpz_t B;
	mpz_init(B);

	unsigned long int uBase;
	int64_t nb_primes;
	modular_root_t *modular_roots;

	uint64_t i, j;

	if (mpz_init_set_str(N, argv[1], 10) == -1) {
		printf("Cannot load N %s\n", argv[1]);
		exit(2);
	}

	mpz_t sqrtN, rem;
	mpz_init(sqrtN);
	mpz_init(rem);
	mpz_sqrtrem(sqrtN, rem, N);

	if (mpz_cmp_ui(rem, 0) != 0) /* if not perfect square, calculate the ceiling */
		mpz_add_ui(sqrtN, sqrtN, 1);
	else /* N is a perfect square, factored! */
	{
		printf("\n<<<[FACTOR]>>> %s\n", mpz_get_str(NULL, 10, sqrtN));
		return 0;
	}

	if (mpz_probab_prime_p(N, 10) > 0) /* don't bother factoring */
	{
		printf("N:%s is prime\n", mpz_get_str(NULL, 10, N));
		exit(0);
	}

	OPEN_LOG_FILE("freq");

//--------------------------------------------------------
//  calculate the smoothness base for the given N
//--------------------------------------------------------
	get_smoothness_base(B, N); /* if N is too small, the program will surely fail, please consider a pen and paper instead */
	uBase = mpz_get_ui(B);
	printf("n: %s\tBase: %s\n", mpz_get_str(NULL, 10, N),
			mpz_get_str(NULL, 10, B));

//--------------------------------------------------------
// sieve primes that are less than the smoothness base using Eratosthenes sieve
//--------------------------------------------------------
	START_TIMER();
	nb_primes = sieve_primes_up_to((int64_t) (uBase));

	printf("\nPrimes found %" PRId64 " [Smoothness Base %lu]\n", nb_primes,
			uBase);
	STOP_TIMER_PRINT_TIME("\tEratosthenes Sieving done");

//--------------------------------------------------------
// fill the primes array with primes to which n is a quadratic residue
//--------------------------------------------------------
	START_TIMER();
	primes = calloc(nb_primes, sizeof(int64_t));
	nb_qr_primes = fill_primes_with_quadratic_residue(primes, N);

	/*for(i=0; i<nb_qr_primes; i++)
	 printf("%" PRId64 "\n", primes[i]);*/

	printf("\nN-Quadratic primes found %" PRId64 "\n", nb_qr_primes);
	STOP_TIMER_PRINT_TIME("\tQuadratic prime filtering done");

//--------------------------------------------------------
// calculate modular roots
//--------------------------------------------------------
	START_TIMER();
	modular_roots = calloc(nb_qr_primes, sizeof(modular_root_t));
	mpz_t tmp, r1, r2;
	mpz_init(tmp);
	mpz_init(r1);
	mpz_init(r2);

	for (i = 0; i < nb_qr_primes; i++) {
		mpz_set_ui(tmp, (unsigned long) primes[i]);
		mpz_sqrtm(r1, N, tmp); /* calculate the modular root */
		mpz_neg(r2, r1); /* -q mod n */
		mpz_mod(r2, r2, tmp);

		modular_roots[i].root1 = mpz_get_ui(r1);
		modular_roots[i].root2 = mpz_get_ui(r2);
	}
	mpz_clear(tmp);
	mpz_clear(r1);
	mpz_clear(r2);
	STOP_TIMER_PRINT_TIME("\nModular roots calculation done");

	/*for(i=0; i<nb_qr_primes; i++)
	 {
	 printf("[%10" PRId64 "-> roots: %10u - %10u]\n", primes[i], modular_roots[i].root1, modular_roots[i].root2);
	 }*/

//--------------------------------------------------------
//         ***** initialize the matrix *****
//--------------------------------------------------------
	START_TIMER();
	init_matrix(&matrix, nb_qr_primes + NB_VECTORS_OFFSET, nb_qr_primes);
	mpz_init2(tmp_matrix_row, nb_qr_primes);
	STOP_TIMER_PRINT_TIME("\nMatrix initialized");

//--------------------------------------------------------
// [Sieving]
//--------------------------------------------------------
	START_TIMER();

	mpz_t x, sieving_index, next_sieving_index;
	unsigned long ui_index, SIEVING_STEP = 50000; /* we sieve for 50000 elements at each loop */
	uint64_t p_pow;
	smooth_number_t *x_squared;

	x_squared = calloc(SIEVING_STEP, sizeof(smooth_number_t));
	smooth_numbers = calloc(nb_qr_primes + NB_VECTORS_OFFSET,
			sizeof(smooth_number_t));

	mpz_init_set(x, sqrtN);
	mpz_init_set(sieving_index, x);
	mpz_init_set(next_sieving_index, x);

	mpz_t p;
	mpz_init(p);
	mpz_t str;
	mpz_init_set(str, sieving_index);
	printf("\nSieving ...\n");

//--------------------------------------------------------
// Init before sieving
//--------------------------------------------------------
	for (i = 0; i < SIEVING_STEP; i++) {
		mpz_init(x_squared[i].value_x);
		mpz_init(x_squared[i].value_x_squared);

		/* the factors_exp array is used to keep track of exponents */
		//x_squared[i].factors_exp = calloc(nb_qr_primes, sizeof(uint64_t));
		/* we use directly the exponents vector modulo 2 to preserve space */mpz_init2(
				x_squared[i].factors_vect, nb_qr_primes);
		mpz_add_ui(x, x, 1);
	}

	int nb_smooth_per_round = 0;
	char s[512];

//--------------------------------------------------------
// WHILE smooth numbers found less than the primes in the smooth base + NB_VECTORS_OFFSET
//--------------------------------------------------------
	while (nb_smooth_numbers_found < nb_qr_primes + NB_VECTORS_OFFSET) {
		nb_smooth_per_round = 0;
		mpz_set(x, next_sieving_index); /* sieve numbers from sieving_index to sieving_index + sieving_step */
		mpz_set(sieving_index, next_sieving_index);

		printf("\r");
		printf(
				"\t\tSieving at: %s30 <--> Smooth numbers found: %" PRId64 "/%" PRId64 "",
				mpz_get_str(NULL, 10, sieving_index), nb_smooth_numbers_found,
				nb_qr_primes);
		fflush(stdout);

		for (i = 0; i < SIEVING_STEP; i++) {
			mpz_set(x_squared[i].value_x, x);

			mpz_pow_ui(x_squared[i].value_x_squared, x, 2); /* calculate value_x_squared <- x²-n */
			mpz_sub(x_squared[i].value_x_squared, x_squared[i].value_x_squared,
					N);

			mpz_clear(x_squared[i].factors_vect);
			mpz_init2(x_squared[i].factors_vect, nb_qr_primes); /* reconstruct a new fresh 0ed vector of size nb_qr_primes bits */

			mpz_add_ui(x, x, 1);
		}
		mpz_set(next_sieving_index, x);

//--------------------------------------------------------
// eliminate factors in the x_squared array, those who are 'destructed' to 1 are smooth
//--------------------------------------------------------

		for (i = 0; i < nb_qr_primes; i++) {
			mpz_set_ui(p, (unsigned long) primes[i]);
			mpz_set(x, sieving_index);

			/* get the first multiple of p that is directly larger that sieving_index
			 * Quadratic SIEVING: all elements from this number and in positions multiples of root1 and root2
			 * are also multiples of p */
			get_sieving_start_index(x, x, p, modular_roots[i].root1);
			mpz_set(str, x);
			mpz_sub(x, x, sieving_index); /* x contains index of first number that is divisible by p */

			for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) {
				p_pow = mpz_remove(x_squared[j].value_x_squared,
						x_squared[j].value_x_squared, p); /* eliminate all factors of p */

				if (p_pow & 1) /* mark bit if odd power of p exists in this x_squared[j] */
				{
					mpz_setbit(x_squared[j].factors_vect, i);
				}

				if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) {
					save_smooth_number(x_squared[j]);
					nb_smooth_per_round++;
				}
				/* sieve next element located p steps from here */
			}

			/* same goes for root2 */
			if (modular_roots[i].root2 == modular_roots[i].root1)
				continue;

			mpz_set(x, sieving_index);

			get_sieving_start_index(x, x, p, modular_roots[i].root2);
			mpz_set(str, x);
			mpz_sub(x, x, sieving_index);

			for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) {
				p_pow = mpz_remove(x_squared[j].value_x_squared,
						x_squared[j].value_x_squared, p);

				if (p_pow & 1) {
					mpz_setbit(x_squared[j].factors_vect, i);
				}

				if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) {
					save_smooth_number(x_squared[j]);
					nb_smooth_per_round++;
				}
			}
		}
		//printf("\tSmooth numbers found %" PRId64 "\n", nb_smooth_numbers_found);
		/*sprintf(s, "[start: %s - end: %s - step: %" PRId64 "] nb_smooth_per_round: %d",
		 mpz_get_str(NULL, 10, sieving_index),
		 mpz_get_str(NULL, 10, next_sieving_index),
		 SIEVING_STEP,
		 nb_smooth_per_round);
		 APPEND_TO_LOG_FILE(s);*/
	}

	STOP_TIMER_PRINT_TIME("\nSieving DONE");

	uint64_t t = 0;

//--------------------------------------------------------
//the matrix ready, start Gauss elimination. The Matrix is filled on the call of save_smooth_number()
//--------------------------------------------------------
	START_TIMER();
	gauss_elimination(&matrix);
	STOP_TIMER_PRINT_TIME("\nGauss elimination done");
	//print_matrix_matrix(&matrix);
	//print_matrix_identity(&matrix);

	uint64_t row_index = nb_qr_primes + NB_VECTORS_OFFSET - 1; /* last row in the matrix */
	int nb_linear_relations = 0;
	mpz_t linear_relation_z, solution_z;
	mpz_init(linear_relation_z);
	mpz_init(solution_z);

	get_matrix_row(linear_relation_z, &matrix, row_index--); /* get the last few rows in the Gauss eliminated matrix*/
	while (mpz_cmp_ui(linear_relation_z, 0) == 0) {
		nb_linear_relations++;
		get_matrix_row(linear_relation_z, &matrix, row_index--);
	}

	printf("\tLinear dependent relations found : %d\n", nb_linear_relations);

//--------------------------------------------------------
// Factor
//--------------------------------------------------------
	//We use the last linear relation to reconstruct our solution
	START_TIMER();
	printf("\nFactorizing..\n");
	mpz_t solution_X, solution_Y;
	mpz_init(solution_X);
	mpz_init(solution_Y);

	/* we start testing from the first linear relation encountered in the matrix */
	for (j = nb_linear_relations; j > 0; j--) {
		printf("Trying %d..\n", nb_linear_relations - j + 1);
		mpz_set_ui(solution_X, 1);
		mpz_set_ui(solution_Y, 1);

		get_identity_row(solution_z, &matrix,
				nb_qr_primes + NB_VECTORS_OFFSET - j + 1);

		for (i = 0; i < nb_qr_primes; i++) {
			if (mpz_tstbit(solution_z, i)) {
				mpz_mul(solution_X, solution_X, smooth_numbers[i].value_x);
				mpz_mod(solution_X, solution_X, N); /* reduce x to modulo N */

				mpz_mul(solution_Y, solution_Y,
						smooth_numbers[i].value_x_squared);
				/*TODO: handling huge stuff here, there is no modulo N like in the solution_X case!
				 * eliminate squares as long as you go*/
			}
		}

		mpz_sqrt(solution_Y, solution_Y);
		mpz_mod(solution_Y, solution_Y, N); /* y = sqrt(MUL(xi²-n)) mod N */

		mpz_sub(solution_X, solution_X, solution_Y);

		mpz_gcd(solution_X, solution_X, N);

		if (mpz_cmp(solution_X, N) != 0 && mpz_cmp_ui(solution_X, 1) != 0) /* factor can be 1 or N, try another relation */
			break;
	}
	mpz_cdiv_q(solution_Y, N, solution_X);

	printf("\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N));
	printf("\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X),
			mpz_get_str(NULL, 10, solution_Y));

	/*sprintf(s, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N));
	 APPEND_TO_LOG_FILE(s);
	 sprintf(s, "\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y));
	 APPEND_TO_LOG_FILE(s);

	 gettimeofday(&end_global, NULL);
	 timersub(&end_global, &start_global, &elapsed);
	 sprintf(s, "****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000);
	 APPEND_TO_LOG_FILE(s);*/

	STOP_TIMER_PRINT_TIME("\nFactorizing done");

	printf("Cleaning memory..\n");

	/********************** clear the x_squared array **********************/
	for (i = 0; i < SIEVING_STEP; i++) {
		mpz_clear(x_squared[i].value_x);
		mpz_clear(x_squared[i].value_x_squared);
		//free(x_squared[i].factors_exp);
		mpz_clear(x_squared[i].factors_vect);
	}
	free(x_squared);
	/********************** clear the x_squared array **********************/

	free(modular_roots);
	/********************** clear the smooth_numbers array **********************/
	for (i = 0; i < nb_qr_primes + NB_VECTORS_OFFSET; i++) {
		mpz_clear(smooth_numbers[i].value_x);
		mpz_clear(smooth_numbers[i].value_x_squared);
		//free(smooth_numbers[i].factors_exp);
	}
	free(smooth_numbers);
	/********************** clear the smooth_numbers array **********************/

	free(primes);
	/********************** clear mpz _t **********************/mpz_clear(B);
	mpz_clear(N);
	sqrtN, rem;
	mpz_clear(x);
	mpz_clear(sieving_index);
	mpz_clear(next_sieving_index);
	mpz_clear(p);
	mpz_clear(str);
	/********************** clear mpz _t **********************/

	free_matrix(&matrix);

	gettimeofday(&end_global, NULL);
	timersub(&end_global, &start_global, &elapsed);
	printf("****** TOTAL TIME: %.3f ms\n",
			elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000);
	show_mem_usage();
	return 0;
}
Ejemplo n.º 4
0
unsigned long tiny_evaluate_candidate(linalg_t * la_inf, QS_t * qs_inf, poly_t * poly_inf, 
                          unsigned long i, unsigned char * sieve)
{
   unsigned long bits, exp, extra_bits, modp, prime;
   unsigned long num_primes = qs_inf->num_primes;
   prime_t * factor_base = qs_inf->factor_base;
   unsigned long * soln1 = poly_inf->soln1;
   unsigned long * soln2 = poly_inf->soln2;
   unsigned long * small = la_inf->small;
   fac_t * factor = la_inf->factor;
   unsigned long A = poly_inf->A;
   unsigned long B = poly_inf->B;
   unsigned long num_factors = 0;
   unsigned long j;
   mpz_t * C = &poly_inf->C;
   unsigned long relations = 0;
   double pinv;
   
   mpz_t X, Y, res, p;
   mpz_init(X); 
   mpz_init(Y); 
   mpz_init(res); 
   mpz_init(p); 
    
#if POLYS
   printf("X = %ld\n", i);
   printf("%ldX^2+2*%ldX+%ld\n", A, B, C);
#endif

   mpz_set_ui(X, i);
   mpz_sub_ui(X, X, SIEVE_SIZE/2); //X
              
   mpz_mul_ui(Y, X, A);
   if ((long) B < 0) 
   {
      mpz_sub_ui(Y, Y, -B);  // Y = AX+B
      mpz_sub_ui(res, Y, -B);  
   }
   else 
   {
      mpz_add_ui(Y, Y, B);
      mpz_add_ui(res, Y, B);
   }
   mpz_mul(res, res, X);  
   mpz_add(res, res, *C); // res = AX^2+2BX+C
           
   bits = mpz_sizeinbase(res, 2);
   bits -= 10; 
   extra_bits = 0;
   
   mpz_set_ui(p, 2); // divide out by powers of 2
   exp = mpz_remove(res, res, p);

#if RELATIONS
   if (exp) printf("2^%ld ", exp);
#endif
   extra_bits += exp;
   small[1] = exp;
     
   if (factor_base[0].p != 1) // divide out powers of the multiplier
   {
      mpz_set_ui(p, factor_base[0].p);
      exp = mpz_remove(res, res, p);
      if (exp) extra_bits += exp*qs_inf->sizes[0];
      small[0] = exp;
#if RELATIONS
      if (exp) printf("%ld^%ld ", factor_base[0].p, exp); 
#endif
   } else small[0] = 0;
   
   
   for (j = 2; j < SMALL_PRIMES; j++) // pull out small primes
   {
      prime = factor_base[j].p;
      pinv = factor_base[j].pinv;
      modp = z_mod_64_precomp(i, prime, pinv);
      if ((modp == soln1[j]) || (modp == soln2[j]))
      {
         mpz_set_ui(p, prime);
         exp = mpz_remove(res, res, p);
         if (exp) extra_bits += qs_inf->sizes[j];
         small[j] = exp;
#if RELATIONS
         if (exp) gmp_printf("%Zd^%ld ", p, exp); 
#endif
      } else small[j] = 0;
   }
   
   if (extra_bits + sieve[i] > bits)
   {
      sieve[i] += extra_bits;
      for (j = SMALL_PRIMES; (j < num_primes) && (extra_bits < sieve[i]); j++) // pull out remaining primes
      {
         prime = factor_base[j].p;
         pinv = factor_base[j].pinv;
         modp = z_mod_64_precomp(i, prime, pinv);
         if (soln2[j] != -1L)
         {
            if ((modp == soln1[j]) || (modp == soln2[j]))
            {
               mpz_set_ui(p, prime);
               exp = mpz_remove(res, res, p);
#if RELATIONS
               if (exp) gmp_printf("%Zd^%ld ", p, exp);
#endif
               if (exp) 
               {
                  extra_bits += qs_inf->sizes[j];
                  factor[num_factors].ind = j;
                  factor[num_factors++].exp = exp; 
               }
            }
         } else
         {
            mpz_set_ui(p, prime);
            exp = mpz_remove(res, res, p);
            factor[num_factors].ind = j;
            factor[num_factors++].exp = exp+1; 
#if RELATIONS
            if (exp) gmp_printf("%Zd^%ld ", p, exp);
#endif
         }    
      }
      if (mpz_cmpabs_ui(res, 1) == 0) // We've found a relation
      {
         unsigned long * A_ind = poly_inf->A_ind;
         unsigned long i;
         for (i = 0; i < poly_inf->s; i++) // Commit any outstanding A factors
         {
            if (A_ind[i] >= j)
            {
               factor[num_factors].ind = A_ind[i];
               factor[num_factors++].exp = 1; 
            }
         }
         la_inf->num_factors = num_factors;
         relations += tiny_insert_relation(la_inf, poly_inf, Y);  // Insert the relation in the matrix
         if (la_inf->num_relations >= 2*(qs_inf->num_primes + EXTRA_RELS + 100))
         {
            printf("Error: too many duplicate relations!\n");
            abort();
         }
         goto cleanup;
      }
   }
#if RELATIONS
   printf("\n");
#endif
  
cleanup:
   mpz_clear(X);
   mpz_clear(Y);
   mpz_clear(res);
   mpz_clear(p);
      
   return relations;
}
Ejemplo n.º 5
0
int
main(void)
{
    int i, result;
    FLINT_TEST_INIT(state);

    flint_printf("remove....");
    fflush(stdout);

    

    /* Compare with MPIR, random input */
    for (i = 0; i < 1000 * flint_test_multiplier(); i++)
    {
        fmpz_t a, b, c;
        mpz_t d, e, f, g;
        slong x, y;

        fmpz_init(a);
        fmpz_init(b);
        fmpz_init(c);

        mpz_init(d);
        mpz_init(e);
        mpz_init(f);
        mpz_init(g);

        fmpz_randtest_not_zero(a, state, 200);
        do {
            fmpz_randtest_not_zero(b, state, 200);
            fmpz_abs(b, b);
        } while (fmpz_is_one(b));
        

        fmpz_get_mpz(d, a);
        fmpz_get_mpz(e, b);

        x = fmpz_remove(c, a, b);
        y = mpz_remove(f, d, e);

        fmpz_get_mpz(g, c);

        result = ((x == y) && (mpz_cmp(f, g) == 0));

        if (!result)
        {
            flint_printf("FAIL:\n");
            gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g);
            abort();
        }

        fmpz_clear(a);
        fmpz_clear(b);
        fmpz_clear(c);

        mpz_clear(d);
        mpz_clear(e);
        mpz_clear(f);
        mpz_clear(g);
    }

    /* Compare with MPIR, random input but ensure that factors exist */
    for (i = 0; i < 1000 * flint_test_multiplier(); i++)
    {
        fmpz_t a, b, c, pow;
        mpz_t d, e, f, g;
        slong x, y;
        ulong n;

        fmpz_init(a);
        fmpz_init(b);
        fmpz_init(c);
        fmpz_init(pow);

        mpz_init(d);
        mpz_init(e);
        mpz_init(f);
        mpz_init(g);

        fmpz_randtest_not_zero(a, state, 200);
        do {
            fmpz_randtest_not_zero(b, state, 200);
            fmpz_abs(b, b);
        } while (fmpz_is_one(b));

        n = n_randint(state, 10);
        fmpz_pow_ui(pow, b, n);
        fmpz_mul(a, a, pow);

        fmpz_get_mpz(d, a);
        fmpz_get_mpz(e, b);

        x = fmpz_remove(c, a, b);
        y = mpz_remove(f, d, e);

        fmpz_get_mpz(g, c);

        result = ((x == y) && (x >= n) && (mpz_cmp(f, g) == 0));

        if (!result)
        {
            flint_printf("FAIL:\n");
            gmp_printf("d = %Zd, e = %Zd, f = %Zd, g = %Zd\n", d, e, f, g);
            abort();
        }

        fmpz_clear(a);
        fmpz_clear(b);
        fmpz_clear(c);
        fmpz_clear(pow);

        mpz_clear(d);
        mpz_clear(e);
        mpz_clear(f);
        mpz_clear(g);
    }

    /* Check aliasing of a and b */
    for (i = 0; i < 100 * flint_test_multiplier(); i++)
    {
        fmpz_t a, c;
        slong x;

        fmpz_init(a);
        fmpz_init(c);

        do {
            fmpz_randtest_not_zero(a, state, 200);
            fmpz_abs(a, a);
        } while (fmpz_is_one(a));

        x = fmpz_remove(c, a, a);

        result = ((x == 1) && (fmpz_cmp_ui(c, 1) == 0));

        if (!result)
        {
            flint_printf("FAIL:\n");
            fmpz_print(a), flint_printf("\n");
            fmpz_print(c), flint_printf("\n");
            abort();
        }

        fmpz_clear(a);
        fmpz_clear(c);
    }

    /* Check aliasing of a and c */
    for (i = 0; i < 100 * flint_test_multiplier(); i++)
    {
        fmpz_t a, b, c;
        slong x, y;

        fmpz_init(a);
        fmpz_init(b);
        fmpz_init(c);

        fmpz_randtest_not_zero(a, state, 200);
        do {
            fmpz_randtest_not_zero(b, state, 200);
            fmpz_abs(b, b);
        } while (fmpz_is_one(b));

        x = fmpz_remove(c, a, b);
        y = fmpz_remove(a, a, b);

        result = ((x == y) && fmpz_equal(a, c));

        if (!result)
        {
            flint_printf("FAIL:\n");
            fmpz_print(a), flint_printf("\n");
            fmpz_print(b), flint_printf("\n");
            fmpz_print(c), flint_printf("\n");
            abort();
        }

        fmpz_clear(a);
        fmpz_clear(b);
        fmpz_clear(c);
    }

    /* Check aliasing of b and c */
    for (i = 0; i < 100 * flint_test_multiplier(); i++)
    {
        fmpz_t a, b, c;
        slong x, y;

        fmpz_init(a);
        fmpz_init(b);
        fmpz_init(c);

        fmpz_randtest_not_zero(a, state, 200);
        do {
            fmpz_randtest_not_zero(b, state, 200);
            fmpz_abs(b, b);
        } while (fmpz_is_one(b));

        x = fmpz_remove(c, a, b);
        y = fmpz_remove(b, a, b);

        result = ((x == y) && fmpz_equal(b, c));

        if (!result)
        {
            flint_printf("FAIL:\n");
            fmpz_print(a), flint_printf("\n");
            fmpz_print(b), flint_printf("\n");
            fmpz_print(c), flint_printf("\n");
            abort();
        }

        fmpz_clear(a);
        fmpz_clear(b);
        fmpz_clear(c);
    }

    FLINT_TEST_CLEANUP(state);
    
    flint_printf("PASS\n");
    return 0;
}
Ejemplo n.º 6
0
/* assuming slaves (workers)) are all homogenous, let them all do the calculations
 regarding primes sieving, calculating the smoothness base and the modular roots */
int main(int argc, char **argv) {
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
	MPI_Comm_size(MPI_COMM_WORLD, &mpi_group_size);
	int len;
	MPI_Get_processor_name(processor_name, &len);

	gettimeofday(&start_global, NULL);
	print_lib_version();

	mpz_init(N);
	mpz_t B;
	mpz_init(B);

	unsigned long int uBase;
	int64_t nb_primes;
	modular_root_t *modular_roots;

	uint64_t i, j;

	if (argc < 2) {
		PRINT(my_rank, "usage: %s Number_to_factorize\n", argv[0]);
		exit(2);
	}

	if (mpz_init_set_str(N, argv[1], 10) == -1) {
		PRINT(my_rank, "Cannot load N %s\n", argv[1]);
		exit(2);
	}

	mpz_t sqrtN, rem;
	mpz_init(sqrtN);
	mpz_init(rem);
	mpz_sqrtrem(sqrtN, rem, N);

	if (mpz_cmp_ui(rem, 0) != 0) /* if not perfect square, calculate the ceiling */
		mpz_add_ui(sqrtN, sqrtN, 1);
	else /* N is a perfect square, factored! */
	{
		PRINT(my_rank, "\n<<<[FACTOR]>>> %s\n", mpz_get_str(NULL, 10, sqrtN));
		return 0;
	}

	if (mpz_probab_prime_p(N, 10) > 0) /* don't bother factoring */
	{
		PRINT(my_rank, "N:%s is prime\n", mpz_get_str(NULL, 10, N));
		exit(0);
	}

	OPEN_LOG_FILE("freq");

//--------------------------------------------------------
//  calculate the smoothness base for the given N
//--------------------------------------------------------
	get_smoothness_base(B, N); /* if N is too small, the program will surely fail, please consider a pen and paper instead */
	uBase = mpz_get_ui(B);
	PRINT(my_rank, "n: %s\tBase: %s\n",
			mpz_get_str(NULL, 10, N), mpz_get_str(NULL, 10, B));

//--------------------------------------------------------
// sieve primes that are less than the smoothness base using Eratosthenes sieve
//--------------------------------------------------------
	START_TIMER();
	nb_primes = sieve_primes_up_to((int64_t) (uBase));

	PRINT(my_rank, "\tPrimes found %" PRId64 " [Smoothness Base %lu]\n",
			nb_primes, uBase);
	STOP_TIMER_PRINT_TIME("\tEratosthenes Sieving done");

//--------------------------------------------------------
// fill the primes array with primes to which n is a quadratic residue
//--------------------------------------------------------
	START_TIMER();
	primes = calloc(nb_primes, sizeof(int64_t));
	nb_qr_primes = fill_primes_with_quadratic_residue(primes, N);

	/*for(i=0; i<nb_qr_primes; i++)
	 PRINT(my_rank, "%" PRId64 "\n", primes[i]);*/

	PRINT(my_rank, "\tN-Quadratic primes found %" PRId64 "\n", nb_qr_primes);
	STOP_TIMER_PRINT_TIME("\tQuadratic prime filtering done");

//--------------------------------------------------------
// calculate modular roots
//--------------------------------------------------------
	START_TIMER();
	modular_roots = calloc(nb_qr_primes, sizeof(modular_root_t));
	mpz_t tmp, r1, r2;
	mpz_init(tmp);
	mpz_init(r1);
	mpz_init(r2);

	for (i = 0; i < nb_qr_primes; i++) {
		mpz_set_ui(tmp, (unsigned long) primes[i]);
		mpz_sqrtm(r1, N, tmp); /* calculate the modular root */
		mpz_neg(r2, r1); /* -q mod n */
		mpz_mod(r2, r2, tmp);

		modular_roots[i].root1 = mpz_get_ui(r1);
		modular_roots[i].root2 = mpz_get_ui(r2);
	}
	mpz_clear(tmp);
	mpz_clear(r1);
	mpz_clear(r2);
	STOP_TIMER_PRINT_TIME("Modular roots calculation done");

//--------------------------------------------------------
//         ***** initialize the matrix *****
//--------------------------------------------------------
	if (my_rank == 0) /* only the master have the matrix */
	{
		START_TIMER();
		init_matrix(&matrix, nb_qr_primes + NB_VECTORS_OFFSET, nb_qr_primes);
		mpz_init2(tmp_matrix_row, nb_qr_primes);
		STOP_TIMER_PRINT_TIME("Matrix initialized");
	}

//--------------------------------------------------------
// [Sieving] - everyones sieves including the master
//--------------------------------------------------------
	START_TIMER();

	mpz_t x, sieving_index, next_sieving_index, relative_start, global_step;
	unsigned long ui_index, SIEVING_STEP = 50000; /* we sieve for 50000 elements at each loop */
	int LOCAL_SIEVING_ROUNDS = 10; /* number of iterations a worker sieves before communicating results to the master */
	unsigned long sieving_round = 0;
	unsigned long nb_big_rounds = 0;

	uint64_t p_pow;
	smooth_number_t *x_squared;

	x_squared = calloc(SIEVING_STEP, sizeof(smooth_number_t));

	if (my_rank == 0)
		smooth_numbers = calloc(nb_qr_primes + NB_VECTORS_OFFSET,
				sizeof(smooth_number_t));
	else
		temp_slaves_smooth_numbers = calloc(500, sizeof(smooth_number_t));
	/* TODO: this is not properly correct, using a linkedlist is better to keep track of temporary
	 * smooth numbers at the slaves nodes however it's pretty rare to find 500 smooth numbers in
	 * 50000 * 10 interval. */

	mpz_init_set(x, sqrtN);
	mpz_init(global_step);
	mpz_init(relative_start);
	mpz_init(sieving_index);
	mpz_init(next_sieving_index);

	mpz_t p;
	mpz_init(p);
	mpz_t str;
	mpz_init_set(str, sieving_index);
	PRINT(my_rank, "\n[%s] Sieving ...\n", processor_name);

//--------------------------------------------------------
// Init before sieving
//--------------------------------------------------------
	for (i = 0; i < SIEVING_STEP; i++) {
		mpz_init(x_squared[i].value_x);
		mpz_init(x_squared[i].value_x_squared);

		mpz_init2(x_squared[i].factors_vect, nb_qr_primes);
		mpz_add_ui(x, x, 1);
	}

	int nb_smooth_per_round = 0;
	char s[512];

//--------------------------------------------------------
// WHILE smooth numbers found less than the primes in the smooth base + NB_VECTORS_OFFSET for master
// Or master asked for more smooth numbers from slaves
//--------------------------------------------------------
	while (1) {
		mpz_set_ui(global_step, nb_big_rounds); /* calculates the coordinate where the workers start sieving from */
		mpz_mul_ui(global_step, global_step, (unsigned long) mpi_group_size);
		mpz_mul_ui(global_step, global_step, SIEVING_STEP);
		mpz_mul_ui(global_step, global_step, LOCAL_SIEVING_ROUNDS);
		mpz_add(global_step, global_step, sqrtN);

		mpz_set_ui(relative_start, SIEVING_STEP);
		mpz_mul_ui(relative_start, relative_start, LOCAL_SIEVING_ROUNDS);
		mpz_mul_ui(relative_start, relative_start, (unsigned long) my_rank);
		mpz_add(relative_start, relative_start, global_step);

		mpz_set(sieving_index, relative_start);
		mpz_set(next_sieving_index, relative_start);

		for (sieving_round = 0; sieving_round < LOCAL_SIEVING_ROUNDS; /* each slave sieves for LOCAL_SIEVING_ROUNDS rounds */
		sieving_round++) {
			nb_smooth_per_round = 0;
			mpz_set(x, next_sieving_index); /* sieve numbers from sieving_index to sieving_index + sieving_step */
			mpz_set(sieving_index, next_sieving_index);

			if (my_rank == 0) {
				printf("\r");
				printf(
						"\t\tSieving at: %s30 <--> Smooth numbers found: %" PRId64 "/%" PRId64 "",
						mpz_get_str(NULL, 10, sieving_index),
						nb_global_smooth_numbers_found, nb_qr_primes);
				fflush(stdout);
			}

			for (i = 0; i < SIEVING_STEP; i++) {
				mpz_set(x_squared[i].value_x, x);

				mpz_pow_ui(x_squared[i].value_x_squared, x, 2); /* calculate value_x_squared <- x²-n */
				mpz_sub(x_squared[i].value_x_squared,
						x_squared[i].value_x_squared, N);

				mpz_clear(x_squared[i].factors_vect);
				mpz_init2(x_squared[i].factors_vect, nb_qr_primes); /* reconstruct a new fresh 0ed vector of size nb_qr_primes bits */

				mpz_add_ui(x, x, 1);
			}
			mpz_set(next_sieving_index, x);

//--------------------------------------------------------
// eliminate factors in the x_squared array, those who are 'destructed' to 1 are smooth
//--------------------------------------------------------
			for (i = 0; i < nb_qr_primes; i++) {
				mpz_set_ui(p, (unsigned long) primes[i]);
				mpz_set(x, sieving_index);

				/* get the first multiple of p that is directly larger that sieving_index
				 * Quadratic SIEVING: all elements from this number and in positions multiples of root1 and root2
				 * are also multiples of p */
				get_sieving_start_index(x, x, p, modular_roots[i].root1);
				mpz_set(str, x);
				mpz_sub(x, x, sieving_index); /* x contains index of first number that is divisible by p */

				for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) {
					p_pow = mpz_remove(x_squared[j].value_x_squared,
							x_squared[j].value_x_squared, p); /* eliminate all factors of p */

					if (p_pow & 1) /* mark bit if odd power of p exists in this x_squared[j] */
					{
						mpz_setbit(x_squared[j].factors_vect, i);
					}

					if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) {
						save_smooth_number(x_squared[j]);
						nb_smooth_per_round++;
					}
					/* sieve next element located p steps from here */
				}

				/* same goes for root2 */
				if (modular_roots[i].root2 == modular_roots[i].root1)
					continue;

				mpz_set(x, sieving_index);

				get_sieving_start_index(x, x, p, modular_roots[i].root2);
				mpz_set(str, x);
				mpz_sub(x, x, sieving_index);

				for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) {
					p_pow = mpz_remove(x_squared[j].value_x_squared,
							x_squared[j].value_x_squared, p);

					if (p_pow & 1) {
						mpz_setbit(x_squared[j].factors_vect, i);
					}

					if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) {
						save_smooth_number(x_squared[j]);
						nb_smooth_per_round++;
					}
				}
			}
		}

		if (my_rank == 0) /* master gathers smooth numbers from slaves */
		{
			gather_smooth_numbers();
			notify_slaves();
		} else /* slaves send their smooth numbers to master */
		{
			send_smooth_numbers_to_master();
			nb_global_smooth_numbers_found = get_server_notification();
		}

		if (nb_global_smooth_numbers_found >= nb_qr_primes + NB_VECTORS_OFFSET)
			break;

		nb_big_rounds++;
	}

	STOP_TIMER_PRINT_TIME("\nSieving DONE");

	if (my_rank == 0) {
		uint64_t t = 0;

//--------------------------------------------------------
//the matrix ready, start Gauss elimination. The Matrix is filled on the call of save_smooth_number()
//--------------------------------------------------------
		START_TIMER();
		gauss_elimination(&matrix);
		STOP_TIMER_PRINT_TIME("\nGauss elimination done");

		uint64_t row_index = nb_qr_primes + NB_VECTORS_OFFSET - 1; /* last row in the matrix */
		int nb_linear_relations = 0;
		mpz_t linear_relation_z, solution_z;
		mpz_init(linear_relation_z);
		mpz_init(solution_z);

		get_matrix_row(linear_relation_z, &matrix, row_index--); /* get the last few rows in the Gauss eliminated matrix*/
		while (mpz_cmp_ui(linear_relation_z, 0) == 0) {
			nb_linear_relations++;
			get_matrix_row(linear_relation_z, &matrix, row_index--);
		}

		PRINT(my_rank, "\tLinear dependent relations found : %d\n",
				nb_linear_relations);

//--------------------------------------------------------
// Factor
//--------------------------------------------------------
		//We use the last linear relation to reconstruct our solution
		START_TIMER();
		PRINT(my_rank, "%s", "\nFactorizing..\n");
		mpz_t solution_X, solution_Y;
		mpz_init(solution_X);
		mpz_init(solution_Y);

		/* we start testing from the first linear relation encountered in the matrix */
		for (j = nb_linear_relations; j > 0; j--) {
			PRINT(my_rank, "Trying %d..\n", nb_linear_relations - j + 1);
			mpz_set_ui(solution_X, 1);
			mpz_set_ui(solution_Y, 1);

			get_identity_row(solution_z, &matrix,
					nb_qr_primes + NB_VECTORS_OFFSET - j + 1);

			for (i = 0; i < nb_qr_primes; i++) {
				if (mpz_tstbit(solution_z, i)) {
					mpz_mul(solution_X, solution_X, smooth_numbers[i].value_x);
					mpz_mod(solution_X, solution_X, N); /* reduce x to modulo N */

					mpz_mul(solution_Y, solution_Y,
							smooth_numbers[i].value_x_squared);
					/*TODO: handling huge stuff here, there is no modulo N like in the solution_X case!
					 * eliminate squares as long as you go*/
				}
			}

			mpz_sqrt(solution_Y, solution_Y);
			mpz_mod(solution_Y, solution_Y, N); /* y = sqrt(MUL(xi²-n)) mod N */

			mpz_sub(solution_X, solution_X, solution_Y);

			mpz_gcd(solution_X, solution_X, N);

			if (mpz_cmp(solution_X, N) != 0 && mpz_cmp_ui(solution_X, 1) != 0) /* factor can be 1 or N, try another relation */
				break;
		}
		mpz_cdiv_q(solution_Y, N, solution_X);

		PRINT(my_rank, "\n>>>>>>>>>>> FACTORED %s =\n",
				mpz_get_str(NULL, 10, N));
		PRINT(
				my_rank,
				"\tFactor 1: %s \n\tFactor 2: %s",
				mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y));

		sprintf(s, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N));
		APPEND_TO_LOG_FILE(s);
		sprintf(s, "\tFactor 1: %s \n\tFactor 2: %s",
				mpz_get_str(NULL, 10, solution_X),
				mpz_get_str(NULL, 10, solution_Y));
		APPEND_TO_LOG_FILE(s);

		gettimeofday(&end_global, NULL);
		timersub(&end_global, &start_global, &elapsed);
		sprintf(s, "****** TOTAL TIME: %.3f ms\n",
				elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000);
		APPEND_TO_LOG_FILE(s);

		STOP_TIMER_PRINT_TIME("\nFactorizing done");
	}

	PRINT(my_rank, "%s", "\nCleaning memory..\n");

	/********************** clear the x_squared array **********************/
	for (i = 0; i < SIEVING_STEP; i++) {
		mpz_clear(x_squared[i].value_x);
		mpz_clear(x_squared[i].value_x_squared);
		//free(x_squared[i].factors_exp);
		mpz_clear(x_squared[i].factors_vect);
	}
	free(x_squared);
	/********************** clear the x_squared array **********************/

	free(modular_roots);
	/********************** clear the smooth_numbers array **********************/
	if (my_rank == 0) {
		for (i = 0; i < nb_qr_primes + NB_VECTORS_OFFSET; i++) {
			mpz_clear(smooth_numbers[i].value_x);
			mpz_clear(smooth_numbers[i].value_x_squared);
			mpz_clear(smooth_numbers[i].factors_vect);
			//free(smooth_numbers[i].factors_exp);
		}
		free(smooth_numbers);
	} else {
		for (i = 0; i < 500; i++) {
			mpz_clear(temp_slaves_smooth_numbers[i].value_x);
			mpz_clear(temp_slaves_smooth_numbers[i].value_x_squared);
			mpz_clear(temp_slaves_smooth_numbers[i].factors_vect);
		}
		free(temp_slaves_smooth_numbers);
	}
	/********************** clear the smooth_numbers array **********************/

	free(primes);
	/********************** clear mpz _t **********************/mpz_clear(B);
	mpz_clear(N);
	sqrtN, rem;
	mpz_clear(x);
	mpz_clear(sieving_index);
	mpz_clear(next_sieving_index);
	mpz_clear(p);
	mpz_clear(str);
	/********************** clear mpz _t **********************/

	free_matrix(&matrix);

	gettimeofday(&end_global, NULL);
	timersub(&end_global, &start_global, &elapsed);
	PRINT(my_rank, "****** TOTAL TIME: %.3f ms\n",
			elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000);
	show_mem_usage();

	MPI_Finalize();

	return 0;
}
Ejemplo n.º 7
0
int
main (int argc, char **argv)
{
  int i;
  int pass, reps = 400;
  mpz_t in1, in2, in3;
  unsigned long int in2i;
  mp_size_t size;
  mpz_t res1, res2, res3;
  mpz_t ref1, ref2, ref3;
  mpz_t t;
  unsigned long int r1, r2;
  gmp_randstate_ptr rands;
  mpz_t bs;
  unsigned long bsi, size_range;

  tests_start ();
  TESTS_REPS (reps, argv, argc);

  rands = RANDS;

  mpz_init (bs);

  mpz_init (in1);
  mpz_init (in2);
  mpz_init (in3);
  mpz_init (ref1);
  mpz_init (ref2);
  mpz_init (ref3);
  mpz_init (res1);
  mpz_init (res2);
  mpz_init (res3);
  mpz_init (t);

  for (pass = 1; pass <= reps; pass++)
    {
      if (isatty (fileno (stdout)))
	{
	  printf ("\r%d/%d passes", pass, reps);
	  fflush (stdout);
	}

      mpz_urandomb (bs, rands, 32);
      size_range = mpz_get_ui (bs) % 21 + 2;

      if ((pass & 1) == 0)
	{
	  /* Make all input operands have quite different sizes */
	  mpz_urandomb (bs, rands, 32);
	  size = mpz_get_ui (bs) % size_range;
	  mpz_rrandomb (in1, rands, size);

	  mpz_urandomb (bs, rands, 32);
	  size = mpz_get_ui (bs) % size_range;
	  mpz_rrandomb (in2, rands, size);

	  mpz_urandomb (bs, rands, 32);
	  size = mpz_get_ui (bs) % size_range;
	  mpz_rrandomb (in3, rands, size);
	}
      else
	{
	  /* Make all input operands have about the same size */
	  mpz_urandomb (bs, rands, size_range);
	  size = mpz_get_ui (bs);
	  mpz_rrandomb (in1, rands, size);

	  mpz_urandomb (bs, rands, size_range);
	  size = mpz_get_ui (bs);
	  mpz_rrandomb (in2, rands, size);

	  mpz_urandomb (bs, rands, size_range);
	  size = mpz_get_ui (bs);
	  mpz_rrandomb (in3, rands, size);
	}

      mpz_urandomb (bs, rands, 3);
      bsi = mpz_get_ui (bs);
      if ((bsi & 1) != 0)
	mpz_neg (in1, in1);
      if ((bsi & 2) != 0)
	mpz_neg (in2, in2);
      if ((bsi & 4) != 0)
	mpz_neg (in3, in3);

      for (i = 0; i < numberof (dss); i++)
	{
	  if (dss[i].isdivision && mpz_sgn (in2) == 0)
	    continue;
	  if (dss[i].isslow && size_range > 19)
	    continue;

	  (dss[i].fptr) (ref1, in1, in2);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, in1);
	  INVOKE_RSS (dss[i], res1, res1, in2);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL (dss, i, in1, in2, NULL);

	  mpz_set (res1, in2);
	  INVOKE_RSS (dss[i], res1, in1, res1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL (dss, i, in1, in2, NULL);
	}

      for (i = 0; i < numberof (ddss_div); i++)
	{
	  if (mpz_sgn (in2) == 0)
	    continue;

	  (ddss_div[i].fptr) (ref1, ref2, in1, in2);
	  MPZ_CHECK_FORMAT (ref1);
	  MPZ_CHECK_FORMAT (ref2);

	  mpz_set (res1, in1);
	  INVOKE_RRSS (ddss_div[i], res1, res2, res1, in2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
	    FAIL (ddss_div, i, in1, in2, NULL);

	  mpz_set (res2, in1);
	  INVOKE_RRSS (ddss_div[i], res1, res2, res2, in2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
	    FAIL (ddss_div, i, in1, in2, NULL);

	  mpz_set (res1, in2);
	  INVOKE_RRSS (ddss_div[i], res1, res2, in1, res1);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
	    FAIL (ddss_div, i, in1, in2, NULL);

	  mpz_set (res2, in2);
	  INVOKE_RRSS (ddss_div[i], res1, res2, in1, res2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
	    FAIL (ddss_div, i, in1, in2, NULL);
	}

      for (i = 0; i < numberof (ds); i++)
	{
	  if (ds[i].nonneg && mpz_sgn (in1) < 0)
	    continue;

	  (ds[i].fptr) (ref1, in1);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, in1);
	  INVOKE_RS (ds[i], res1, res1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL (ds, i, in1, in2, NULL);
	}

      in2i = mpz_get_ui (in2);

      for (i = 0; i < numberof (dsi); i++)
	{
	  if (dsi[i].mod != 0)
	    in2i = mpz_get_ui (in2) % dsi[i].mod;

	  (dsi[i].fptr) (ref1, in1, in2i);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, in1);
	  INVOKE_RRS (dsi[i], res1, res1, in2i);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL (dsi, i, in1, in2, NULL);
	}

      if (in2i != 0)	  /* Don't divide by 0.  */
	{
	  for (i = 0; i < numberof (dsi_div); i++)
	    {
	      r1 = (dsi_div[i].fptr) (ref1, in1, in2i);
	      MPZ_CHECK_FORMAT (ref1);

	      mpz_set (res1, in1);
	      r2 = (dsi_div[i].fptr) (res1, res1, in2i);
	      MPZ_CHECK_FORMAT (res1);
	      if (mpz_cmp (ref1, res1) != 0 || r1 != r2)
		FAIL (dsi_div, i, in1, in2, NULL);
	    }

	  for (i = 0; i < numberof (ddsi_div); i++)
	    {
	      r1 = (ddsi_div[i].fptr) (ref1, ref2, in1, in2i);
	      MPZ_CHECK_FORMAT (ref1);

	      mpz_set (res1, in1);
	      r2 = (ddsi_div[i].fptr) (res1, res2, res1, in2i);
	      MPZ_CHECK_FORMAT (res1);
	      if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
		FAIL (ddsi_div, i, in1, in2, NULL);

	      mpz_set (res2, in1);
	      (ddsi_div[i].fptr) (res1, res2, res2, in2i);
	      MPZ_CHECK_FORMAT (res1);
	      if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2)
		FAIL (ddsi_div, i, in1, in2, NULL);
	    }
	}

      if (mpz_sgn (in1) >= 0)
	{
	  mpz_sqrtrem (ref1, ref2, in1);
	  MPZ_CHECK_FORMAT (ref1);
	  MPZ_CHECK_FORMAT (ref2);

	  mpz_set (res1, in1);
	  mpz_sqrtrem (res1, res2, res1);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);

	  mpz_set (res2, in1);
	  mpz_sqrtrem (res1, res2, res2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);

	  mpz_set (res1, in1);
	  mpz_sqrtrem (res1, res1, res1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref2, res1) != 0)
	    FAIL2 (mpz_sqrtrem, in1, NULL, NULL);
	}

      if (mpz_sgn (in1) >= 0)
	{
	  mpz_root (ref1, in1, in2i % 0x100 + 1);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, in1);
	  mpz_root (res1, res1, in2i % 0x100 + 1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_root, in1, in2, NULL);
	}

      if (mpz_sgn (in1) >= 0)
	{
	  mpz_rootrem (ref1, ref2, in1, in2i % 0x100 + 1);
	  MPZ_CHECK_FORMAT (ref1);
	  MPZ_CHECK_FORMAT (ref2);

	  mpz_set (res1, in1);
	  mpz_rootrem (res1, res2, res1, in2i % 0x100 + 1);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
	    FAIL2 (mpz_rootrem, in1, in2, NULL);

	  mpz_set (res2, in1);
	  mpz_rootrem (res1, res2, res2, in2i % 0x100 + 1);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0)
	    FAIL2 (mpz_rootrem, in1, in2, NULL);
	}

      if (size_range < 18)	/* run fewer tests since gcdext lots of time */
	{
	  mpz_gcdext (ref1, ref2, ref3, in1, in2);
	  MPZ_CHECK_FORMAT (ref1);
	  MPZ_CHECK_FORMAT (ref2);
	  MPZ_CHECK_FORMAT (ref3);

	  mpz_set (res1, in1);
	  mpz_gcdext (res1, res2, res3, res1, in2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  MPZ_CHECK_FORMAT (res3);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res2, in1);
	  mpz_gcdext (res1, res2, res3, res2, in2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  MPZ_CHECK_FORMAT (res3);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res3, in1);
	  mpz_gcdext (res1, res2, res3, res3, in2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  MPZ_CHECK_FORMAT (res3);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res1, in2);
	  mpz_gcdext (res1, res2, res3, in1, res1);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  MPZ_CHECK_FORMAT (res3);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res2, in2);
	  mpz_gcdext (res1, res2, res3, in1, res2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  MPZ_CHECK_FORMAT (res3);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res3, in2);
	  mpz_gcdext (res1, res2, res3, in1, res3);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  MPZ_CHECK_FORMAT (res3);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res1, in1);
	  mpz_gcdext (res1, res2, NULL, res1, in2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res2, in1);
	  mpz_gcdext (res1, res2, NULL, res2, in2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res1, in2);
	  mpz_gcdext (res1, res2, NULL, in1, res1);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);

	  mpz_set (res2, in2);
	  mpz_gcdext (res1, res2, NULL, in1, res2);
	  MPZ_CHECK_FORMAT (res1);
	  MPZ_CHECK_FORMAT (res2);
	  if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0
	      || mpz_cmp (ref3, res3) != 0)
	    FAIL2 (mpz_gcdext, in1, in2, NULL);
	}

      /* Don't run mpz_powm for huge exponents or when undefined.  */
      if (size_range < 17 && mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0
	  && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3)))
	{
	  mpz_powm (ref1, in1, in2, in3);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, in1);
	  mpz_powm (res1, res1, in2, in3);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_powm, in1, in2, in3);

	  mpz_set (res1, in2);
	  mpz_powm (res1, in1, res1, in3);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_powm, in1, in2, in3);

	  mpz_set (res1, in3);
	  mpz_powm (res1, in1, in2, res1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_powm, in1, in2, in3);
	}

      /* Don't run mpz_powm_ui when undefined.  */
      if (size_range < 17 && mpz_sgn (in3) != 0)
	{
	  mpz_powm_ui (ref1, in1, in2i, in3);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, in1);
	  mpz_powm_ui (res1, res1, in2i, in3);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_powm_ui, in1, in2, in3);

	  mpz_set (res1, in3);
	  mpz_powm_ui (res1, in1, in2i, res1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_powm_ui, in1, in2, in3);
	}

      {
	r1 = mpz_gcd_ui (ref1, in1, in2i);
	MPZ_CHECK_FORMAT (ref1);

	mpz_set (res1, in1);
	r2 = mpz_gcd_ui (res1, res1, in2i);
	MPZ_CHECK_FORMAT (res1);
	if (mpz_cmp (ref1, res1) != 0)
	  FAIL2 (mpz_gcd_ui, in1, in2, NULL);
      }

      if (mpz_sgn (in2) != 0)
	{
	  /* Test mpz_remove */
	  mp_bitcnt_t refretval, retval;
	  refretval = mpz_remove (ref1, in1, in2);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, in1);
	  retval = mpz_remove (res1, res1, in2);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0 || refretval != retval)
	    FAIL2 (mpz_remove, in1, in2, NULL);

	  mpz_set (res1, in2);
	  retval = mpz_remove (res1, in1, res1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0 || refretval != retval)
	    FAIL2 (mpz_remove, in1, in2, NULL);
	}

      if (mpz_sgn (in2) != 0)
	{
	  /* Test mpz_divexact */
	  mpz_mul (t, in1, in2);
	  mpz_divexact (ref1, t, in2);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, t);
	  mpz_divexact (res1, res1, in2);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_divexact, t, in2, NULL);

	  mpz_set (res1, in2);
	  mpz_divexact (res1, t, res1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_divexact, t, in2, NULL);
	}

      if (mpz_sgn (in2) > 0)
	{
	  /* Test mpz_divexact_gcd, same as mpz_divexact */
	  mpz_mul (t, in1, in2);
	  mpz_divexact_gcd (ref1, t, in2);
	  MPZ_CHECK_FORMAT (ref1);

	  mpz_set (res1, t);
	  mpz_divexact_gcd (res1, res1, in2);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_divexact_gcd, t, in2, NULL);

	  mpz_set (res1, in2);
	  mpz_divexact_gcd (res1, t, res1);
	  MPZ_CHECK_FORMAT (res1);
	  if (mpz_cmp (ref1, res1) != 0)
	    FAIL2 (mpz_divexact_gcd, t, in2, NULL);
	}
    }

  if (isatty (fileno (stdout)))
    printf ("\r%20s", "");

  mpz_clear (bs);
  mpz_clear (in1);
  mpz_clear (in2);
  mpz_clear (in3);
  mpz_clear (ref1);
  mpz_clear (ref2);
  mpz_clear (ref3);
  mpz_clear (res1);
  mpz_clear (res2);
  mpz_clear (res3);
  mpz_clear (t);

  if (isatty (fileno (stdout)))
    printf ("\r");

  tests_end ();
  exit (0);
}
Ejemplo n.º 8
0
/*==========================================================================
   evaluateSieve:

   Function: searches sieve for relations and sticks them into a matrix, then
             sticks their X and Y values into two arrays XArr and YArr

===========================================================================*/
static void evaluateSieve(
    unsigned long numPrimes,
    unsigned long Mdiv2,
    unsigned long * relations,
    unsigned long ctimesreps,
    unsigned long M,
    unsigned char * sieve,
    mpz_t A,
    mpz_t B,
    mpz_t C,
    unsigned long * soln1,
    unsigned long * soln2,
    unsigned char * flags,
    matrix_t m,
    mpz_t * XArr,
    unsigned long * aind,
    int min,
    int s,
    int * exponents,
    unsigned long * npartials,
    unsigned long * nrelsfound,
    unsigned long * nrelssought,
    mpz_t temp,
    mpz_t temp2,
    mpz_t temp3,
    mpz_t res)
{
     long i,j,ii;
     unsigned int k;
     unsigned int exponent, vv;
     unsigned char extra;
     unsigned int modp;
     unsigned long * sieve2;
     unsigned char bits;
     int numfactors;
     unsigned long relsFound = *nrelsfound;
     unsigned long relSought = *nrelssought;

     mpz_set_ui(temp, 0);
     mpz_set_ui(temp2, 0);
     mpz_set_ui(temp3, 0);
     mpz_set_ui(res, 0);
     i = 0;
     j = 0;
     sieve2 = (unsigned long *) sieve;
#ifdef POLS
     gmp_printf("%Zdx^2%+Zdx\n%+Zd\n",A,B,C);
#endif

     while ( (unsigned long)j < M/sizeof(unsigned long))
     {
        do
        {
           while (!(sieve2[j] & SIEVEMASK)) j++;
           i = j * sizeof(unsigned long);
           j++;
           while (((unsigned long)i < j*sizeof(unsigned long)) && (sieve[i] < threshold)) i++;
        } while (sieve[i] < threshold);

        if (((unsigned long)i<M) && (relsFound < relSought))
        {
           mpz_set_ui(temp,i+ctimesreps);
           mpz_sub_ui(temp, temp, Mdiv2); /* X         */

           mpz_set(temp3, B);             /* B          */
           mpz_addmul(temp3, A, temp);    /* AX+B       */
           mpz_add(temp2, temp3, B);      /* AX+2B      */
           mpz_mul(temp2, temp2, temp);   /* AX^2+2BX   */
           mpz_add(res, temp2, C);        /* AX^2+2BX+C */

           bits = mpz_sizeinbase(res,2) - errorbits;

           numfactors=0;
           extra = 0;
           memset(exponents, 0, firstprime * sizeof(int));

           if (factorBase[0] != 1 && mpz_divisible_ui_p(res, factorBase[0]))
           {
             extra += primeSizes[0];
             if (factorBase[0] == 2) {
                exponent = mpz_scan1(res, 0);
                mpz_tdiv_q_2exp(res, res, exponent);
             } else {
               mpz_set_ui(temp,factorBase[0]);
               exponent = mpz_remove(res,res,temp);
             }
             exponents[0] = exponent;
           }

           exponents[1] = 0;
           if (mpz_divisible_ui_p(res, factorBase[1]))
           {
             extra += primeSizes[1];
             if (factorBase[1] == 2) {
                exponent = mpz_scan1(res, 0);
                mpz_tdiv_q_2exp(res, res, exponent);
             } else {
               mpz_set_ui(temp,factorBase[1]);
               exponent = mpz_remove(res,res,temp);
             }
             exponents[1] = exponent;
           }

           for (k = 2; k < firstprime; k++)
           {
              modp=(i+ctimesreps)%factorBase[k];

              exponents[k] = 0;
              if (soln2[k] != (unsigned long)-1)
              {
                 if ((modp==soln1[k]) || (modp==soln2[k]))
                 {
                    extra+=primeSizes[k];
                    mpz_set_ui(temp,factorBase[k]);
                    exponent = mpz_remove(res,res,temp);
                    CHECK_EXPONENT(exponent, k);
                    PRINT_FB(exponent, k);
                    exponents[k] = exponent;
                 }
              } else if (mpz_divisible_ui_p(res, factorBase[k]))
              {
                 extra += primeSizes[k];
                 mpz_set_ui(temp,factorBase[k]);
                 exponent = mpz_remove(res,res,temp);
                 PRINT_FB(exponent, k);
                 exponents[k] = exponent;
              }
           }
           sieve[i]+=extra;
           if (sieve[i] >= bits)
           {
              vv=((unsigned char)1<<(i&7));
              for (k = firstprime; (k<secondprime)&&(extra<sieve[i]); k++)
              {
                 modp=(i+ctimesreps)%factorBase[k];
                 if (soln2[k] != (unsigned long)-1)
                 {
                    if ((modp==soln1[k]) || (modp==soln2[k]))
                    {
                       extra+=primeSizes[k];
                       mpz_set_ui(temp,factorBase[k]);
                       exponent = mpz_remove(res,res,temp);
                       CHECK_EXPONENT(exponent, k);
                       PRINT_FB(exponent, k);
                       if (exponent)
                         for (ii = 0; ii < (long)exponent; ii++)
                           set_relation(relations, relsFound, ++numfactors, k);
                       if (exponent & 1)
                         insertEntry(m,relsFound,k);
                    }
                 } else if (mpz_divisible_ui_p(res, factorBase[k]))
                 {
                    extra += primeSizes[k];
                    mpz_set_ui(temp,factorBase[k]);
                    exponent = mpz_remove(res,res,temp);
                    PRINT_FB(exponent, k);
                    for (ii = 0; ii < (long)exponent; ii++)
                      set_relation(relations, relsFound, ++numfactors, k);
                    if (exponent & 1)
                      insertEntry(m,relsFound,k);
                 }
              }


              for (k = secondprime; (k<numPrimes)&&(extra<sieve[i]); k++)
              {
                 if (flags[k]&vv)
                 {
                    modp=(i+ctimesreps)%factorBase[k];
                    if ((modp==soln1[k]) || (modp==soln2[k]))
                    {
                       extra+=primeSizes[k];
                       mpz_set_ui(temp,factorBase[k]);
                       exponent = mpz_remove(res,res,temp);
                       CHECK_EXPONENT(exponent, k);
                       PRINT_FB(exponent, k);
                       if (exponent)
                         for (ii = 0; ii < (long)exponent; ii++)
                           set_relation(relations, relsFound, ++numfactors, k);
                       if (exponent & 1)
                         insertEntry(m,relsFound,k);
                    }
                 }
              }

              for (ii =0; ii<s; ii++)
              {
                 xorEntry(m,relsFound,aind[ii]+min);
                 set_relation(relations, relsFound, ++numfactors, aind[ii]+min);
              }

              if (mpz_cmp_ui(res,1000)>0)
              {
                 if (mpz_cmp_ui(res,largeprime)<0)
                 {
                    (*npartials)++;
                 }
                 clearRow(m,numPrimes,relsFound);
#ifdef RELPRINT
                 gmp_printf(" %Zd\n",res);
#endif
              } else
              {
                 mpz_neg(res,res);
                 if (mpz_cmp_ui(res,1000)>0)
                 {
                    if (mpz_cmp_ui(res,largeprime)<0)
                    {
                       (*npartials)++;
                    }
                    clearRow(m,numPrimes,relsFound);
#ifdef RELPRINT
                    gmp_printf(" %Zd\n",res);
#endif
                 } else
                 {
#ifdef RELPRINT
                    printf("....R\n");
#endif
                    for (ii = 0; ii < (long)firstprime; ii++)
                    {
                       int jj;
                       for (jj = 0; jj < exponents[ii]; jj++)
                         set_relation(relations, relsFound, ++numfactors, ii);
                       if (exponents[ii] & 1)
                         insertEntry(m,relsFound,ii);
                    }
                    set_relation(relations, relsFound, 0, numfactors);

                    mpz_init_set(XArr[relsFound], temp3);  /* (AX+B) */

                    relsFound++;
#ifdef COUNT
                    if (relsFound%20==0) fprintf(stderr,"%lu relations, %lu partials.\n", relsFound, *npartials);
#endif
                 }
              }
           } else
           {
              clearRow(m,numPrimes,relsFound);
#ifdef RELPRINT
              printf("\r                                                                    \r");
#endif

           }
           i++;

        } else if (relsFound >= relSought) i++;
     }
     /* Update caller */
     *nrelsfound = relsFound;
     *nrelssought = relSought;
}