void _pq_nmod_insure_mono(const pq_nmod_elt_t x, const pq_nmod_t A) { if (nmod_poly_is_zero(x->mono) && !nmod_poly_is_zero(x->dual)) { pq_nmod_elt_struct* tmp = (pq_nmod_elt_struct*)x; nmod_poly_convert_from_trace(tmp->mono, x->dual->coeffs, A->M, A->iM); } }
void _pq_nmod_insure_dual(const pq_nmod_elt_t x, const pq_nmod_t A) { if (nmod_poly_is_zero(x->dual) && !nmod_poly_is_zero(x->mono)) { pq_nmod_elt_struct* tmp = (pq_nmod_elt_struct*)x; nmod_poly_fit_length(tmp->dual, nmod_poly_degree(A->M)); nmod_poly_tmulmod(tmp->dual->coeffs, A->newton->coeffs, x->mono, A->M, A->S); tmp->dual->length = nmod_poly_degree(A->M); } }
void nmod_poly_randtest_monic_irreducible(nmod_poly_t poly, flint_rand_t state, slong len) { do { nmod_poly_randtest_monic(poly, state, len); } while (nmod_poly_is_zero(poly) || !(nmod_poly_is_irreducible(poly))); }
void pq_nmod_mul(pq_nmod_elt_t res, const pq_nmod_elt_t x, const pq_nmod_elt_t y, const pq_nmod_t A) { switch (nmod_poly_is_zero(y->mono) | (nmod_poly_is_zero(y->dual) << 1) | (nmod_poly_is_zero(x->mono) << 4) | (nmod_poly_is_zero(x->dual) << 5)) { const pq_nmod_elt_struct* tmp; case 0x22: // Both have only dual -> add mono to x _pq_nmod_insure_mono(x, A); case 0x12: case 0x32: // x has mono, y has dual -> swap them tmp = x; x = y; y = tmp; case 0x21: case 0x23: // y has mono, x has dual nmod_poly_fit_length(res->dual, A->degree); nmod_poly_tmulmod(res->dual->coeffs, x->dual->coeffs, y->mono, A->M, A->S); nmod_poly_zero(res->mono); break; case 0x11: case 0x13: case 0x31: case 0x33: // both have mono nmod_poly_mulmod(res->mono, x->mono, y->mono, A->M); nmod_poly_zero(res->dual); break; default: // in any other case, result is 0 nmod_poly_zero(res->mono); nmod_poly_zero(res->dual); break; } }
int pq_nmod_elt_equal(const pq_nmod_elt_t x, const pq_nmod_elt_t y, const pq_nmod_t A) { if ((nmod_poly_is_zero(x->mono) ^ nmod_poly_is_zero(y->mono)) && (nmod_poly_is_zero(x->dual) ^ nmod_poly_is_zero(y->dual))) { _pq_nmod_insure_mono(x, A); _pq_nmod_insure_mono(y, A); } return (nmod_poly_is_zero(x->mono) && nmod_poly_is_zero(y->mono)) || nmod_poly_equal(x->mono, y->mono) || nmod_poly_equal(x->dual, y->dual); }
int nmod_poly_randtest_trinomial_irreducible(nmod_poly_t poly, flint_rand_t state, slong len, slong max_attempts) { slong i = 0; while (max_attempts == 0 || i < max_attempts) { nmod_poly_randtest_trinomial(poly, state, len); if (!nmod_poly_is_zero(poly) && nmod_poly_is_irreducible(poly)) { return 1; } i++; } return 0; }
int main(void) { int iter; FLINT_TEST_INIT(state); flint_printf("is_squarefree...."); fflush(stdout); for (iter = 0; iter < 200 * flint_test_multiplier(); iter++) { nmod_poly_t poly, Q, R, t; mp_limb_t modulus; slong i, num_factors, exp, max_exp; int v, result; modulus = n_randtest_prime(state, 0); nmod_poly_init(poly, modulus); nmod_poly_init(t, modulus); nmod_poly_init(Q, modulus); nmod_poly_init(R, modulus); nmod_poly_set_coeff_ui(poly, 0, n_randint(state, modulus)); num_factors = n_randint(state, 5); max_exp = 0; for (i = 0; i < num_factors; i++) { do { nmod_poly_randtest(t, state, n_randint(state, 10)); } while (!nmod_poly_is_irreducible(t) || (nmod_poly_length(t) < 2)); exp = n_randint(state, 4) + 1; if (n_randint(state, 2) == 0) exp = 1; nmod_poly_divrem(Q, R, poly, t); if (!nmod_poly_is_zero(R)) { nmod_poly_pow(t, t, exp); nmod_poly_mul(poly, poly, t); max_exp = FLINT_MAX(exp, max_exp); } } v = nmod_poly_is_squarefree(poly); if (v == 1) result = (max_exp <= 1 && !nmod_poly_is_zero(poly)); else result = (max_exp > 1 || nmod_poly_is_zero(poly)); if (!result) { flint_printf("FAIL: %wu, %wd, %d\n", modulus, max_exp, v); nmod_poly_print(poly); flint_printf("\n"); abort(); } nmod_poly_clear(poly); nmod_poly_clear(t); nmod_poly_clear(Q); nmod_poly_clear(R); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; }
int main(void) { int i, result; flint_rand_t state; printf("revert_series...."); fflush(stdout); flint_randinit(state); /* Check aliasing */ for (i = 0; i < 100; i++) { nmod_poly_t f, g; mp_limb_t m; long n; m = n_randtest_prime(state, 0); nmod_poly_init(f, m); nmod_poly_init(g, m); do { nmod_poly_randtest(g, state, n_randint(state, 100)); } while (nmod_poly_get_coeff_ui(g, 1) == 0); nmod_poly_set_coeff_ui(g, 0, 0); do { n = n_randint(state, 100); } while (n >= m); nmod_poly_revert_series(f, g, n); nmod_poly_revert_series(g, g, n); result = (nmod_poly_equal(f, g)); if (!result) { printf("FAIL (aliasing):\n"); nmod_poly_print(f), printf("\n\n"); nmod_poly_print(g), printf("\n\n"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); } /* Check f(f^(-1)) = id */ for (i = 0; i < 1000; i++) { nmod_poly_t f, g, h; mp_limb_t m; long n; m = n_randtest_prime(state, 0); nmod_poly_init(f, m); nmod_poly_init(g, m); nmod_poly_init(h, m); do { nmod_poly_randtest(g, state, n_randint(state, 100)); } while (nmod_poly_get_coeff_ui(g, 1) == 0); nmod_poly_set_coeff_ui(g, 0, 0); do { n = n_randint(state, 100); } while (n >= m); nmod_poly_revert_series(f, g, n); nmod_poly_compose_series(h, g, f, n); result = ((n <= 1 && nmod_poly_is_zero(h)) || (h->length == 2 && h->coeffs[0] == 0 && h->coeffs[1] == 1)); if (!result) { printf("FAIL (comparison):\n"); nmod_poly_print(g), printf("\n\n"); nmod_poly_print(f), printf("\n\n"); nmod_poly_print(h), printf("\n\n"); abort(); } nmod_poly_clear(f); nmod_poly_clear(g); nmod_poly_clear(h); } flint_randclear(state); printf("PASS\n"); return 0; }
long nmod_poly_mat_nullspace(nmod_poly_mat_t res, const nmod_poly_mat_t mat) { long i, j, k, m, n, rank, nullity; long * pivots; long * nonpivots; nmod_poly_mat_t tmp; nmod_poly_t den; m = mat->r; n = mat->c; nmod_poly_init(den, nmod_poly_mat_modulus(mat)); nmod_poly_mat_init_set(tmp, mat); rank = nmod_poly_mat_rref(tmp, den, NULL, tmp); nullity = n - rank; nmod_poly_mat_zero(res); if (rank == 0) { for (i = 0; i < nullity; i++) nmod_poly_one(res->rows[i] + i); } else if (nullity) { pivots = flint_malloc(rank * sizeof(long)); nonpivots = flint_malloc(nullity * sizeof(long)); for (i = j = k = 0; i < rank; i++) { while (nmod_poly_is_zero(tmp->rows[i] + j)) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < nullity) { nonpivots[k] = j; k++; j++; } nmod_poly_set(den, tmp->rows[0] + pivots[0]); for (i = 0; i < nullity; i++) { for (j = 0; j < rank; j++) nmod_poly_set(res->rows[pivots[j]] + i, tmp->rows[j] + nonpivots[i]); nmod_poly_neg(res->rows[nonpivots[i]] + i, den); } flint_free(pivots); flint_free(nonpivots); } nmod_poly_clear(den); nmod_poly_mat_clear(tmp); return nullity; }
void nmod_poly_factor_squarefree(nmod_poly_factor_t res, const nmod_poly_t f) { nmod_poly_t f_d, g, g_1; mp_limb_t p; slong deg, i; if (f->length <= 1) { res->num = 0; return; } if (f->length == 2) { nmod_poly_factor_insert(res, f, 1); return; } p = nmod_poly_modulus(f); deg = nmod_poly_degree(f); /* Step 1, look at f', if it is zero then we are done since f = h(x)^p for some particular h(x), clearly f(x) = sum a_k x^kp, k <= deg(f) */ nmod_poly_init(g_1, p); nmod_poly_init(f_d, p); nmod_poly_init(g, p); nmod_poly_derivative(f_d, f); /* Case 1 */ if (nmod_poly_is_zero(f_d)) { nmod_poly_factor_t new_res; nmod_poly_t h; nmod_poly_init(h, p); for (i = 0; i <= deg / p; i++) /* this will be an integer since f'=0 */ { nmod_poly_set_coeff_ui(h, i, nmod_poly_get_coeff_ui(f, i * p)); } /* Now run square-free on h, and return it to the pth power */ nmod_poly_factor_init(new_res); nmod_poly_factor_squarefree(new_res, h); nmod_poly_factor_pow(new_res, p); nmod_poly_factor_concat(res, new_res); nmod_poly_clear(h); nmod_poly_factor_clear(new_res); } else { nmod_poly_t h, z; nmod_poly_gcd(g, f, f_d); nmod_poly_div(g_1, f, g); i = 1; nmod_poly_init(h, p); nmod_poly_init(z, p); /* Case 2 */ while (!nmod_poly_is_one(g_1)) { nmod_poly_gcd(h, g_1, g); nmod_poly_div(z, g_1, h); /* out <- out.z */ if (z->length > 1) { nmod_poly_factor_insert(res, z, 1); nmod_poly_make_monic(res->p + (res->num - 1), res->p + (res->num - 1)); if (res->num) res->exp[res->num - 1] *= i; } i++; nmod_poly_set(g_1, h); nmod_poly_div(g, g, h); } nmod_poly_clear(h); nmod_poly_clear(z); nmod_poly_make_monic(g, g); if (!nmod_poly_is_one(g)) { /* so now we multiply res with square-free(g^1/p) ^ p */ nmod_poly_t g_p; /* g^(1/p) */ nmod_poly_factor_t new_res_2; nmod_poly_init(g_p, p); for (i = 0; i <= nmod_poly_degree(g) / p; i++) nmod_poly_set_coeff_ui(g_p, i, nmod_poly_get_coeff_ui(g, i*p)); nmod_poly_factor_init(new_res_2); /* square-free(g^(1/p)) */ nmod_poly_factor_squarefree(new_res_2, g_p); nmod_poly_factor_pow(new_res_2, p); nmod_poly_factor_concat(res, new_res_2); nmod_poly_clear(g_p); nmod_poly_factor_clear(new_res_2); } } nmod_poly_clear(g_1); nmod_poly_clear(f_d); nmod_poly_clear(g); }
int nmod_poly_mat_inv(nmod_poly_mat_t Ainv, nmod_poly_t den, const nmod_poly_mat_t A) { slong n = nmod_poly_mat_nrows(A); if (n == 0) { nmod_poly_one(den); return 1; } else if (n == 1) { nmod_poly_set(den, E(A, 0, 0)); nmod_poly_one(E(Ainv, 0, 0)); return !nmod_poly_is_zero(den); } else if (n == 2) { nmod_poly_mat_det(den, A); if (nmod_poly_is_zero(den)) { return 0; } else if (Ainv == A) { nmod_poly_swap(E(A, 0, 0), E(A, 1, 1)); nmod_poly_neg(E(A, 0, 1), E(A, 0, 1)); nmod_poly_neg(E(A, 1, 0), E(A, 1, 0)); return 1; } else { nmod_poly_set(E(Ainv, 0, 0), E(A, 1, 1)); nmod_poly_set(E(Ainv, 1, 1), E(A, 0, 0)); nmod_poly_neg(E(Ainv, 0, 1), E(A, 0, 1)); nmod_poly_neg(E(Ainv, 1, 0), E(A, 1, 0)); return 1; } } else { nmod_poly_mat_t LU, I; slong * perm; int result; perm = _perm_init(n); nmod_poly_mat_init_set(LU, A); result = (nmod_poly_mat_fflu(LU, den, perm, LU, 1) == n); if (result) { nmod_poly_mat_init(I, n, n, nmod_poly_mat_modulus(A)); nmod_poly_mat_one(I); nmod_poly_mat_solve_fflu_precomp(Ainv, perm, LU, I); nmod_poly_mat_clear(I); } else nmod_poly_zero(den); if (_perm_parity(perm, n)) { nmod_poly_mat_neg(Ainv, Ainv); nmod_poly_neg(den, den); } _perm_clear(perm); nmod_poly_mat_clear(LU); return result; } }
int main(void) { int i, result; flint_rand_t state; flint_randinit(state); printf("mulmod...."); fflush(stdout); /* Aliasing res and a */ for (i = 0; i < 500; i++) { nmod_poly_t a, b, res, t, f; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_mulmod(res, a, b, f); nmod_poly_mulmod(a, a, b, f); result = (nmod_poly_equal(res, a)); if (!result) { printf("FAIL:\n"); printf("a:\n"); nmod_poly_print(a), printf("\n\n"); printf("b:\n"); nmod_poly_print(b), printf("\n\n"); printf("f:\n"); nmod_poly_print(f), printf("\n\n"); printf("res1:\n"); nmod_poly_print(res), printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(res); nmod_poly_clear(t); } /* Aliasing res and b */ for (i = 0; i < 500; i++) { nmod_poly_t a, b, res, t, f; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_mulmod(res, a, b, f); nmod_poly_mulmod(b, a, b, f); result = (nmod_poly_equal(res, b)); if (!result) { printf("FAIL:\n"); printf("a:\n"); nmod_poly_print(a), printf("\n\n"); printf("b:\n"); nmod_poly_print(b), printf("\n\n"); printf("f:\n"); nmod_poly_print(f), printf("\n\n"); printf("res1:\n"); nmod_poly_print(res), printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(res); nmod_poly_clear(t); } /* Aliasing res and f */ for (i = 0; i < 500; i++) { nmod_poly_t a, b, res, t, f; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(res, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_mulmod(res, a, b, f); nmod_poly_mulmod(f, a, b, f); result = (nmod_poly_equal(res, f)); if (!result) { printf("FAIL:\n"); printf("a:\n"); nmod_poly_print(a), printf("\n\n"); printf("b:\n"); nmod_poly_print(b), printf("\n\n"); printf("f:\n"); nmod_poly_print(f), printf("\n\n"); printf("res1:\n"); nmod_poly_print(res), printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(res); nmod_poly_clear(t); } /* No aliasing */ for (i = 0; i < 1000; i++) { nmod_poly_t a, b, res1, res2, t, f; mp_limb_t n = n_randtest_prime(state, 0); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(f, n); nmod_poly_init(res1, n); nmod_poly_init(res2, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 50)); nmod_poly_randtest(b, state, n_randint(state, 50)); do { nmod_poly_randtest(f, state, n_randint(state, 50)); } while (nmod_poly_is_zero(f)); nmod_poly_mulmod(res1, a, b, f); nmod_poly_mul(res2, a, b); nmod_poly_divrem(t, res2, res2, f); result = (nmod_poly_equal(res1, res2)); if (!result) { printf("FAIL:\n"); printf("a:\n"); nmod_poly_print(a), printf("\n\n"); printf("b:\n"); nmod_poly_print(b), printf("\n\n"); printf("f:\n"); nmod_poly_print(f), printf("\n\n"); printf("res1:\n"); nmod_poly_print(res1), printf("\n\n"); printf("res2:\n"); nmod_poly_print(res2), printf("\n\n"); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(f); nmod_poly_clear(res1); nmod_poly_clear(res2); nmod_poly_clear(t); } flint_randclear(state); printf("PASS\n"); return 0; }
slong nmod_poly_mat_rref(nmod_poly_mat_t R, nmod_poly_t den, const nmod_poly_mat_t A) { slong i, j, k, m, n, rank; slong *pivots, *nonpivots; rank = nmod_poly_mat_fflu(R, den, NULL, A, 0); m = nmod_poly_mat_nrows(R); n = nmod_poly_mat_ncols(R); /* clear bottom */ for (i = rank; i < m; i++) for (j = 0; j < n; j++) nmod_poly_zero(nmod_poly_mat_entry(R, i, j)); /* Convert row echelon form to reduced row echelon form */ if (rank > 1) { nmod_poly_t tmp, tmp2; nmod_poly_init(tmp, nmod_poly_mat_modulus(R)); nmod_poly_init(tmp2, nmod_poly_mat_modulus(R)); pivots = flint_malloc(sizeof(slong) * n); nonpivots = pivots + rank; /* find pivot positions */ for (i = j = k = 0; i < rank; i++) { while (nmod_poly_is_zero(nmod_poly_mat_entry(R, i, j))) { nonpivots[k] = j; k++; j++; } pivots[i] = j; j++; } while (k < n - rank) { nonpivots[k] = j; k++; j++; } for (k = 0; k < n - rank; k++) { for (i = rank - 2; i >= 0; i--) { nmod_poly_mul(tmp, den, nmod_poly_mat_entry(R, i, nonpivots[k])); for (j = i + 1; j < rank; j++) { nmod_poly_mul(tmp2, nmod_poly_mat_entry(R, i, pivots[j]), nmod_poly_mat_entry(R, j, nonpivots[k])); nmod_poly_sub(tmp, tmp, tmp2); } nmod_poly_div(nmod_poly_mat_entry(R, i, nonpivots[k]), tmp, nmod_poly_mat_entry(R, i, pivots[i])); } } /* clear pivot columns */ for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { if (i == j) nmod_poly_set(nmod_poly_mat_entry(R, j, pivots[i]), den); else nmod_poly_zero(nmod_poly_mat_entry(R, j, pivots[i])); } } flint_free(pivots); nmod_poly_clear(tmp); nmod_poly_clear(tmp2); } return rank; }