/*
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"
int
n_factor_ecm_select_curve(mp_limb_t *f, mp_limb_t sig, mp_limb_t n, n_ecm_t n_ecm_inf)
{
mp_limb_t u, v, w, t, hi, lo;
mp_ptr a;
TMP_INIT;
TMP_START;
a = TMP_ALLOC(2 * sizeof(mp_limb_t));
u = sig;
/* v = sig * 4 */
v = n_mulmod_preinv(u, UWORD(4) << n_ecm_inf->normbits, n, n_ecm_inf->ninv,
n_ecm_inf->normbits);
/* w = sig ^ 2 */
w = n_mulmod_preinv(u, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
u = w - (UWORD(5) << n_ecm_inf->normbits); /* u = sig^2 - 5 */
/* w = u * u */
w = n_mulmod_preinv(u, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
/* x = u * u * u */
n_ecm_inf->x = n_mulmod_preinv(w, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
/* w = v * v */
w = n_mulmod_preinv(v, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
/* z = v * v * v */
n_ecm_inf->z = n_mulmod_preinv(w, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
w = n_mulmod_preinv(n_ecm_inf->x, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
t = n_mulmod_preinv(w, UWORD(4) << n_ecm_inf->normbits, n, n_ecm_inf->ninv,
n_ecm_inf->normbits);
w = n_mulmod_preinv(u, UWORD(3) << n_ecm_inf->normbits, n, n_ecm_inf->ninv,
n_ecm_inf->normbits);
u = n_submod(v, u, n);
v = n_addmod(v, w, n);
w = n_mulmod_preinv(u, u, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
u = n_mulmod_preinv(u, w, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
n_ecm_inf->a24 = n_mulmod_preinv(u, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
v = n_mulmod_preinv(t, n_ecm_inf->z, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
*f = n_gcdinv(&u, v, n);
if (*f == n)
return 0;
else if (*f > n_ecm_inf->one)
return 1;
a[1] = UWORD(0);
a[0] = u;
mpn_lshift(a, a, 2, n_ecm_inf->normbits); /* shifting back right */
hi = a[1];
lo = a[0];
u = n_ll_mod_preinv(hi, lo, n, n_ecm_inf->ninv);
v = n_mulmod_preinv(u, t, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
n_ecm_inf->x = n_mulmod_preinv(n_ecm_inf->x, v, n, n_ecm_inf->ninv,
n_ecm_inf->normbits);
v = n_mulmod_preinv(u, n_ecm_inf->z, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
w = n_mulmod_preinv(n_ecm_inf->a24, v, n, n_ecm_inf->ninv, n_ecm_inf->normbits);
n_ecm_inf->a24 = n_addmod(w, UWORD(2) << n_ecm_inf->normbits, n);
n_ecm_inf->a24 >>= 2;
n_ecm_inf->a24 >>= n_ecm_inf->normbits;
n_ecm_inf->a24 <<= n_ecm_inf->normbits;
n_ecm_inf->z = n_ecm_inf->one;
TMP_END;
return 0;
}