/*
Copyright (C) 2015 Kushagra Singh
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
*/
#include
#include "flint.h"
#include "ulong_extras.h"
static
ulong n_ecm_primorial[] =
{
#ifdef FLINT64
UWORD(2), UWORD(6), UWORD(30), UWORD(210), UWORD(2310), UWORD(30030),
UWORD(510510), UWORD(9699690), UWORD(223092870), UWORD(6469693230),
UWORD(200560490130), UWORD(7420738134810), UWORD(304250263527210),
UWORD(13082761331670030), UWORD(614889782588491410)
#else
UWORD(2), UWORD(6), UWORD(30), UWORD(210), UWORD(2310), UWORD(30030),
UWORD(510510), UWORD(9699690)
#endif
};
#ifdef FLINT64
#define num_n_ecm_primorials 15
#else
#define num_n_ecm_primorials 9
#endif
int
n_factor_ecm(mp_limb_t *f, mp_limb_t curves, mp_limb_t B1, mp_limb_t B2,
flint_rand_t state, mp_limb_t n)
{
mp_limb_t P, num, maxD, mmin, mmax, mdiff, prod, maxj, sig;
int i, j, ret;
n_ecm_t n_ecm_inf;
const mp_limb_t *prime_array;
count_leading_zeros(n_ecm_inf->normbits, n);
n <<= n_ecm_inf->normbits;
n_ecm_inf->ninv = n_preinvert_limb(n);
n_ecm_inf->one = UWORD(1) << n_ecm_inf->normbits;
ret = 0;
/************************ STAGE I PRECOMPUTATIONS ************************/
num = n_prime_pi(B1); /* number of primes under B1 */
/* compute list of primes under B1 for stage I */
prime_array = n_primes_arr_readonly(num);
/************************ STAGE II PRECOMPUTATIONS ***********************/
maxD = n_sqrt(B2);
/* Selecting primorial */
j = 1;
while ((j < num_n_ecm_primorials) && (n_ecm_primorial[j] < maxD))
j += 1;
P = n_ecm_primorial[j - 1];
mmin = (B1 + (P/2)) / P;
mmax = ((B2 - P/2) + P - 1)/P; /* ceil */
maxj = (P + 1)/2;
mdiff = mmax - mmin + 1;
/* compute GCD_table */
n_ecm_inf->GCD_table = flint_malloc(maxj + 1);
for (j = 1; j <= maxj; j += 2)
{
if ((j%2) && n_gcd(j, P) == 1)
n_ecm_inf->GCD_table[j] = 1;
else
n_ecm_inf->GCD_table[j] = 0;
}
/* compute prime table */
n_ecm_inf->prime_table = flint_malloc(mdiff * sizeof(unsigned char*));
for (i = 0; i < mdiff; i++)
n_ecm_inf->prime_table[i] = flint_malloc((maxj + 1) * sizeof(unsigned char));
for (i = 0; i < mdiff; i++)
{
for (j = 1; j <= maxj; j += 2)
{
n_ecm_inf->prime_table[i][j] = 0;
/* if (i + mmin)*D + j
is prime, mark 1. Can be possibly prime
only if gcd(j, D) = 1 */
if (n_ecm_inf->GCD_table[j] == 1)
{
prod = (i + mmin)*P + j;
if (n_is_prime(prod))
n_ecm_inf->prime_table[i][j] = 1;
prod = (i + mmin)*P - j;
if (n_is_prime(prod))
n_ecm_inf->prime_table[i][j] = 1;
}
}
}
/****************************** TRY "CURVES" *****************************/
for (j = 0; j < curves; j++)
{
sig = n_randint(state, n >> n_ecm_inf->normbits);
sig = n_addmod(sig, 7, n >> n_ecm_inf->normbits);
sig <<= n_ecm_inf->normbits;
/************************ SELECT CURVE ************************/
if (n_factor_ecm_select_curve(f, sig, n, n_ecm_inf))
{
/* Found factor while selecting curve,
very very lucky :) */
(*f) >>= n_ecm_inf->normbits;
ret = -1;
goto cleanup;
}
/************************** STAGE I ***************************/
ret = n_factor_ecm_stage_I(f, prime_array, num, B1, n, n_ecm_inf);
if (ret)
{
/* Found factor after stage I */
(*f) >>= n_ecm_inf->normbits;
ret = 1;
goto cleanup;
}
/************************** STAGE II ***************************/
ret = n_factor_ecm_stage_II(f, B1, B2, P, n, n_ecm_inf);
if (ret)
{
/* Found factor after stage II */
(*f) >>= n_ecm_inf->normbits;
ret = 2;
goto cleanup;
}
}
cleanup:
flint_free(n_ecm_inf->GCD_table);
for (i = 0; i < mdiff; i++)
flint_free(n_ecm_inf->prime_table[i]);
flint_free(n_ecm_inf->prime_table);
return ret;
}