/*
Copyright (C) 2014 William Hart
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 .
*/
#define ulong ulongxx /* interferes with system includes */
#include
#include
#include
#include
#undef ulong
#define ulong mp_limb_t
#include
#include "flint.h"
#include "ulong_extras.h"
#include "fmpz.h"
#include "fmpz_vec.h"
int fmpz_is_probabprime_lucas(const fmpz_t n)
{
fmpz_t A, Q, D, t, m, Vm, Vm1;
int res = 0;
if (fmpz_cmp_ui(n, 1) <= 0)
return 0;
if (fmpz_is_even(n))
return fmpz_cmp_ui(n, 2) == 0; /* ensure 2, n coprime */
if (fmpz_is_square(n))
return 0;
fmpz_init(A);
fmpz_init(Q);
fmpz_init(D);
fmpz_init(t);
fmpz_init(m);
fmpz_init(Vm);
fmpz_init(Vm1);
fmpz_set_si(D, WORD(-3)); /* -3 becomes 5 after first iteration */
do {
/* check D = 5, -7, 9, -11 such that (D/n) = -1 */
do {
if (fmpz_sgn(D) > 0)
fmpz_add_ui(D, D, 2);
else
fmpz_sub_ui(D, D, 2);
fmpz_neg(D, D);
} while (fmpz_jacobi(D, n) != -1); /* this ensures D, n coprime */
fmpz_sub_ui(t, D, 1);
fmpz_neg(t, t);
fmpz_tdiv_q_2exp(Q, t, 2);
fmpz_gcd(t, Q, n); /* require Q, n coprime */
} while (fmpz_equal(t, n));
if (fmpz_is_one(t)) /* check no factor found */
{
fmpz_invmod(A, Q, n); /* A = P^2Q^-1 - 2 mod n, where P = 1 */
fmpz_sub_ui(A, A, 2);
if (fmpz_sgn(A) < 0)
fmpz_add(A, A, n);
fmpz_add_ui(m, n, 1); /* m = (n - jacobi(D/n))/2 = (n + 1)/2 */
fmpz_tdiv_q_2exp(m, m, 1);
fmpz_lucas_chain(Vm, Vm1, A, m, n);
fmpz_mul(Vm, Vm, A);
fmpz_submul_ui(Vm, Vm1, 2);
res = fmpz_divisible(Vm, n);
}
fmpz_clear(A);
fmpz_clear(Q);
fmpz_clear(D);
fmpz_clear(t);
fmpz_clear(m);
fmpz_clear(Vm);
fmpz_clear(Vm1);
return res;
}