Ejemplo n.º 1
0
int pm1_wrapper(fact_obj_t *fobj)
{
	int status;

	mpz_set(pm1_data.gmp_n, fobj->pm1_obj.gmp_n);

	pm1_data.params->B1done = 1.0 + floor (1 * 128.) / 134217728.;
	if (VFLAG >= 3)
		pm1_data.params->verbose = VFLAG - 2;		

	if (fobj->pm1_obj.stg2_is_default == 0)
	{
		//not default, tell gmp-ecm to use the requested B2
		//printf("using requested B2 value\n");
		uint64_2gmp(fobj->pm1_obj.B2, pm1_data.params->B2);
	}

	status = ecm_factor(pm1_data.gmp_factor, pm1_data.gmp_n,
			fobj->pm1_obj.B1, pm1_data.params);

	mpz_set(fobj->pm1_obj.gmp_n, pm1_data.gmp_n);

	//NOTE: this required a modification to the GMP-ECM source code in pp1.c
	//in order to get the automatically computed B2 value out of the
	//library
	//gmp2mp(pp1_data.params->B2,f);
	//WILL_STG2_MAX = z264(f);

	mpz_set(fobj->pm1_obj.gmp_f, pm1_data.gmp_factor);

	//the return value is the stage the factor was found in, if no error
	pm1_data.stagefound = status;

	return status;
}
Ejemplo n.º 2
0
int
main (int argc, char *argv[])
{
  mpz_t n, f;
  int res;
  double B1;

  if (argc != 3)
    {
      fprintf (stderr, "Usage: ecmfactor <number> <B1>\n");
      exit (1);
    }

  mpz_init (n);

  /* read number on command line */
  if (mpz_set_str (n, argv[1], 10))
    {
      fprintf (stderr, "Invalid number: %s\n", argv[1]);
      exit (1);
    }

  B1 = atof (argv[2]);

  mpz_init (f); /* for potential factor */

  printf ("Performing one curve with B1=%1.0f\n", B1);

  res = ecm_factor (f, n, B1, NULL);

  if (res > 0)
    {
      printf ("found factor in step %u: ", res);
      mpz_out_str (stdout, 10, f);
      printf ("\n");
#if 0
      printf ("lucky curve was b*y^2 = x^3 + a*x^2 + x\n");
      printf ("with a = (v-u)^3*(3*u+v)/(4*u^3*v)-2,");
      printf (" u = sigma^2-5, v = 4*sigma\n");
#endif
    }
  else if (res == ECM_NO_FACTOR_FOUND)
    printf ("found no factor\n");
  else
    printf ("error\n");

  mpz_clear (f);
  mpz_clear (n);

  return 0;
}
Ejemplo n.º 3
0
// Factorization
int factor(const Ptr<RCP<const Integer>> &f, const Integer &n, double B1)
{
    int ret_val = 0;
    integer_class _n, _f;

    _n = n.as_integer_class();

#ifdef HAVE_SYMENGINE_ECM
    if (mp_perfect_power_p(_n)) {

        unsigned long int i = 1;
        integer_class m, rem;
        rem = 1; // Any non zero number
        m = 2;   // set `m` to 2**i, i = 1 at the begining

        // calculate log2n, this can be improved
        for (; m < _n; ++i)
            m = m * 2;

        // eventually `rem` = 0 zero as `n` is a perfect power. `f_t` will
        // be set to a factor of `n` when that happens
        while (i > 1 and rem != 0) {
            mp_rootrem(_f, rem, _n, i);
            --i;
        }

        ret_val = 1;
    } else {

        if (mp_probab_prime_p(_n, 25) > 0) { // most probably, n is a prime
            ret_val = 0;
            _f = _n;
        } else {

            for (int i = 0; i < 10 and not ret_val; ++i)
                ret_val = ecm_factor(get_mpz_t(_f), get_mpz_t(_n), B1, nullptr);
            mp_demote(_f);
            if (not ret_val)
                throw SymEngineException(
                    "ECM failed to factor the given number");
        }
    }
#else
    // B1 is discarded if gmp-ecm is not installed
    ret_val = _factor_trial_division_sieve(_f, _n);
#endif // HAVE_SYMENGINE_ECM
    *f = integer(std::move(_f));

    return ret_val;
}
Ejemplo n.º 4
0
// Factorization
int factor(const Ptr<RCP<const Integer>> &f, const Integer &n, double B1)
{
    int ret_val = 0;
    mpz_class _n, _f;

    _n = n.as_mpz();

#ifdef HAVE_CSYMPY_ECM
    if (mpz_perfect_power_p(_n.get_mpz_t())) {

        unsigned long int i = 1;
        mpz_class m, rem;
        rem = 1; // Any non zero number
        m = 2; // set `m` to 2**i, i = 1 at the begining

        // calculate log2n, this can be improved
        for (; m < _n; i++)
            m = m * 2;

        // eventually `rem` = 0 zero as `n` is a perfect power. `f_t` will
        // be set to a factor of `n` when that happens
        while (i > 1 && rem != 0) {
            mpz_rootrem(_f.get_mpz_t(), rem.get_mpz_t(), _n.get_mpz_t(), i);
            i--;
        }

        ret_val = 1;
    }
    else {

        if (mpz_probab_prime_p(_n.get_mpz_t(), 25) > 0) { // most probably, n is a prime
            ret_val = 0;
            _f = _n;
        }
        else {

            for (int i = 0; i < 10 && !ret_val; i++)
                ret_val = ecm_factor(_f.get_mpz_t(), _n.get_mpz_t(), B1, NULL);
            if (!ret_val)
                throw std::runtime_error("ECM failed to factor the given number");
        }
    }
#else
    // B1 is discarded if gmp-ecm is not installed
    ret_val = _factor_trial_division_sieve(_f, _n);
#endif // HAVE_CSYMPY_ECM
    *f = integer(_f);

    return ret_val;
}
Ejemplo n.º 5
0
static int check_for_factor2(mpz_t f, mpz_t inputn, mpz_t fmin, mpz_t n, int stage, mpz_t* sfacs, int* nsfacs, int degree)
{
  int success, sfaci;
  UV B1;

  /* Use this so we don't modify their input value */
  mpz_set(n, inputn);

  if (mpz_cmp(n, fmin) <= 0) return 0;

#if 0
  {
    /* Straightforward trial division up to 3000. */
    PRIME_ITERATOR(iter);
    UV tf;
    UV const trial_limit = 3000;
    for (tf = 2; tf < trial_limit; tf = prime_iterator_next(&iter)) {
      if (mpz_cmp_ui(n, tf*tf) < 0) break;
      while (mpz_divisible_ui_p(n, tf))
        mpz_divexact_ui(n, n, tf);
    }
    prime_iterator_destroy(&iter);
  }
#else
  /* Utilize GMP's fast gcd algorithms.  Trial to 224737 with two gcds. */
  mpz_tdiv_q_2exp(n, n, mpz_scan1(n, 0));
  while (mpz_divisible_ui_p(n, 3))  mpz_divexact_ui(n, n, 3);
  while (mpz_divisible_ui_p(n, 5))  mpz_divexact_ui(n, n, 5);
  if (mpz_cmp(n, fmin) <= 0) return 0;
  mpz_gcd(f, n, _gcd_small);
  while (mpz_cmp_ui(f, 1) > 0) {
    mpz_divexact(n, n, f);
    mpz_gcd(f, n, _gcd_small);
  }
  if (mpz_cmp(n, fmin) <= 0) return 0;
  mpz_gcd(f, n, _gcd_large);
  while (mpz_cmp_ui(f, 1) > 0) {
    mpz_divexact(n, n, f);
    mpz_gcd(f, n, _gcd_large);
  }
  /* Quick stage 1 n-1 using a single big powm + gcd. */
  if (stage == 0) {
    if (mpz_cmp(n, fmin) <= 0) return 0;
    mpz_set_ui(f, 2);
    mpz_powm(f, f, _lcm_small, n);
    mpz_sub_ui(f, f, 1);
    mpz_gcd(f, f, n);
    if (mpz_cmp_ui(f, 1) != 0 && mpz_cmp(f, n) != 0) {
      mpz_divexact(n, n, f);
      if (mpz_cmp(f, n) > 0)
        mpz_set(n, f);
    }
  }
#endif

  sfaci = 0;
  success = 1;
  while (success) {
    UV nsize = mpz_sizeinbase(n, 2);

    if (mpz_cmp(n, fmin) <= 0) return 0;
    if (_GMP_is_prob_prime(n)) { mpz_set(f, n); return (mpz_cmp(f, fmin) > 0); }

    success = 0;
    B1 = 300 + 3 * nsize;
    if (degree <= 2) B1 += nsize; /* D1 & D2 are cheap to prove.  Encourage. */
    if (degree <= 0) B1 += nsize; /* N-1 and N+1 are really cheap. */
    if (degree > 20 && stage <= 1) B1 -= nsize;   /* Less time on big polys. */
    if (degree > 40) B1 -= nsize/2;               /* Less time on big polys. */
    if (stage >= 1) {
#ifdef USE_LIBECM
      /* TODO: Tune stage 1 (PM1?) */
      /* TODO: LIBECM in other stages */
      if (!success) {
        ecm_params params;
        ecm_init(params);
        params->method = ECM_ECM;
        mpz_set_ui(params->B2, 10*B1);
        mpz_set_ui(params->sigma, 0);
        success = ecm_factor(f, n, B1/4, params);
        ecm_clear(params);
        if (mpz_cmp(f, n) == 0)  success = 0;
      }
#else
      if (!success) success = _GMP_pminus1_factor(n, f, B1, 6*B1);
      if (!success) success = _GMP_pplus1_factor(n, f, 0, B1/8, B1/8);
      if (!success && nsize < 500) success = _GMP_pbrent_factor(n, f, nsize, 1024-nsize);
#endif
    }
    /* Try any factors found in previous stage 2+ calls */
    while (!success && sfaci < *nsfacs) {
      if (mpz_divisible_p(n, sfacs[sfaci])) {
        mpz_set(f, sfacs[sfaci]);
        success = 1;
      }
      sfaci++;
    }
    if (stage > 1 && !success) {
      if (stage == 2) {
        if (!success) success = _GMP_pbrent_factor(n, f, nsize-1, 8192);
        if (!success) success = _GMP_pminus1_factor(n, f, 6*B1, 60*B1);
        /* p+1 with different initial point and searching farther */
        if (!success) success = _GMP_pplus1_factor(n, f, 1, B1/2, B1/2);
        if (!success) success = _GMP_ecm_factor_projective(n, f, 250, 3);
      } else if (stage == 3) {
        if (!success) success = _GMP_pbrent_factor(n, f, nsize+1, 16384);
        if (!success) success = _GMP_pminus1_factor(n, f, 60*B1, 600*B1);
        /* p+1 with a third initial point and searching farther */
        if (!success) success = _GMP_pplus1_factor(n, f, 2, 1*B1, 1*B1);
        if (!success) success = _GMP_ecm_factor_projective(n, f, B1/4, 4);
      } else if (stage == 4) {
        if (!success) success = _GMP_pminus1_factor(n, f, 300*B1, 300*20*B1);
        if (!success) success = _GMP_ecm_factor_projective(n, f, B1/2, 4);
      } else if (stage >= 5) {
        UV B = B1 * (stage-4) * (stage-4) * (stage-4);
        if (!success) success = _GMP_ecm_factor_projective(n, f, B, 8+stage);
      }
    }
    if (success) {
      if (mpz_cmp_ui(f, 1) == 0 || mpz_cmp(f, n) == 0) {
        gmp_printf("factoring %Zd resulted in factor %Zd\n", n, f);
        croak("internal error in ECPP factoring");
      }
      /* Add the factor to the saved factors list */
      if (stage > 1 && *nsfacs < MAX_SFACS) {
        /* gmp_printf(" ***** adding factor %Zd ****\n", f); */
        mpz_init_set(sfacs[*nsfacs], f);
        nsfacs[0]++;
      }
      /* Is the factor f what we want? */
      if ( mpz_cmp(f, fmin) > 0 && _GMP_is_prob_prime(f) )  return 1;
      /* Divide out f */
      mpz_divexact(n, n, f);
    }
  }
  /* n is larger than fmin and not prime */
  mpz_set(f, n);
  return -1;
}
Ejemplo n.º 6
0
uint32 ecm_pp1_pm1(msieve_obj *obj, mp_t *n, mp_t *reduced_n, 
		   factor_list_t *factor_list) {

	uint32 i, j, max_digits;
	uint32 bits;
	mpz_t gmp_n, gmp_factor;
	pm1_pp1_t non_ecm_vals[NUM_NON_ECM];
	uint32 factor_found = 0;
	uint32 num_trivial = 0;
	ecm_params params;

	/* factorization will continue until any remaining
	   composite cofactors are smaller than the cutoff for
	   using other methods */

	/* initialize */

	mpz_init(gmp_n);
	mpz_init(gmp_factor);
	for (i = 0; i < NUM_NON_ECM; i++) {
		pm1_pp1_t *tmp = non_ecm_vals + i;
		tmp->stage_1_done = 1.0;
		mpz_init_set_ui(tmp->start_val, (unsigned long)0);
	}
	ecm_init(params);
	gmp_randseed_ui(params->rng, get_rand(&obj->seed1, &obj->seed2));
	mp2gmp(n, gmp_n);
	max_digits = choose_max_digits(obj, mp_bits(n));

	/* for each digit level */

	for (i = 0; i < NUM_TABLE_ENTRIES; i++) {
		const work_t *curr_work = work_table + i;
		uint32 log_rate, next_log;
		int status;

		if (curr_work->digits > max_digits)
			break;

		logprintf(obj, "searching for %u-digit factors\n",
				curr_work->digits);

		/* perform P-1. Stage 1 runs much faster for this
		   algorithm than it does for ECM, so crank up the
		   stage 1 bound
		
		   We save the stage 1 output to reduce the work at
		   the next digit level */

		for (j = 0; j < NUM_PM1_TRIALS; j++) {
			pm1_pp1_t *tmp = non_ecm_vals + j;

			params->method = ECM_PM1;
			params->B1done = tmp->stage_1_done;
			mpz_set(params->x, tmp->start_val);

			status = ecm_factor(gmp_factor, gmp_n,
					10 * curr_work->stage_1_bound, params);

			tmp->stage_1_done = params->B1done;
			mpz_set(tmp->start_val, params->x);
			HANDLE_FACTOR_FOUND("P-1");
		}

		/* perform P+1. Stage 1 runs somewhat faster for this
		   algorithm than it does for ECM, so crank up the
		   stage 1 bound
		
		   We save the stage 1 output to reduce the work at
		   the next digit level */

		for (j = 0; j < NUM_PP1_TRIALS; j++) {
			pm1_pp1_t *tmp = non_ecm_vals + NUM_PM1_TRIALS + j;

			params->method = ECM_PP1;
			params->B1done = tmp->stage_1_done;
			mpz_set(params->x, tmp->start_val);

			status = ecm_factor(gmp_factor, gmp_n,
					5 * curr_work->stage_1_bound, params);

			tmp->stage_1_done = params->B1done;
			mpz_set(tmp->start_val, params->x);
			HANDLE_FACTOR_FOUND("P+1");
		}

		/* run the specified number of ECM curves. Because
		   so many curves could be necessary, just start each
		   one from scratch */

		log_rate = 0;
		if (obj->flags & (MSIEVE_FLAG_USE_LOGFILE |
	    		   	  MSIEVE_FLAG_LOG_TO_STDOUT)) {
			if (curr_work->digits >= 35)
				log_rate = 1;
			else if (curr_work->digits >= 30)
				log_rate = 5;
			else if (curr_work->digits >= 25)
				log_rate = 20;
		}

		next_log = log_rate;
		for (j = 0; j < curr_work->num_ecm_trials; j++) {

			params->method = ECM_ECM;
			params->B1done = 1.0;
			mpz_set_ui(params->x, (unsigned long)0);
			mpz_set_ui(params->sigma, (unsigned long)0);

			status = ecm_factor(gmp_factor, gmp_n,
					curr_work->stage_1_bound, params);
			HANDLE_FACTOR_FOUND("ECM");

			if (log_rate && j == next_log) {
				next_log += log_rate;
				fprintf(stderr, "%u of %u curves\r",
						j, curr_work->num_ecm_trials);
				fflush(stderr);
			}
		}

		if (log_rate)
			fprintf(stderr, "\ncompleted %u ECM curves\n", j);
	}

clean_up:
	ecm_clear(params);
	gmp2mp(gmp_n, reduced_n);
	mpz_clear(gmp_n);
	mpz_clear(gmp_factor);
	for (i = 0; i < NUM_NON_ECM; i++)
		mpz_clear(non_ecm_vals[i].start_val);
	return factor_found;
}
Ejemplo n.º 7
0
static int check_for_factor(mpz_t f, mpz_t inputn, mpz_t fmin, mpz_t n, int stage, mpz_t* sfacs, int* nsfacs, int degree)
{
  int success, sfaci;
  UV B1;

  /* Use this so we don't modify their input value */
  mpz_set(n, inputn);

  if (mpz_cmp(n, fmin) <= 0) return 0;

#if 0
  /* Use this to really encourage n-1 / n+1 proof types */
  if (degree <= 0) {
    if (stage == 1) return -1;
    if (stage == 0) stage = 1;
  }
#endif

  /* Utilize GMP's fast gcd algorithms.  Trial to 224737+ with two gcds. */
  mpz_tdiv_q_2exp(n, n, mpz_scan1(n, 0));
  while (mpz_divisible_ui_p(n, 3))  mpz_divexact_ui(n, n, 3);
  while (mpz_divisible_ui_p(n, 5))  mpz_divexact_ui(n, n, 5);
  if (mpz_cmp(n, fmin) <= 0) return 0;
  mpz_gcd(f, n, _gcd_small);
  while (mpz_cmp_ui(f, 1) > 0) {
    mpz_divexact(n, n, f);
    mpz_gcd(f, f, n);
  }
  if (mpz_cmp(n, fmin) <= 0) return 0;
  mpz_gcd(f, n, _gcd_large);
  while (mpz_cmp_ui(f, 1) > 0) {
    mpz_divexact(n, n, f);
    mpz_gcd(f, f, n);
  }

  sfaci = 0;
  success = 1;
  while (success) {
    UV nsize = mpz_sizeinbase(n, 2);
    const int do_pm1 = 1;
    const int do_pp1 = 1;
    const int do_pbr = 0;
    const int do_ecm = 0;

    if (mpz_cmp(n, fmin) <= 0) return 0;
    if (is_bpsw_prime(n)) { mpz_set(f, n); return (mpz_cmp(f, fmin) > 0); }

    success = 0;
    B1 = 300 + 3 * nsize;
    if (degree <= 2) B1 += nsize;             /* D1 & D2 are cheap to prove. */
    if (degree <= 0) B1 += 2*nsize;         /* N-1 and N+1 are really cheap. */
    if (degree > 20 && stage <= 1) B1 -= nsize;   /* Less time on big polys. */
    if (degree > 40) B1 -= nsize/2;               /* Less time on big polys. */
    if (stage == 0) {
      /* A relatively small performance hit, makes slightly smaller proofs. */
      if (nsize < 900 && degree <= 2) B1 *= 1.8;
      /* We need to try a bit harder for the large sizes :( */
      if (nsize > 1400)  B1 *= 2;
      if (nsize > 2000)  B1 *= 2;
      if (!success)
        success = _GMP_pminus1_factor(n, f, 100+B1/8, 100+B1);
    } else if (stage >= 1) {
      /* P-1 */
      if ((!success && do_pm1))
        success = _GMP_pminus1_factor(n, f, B1, 6*B1);
      /* Pollard's Rho */
      if ((!success && do_pbr && nsize < 500))
        success = _GMP_pbrent_factor(n, f, nsize % 53, 1000-nsize);
      /* P+1 */
      if ((!success && do_pp1)) {
        UV ppB = (nsize < 2000) ? B1/4 : B1/16;
        success = _GMP_pplus1_factor(n, f, 0, ppB, ppB);
      }
      if ((!success && do_ecm))
        success = _GMP_ecm_factor_projective(n, f, 400, 2000, 1);
#ifdef USE_LIBECM
      /* TODO: LIBECM in other stages */
      /* Note: this will be substantially slower than our code for small sizes
       *       and the small B1/B2 values we're using. */
      if (!success && degree <= 2 && nsize > 600) {
        ecm_params params;
        ecm_init(params);
        params->method = ECM_ECM;
        mpz_set_ui(params->B2, 10*B1);
        mpz_set_ui(params->sigma, 0);
        success = ecm_factor(f, n, B1/4, params);
        ecm_clear(params);
        if (mpz_cmp(f, n) == 0)  success = 0;
        if (success) { printf("ECM FOUND FACTOR\n"); }
      }
#endif
    }
    /* Try any factors found in previous stage 2+ calls */
    while (!success && sfaci < *nsfacs) {
      if (mpz_divisible_p(n, sfacs[sfaci])) {
        mpz_set(f, sfacs[sfaci]);
        success = 1;
      }
      sfaci++;
    }
    if (stage > 1 && !success) {
      if (stage == 2) {
        /* if (!success) success = _GMP_pbrent_factor(n, f, nsize-1, 8192); */
        if (!success) success = _GMP_pminus1_factor(n, f, 6*B1, 60*B1);
        /* p+1 with different initial point and searching farther */
        if (!success) success = _GMP_pplus1_factor(n, f, 1, B1/2, B1/2);
        if (!success) success = _GMP_ecm_factor_projective(n, f, 250, 2500, 8);
      } else if (stage == 3) {
        if (!success) success = _GMP_pbrent_factor(n, f, nsize+1, 16384);
        if (!success) success = _GMP_pminus1_factor(n, f, 60*B1, 600*B1);
        /* p+1 with a third initial point and searching farther */
        if (!success) success = _GMP_pplus1_factor(n, f, 2, 1*B1, 1*B1);
        if (!success) success = _GMP_ecm_factor_projective(n, f, B1/4, B1*4, 5);
      } else if (stage == 4) {
        if (!success) success = _GMP_pminus1_factor(n, f, 300*B1, 300*20*B1);
        if (!success) success = _GMP_ecm_factor_projective(n, f, B1/2, B1*8, 4);
      } else if (stage >= 5) {
        UV B = B1 * (stage-4) * (stage-4) * (stage-4);
        if (!success) success = _GMP_ecm_factor_projective(n, f, B, 10*B, 8+stage);
      }
    }
    if (success) {
      if (mpz_cmp_ui(f, 1) == 0 || mpz_cmp(f, n) == 0) {
        gmp_printf("factoring %Zd resulted in factor %Zd\n", n, f);
        croak("internal error in ECPP factoring");
      }
      /* Add the factor to the saved factors list */
      if (stage > 1 && *nsfacs < MAX_SFACS) {
        /* gmp_printf(" ***** adding factor %Zd ****\n", f); */
        mpz_init_set(sfacs[*nsfacs], f);
        nsfacs[0]++;
      }
      /* Is the factor f what we want? */
      if ( mpz_cmp(f, fmin) > 0 && is_bpsw_prime(f) )  return 1;
      /* Divide out f */
      mpz_divexact(n, n, f);
    }
  }
  /* n is larger than fmin and not prime */
  mpz_set(f, n);
  return -1;
}