コード例 #1
0
ファイル: sqrt_classical.c プロジェクト: goens/flint2
int
fmpz_poly_sqrt_classical(fmpz_poly_t b, const fmpz_poly_t a)
{
    long blen, len = a->length;
    int result;

    if (len % 2 == 0)
    {
        fmpz_poly_zero(b);
        return len == 0;
    }

    if (b == a)
    {
        fmpz_poly_t tmp;
        fmpz_poly_init(tmp);
        result = fmpz_poly_sqrt(tmp, a);
        fmpz_poly_swap(b, tmp);
        fmpz_poly_clear(tmp);
        return result;
    }

    blen = len / 2 + 1;
    fmpz_poly_fit_length(b, blen);
    _fmpz_poly_set_length(b, blen);
    result = _fmpz_poly_sqrt_classical(b->coeffs, a->coeffs, len);
    if (!result)
        _fmpz_poly_set_length(b, 0);
    return result;
}
コード例 #2
0
ファイル: mulhigh_classical.c プロジェクト: goens/flint2
void
fmpz_poly_mulhigh_classical(fmpz_poly_t res,
                            const fmpz_poly_t poly1, const fmpz_poly_t poly2,
                            long start)
{
    long len_out = poly1->length + poly2->length - 1;

    if (poly1->length == 0 || poly2->length == 0 || start >= len_out)
    {
        fmpz_poly_zero(res);
        return;
    }

    if (res == poly1 || res == poly2)
    {
        fmpz_poly_t temp;
        fmpz_poly_init2(temp, len_out);
        _fmpz_poly_mulhigh_classical(temp->coeffs, poly1->coeffs,
                                     poly1->length, poly2->coeffs,
                                     poly2->length, start);
        fmpz_poly_swap(res, temp);
        fmpz_poly_clear(temp);
    }
    else
    {
        fmpz_poly_fit_length(res, len_out);
        _fmpz_poly_mulhigh_classical(res->coeffs, poly1->coeffs, poly1->length,
                                     poly2->coeffs, poly2->length, start);
    }

    _fmpz_poly_set_length(res, len_out);
}
コード例 #3
0
ファイル: mullow_classical.c プロジェクト: goens/flint2
void
fmpz_poly_mullow_classical(fmpz_poly_t res, const fmpz_poly_t poly1, 
                                            const fmpz_poly_t poly2, long n)
{
    long len_out;

    if (poly1->length == 0 || poly2->length == 0 || n == 0)
    {
        fmpz_poly_zero(res);
        return;
    }

    len_out = poly1->length + poly2->length - 1;
    if (n > len_out)
        n = len_out;

    if (res == poly1 || res == poly2)
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, n);
        _fmpz_poly_mullow_classical(t->coeffs, poly1->coeffs, poly1->length,
                                    poly2->coeffs, poly2->length, n);
        fmpz_poly_swap(res, t);
        fmpz_poly_clear(t);
    }
    else
    {
        fmpz_poly_fit_length(res, n);
        _fmpz_poly_mullow_classical(res->coeffs, poly1->coeffs, poly1->length,
                                    poly2->coeffs, poly2->length, n);
    }

    _fmpz_poly_set_length(res, n);
    _fmpz_poly_normalise(res);
}
コード例 #4
0
ファイル: sqr_classical.c プロジェクト: goens/flint2
void fmpz_poly_sqr_classical(fmpz_poly_t rop, const fmpz_poly_t op)
{
    long len;

    if (op->length == 0)
    {
        fmpz_poly_zero(rop);
        return;
    }

    len = 2 * op->length - 1;

    if (rop == op)
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, len);
        _fmpz_poly_sqr_classical(t->coeffs, op->coeffs, op->length);
        fmpz_poly_swap(rop, t);
        fmpz_poly_clear(t);
    }
    else
    {
        fmpz_poly_fit_length(rop, len);
        _fmpz_poly_sqr_classical(rop->coeffs, op->coeffs, op->length);
    }

    _fmpz_poly_set_length(rop, len);
}
コード例 #5
0
ファイル: mulmid_classical.c プロジェクト: clear731/lattice
void
fmpz_poly_mulmid_classical(fmpz_poly_t res,
                           const fmpz_poly_t poly1, const fmpz_poly_t poly2)
{
    slong len_out;

    if (poly1->length == 0 || poly2->length == 0)
    {
        fmpz_poly_zero(res);
        return;
    }

    len_out = poly1->length - poly2->length + 1;

    if (res == poly1 || res == poly2)
    {
        fmpz_poly_t temp;
        fmpz_poly_init2(temp, len_out);
        _fmpz_poly_mulmid_classical(temp->coeffs, poly1->coeffs, poly1->length,
                                    poly2->coeffs, poly2->length);
        fmpz_poly_swap(res, temp);
        fmpz_poly_clear(temp);
    }
    else
    {
        fmpz_poly_fit_length(res, len_out);
        _fmpz_poly_mulmid_classical(res->coeffs, poly1->coeffs, poly1->length,
                                    poly2->coeffs, poly2->length);
    }

    _fmpz_poly_set_length(res, len_out);
    _fmpz_poly_normalise(res);
}
コード例 #6
0
ファイル: sqrlow.c プロジェクト: goens/flint2
void fmpz_poly_sqrlow(fmpz_poly_t res, const fmpz_poly_t poly, long n)
{
    const long len = poly->length;

    if (len == 0 || n == 0)
    {
        fmpz_poly_zero(res);
        return;
    }

    if (res == poly)
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, n);
        fmpz_poly_sqrlow(t, poly, n);
        fmpz_poly_swap(res, t);
        fmpz_poly_clear(t);
        return;
    }

    n = FLINT_MIN(2 * len - 1, n);

    fmpz_poly_fit_length(res, n);
    _fmpz_poly_sqrlow(res->coeffs, poly->coeffs, len, n);
    _fmpz_poly_set_length(res, n);
    _fmpz_poly_normalise(res);
}
コード例 #7
0
ファイル: mullow_KS.c プロジェクト: goens/flint2
void
fmpz_poly_mullow_KS(fmpz_poly_t res,
                    const fmpz_poly_t poly1, const fmpz_poly_t poly2, long n)
{
    const long len1 = poly1->length;
    const long len2 = poly2->length;

    if (len1 == 0 || len2 == 0 || n == 0)
    {
        fmpz_poly_zero(res);
        return;
    }

    if (res == poly1 || res == poly2)
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, n);
        fmpz_poly_mullow_KS(t, poly1, poly2, n);
        fmpz_poly_swap(res, t);
        fmpz_poly_clear(t);
        return;
    }

    fmpz_poly_fit_length(res, n);

    if (len1 >= len2)
        _fmpz_poly_mullow_KS(res->coeffs, poly1->coeffs, len1,
                                          poly2->coeffs, len2, n);
    else
        _fmpz_poly_mullow_KS(res->coeffs, poly2->coeffs, len2,
                                          poly1->coeffs, len1, n);

    _fmpz_poly_set_length(res, n);
    _fmpz_poly_normalise(res);
}
コード例 #8
0
void
fmpz_poly_revert_series_lagrange(fmpz_poly_t Qinv,
                                        const fmpz_poly_t Q, slong n)
{
    fmpz *Qcopy;
    int Qalloc;
    slong Qlen = Q->length;

    if (Qlen < 2 || !fmpz_is_zero(Q->coeffs) || !fmpz_is_pm1(Q->coeffs + 1))
    {
        flint_printf("Exception (fmpz_poly_revert_series_lagrange). Input must have \n"
               "zero constant term and +1 or -1 as coefficient of x^1.\n");
        abort();
    }

    if (Qlen >= n)
    {
        Qcopy = Q->coeffs;
        Qalloc = 0;
    }
    else
    {
        slong i;
        Qcopy = (fmpz *) flint_malloc(n * sizeof(fmpz));
        for (i = 0; i < Qlen; i++)
            Qcopy[i] = Q->coeffs[i];
        for ( ; i < n; i++)
            Qcopy[i] = 0;
        Qalloc = 1;
    }

    if (Qinv != Q)
    {
        fmpz_poly_fit_length(Qinv, n);
        _fmpz_poly_revert_series_lagrange(Qinv->coeffs, Qcopy, n);
    }
    else
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, n);
        _fmpz_poly_revert_series_lagrange(t->coeffs, Qcopy, n);
        fmpz_poly_swap(Qinv, t);
        fmpz_poly_clear(t);
    }
    
    _fmpz_poly_set_length(Qinv, n);
    _fmpz_poly_normalise(Qinv);

    if (Qalloc)
        flint_free(Qcopy);
}
コード例 #9
0
ファイル: compose_series.c プロジェクト: goens/flint2
void
fmpz_poly_compose_series(fmpz_poly_t res, 
                    const fmpz_poly_t poly1, const fmpz_poly_t poly2, long n)
{
    long len1 = poly1->length;
    long len2 = poly2->length;
    long lenr;

    if (len2 != 0 && !fmpz_is_zero(poly2->coeffs))
    {
        printf("exception: fmpz_poly_compose_series: inner polynomial "
                "must have zero constant term\n");
        abort();
    }

    if (len1 == 0 || n == 0)
    {
        fmpz_poly_zero(res);
        return;
    }

    if (len2 == 0 || len1 == 1)
    {
        fmpz_poly_set_fmpz(res, poly1->coeffs);
        return;
    }

    lenr = FLINT_MIN((len1 - 1) * (len2 - 1) + 1, n);
    len1 = FLINT_MIN(len1, lenr);
    len2 = FLINT_MIN(len2, lenr);

    if ((res != poly1) && (res != poly2))
    {
        fmpz_poly_fit_length(res, lenr);
        _fmpz_poly_compose_series(res->coeffs, poly1->coeffs, len1, 
                                               poly2->coeffs, len2, lenr);
        _fmpz_poly_set_length(res, lenr);
        _fmpz_poly_normalise(res);
    }
    else
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, lenr);
        _fmpz_poly_compose_series(t->coeffs, poly1->coeffs, len1,
                                             poly2->coeffs, len2, lenr);
        _fmpz_poly_set_length(t, lenr);
        _fmpz_poly_normalise(t);
        fmpz_poly_swap(res, t);
        fmpz_poly_clear(t);
    }
}
コード例 #10
0
ファイル: t-swap.c プロジェクト: clear731/lattice
int
main(void)
{
    int i, result;
    FLINT_TEST_INIT(state);

    flint_printf("swap....");
    fflush(stdout);

    

    for (i = 0; i < 1000 * flint_test_multiplier(); i++)
    {
        fmpz_poly_t a, b, c;

        fmpz_poly_init(a);
        fmpz_poly_init(b);
        fmpz_poly_init(c);
        fmpz_poly_randtest(a, state, n_randint(state, 100), 200);
        fmpz_poly_randtest(b, state, n_randint(state, 100), 200);

        fmpz_poly_set(c, b);
        fmpz_poly_swap(a, b);

        result = (fmpz_poly_equal(a, c));
        if (!result)
        {
            flint_printf("FAIL:\n");
            fmpz_poly_print(a), flint_printf("\n\n");
            fmpz_poly_print(b), flint_printf("\n\n");
            fmpz_poly_print(c), flint_printf("\n\n");
            abort();
        }

        fmpz_poly_clear(a);
        fmpz_poly_clear(b);
        fmpz_poly_clear(c);
    }

    FLINT_TEST_CLEANUP(state);
    
    flint_printf("PASS\n");
    return 0;
}
コード例 #11
0
ファイル: pow_multinomial.c プロジェクト: goens/flint2
void
fmpz_poly_pow_multinomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e)
{
    const long len = poly->length;
    long rlen;

    if ((len < 2) | (e < 3UL))
    {
        if (e == 0UL)
            fmpz_poly_set_ui(res, 1);
        else if (len == 0)
            fmpz_poly_zero(res);
        else if (len == 1)
        {
            fmpz_poly_fit_length(res, 1);
            fmpz_pow_ui(res->coeffs, poly->coeffs, e);
            _fmpz_poly_set_length(res, 1);
        }
        else if (e == 1UL)
            fmpz_poly_set(res, poly);
        else  /* e == 2UL */
            fmpz_poly_sqr(res, poly);
        return;
    }
    
    rlen = (long) e * (len - 1) + 1;

    if (res != poly)
    {
        fmpz_poly_fit_length(res, rlen);
        _fmpz_poly_pow_multinomial(res->coeffs, poly->coeffs, len, e);
        _fmpz_poly_set_length(res, rlen);
    }
    else
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, rlen);
        _fmpz_poly_pow_multinomial(t->coeffs, poly->coeffs, len, e);
        _fmpz_poly_set_length(t, rlen);
        fmpz_poly_swap(res, t);
        fmpz_poly_clear(t);
    }
}
コード例 #12
0
ファイル: pow_binomial.c プロジェクト: goens/flint2
void
fmpz_poly_pow_binomial(fmpz_poly_t res, const fmpz_poly_t poly, ulong e)
{
    const long len = poly->length;
    long rlen;

    if (len != 2)
    {
        printf("Exception: poly->length not equal to 2 in fmpz_poly_pow_binomial\n");
        abort();
    }

    if (e < 3UL)
    {
        if (e == 0UL)
            fmpz_poly_set_ui(res, 1UL);
        else if (e == 1UL)
            fmpz_poly_set(res, poly);
        else  /* e == 2UL */
            fmpz_poly_sqr(res, poly);
        return;
    }
    
    rlen = (long) e + 1;

    if (res != poly)
    {
        fmpz_poly_fit_length(res, rlen);
        _fmpz_poly_set_length(res, rlen);
        _fmpz_poly_pow_binomial(res->coeffs, poly->coeffs, e);
    }
    else
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, rlen);
        _fmpz_poly_set_length(t, rlen);
        _fmpz_poly_pow_binomial(t->coeffs, poly->coeffs, e);
        fmpz_poly_swap(res, t);
        fmpz_poly_clear(t);
    }
}
コード例 #13
0
ファイル: compose_divconquer.c プロジェクト: hemmecke/flint2
void
fmpz_poly_compose_divconquer(fmpz_poly_t res, 
                             const fmpz_poly_t poly1, const fmpz_poly_t poly2)
{
    const long len1 = poly1->length;
    const long len2 = poly2->length;
    long lenr;
    
    if (len1 == 0)
    {
        fmpz_poly_zero(res);
        return;
    }
    if (len1 == 1 || len2 == 0)
    {
        fmpz_poly_set_fmpz(res, poly1->coeffs);
        return;
    }
    
    lenr = (len1 - 1) * (len2 - 1) + 1;
    
    if (res != poly1 && res != poly2)
    {
        fmpz_poly_fit_length(res, lenr);
        _fmpz_poly_compose_divconquer(res->coeffs, poly1->coeffs, len1, 
                                                   poly2->coeffs, len2);
        _fmpz_poly_set_length(res, lenr);
        _fmpz_poly_normalise(res);
    }
    else
    {
        fmpz_poly_t t;
        fmpz_poly_init2(t, lenr);
        _fmpz_poly_compose_divconquer(t->coeffs, poly1->coeffs, len1,
                                                 poly2->coeffs, len2);
        _fmpz_poly_set_length(t, lenr);
        _fmpz_poly_normalise(t);
        fmpz_poly_swap(res, t);
        fmpz_poly_clear(t);
    }
}
コード例 #14
0
ファイル: divrem_divconquer.c プロジェクト: goens/flint2
void
fmpz_poly_divrem_divconquer(fmpz_poly_t Q, fmpz_poly_t R,
                            const fmpz_poly_t A, const fmpz_poly_t B)
{
    const long lenA = A->length;
    const long lenB = B->length;
    fmpz_poly_t tQ, tR;
    fmpz *q, *r;

    if (lenB == 0)
    {
        printf("Exception: division by zero in fmpz_poly_divrem_divconquer\n");
        abort();
    }

    if (lenA < lenB)
    {
        fmpz_poly_set(R, A);
        fmpz_poly_zero(Q);
        return;
    }

    if (Q == A || Q == B)
    {
        fmpz_poly_init2(tQ, lenA - lenB + 1);
        q = tQ->coeffs;
    }
    else
    {
        fmpz_poly_fit_length(Q, lenA - lenB + 1);
        q = Q->coeffs;
    }

    if (R == A || R == B)
    {
        fmpz_poly_init2(tR, lenA);
        r = tR->coeffs;
    }
    else
    {
        fmpz_poly_fit_length(R, lenA);
        r = R->coeffs;
    }

    _fmpz_poly_divrem_divconquer(q, r, A->coeffs, lenA, B->coeffs, lenB);

    if (Q == A || Q == B)
    {
        _fmpz_poly_set_length(tQ, lenA - lenB + 1);
        fmpz_poly_swap(tQ, Q);
        fmpz_poly_clear(tQ);
    }
    else
        _fmpz_poly_set_length(Q, lenA - lenB + 1);

    if (R == A || R == B)
    {
        _fmpz_poly_set_length(tR, lenA);
        fmpz_poly_swap(tR, R);
        fmpz_poly_clear(tR);
    }
    else
        _fmpz_poly_set_length(R, lenA);

    _fmpz_poly_normalise(Q);
    _fmpz_poly_normalise(R);
}
コード例 #15
0
ファイル: ntru_poly.c プロジェクト: hasufell/pqc
bool
poly_inverse_poly_q(fmpz_poly_t Fq,
		const fmpz_poly_t a,
		const ntru_params *params)
{
	bool retval = false;
	int k = 0,
		j = 0;
	fmpz *b_last;
	fmpz_poly_t a_tmp,
				b,
				c,
				f,
				g;

	/* general initialization of temp variables */
	fmpz_poly_init(b);
	fmpz_poly_set_coeff_ui(b, 0, 1);
	fmpz_poly_init(c);
	fmpz_poly_init(f);
	fmpz_poly_set(f, a);

	/* set g(x) = x^N − 1 */
	fmpz_poly_init(g);
	fmpz_poly_set_coeff_si(g, 0, -1);
	fmpz_poly_set_coeff_si(g, params->N, 1);

	/* avoid side effects */
	fmpz_poly_init(a_tmp);
	fmpz_poly_set(a_tmp, a);
	fmpz_poly_zero(Fq);

	while (1) {
		while (fmpz_poly_get_coeff_ptr(f, 0) &&
				fmpz_is_zero(fmpz_poly_get_coeff_ptr(f, 0))) {
			for (uint32_t i = 1; i <= params->N; i++) {
				fmpz *f_coeff = fmpz_poly_get_coeff_ptr(f, i);
				fmpz *c_coeff = fmpz_poly_get_coeff_ptr(c, params->N - i);

				/* f(x) = f(x) / x */
				fmpz_poly_set_coeff_fmpz_n(f, i - 1,
						f_coeff);

				/* c(x) = c(x) * x */
				fmpz_poly_set_coeff_fmpz_n(c, params->N + 1 - i,
						c_coeff);
			}

			fmpz_poly_set_coeff_si(f, params->N, 0);
			fmpz_poly_set_coeff_si(c, 0, 0);

			k++;

			if (fmpz_poly_degree(f) == -1)
				goto cleanup;
		}

		if (fmpz_poly_is_zero(g) == 1)
			goto cleanup;

		if (fmpz_poly_degree(f) == 0)
			break;

		if (fmpz_poly_degree(f) < fmpz_poly_degree(g)) {
			fmpz_poly_swap(f, g);
			fmpz_poly_swap(b, c);
		}

		fmpz_poly_add(f, g, f);
		fmpz_poly_mod_unsigned(f, 2);

		fmpz_poly_add(b, c, b);
		fmpz_poly_mod_unsigned(b, 2);
	}

	k = k % params->N;

	b_last = fmpz_poly_get_coeff_ptr(b, params->N);
	if (fmpz_cmp_si_n(b_last, 0))
		goto cleanup;

	/* Fq(x) = x^(N-k) * b(x) */
	for (int i = params->N - 1; i >= 0; i--) {
		fmpz *b_i;

		j = i - k;

		if (j < 0)
			j = j + params->N;

		b_i = fmpz_poly_get_coeff_ptr(b, i);
		fmpz_poly_set_coeff_fmpz_n(Fq, j, b_i);
	}

	poly_mod2_to_modq(Fq, a_tmp, params);

	/* check if the f * Fq = 1 (mod p) condition holds true */
	fmpz_poly_set(a_tmp, a);
	poly_starmultiply(a_tmp, a_tmp, Fq, params, params->q);
	if (fmpz_poly_is_one(a_tmp))
		retval = true;
	else
		fmpz_poly_zero(Fq);

cleanup:
	fmpz_poly_clear(a_tmp);
	fmpz_poly_clear(b);
	fmpz_poly_clear(c);
	fmpz_poly_clear(f);
	fmpz_poly_clear(g);

	return retval;
}
コード例 #16
0
ファイル: ntru_poly.c プロジェクト: hasufell/pqc
bool
poly_inverse_poly_p(fmpz_poly_t Fp,
		const fmpz_poly_t a,
		const ntru_params *params)
{
	bool retval = false;
	int k = 0,
		j = 0;
	fmpz *b_last;
	fmpz_poly_t a_tmp,
				b,
				c,
				f,
				g;

	/* general initialization of temp variables */
	fmpz_poly_init(b);
	fmpz_poly_set_coeff_ui(b, 0, 1);
	fmpz_poly_init(c);
	fmpz_poly_init(f);
	fmpz_poly_set(f, a);

	/* set g(x) = x^N − 1 */
	fmpz_poly_init(g);
	fmpz_poly_set_coeff_si(g, 0, -1);
	fmpz_poly_set_coeff_si(g, params->N, 1);

	/* avoid side effects */
	fmpz_poly_init(a_tmp);
	fmpz_poly_set(a_tmp, a);
	fmpz_poly_zero(Fp);

	while (1) {
		while (fmpz_poly_get_coeff_ptr(f, 0) &&
				fmpz_is_zero(fmpz_poly_get_coeff_ptr(f, 0))) {
			for (uint32_t i = 1; i <= params->N; i++) {
				fmpz *f_coeff = fmpz_poly_get_coeff_ptr(f, i);
				fmpz *c_coeff = fmpz_poly_get_coeff_ptr(c, params->N - i);

				/* f(x) = f(x) / x */
				fmpz_poly_set_coeff_fmpz_n(f, i - 1,
						f_coeff);

				/* c(x) = c(x) * x */
				fmpz_poly_set_coeff_fmpz_n(c, params->N + 1 - i,
						c_coeff);
			}

			fmpz_poly_set_coeff_si(f, params->N, 0);
			fmpz_poly_set_coeff_si(c, 0, 0);

			k++;

			if (fmpz_poly_degree(f) == -1)
				goto cleanup;
		}

		if (fmpz_poly_is_zero(g) == 1)
			goto cleanup;

		if (fmpz_poly_degree(f) == 0)
			break;

		if (fmpz_poly_degree(f) < fmpz_poly_degree(g)) {
			/* exchange f and g and exchange b and c */
			fmpz_poly_swap(f, g);
			fmpz_poly_swap(b, c);
		}

		{
			fmpz_poly_t c_tmp,
						g_tmp;
			fmpz_t u,
				   mp_tmp;

			fmpz_init(u);
			fmpz_zero(u);

			fmpz_init_set(mp_tmp, fmpz_poly_get_coeff_ptr(f, 0));

			fmpz_poly_init(g_tmp);
			fmpz_poly_set(g_tmp, g);

			fmpz_poly_init(c_tmp);
			fmpz_poly_set(c_tmp, c);

			/* u = f[0] * g[0]^(-1) mod p */
			  /* = (f[0] mod p) * (g[0] inverse mod p) mod p */
			fmpz_invmod_ui(u,
					fmpz_poly_get_coeff_ptr(g, 0),
					params->p);
			fmpz_mod_ui(mp_tmp, mp_tmp, params->p);
			fmpz_mul(u, mp_tmp, u);
			fmpz_mod_ui(u, u, params->p);

			/* f = f - u * g mod p */
			fmpz_poly_scalar_mul_fmpz(g_tmp, g_tmp, u);
			fmpz_poly_sub(f, f, g_tmp);
			fmpz_poly_mod_unsigned(f, params->p);

			/* b = b - u * c mod p */
			fmpz_poly_scalar_mul_fmpz(c_tmp, c_tmp, u);
			fmpz_poly_sub(b, b, c_tmp);
			fmpz_poly_mod_unsigned(b, params->p);

			fmpz_clear(u);
			fmpz_poly_clear(g_tmp);
			fmpz_poly_clear(c_tmp);
		}
	}

	k = k % params->N;

	b_last = fmpz_poly_get_coeff_ptr(b, params->N);
	if (fmpz_cmp_si_n(b_last, 0))
		goto cleanup;

	/* Fp(x) = x^(N-k) * b(x) */
	for (int i = params->N - 1; i >= 0; i--) {
		fmpz *b_i;

		/* b(X) = f[0]^(-1) * b(X) (mod p) */
		{
			fmpz_t mp_tmp;

			fmpz_init(mp_tmp);

			fmpz_invmod_ui(mp_tmp,
					fmpz_poly_get_coeff_ptr(f, 0),
					params->p);

			if (fmpz_poly_get_coeff_ptr(b, i)) {
				fmpz_mul(fmpz_poly_get_coeff_ptr(b, i),
						fmpz_poly_get_coeff_ptr(b, i),
						mp_tmp);
				fmpz_mod_ui(fmpz_poly_get_coeff_ptr(b, i),
						fmpz_poly_get_coeff_ptr(b, i),
						params->p);
			}
		}

		j = i - k;
		if (j < 0)
			j = j + params->N;

		b_i = fmpz_poly_get_coeff_ptr(b, i);
		fmpz_poly_set_coeff_fmpz_n(Fp, j, b_i);
	}

	/* check if the f * Fp = 1 (mod p) condition holds true */
	fmpz_poly_set(a_tmp, a);
	poly_starmultiply(a_tmp, a_tmp, Fp, params, params->p);
	if (fmpz_poly_is_one(a_tmp))
		retval = true;
	else
		fmpz_poly_zero(Fp);

cleanup:
	fmpz_poly_clear(a_tmp);
	fmpz_poly_clear(b);
	fmpz_poly_clear(c);
	fmpz_poly_clear(f);
	fmpz_poly_clear(g);

	return retval;
}
コード例 #17
0
ファイル: gcd_heuristic.c プロジェクト: goens/flint2
int
fmpz_poly_gcd_heuristic(fmpz_poly_t res,
                           const fmpz_poly_t poly1, const fmpz_poly_t poly2)
{
    const long len1 = poly1->length;
    const long len2 = poly2->length;
    long rlen;
    int done = 0;

    if (len1 == 0)
    {
        if (len2 == 0)
            fmpz_poly_zero(res);
        else
        {
            if (fmpz_sgn(poly2->coeffs + (len2 - 1)) > 0)
                fmpz_poly_set(res, poly2);
            else
                fmpz_poly_neg(res, poly2);
        }
        return 1;
    }
    else
    {
        if (len2 == 0)
        {
            if (fmpz_sgn(poly1->coeffs + (len1 - 1)) > 0)
                fmpz_poly_set(res, poly1);
            else
                fmpz_poly_neg(res, poly1);
            return 1;
        }
    }

    rlen = FLINT_MIN(len1, len2);

    if (res == poly1 || res == poly2)
    {
       fmpz_poly_t temp;
       fmpz_poly_init2(temp, rlen);
       if (len1 >= len2)
          done = _fmpz_poly_gcd_heuristic(temp->coeffs, poly1->coeffs, len1,
                                    poly2->coeffs, len2);
       else
          done = _fmpz_poly_gcd_heuristic(temp->coeffs, poly2->coeffs, len2,
                                    poly1->coeffs, len1);
       fmpz_poly_swap(temp, res);
       fmpz_poly_clear(temp);
    }
    else
    {
       fmpz_poly_fit_length(res, rlen);
       if (len1 >= len2)
          done = _fmpz_poly_gcd_heuristic(res->coeffs, poly1->coeffs, len1,
                                    poly2->coeffs, len2);
       else
          done = _fmpz_poly_gcd_heuristic(res->coeffs, poly2->coeffs, len2,
                                    poly1->coeffs, len1);
    }
    
    if (done)
    {
       _fmpz_poly_set_length(res, rlen);
       _fmpz_poly_normalise(res);
    }

    return done;
}
コード例 #18
0
ファイル: inv.c プロジェクト: goens/flint2
int
fmpz_poly_mat_inv(fmpz_poly_mat_t Ainv, fmpz_poly_t den,
                    const fmpz_poly_mat_t A)
{
    long n = fmpz_poly_mat_nrows(A);

    if (n == 0)
    {
        fmpz_poly_one(den);
        return 1;
    }
    else if (n == 1)
    {
        fmpz_poly_set(den, E(A, 0, 0));
        fmpz_poly_one(E(Ainv, 0, 0));
        return !fmpz_poly_is_zero(den);
    }
    else if (n == 2)
    {
        fmpz_poly_mat_det(den, A);
        if (fmpz_poly_is_zero(den))
        {
            return 0;
        }
        else if (Ainv == A)
        {
            fmpz_poly_swap(E(A, 0, 0), E(A, 1, 1));
            fmpz_poly_neg(E(A, 0, 1), E(A, 0, 1));
            fmpz_poly_neg(E(A, 1, 0), E(A, 1, 0));
            return 1;
        }
        else
        {
            fmpz_poly_set(E(Ainv, 0, 0), E(A, 1, 1));
            fmpz_poly_set(E(Ainv, 1, 1), E(A, 0, 0));
            fmpz_poly_neg(E(Ainv, 0, 1), E(A, 0, 1));
            fmpz_poly_neg(E(Ainv, 1, 0), E(A, 1, 0));
            return 1;
        }
    }
    else
    {
        fmpz_poly_mat_t LU, I;
        long * perm;
        int result;

        perm = _perm_init(n);
        fmpz_poly_mat_init_set(LU, A);
        result = (fmpz_poly_mat_fflu(LU, den, perm, LU, 1) == n);

        if (result)
        {
            fmpz_poly_mat_init(I, n, n);
            fmpz_poly_mat_one(I);
            fmpz_poly_mat_solve_fflu_precomp(Ainv, perm, LU, I);
            fmpz_poly_mat_clear(I);
        }
        else
            fmpz_poly_zero(den);

        if (_perm_parity(perm, n))
        {
            fmpz_poly_mat_neg(Ainv, Ainv);
            fmpz_poly_neg(den, den);
        }

        _perm_clear(perm);
        fmpz_poly_mat_clear(LU);
        return result;
    }
}
コード例 #19
0
ファイル: frob.c プロジェクト: SPancratz/deformation
void frob(const mpoly_t P, const ctx_t ctxFracQt,
          const qadic_t t1, const qadic_ctx_t Qq,
          prec_t *prec, const prec_t *prec_in,
          int verbose)
{
    const padic_ctx_struct *Qp = &Qq->pctx;
    const fmpz *p = Qp->p;
    const long a  = qadic_ctx_degree(Qq);
    const long n  = P->n - 1;
    const long d  = mpoly_degree(P, -1, ctxFracQt);
    const long b  = gmc_basis_size(n, d);

    long i, j, k;

    /* Diagonal fibre */
    padic_mat_t F0;

    /* Gauss--Manin Connection */
    mat_t M;
    mon_t *bR, *bC;
    fmpz_poly_t r;

    /* Local solution */
    fmpz_poly_mat_t C, Cinv;
    long vC, vCinv;

    /* Frobenius */
    fmpz_poly_mat_t F;
    long vF;

    fmpz_poly_mat_t F1;
    long vF1;

    fmpz_poly_t cp;

    clock_t c0, c1;
    double c;

    if (verbose)
    {
        printf("Input:\n");
        printf("  P  = "), mpoly_print(P, ctxFracQt), printf("\n");
        printf("  p  = "), fmpz_print(p), printf("\n");
        printf("  t1 = "), qadic_print_pretty(t1, Qq), printf("\n");
        printf("\n");
        fflush(stdout);
    }

    /* Step 1 {M, r} *********************************************************/

    c0 = clock();

    mat_init(M, b, b, ctxFracQt);
    fmpz_poly_init(r);

    gmc_compute(M, &bR, &bC, P, ctxFracQt);

    {
        fmpz_poly_t t;

        fmpz_poly_init(t);
        fmpz_poly_set_ui(r, 1);
        for (i = 0; i < M->m; i++)
            for (j = 0; j < M->n; j++)
            {
                fmpz_poly_lcm(t, r, fmpz_poly_q_denref(
                                  (fmpz_poly_q_struct *) mat_entry(M, i, j, ctxFracQt)));
                fmpz_poly_swap(r, t);
            }
        fmpz_poly_clear(t);
    }

    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;

    if (verbose)
    {
        printf("Gauss-Manin connection:\n");
        printf("  r(t) = "), fmpz_poly_print_pretty(r, "t"), printf("\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    {
        qadic_t t;

        qadic_init2(t, 1);
        fmpz_poly_evaluate_qadic(t, r, t1, Qq);

        if (qadic_is_zero(t))
        {
            printf("Exception (deformation_frob).\n");
            printf("The resultant r evaluates to zero (mod p) at t1.\n");
            abort();
        }
        qadic_clear(t);
    }

    /* Precisions ************************************************************/

    if (prec_in != NULL)
    {
        *prec = *prec_in;
    }
    else
    {
        deformation_precisions(prec, p, a, n, d, fmpz_poly_degree(r));
    }

    if (verbose)
    {
        printf("Precisions:\n");
        printf("  N0   = %ld\n", prec->N0);
        printf("  N1   = %ld\n", prec->N1);
        printf("  N2   = %ld\n", prec->N2);
        printf("  N3   = %ld\n", prec->N3);
        printf("  N3i  = %ld\n", prec->N3i);
        printf("  N3w  = %ld\n", prec->N3w);
        printf("  N3iw = %ld\n", prec->N3iw);
        printf("  N4   = %ld\n", prec->N4);
        printf("  m    = %ld\n", prec->m);
        printf("  K    = %ld\n", prec->K);
        printf("  r    = %ld\n", prec->r);
        printf("  s    = %ld\n", prec->s);
        printf("\n");
        fflush(stdout);
    }

    /* Initialisation ********************************************************/

    padic_mat_init2(F0, b, b, prec->N4);

    fmpz_poly_mat_init(C, b, b);
    fmpz_poly_mat_init(Cinv, b, b);

    fmpz_poly_mat_init(F, b, b);
    vF = 0;

    fmpz_poly_mat_init(F1, b, b);
    vF1 = 0;

    fmpz_poly_init(cp);

    /* Step 2 {F0} ***********************************************************/

    {
        padic_ctx_t pctx_F0;
        fmpz *t;

        padic_ctx_init(pctx_F0, p, FLINT_MIN(prec->N4 - 10, 0), prec->N4, PADIC_VAL_UNIT);
        t = _fmpz_vec_init(n + 1);

        c0 = clock();

        mpoly_diagonal_fibre(t, P, ctxFracQt);

        diagfrob(F0, t, n, d, prec->N4, pctx_F0, 0);
        padic_mat_transpose(F0, F0);

        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;

        if (verbose)
        {
            printf("Diagonal fibre:\n");
            printf("  P(0) = {"), _fmpz_vec_print(t, n + 1), printf("}\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }

        _fmpz_vec_clear(t, n + 1);
        padic_ctx_clear(pctx_F0);
    }

    /* Step 3 {C, Cinv} ******************************************************/
    /*
        Compute C as a matrix over Z_p[[t]].  A is the same but as a series
        of matrices over Z_p.  Mt is the matrix -M^t, and Cinv is C^{-1}^t,
        the local solution of the differential equation replacing M by Mt.
     */

    c0 = clock();
    {
        const long K = prec->K;
        padic_mat_struct *A;

        gmde_solve(&A, K, p, prec->N3, prec->N3w, M, ctxFracQt);
        gmde_convert_soln(C, &vC, A, K, p);

        for(i = 0; i < K; i++)
            padic_mat_clear(A + i);
        free(A);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Local solution:\n");
        printf("  Time for C      = %f\n", c);
        fflush(stdout);
    }

    c0 = clock();
    {
        const long K = (prec->K + (*p) - 1) / (*p);
        mat_t Mt;
        padic_mat_struct *Ainv;

        mat_init(Mt, b, b, ctxFracQt);
        mat_transpose(Mt, M, ctxFracQt);
        mat_neg(Mt, Mt, ctxFracQt);
        gmde_solve(&Ainv, K, p, prec->N3i, prec->N3iw, Mt, ctxFracQt);
        gmde_convert_soln(Cinv, &vCinv, Ainv, K, p);

        fmpz_poly_mat_transpose(Cinv, Cinv);
        fmpz_poly_mat_compose_pow(Cinv, Cinv, *p);

        for(i = 0; i < K; i++)
            padic_mat_clear(Ainv + i);
        free(Ainv);
        mat_clear(Mt, ctxFracQt);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("  Time for C^{-1} = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Step 4 {F(t) := C(t) F(0) C(t^p)^{-1}} ********************************/
    /*
        Computes the product C(t) F(0) C(t^p)^{-1} modulo (p^{N_2}, t^K).
        This is done by first computing the unit part of the product
        exactly over the integers modulo t^K.
     */

    c0 = clock();
    {
        fmpz_t pN;
        fmpz_poly_mat_t T;

        fmpz_init(pN);
        fmpz_poly_mat_init(T, b, b);

        for (i = 0; i < b; i++)
        {
            /* Find the unique k s.t. F0(i,k) is non-zero */
            for (k = 0; k < b; k++)
                if (!fmpz_is_zero(padic_mat_entry(F0, i, k)))
                    break;
            if (k == b)
            {
                printf("Exception (frob). F0 is singular.\n\n");
                abort();
            }

            for (j = 0; j < b; j++)
            {
                fmpz_poly_scalar_mul_fmpz(fmpz_poly_mat_entry(T, i, j),
                                          fmpz_poly_mat_entry(Cinv, k, j),
                                          padic_mat_entry(F0, i, k));
            }
        }

        fmpz_poly_mat_mul(F, C, T);
        fmpz_poly_mat_truncate(F, prec->K);
        vF = vC + padic_mat_val(F0) + vCinv;

        /* Canonicalise (F, vF) */
        {
            long v = fmpz_poly_mat_ord_p(F, p);

            if (v == LONG_MAX)
            {
                printf("ERROR (deformation_frob).  F(t) == 0.\n");
                abort();
            }
            else if (v > 0)
            {
                fmpz_pow_ui(pN, p, v);
                fmpz_poly_mat_scalar_divexact_fmpz(F, F, pN);
                vF = vF + v;
            }
        }

        /* Reduce (F, vF) modulo p^{N2} */
        fmpz_pow_ui(pN, p, prec->N2 - vF);
        fmpz_poly_mat_scalar_mod_fmpz(F, F, pN);

        fmpz_clear(pN);
        fmpz_poly_mat_clear(T);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Matrix for F(t):\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Step 5 {G = r(t)^m F(t)} **********************************************/

    c0 = clock();
    {
        fmpz_t pN;
        fmpz_poly_t t;

        fmpz_init(pN);
        fmpz_poly_init(t);

        fmpz_pow_ui(pN, p, prec->N2 - vF);

        /* Compute r(t)^m mod p^{N2-vF} */
        if (prec->denR == NULL)
        {
            fmpz_mod_poly_t _t;

            fmpz_mod_poly_init(_t, pN);
            fmpz_mod_poly_set_fmpz_poly(_t, r);
            fmpz_mod_poly_pow(_t, _t, prec->m);
            fmpz_mod_poly_get_fmpz_poly(t, _t);
            fmpz_mod_poly_clear(_t);
        }
        else
        {
            /* TODO: We don't really need a copy */
            fmpz_poly_set(t, prec->denR);
        }

        fmpz_poly_mat_scalar_mul_fmpz_poly(F, F, t);
        fmpz_poly_mat_scalar_mod_fmpz(F, F, pN);

        /* TODO: This should not be necessary? */
        fmpz_poly_mat_truncate(F, prec->K);

        fmpz_clear(pN);
        fmpz_poly_clear(t);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Analytic continuation:\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Steps 6 and 7 *********************************************************/

    if (a == 1)
    {
        /* Step 6 {F(1) = r(t_1)^{-m} G(t_1)} ********************************/

        c0 = clock();
        {
            const long N = prec->N2 - vF;

            fmpz_t f, g, t, pN;

            fmpz_init(f);
            fmpz_init(g);
            fmpz_init(t);
            fmpz_init(pN);

            fmpz_pow_ui(pN, p, N);

            /* f := \hat{t_1}, g := r(\hat{t_1})^{-m} */
            _padic_teichmuller(f, t1->coeffs + 0, p, N);
            if (prec->denR == NULL)
            {
                _fmpz_mod_poly_evaluate_fmpz(g, r->coeffs, r->length, f, pN);
                fmpz_powm_ui(t, g, prec->m, pN);
            }
            else
            {
                _fmpz_mod_poly_evaluate_fmpz(t, prec->denR->coeffs, prec->denR->length, f, pN);
            }
            _padic_inv(g, t, p, N);

            /* F1 := g G(\hat{t_1}) */
            for (i = 0; i < b; i++)
                for (j = 0; j < b; j++)
                {
                    const fmpz_poly_struct *poly = fmpz_poly_mat_entry(F, i, j);
                    const long len               = poly->length;

                    if (len == 0)
                    {
                        fmpz_poly_zero(fmpz_poly_mat_entry(F1, i, j));
                    }
                    else
                    {
                        fmpz_poly_fit_length(fmpz_poly_mat_entry(F1, i, j), 1);

                        _fmpz_mod_poly_evaluate_fmpz(t, poly->coeffs, len, f, pN);
                        fmpz_mul(fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, g, t);
                        fmpz_mod(fmpz_poly_mat_entry(F1, i, j)->coeffs + 0,
                                 fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, pN);

                        _fmpz_poly_set_length(fmpz_poly_mat_entry(F1, i, j), 1);
                        _fmpz_poly_normalise(fmpz_poly_mat_entry(F1, i, j));
                    }
                }

            vF1 = vF;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(f);
            fmpz_clear(g);
            fmpz_clear(t);
            fmpz_clear(pN);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Evaluation:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }
    }
    else
    {
        /* Step 6 {F(1) = r(t_1)^{-m} G(t_1)} ********************************/

        c0 = clock();
        {
            const long N = prec->N2 - vF;
            fmpz_t pN;
            fmpz *f, *g, *t;

            fmpz_init(pN);

            f = _fmpz_vec_init(a);
            g = _fmpz_vec_init(2 * a - 1);
            t = _fmpz_vec_init(2 * a - 1);

            fmpz_pow_ui(pN, p, N);

            /* f := \hat{t_1}, g := r(\hat{t_1})^{-m} */
            _qadic_teichmuller(f, t1->coeffs, t1->length, Qq->a, Qq->j, Qq->len, p, N);
            if (prec->denR == NULL)
            {
                fmpz_t e;
                fmpz_init_set_ui(e, prec->m);
                _fmpz_mod_poly_compose_smod(g, r->coeffs, r->length, f, a,
                                            Qq->a, Qq->j, Qq->len, pN);
                _qadic_pow(t, g, a, e, Qq->a, Qq->j, Qq->len, pN);
                fmpz_clear(e);
            }
            else
            {
                _fmpz_mod_poly_reduce(prec->denR->coeffs, prec->denR->length, Qq->a, Qq->j, Qq->len, pN);
                _fmpz_poly_normalise(prec->denR);

                _fmpz_mod_poly_compose_smod(t, prec->denR->coeffs, prec->denR->length, f, a,
                                            Qq->a, Qq->j, Qq->len, pN);
            }
            _qadic_inv(g, t, a, Qq->a, Qq->j, Qq->len, p, N);

            /* F1 := g G(\hat{t_1}) */
            for (i = 0; i < b; i++)
                for (j = 0; j < b; j++)
                {
                    const fmpz_poly_struct *poly = fmpz_poly_mat_entry(F, i, j);
                    const long len               = poly->length;

                    fmpz_poly_struct *poly2 = fmpz_poly_mat_entry(F1, i, j);

                    if (len == 0)
                    {
                        fmpz_poly_zero(poly2);
                    }
                    else
                    {
                        _fmpz_mod_poly_compose_smod(t, poly->coeffs, len, f, a,
                                                    Qq->a, Qq->j, Qq->len, pN);

                        fmpz_poly_fit_length(poly2, 2 * a - 1);
                        _fmpz_poly_mul(poly2->coeffs, g, a, t, a);
                        _fmpz_mod_poly_reduce(poly2->coeffs, 2 * a - 1, Qq->a, Qq->j, Qq->len, pN);
                        _fmpz_poly_set_length(poly2, a);
                        _fmpz_poly_normalise(poly2);
                    }
                }

            /* Now the matrix for p^{-1} F_p at t=t_1 is (F1, vF1). */
            vF1 = vF;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(pN);
            _fmpz_vec_clear(f, a);
            _fmpz_vec_clear(g, 2 * a - 1);
            _fmpz_vec_clear(t, 2 * a - 1);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Evaluation:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }

        /* Step 7 {Norm} *****************************************************/
        /*
            Computes the matrix for $q^{-1} F_q$ at $t = t_1$ as the
            product $F \sigma(F) \dotsm \sigma^{a-1}(F)$ up appropriate
            transpositions because our convention of columns vs rows is
            the opposite of that used by Gerkmann.

            Note that, in any case, transpositions do not affect
            the characteristic polynomial.
         */

        c0 = clock();
        {
            const long N = prec->N1 - a * vF1;

            fmpz_t pN;
            fmpz_poly_mat_t T;

            fmpz_init(pN);
            fmpz_poly_mat_init(T, b, b);

            fmpz_pow_ui(pN, p, N);

            fmpz_poly_mat_frobenius(T, F1, 1, p, N, Qq);
            _qadic_mat_mul(F1, F1, T, pN, Qq);

            for (i = 2; i < a; i++)
            {
                fmpz_poly_mat_frobenius(T, T, 1, p, N, Qq);
                _qadic_mat_mul(F1, F1, T, pN, Qq);
            }

            vF1 = a * vF1;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(pN);
            fmpz_poly_mat_clear(T);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Norm:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }
    }

    /* Step 8 {Reverse characteristic polynomial} ****************************/

    c0 = clock();

    deformation_revcharpoly(cp, F1, vF1, n, d, prec->N0, prec->r, prec->s, Qq);

    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Reverse characteristic polynomial:\n");
        printf("  p(T) = "), fmpz_poly_print_pretty(cp, "T"), printf("\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Clean up **************************************************************/

    padic_mat_clear(F0);

    mat_clear(M, ctxFracQt);
    free(bR);
    free(bC);
    fmpz_poly_clear(r);

    fmpz_poly_mat_clear(C);
    fmpz_poly_mat_clear(Cinv);

    fmpz_poly_mat_clear(F);
    fmpz_poly_mat_clear(F1);
    fmpz_poly_clear(cp);
}