void nmod_mat_init_set(nmod_mat_t mat, const nmod_mat_t src) { slong rows = src->r; slong cols = src->c; if ((rows) && (cols)) { slong i; mat->entries = flint_malloc(rows * cols * sizeof(mp_limb_t)); mat->rows = flint_malloc(rows * sizeof(mp_limb_t *)); for (i = 0; i < rows; i++) { mat->rows[i] = mat->entries + i * cols; flint_mpn_copyi(mat->rows[i], src->rows[i], cols); } } else mat->entries = NULL; mat->r = rows; mat->c = cols; mat->mod = src->mod; }
renf_elem_class::renf_elem_class(const renf_class & k, const std::string & str) : renf_elem_class(k) { const char * s = str.c_str(); int err; const char * i = strchr(s, '~'); char * t; if (i != nullptr) { t = (char *) flint_malloc((i - s + 1) * sizeof(char)); strncpy(t, s, i - s); t[i - s] = '\0'; } else { t = (char *) flint_malloc((strlen(s) + 1) * sizeof(char)); strcpy(t, s); } fmpq_poly_t p; fmpq_poly_init(p); err = fmpq_poly_set_str_pretty(p, t, nf->gen_name().c_str()); if (err) { fmpq_poly_clear(p); throw std::invalid_argument("renf_elem_class fmpq_poly_set_str_pretty"); } renf_elem_set_fmpq_poly(a, p, nf->renf_t()); fmpq_poly_clear(p); flint_free(t); }
__mpz_struct * _fmpz_new_mpz(void) { if (fmpz_num_unused == 0) /* time to allocate MPZ_BLOCK more mpz_t's */ { ulong i; if (fmpz_allocated) /* realloc mpz_t's and unused array */ { fmpz_arr = (__mpz_struct *) flint_realloc(fmpz_arr, (fmpz_allocated + MPZ_BLOCK) * sizeof(__mpz_struct)); fmpz_unused_arr = (ulong *) flint_realloc(fmpz_unused_arr, (fmpz_allocated + MPZ_BLOCK) * sizeof(ulong)); } else /* first time alloc of mpz_t's and unused array */ { fmpz_arr = (__mpz_struct *) flint_malloc(MPZ_BLOCK*sizeof(__mpz_struct)); fmpz_unused_arr = (ulong *) flint_malloc(MPZ_BLOCK*sizeof(ulong)); } /* initialise the new mpz_t's and unused array */ for (i = 0; i < MPZ_BLOCK; i++) { mpz_init(fmpz_arr + fmpz_allocated + i); fmpz_unused_arr[fmpz_num_unused] = fmpz_allocated + i; fmpz_num_unused++; } fmpz_allocated += MPZ_BLOCK; } fmpz_num_unused--; return fmpz_arr + fmpz_unused_arr[fmpz_num_unused]; }
void spanning_tree(tree_t tree, acb_srcptr x, slong len, int type) { slong k, i, n; cdouble * w; int * t; edge_t * e; /* small approx of roots */ w = flint_malloc(len * sizeof(cdouble)); for (k = 0; k < len; k++) w[k] = acb_get_cdouble(x + k); n = (len * (len - 1)) / 2; e = flint_malloc(n * sizeof(edge_t)); if (type == INT_GC || type == INT_D2) edges_init(e, param_gc_r, w, len); else if (type == INT_DE) edges_init(e, param_de_tau, w, len); else printf("unknown type\n"), abort(); /* order edges */ qsort(e, n, sizeof(edge_t), (int(*)(const void*,const void*))edge_cmp); t = flint_malloc(len * sizeof(int)); for (k = 0; k < len; k++) t[k] = 0; for (k = 0; k < tree->n; k++) { /* start from last edge, discard if both left or taken */ /* remark: stupid to loop many times, otherwise one can * take non-connected edges but one must reorder the * edges at the end */ for (i = n - 1; k && t[e[i].a] == t[e[i].b]; i--); /* ensure a already in tree */ if (t[e[i].b]) edge_flip(e[i]); t[e[i].a] = 1; t[e[i].b] = 1; tree->e[k] = e[i]; /* save worst edge and complexity estimate */ if (!tree->r || e[i].r < tree->r) { tree->r = e[i].r; tree->min = k; } } flint_free(w); flint_free(e); flint_free(t); }
void fmpz_poly_hensel_lift_once(fmpz_poly_factor_t lifted_fac, const fmpz_poly_t f, const nmod_poly_factor_t local_fac, long N) { const long r = local_fac->num; long i; long *link; fmpz_poly_t *v, *w; link = flint_malloc((2*r - 2) * sizeof(long)); v = flint_malloc(2*(2*r - 2) * sizeof(fmpz_poly_t)); w = v + (2*r - 2); for(i = 0; i < 2*r - 2; i++) { fmpz_poly_init(v[i]); fmpz_poly_init(w[i]); } _fmpz_poly_hensel_start_lift(lifted_fac, link, v, w, f, local_fac, N); for (i = 0; i < 2*r - 2; i++) { fmpz_poly_clear(v[i]); fmpz_poly_clear(w[i]); } flint_free(link); flint_free(v); }
void custom_rate_mixture_init(custom_rate_mixture_t x, int n) { x->n = n; x->rates = flint_malloc(n * sizeof(double)); x->prior = flint_malloc(n * sizeof(double)); }
void fmpz_poly_q_init(fmpz_poly_q_t rop) { rop->num = flint_malloc(sizeof(fmpz_poly_struct)); rop->den = flint_malloc(sizeof(fmpz_poly_struct)); fmpz_poly_init(rop->num); fmpz_poly_init(rop->den); fmpz_poly_set_si(rop->den, 1); }
int main(void) { int i; mp_size_t j; flint_rand_t state; printf("split/combine_bits...."); fflush(stdout); flint_randinit(state); _flint_rand_init_gmp(state); for (i = 0; i < 10000; i++) { mp_size_t total_limbs = n_randint(state, 1000) + 1; mp_limb_t * in = flint_malloc(total_limbs*sizeof(mp_limb_t)); mp_limb_t * out = flint_calloc(total_limbs, sizeof(mp_limb_t)); mp_bitcnt_t bits = n_randint(state, 200) + 1; mp_size_t limbs = (2*bits - 1)/FLINT_BITS + 1; long length = (total_limbs*FLINT_BITS - 1)/bits + 1; mp_limb_t ** poly; poly = flint_malloc(length*sizeof(mp_limb_t *)); for (j = 0; j < length; j++) poly[j] = flint_malloc((limbs + 1)*sizeof(mp_limb_t)); mpn_urandomb(in, state->gmp_state, total_limbs*FLINT_BITS); fft_split_bits(poly, in, total_limbs, bits, limbs); fft_combine_bits(out, poly, length, bits, limbs, total_limbs); for (j = 0; j < total_limbs; j++) { if (in[j] != out[j]) { printf("FAIL:\n"); printf("Error in limb %ld, %lu != %lu\n", j, in[j], out[j]); abort(); } } flint_free(in); flint_free(out); for (j = 0; j < length; j++) flint_free(poly[j]); flint_free(poly); } flint_randclear(state); printf("PASS\n"); return 0; }
int main() { slong n, i, m, prec = 60; flint_rand_t state; flint_printf("symplectic basis..."); fflush(stdout); flint_randinit(state); for (n = 3; n < 10; n++) { for (i = 0; i < 5; i++) { acb_ptr x; tree_t tree; x = _acb_vec_init(n); acb_vec_set_random(x, n, state, prec, 4); tree_init(tree, n - 1); spanning_tree(tree, x, n, INT_DE); for (m = 2; m < 7; m++) { sec_t c; homol_t alpha, beta; sec_init(&c, m, n); tree_ydata_init(tree, x, n, m, prec); alpha = flint_malloc(c.g * sizeof(loop_t)); beta = flint_malloc(c.g * sizeof(loop_t)); symplectic_basis(alpha, beta, tree, c); homol_clear(alpha, c.g); homol_clear(beta, c.g); tree_ydata_clear(tree); sec_clear(c); } tree_clear(tree); _acb_vec_clear(x, n); } } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return 0; }
int main(void) { int n, k, s; int * mu; printf("moebius_mu...."); fflush(stdout); check(0, n_moebius_mu(0), 0); check(1, n_moebius_mu(1), 1); for (n = 1; n < 100; n++) { mu = flint_malloc(sizeof(int) * n); n_moebius_mu_vec(mu, n); for (k = 0; k < n; k++) check(k, mu[k], n_moebius_mu(k)); flint_free(mu); } mu = flint_malloc(sizeof(int) * 10000); n_moebius_mu_vec(mu, 10000); for (k = 0; k < n; k++) check(k, mu[k], n_moebius_mu(k)); flint_free(mu); check(10000, n_moebius_mu(10000), 0); check(10001, n_moebius_mu(10001), 1); check(10002, n_moebius_mu(10002), -1); check(10003, n_moebius_mu(10003), 1); check(10004, n_moebius_mu(10004), 0); check(10005, n_moebius_mu(10005), 1); check(10006, n_moebius_mu(10006), 1); check(10007, n_moebius_mu(10007), -1); check(10008, n_moebius_mu(10008), 0); check(10009, n_moebius_mu(10009), -1); check(10010, n_moebius_mu(10010), -1); s = 0; for (k = 0; k <= 10000; k++) s += n_moebius_mu(k); if (s != -23) { printf("FAIL:\n"); printf("expected mu(k), k <= 10000 to sum to %d (got %d)\n", -23, s); abort(); } printf("PASS\n"); return 0; }
void tmod_mat_init_fast(tmod_mat_t mat, long rows, long cols) // same result as tmod_mat_init(), only matrice is somewhat random rather than // zero { slong i; mp_limb_t* e = mat->entries = flint_malloc(rows * cols * sizeof(mp_limb_t)); mat->rows = flint_malloc( rows * sizeof(mp_limb_t*) ); mat->r = rows; mat->c = cols; for(i=0; i<rows; i++, e += cols) mat->rows[i] = e; }
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; } }
static __inline__ void fmpz_mat_to_window_unsh( fmpz_mat_window_unsh_t W, const fmpz_mat_t A ) // deep copy-constructor { slong i, cc=A->c, rc=A->r; W->delta = W->c = cc; W->r = rc; W->rows = flint_malloc( rc * sizeof(fmpz *) ); fmpz* e = flint_malloc( rc * cc * sizeof(fmpz) ); for( i=0; i<rc; i++, e += cc ) { W->rows[i] = e; fmpz_vec_init_set(e, A->rows[i], cc); } }
void acb_dirichlet_jacobi_sum_naive(acb_t res, const dirichlet_group_t G, const dirichlet_char_t chi1, const dirichlet_char_t chi2, slong prec) { ulong k1, k2, m1, m2, g, e, m; ulong * v1, * v2; slong *v; nmod_t expo; acb_t z; v1 = flint_malloc(G->q * sizeof(ulong)); v2 = flint_malloc(G->q * sizeof(ulong)); dirichlet_vec_set_null(v1, G, G->q); dirichlet_chi_vec_loop(v1, G, chi1, G->q); dirichlet_vec_set_null(v2, G, G->q); dirichlet_chi_vec_loop(v2, G, chi2, G->q); nmod_init(&expo, G->expo); m1 = dirichlet_order_char(G, chi1); m2 = dirichlet_order_char(G, chi2); g = m1 * m2 / n_gcd(m1, m2); m = G->expo / g; v = flint_malloc(g * sizeof(slong)); for (e = 0; e < g; e++) v[e] = 0; for (k1 = 2, k2 = G->q - 1; k2 > 1; k1++, k2--) { if (v1[k1] == DIRICHLET_CHI_NULL || v2[k2] == DIRICHLET_CHI_NULL) continue; e = nmod_add(v1[k1], v2[k2], expo) / m; v[e]++; } acb_init(z); acb_unit_root(z, g, prec); acb_dirichlet_si_poly_evaluate(res, v, g, z, prec); acb_clear(z); flint_free(v); flint_free(v2); flint_free(v1); }
void sample(void * arg, ulong count) { mp_limb_t n, d, r = 0; double dpre; ulong i; mp_ptr array = (mp_ptr) flint_malloc(1024*sizeof(mp_limb_t)); flint_rand_t state; flint_randinit(state); for (i = 0; i < count; i++) { int j; d = n_randtest(state); if (d == 0UL) d++; dpre = n_precompute_inverse(d); for (j = 0; j < 1024; j++) { array[j] = n_randtest(state); } prof_start(); for (j = 0; j < 10000; j++) { r += n_mod2_precomp(array[j&1023], d, dpre); } prof_stop(); } if (r == 0) abort(); flint_randclear(state); flint_free(array); }
int main(void) { double min, max; fac_one_line_t params; flint_rand_t state; int i; flint_randinit(state); params.composites = flint_malloc(1024*sizeof(ulong)); printf("factor_one_line:\n"); for (i = 4; i <= 64; i++) { fill_array(params.composites, i, state); params.bits = i; prof_repeat(&min, &max, sample, ¶ms); printf("bits = %d, time is %.3f us\n", i, max/(double)ITERS); } flint_randclear(state); flint_free(params.composites); return 0; }
void fmpq_poly_exp_series(fmpq_poly_t res, const fmpq_poly_t poly, long n) { fmpz *copy; int alloc; if (poly->length == 0) { fmpq_poly_set_ui(res, 1UL); return; } if (!fmpz_is_zero(poly->coeffs)) { printf("Exception: fmpq_poly_exp_series: constant term != 0"); abort(); } if (n < 2) { if (n == 0) fmpq_poly_zero(res); if (n == 1) fmpq_poly_set_ui(res, 1UL); return; } if (poly->length >= n) { copy = poly->coeffs; alloc = 0; } else { long i; copy = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < poly->length; i++) copy[i] = poly->coeffs[i]; for ( ; i < n; i++) copy[i] = 0; alloc = 1; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_exp_series(res->coeffs, res->den, copy, poly->den, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_exp_series(t->coeffs, t->den, copy, poly->den, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); if (alloc) flint_free(copy); }
char * nmod_poly_get_str(const nmod_poly_t poly) { long i; char * buf, * ptr; /* estimate for the length, n and three spaces */ #if FLINT64 long size = 21*2 + 1; #else long size = 11*2 + 1; #endif for (i = 0; i < poly->length; i++) { if (poly->coeffs[i]) /* log(2)/log(10) < 0.30103, +1 for space/null */ size += (ulong) ceil(0.30103*FLINT_BIT_COUNT(poly->coeffs[i])) + 1; else size += 2; } buf = (char *) flint_malloc(size); ptr = buf + sprintf(buf, "%ld %lu", poly->length, poly->mod.n); if (poly->length) ptr += sprintf(ptr, " "); for (i = 0; i < poly->length; i++) ptr += sprintf(ptr, " %lu", poly->coeffs[i]); return buf; }
mp_limb_t _nmod_mat_det(nmod_mat_t A) { mp_limb_t det; long * P; long m = A->r; long rank; long i; P = flint_malloc(sizeof(long) * m); rank = nmod_mat_lu(P, A, 1); det = 0UL; if (rank == m) { det = 1UL; for (i = 0; i < m; i++) det = n_mulmod2_preinv(det, nmod_mat_entry(A, i, i), A->mod.n, A->mod.ninv); } if (_perm_parity(P, m) == 1) det = nmod_neg(det, A->mod); flint_free(P); return det; }
static void _si_stack_init(_si_stack_t s, slong capacity) { s->data = flint_malloc(capacity * sizeof(slong)); s->capacity = capacity; s->size = 0; }
void _fmpz_poly_sqrlow(fmpz * res, const fmpz * poly, long len, long n) { mp_size_t limbs; if (n < 7) { _fmpz_poly_sqrlow_classical(res, poly, len, n); return; } limbs = _fmpz_vec_max_limbs(poly, len); if (n < 16 && limbs > 12) { int i; fmpz *copy; copy = flint_malloc(n * sizeof(fmpz)); for (i = 0; i < len; i++) copy[i] = poly[i]; mpn_zero((mp_ptr) copy + len, n - len); _fmpz_poly_sqrlow_karatsuba_n(res, copy, n); flint_free(copy); } else if (limbs <= 4) _fmpz_poly_sqrlow_KS(res, poly, len, n); else if (limbs/2048 > len) _fmpz_poly_sqrlow_KS(res, poly, len, n); else if (limbs*FLINT_BITS*4 < len) _fmpz_poly_sqrlow_KS(res, poly, len, n); else _fmpz_poly_mullow_SS(res, poly, len, poly, len, n); }
void tmod_mat_init_set_fmpz_mat(tmod_mat_t tgt, const fmpz_mat_t sou) { slong i, j, rows=sou->r, cols=sou->c; mp_limb_t* e = tgt->entries = flint_malloc(rows * cols * sizeof(mp_limb_t)); mp_limb_t** tgt_rows = tgt->rows = flint_malloc( rows * sizeof(mp_limb_t*) ); tgt->r = rows; tgt->c = cols; fmpz* souP; for(i=0; i<rows; i++, e += cols) { tgt_rows[i] = e; for(j=0,souP=sou->rows[i]; j<cols; j++,souP++) e[j]=fmpz_to_t( souP ); } }
void acb_dirichlet_chi_vec(acb_ptr v, const dirichlet_group_t G, const dirichlet_char_t chi, slong nv, slong prec) { slong k; ulong * a, order; acb_dirichlet_roots_t t; a = flint_malloc(nv * sizeof(ulong)); order = dirichlet_order_char(G, chi); dirichlet_chi_vec_order(a, G, chi, order, nv); acb_dirichlet_roots_init(t, order, nv, prec); acb_zero(v + 0); for (k = 0; k < nv; k++) { if (a[k] != DIRICHLET_CHI_NULL) acb_dirichlet_root(v + k, t, a[k], prec); else acb_zero(v + k); } acb_dirichlet_roots_clear(t); flint_free(a); }
int main(void) { int i; flint_rand_t state; flint_randinit(state); printf("dot_ptr...."); fflush(stdout); for (i = 0; i < 10000; i++) { long len; nmod_t mod; mp_limb_t m, res, res2; mp_ptr x, y; mp_ptr * z; int limbs1; long j, offset; len = n_randint(state, 1000) + 1; m = n_randtest_not_zero(state); offset = n_randint(state, 10); nmod_init(&mod, m); x = _nmod_vec_init(len); y = _nmod_vec_init(len); z = flint_malloc(sizeof(mp_ptr) * len); _nmod_vec_randtest(x, state, len, mod); _nmod_vec_randtest(y, state, len, mod); for (j = 0; j < len; j++) z[j] = &y[j] + offset; limbs1 = _nmod_vec_dot_bound_limbs(len, mod); res = _nmod_vec_dot_ptr(x, z, -offset, len, mod, limbs1); res2 = _nmod_vec_dot(x, y, len, mod, limbs1); if (res != res2) { printf("FAIL:\n"); printf("m = %lu\n", m); printf("len = %ld\n", len); printf("limbs1 = %d\n", limbs1); abort(); } _nmod_vec_clear(x); _nmod_vec_clear(y); flint_free(z); } flint_randclear(state); printf("PASS\n"); return 0; }
mp_limb_t tmod_mat_invert_transpose(tmod_mat_t R, const tmod_mat_t S) /* S,R square, virgin If S in inverible, R:=S inverted transposed in virgin state Return S deterimant modulo t */ { slong n=S->r; slong row_size=n*sizeof(mp_limb_t); memcpy(R->entries,S->entries,n*row_size); mp_limb_t* PR=flint_malloc(2*row_size); mp_limb_t d=0; if(tmod_mat_PLU_mod_machine_word(PR,R)) { int p_parity=count_permutation_parity(PR,n); d=tmod_mat_diag_product_ZZ_ui(R)*p_parity; tmod_mat_t K; tmod_mat_init_fast(K,n,n); _20141102_Lo(K,R,n); _20141102_Up(K,R,PR+n,n); tmod_mat_virginize(R); _20141102_unLU(R,K,n); _20141102_shift_rows(R,K,PR,n,p_parity); tmod_mat_clear(K); } flint_free(PR); return d; }
void fmpq_poly_revert_series(fmpq_poly_t res, const fmpq_poly_t poly, long n) { fmpz *copy; int alloc; if (poly->length < 2 || !fmpz_is_zero(poly->coeffs) || fmpz_is_zero(poly->coeffs + 1)) { printf("exception: fmpq_poly_revert_series: input must have " "zero constant term and nonzero coefficient of x^1"); abort(); } if (n < 2) { fmpq_poly_zero(res); return; } if (poly->length >= n) { copy = poly->coeffs; alloc = 0; } else { long i; copy = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < poly->length; i++) copy[i] = poly->coeffs[i]; for ( ; i < n; i++) copy[i] = 0; alloc = 1; } if (res != poly) { fmpq_poly_fit_length(res, n); _fmpq_poly_revert_series(res->coeffs, res->den, copy, poly->den, n); } else { fmpq_poly_t t; fmpq_poly_init2(t, n); _fmpq_poly_revert_series(t->coeffs, t->den, copy, poly->den, n); fmpq_poly_swap(res, t); fmpq_poly_clear(t); } _fmpq_poly_set_length(res, n); _fmpq_poly_normalise(res); if (alloc) flint_free(copy); }
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 tree_init(tree_t tree, slong n) { tree->n = n; tree->e = flint_malloc(n * sizeof(edge_t)); tree->r = 0.; tree->min = 0; tree->data = NULL; }
static void _toposort_init(_toposort_s *s, slong size) { s->size = size; s->u = flint_calloc(size, sizeof(int)); s->v = flint_calloc(size, sizeof(int)); s->post = flint_malloc(size * sizeof(slong)); s->npost = 0; }
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); }