mp_limb_t n_powmod_precomp(mp_limb_t a, mp_limb_signed_t exp, mp_limb_t n, double npre) { mp_limb_t x, y; mp_limb_signed_t e; if (n == 1UL) return 0L; e = (exp < 0L ? -exp : exp); x = 1UL; y = a; while (e) { if (e & 1L) x = n_mulmod_precomp(x, y, n, npre); e >>= 1; if (e) y = n_mulmod_precomp(y, y, n, npre); } return (exp < 0L ? n_invmod(x, n) : x); }
int n_is_probabprime_fibonacci(mp_limb_t n) { mp_limb_t m; n_pair_t V; if (FLINT_ABS((mp_limb_signed_t) n) <= 3UL) { if (n >= 2UL) return 1; return 0; } m = (n - n_jacobi(5L, n)) / 2; /* cannot overflow as (5/n) = 0 for n = 2^64-1 */ if (FLINT_BIT_COUNT(n) <= FLINT_D_BITS) { double npre = n_precompute_inverse(n); V = fchain_precomp(m, n, npre); return (n_mulmod_precomp(n - 3UL, V.x, n, npre) == n_mulmod_precomp(2UL, V.y, n, npre)); } else { mp_limb_t ninv = n_preinvert_limb(n); V = fchain2_preinv(m, n, ninv); return (n_mulmod2_preinv(n - 3UL, V.x, n, ninv) == n_mulmod2_preinv(2UL, V.y, n, ninv)); } }
n_pair_t fchain_precomp(mp_limb_t m, mp_limb_t n, double npre) { n_pair_t current = {0, 0}, old; int length; mp_limb_t power, xy; old.x = 2UL; old.y = n - 3UL; length = FLINT_BIT_COUNT(m); power = (1UL << (length - 1)); for (; length > 0; length--) { xy = n_mulmod_precomp(old.x, old.y, n, npre); xy = n_addmod(xy, 3UL, n); if (m & power) { current.y = n_submod(n_mulmod_precomp(old.y, old.y, n, npre), 2UL, n); current.x = xy; } else { current.x = n_submod(n_mulmod_precomp(old.x, old.x, n, npre), 2UL, n); current.y = xy; } power >>= 1; old = current; } return current; }
int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mulmod_precomp...."); fflush(stdout); for (i = 0; i < 100000 * flint_test_multiplier(); i++) { mp_limb_t a, b, d, r1, r2, p1, p2, dinv; double dpre; mp_limb_t bits = n_randint(state, FLINT_D_BITS) + 1; d = n_randtest_bits(state, bits); a = n_randtest(state) % d; b = n_randtest(state) % d; dpre = n_precompute_inverse(d); r1 = n_mulmod_precomp(a, b, d, dpre); umul_ppmm(p1, p2, a, b); dinv = n_preinvert_limb(d); r2 = n_ll_mod_preinv(p1, p2, d, dinv); result = (r1 == r2); if (!result) { flint_printf("FAIL:\n"); flint_printf("a = %wu, b = %wu, d = %wu, dinv = %f\n", a, b, d, dpre); flint_printf("r1 = %wu, r2 = %wu\n", r1, r2); abort(); } } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; }