mp_limb_t n_primitive_root_prime(mp_limb_t p) { mp_limb_t a; n_factor_t factors; n_factor_init(&factors); n_factor(&factors, p - 1, 1); a = n_primitive_root_prime_prefactor(p, &factors); return a; }
void acb_dirichlet_group_init(acb_dirichlet_group_t G, ulong q) { slong k; n_factor_t fac; G->q = q; G->q_odd = q; G->q_even = 1; while (G->q_odd % 2 == 0) { G->q_odd /= 2; G->q_even *= 2; } n_factor_init(&fac); n_factor(&fac, G->q_odd, 1); G->num = fac.num; G->primes = flint_malloc(G->num * sizeof(ulong)); G->exponents = flint_malloc(G->num * sizeof(ulong)); G->generators = flint_malloc(G->num * sizeof(ulong)); G->PHI = flint_malloc(G->num * sizeof(ulong)); for (k = 0; k < G->num; k++) { G->primes[k] = fac.p[k]; G->exponents[k] = fac.exp[k]; } G->phi_q_odd = 1; for (k = 0; k < G->num; k++) G->phi_q_odd *= (G->primes[k] - 1) * n_pow(G->primes[k], G->exponents[k]-1); if (G->q_even == 1) G->phi_q = G->phi_q_odd; else G->phi_q = G->phi_q_odd * (G->q_even / 2); for (k = 0; k < G->num; k++) { ulong phi; G->generators[k] = primitive_root_p_and_p2(G->primes[k]); phi = n_pow(G->primes[k], G->exponents[k] - 1) * (G->primes[k] - 1); G->PHI[k] = G->phi_q_odd / phi; } }
ulong dlog_crt_init(dlog_crt_t t, ulong a, ulong mod, ulong n, ulong num) { int k; n_factor_t fac; ulong * M, * u; ulong cost = 0; n_factor_init(&fac); n_factor(&fac, n, 1); t->num = fac.num; nmod_init(&t->mod,mod); nmod_init(&t->n, n); M = t->expo = flint_malloc(t->num * sizeof(ulong)); u = t->crt_coeffs = flint_malloc(t->num * sizeof(ulong)); t->pre = flint_malloc(t->num * sizeof(dlog_precomp_struct)); for (k = 0; k < t->num; k++) { ulong p, e, mk; p = fac.p[k]; e = fac.exp[k]; if (0 && mod % p == 0) { flint_printf("dlog_crt_init: modulus must be prime to order.\n"); abort(); } mk = n_pow(p, e); M[k] = n / mk; u[k] = nmod_mul(M[k], n_invmod(M[k] % mk, mk), t->n); /* depends on the power */ #if 0 flint_printf("[sub-crt -- init for size %wu mod %wu]\n", mk, mod); #endif dlog_precomp_pe_init(t->pre + k, nmod_pow_ui(a, M[k], t->mod), mod, p, e, mk, num); cost += t->pre[k].cost; } #if 0 if (cost > 500) flint_printf("[crt init for size %wu mod %wu -> cost %wu]\n", n,mod,cost); #endif return cost; }
void dirichlet_group_init(dirichlet_group_t G, ulong q) { slong k; ulong e2; n_factor_t fac; G->q = q; nmod_init(&G->mod, q); e2 = n_remove(&q, 2); G->q_even = 1 << e2; /* number of components at p=2 */ G->neven = (e2 >= 3) ? 2 : (e2 == 2) ? 1 : 0; /* warning: only factor odd part */ n_factor_init(&fac); n_factor(&fac, q, 1); G->num = fac.num + G->neven; G->P = flint_malloc(G->num * sizeof(dirichlet_prime_group_struct)); G->generators = flint_malloc(G->num * sizeof(ulong)); G->PHI = flint_malloc(G->num * sizeof(ulong)); /* even part */ if (G->neven >= 1) dirichlet_prime_group_init(&G->P[0], 2, e2); if (G->neven == 2) dirichlet_prime_group_init(&G->P[1], 4, e2); /* odd part */ G->rad_q = 1; for (k = G->neven; k < G->num; k++) { ulong p, e; p = fac.p[k - G->neven]; e = fac.exp[k - G->neven]; G->rad_q *= p; dirichlet_prime_group_init(&G->P[k], p, e); } dirichlet_group_lift_generators(G); }
slong Util::compute_multiplicative_order(ulong a, ulong modulus) { n_factor_t factors; n_factor_init(&factors); ulong order = modulus - 1; n_factor(&factors, order, 1); slong temp = 1; for (slong i = 0; i < factors.num; i++) { while (temp == 1 && factors.exp[i] > 0) { order /= factors.p[i]; factors.exp[i]--; temp = n_powmod(a, order, modulus); } if (temp != 1) { order *= factors.p[i]; temp = 1; } } return order; }