Example #1
0
static void
poly_mod2_to_modq(fmpz_poly_t Fq,
		const fmpz_poly_t a,
		const ntru_params *params)
{
	int v = 2;
	fmpz_poly_t poly_tmp, two;

	fmpz_poly_init(poly_tmp);
	fmpz_poly_zero(poly_tmp);
	fmpz_poly_init(two);
	fmpz_poly_set_coeff_ui(two, 0, 2);

	while (v < (int)(params->q)) {
		v = v * 2;

		poly_starmultiply(poly_tmp, a, Fq, params, v);
		fmpz_poly_sub(poly_tmp, two, poly_tmp);
		fmpz_poly_mod_unsigned(poly_tmp, v);
		poly_starmultiply(Fq, Fq, poly_tmp, params, v);

	}

	fmpz_poly_clear(poly_tmp);
	fmpz_poly_clear(two);

}
Example #2
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 < 50; i++)
    {
        fmpz_poly_t f, g;
        long n;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_poly_randtest(g, state, n_randint(state, 50),
            1+n_randint(state,100));
        fmpz_poly_set_coeff_ui(g, 0, 0);
        fmpz_poly_set_coeff_ui(g, 1, 1);
        if (n_randlimb(state) % 2)
            fmpz_poly_neg(g, g);  /* get -x term */
        n = n_randint(state, 50);

        fmpz_poly_revert_series(f, g, n);
        fmpz_poly_revert_series(g, g, n);

        result = (fmpz_poly_equal(f, g));
        if (!result)
        {
            printf("FAIL (aliasing):\n");
            fmpz_poly_print(f), printf("\n\n");
            fmpz_poly_print(g), printf("\n\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
    }

    /* Check f(f^(-1)) = id */
    for (i = 0; i < 50; i++)
    {
        fmpz_poly_t f, g, h;
        long n;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_poly_init(h);
        fmpz_poly_randtest(g, state, n_randint(state, 50), 10);
        fmpz_poly_set_coeff_ui(g, 0, 0);
        fmpz_poly_set_coeff_ui(g, 1, 1);
        if (n_randlimb(state) % 2)
            fmpz_poly_neg(g, g);  /* get -x term */
        n = n_randint(state, 50);

        fmpz_poly_revert_series(f, g, n);
        fmpz_poly_compose_series(h, g, f, n);

        result = ((n <= 1 && fmpz_poly_is_zero(h)) ||
            (h->length == 2 && fmpz_is_zero(h->coeffs + 0) &&
                fmpz_is_one(h->coeffs + 1)));
        if (!result)
        {
            printf("FAIL (comparison):\n");
            fmpz_poly_print(f), printf("\n\n");
            fmpz_poly_print(g), printf("\n\n");
            fmpz_poly_print(h), printf("\n\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
        fmpz_poly_clear(h);
    }

    flint_randclear(state);
    _fmpz_cleanup();
    printf("PASS\n");
    return 0;
}
int
main(void)
{
    int i, result;
    FLINT_TEST_INIT(state);

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

    

    /* Check aliasing */
    for (i = 0; i < 10 * flint_test_multiplier(); i++)
    {
        fmpz_poly_t f, g;
        slong n;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_poly_randtest(g, state, n_randint(state, 50),
            1+n_randint(state,100));
        fmpz_poly_set_coeff_ui(g, 0, 0);
        fmpz_poly_set_coeff_ui(g, 1, 1);
        if (n_randlimb(state) % 2)
            fmpz_poly_neg(g, g);  /* get -x term */
        n = n_randint(state, 50);

        fmpz_poly_revert_series_lagrange_fast(f, g, n);
        fmpz_poly_revert_series_lagrange_fast(g, g, n);

        result = (fmpz_poly_equal(f, g));
        if (!result)
        {
            flint_printf("FAIL (aliasing):\n");
            fmpz_poly_print(f), flint_printf("\n\n");
            fmpz_poly_print(g), flint_printf("\n\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
    }

    /* Check f(f^(-1)) = id */
    for (i = 0; i < 10 * flint_test_multiplier(); i++)
    {
        fmpz_poly_t f, g, h;
        slong n;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_poly_init(h);
        fmpz_poly_randtest(g, state, n_randint(state, 50), 1+n_randint(state,100));
        fmpz_poly_set_coeff_ui(g, 0, 0);
        fmpz_poly_set_coeff_ui(g, 1, 1);
        if (n_randlimb(state) % 2)
            fmpz_poly_neg(g, g);  /* get -x term */
        n = n_randint(state, 50);

        fmpz_poly_revert_series_lagrange_fast(f, g, n);
        fmpz_poly_compose_series(h, g, f, n);

        result = ((n <= 1 && fmpz_poly_is_zero(h)) ||
            (h->length == 2 && fmpz_is_zero(h->coeffs + 0) &&
                fmpz_is_one(h->coeffs + 1)));
        if (!result)
        {
            flint_printf("FAIL (comparison):\n");
            fmpz_poly_print(f), flint_printf("\n\n");
            fmpz_poly_print(g), flint_printf("\n\n");
            fmpz_poly_print(h), flint_printf("\n\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
        fmpz_poly_clear(h);
    }

    FLINT_TEST_CLEANUP(state);
    
    flint_printf("PASS\n");
    return 0;
}
int
main(void)
{
    int i;
    FLINT_TEST_INIT(state);

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

    

    /* Check aliasing */
    for (i = 0; i < 100 * flint_test_multiplier(); i++)
    {
        fmpz_poly_t f, g;
        fmpz_t c;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_init(c);

        fmpz_poly_randtest(f, state, 1 + n_randint(state, 20),
                                     1 + n_randint(state, 200));

        fmpz_randtest(c, state, n_randint(state, 200));

        fmpz_poly_taylor_shift_divconquer(g, f, c);
        fmpz_poly_taylor_shift_divconquer(f, f, c);

        if (!fmpz_poly_equal(g, f))
        {
            flint_printf("FAIL\n");
            fmpz_poly_print(f); flint_printf("\n");
            fmpz_poly_print(g); flint_printf("\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
        fmpz_clear(c);
    }

    /* Compare with composition */
    for (i = 0; i < 100 * flint_test_multiplier(); i++)
    {
        fmpz_poly_t f, g, h1, h2;
        fmpz_t c;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_poly_init(h1);
        fmpz_poly_init(h2);

        fmpz_init(c);

        fmpz_poly_randtest(f, state, 1 + n_randint(state, 20),
                                     1 + n_randint(state, 200));

        fmpz_randtest(c, state, n_randint(state, 200));

        fmpz_poly_set_coeff_ui(g, 1, 1);
        fmpz_poly_set_coeff_fmpz(g, 0, c);

        fmpz_poly_taylor_shift_divconquer(h1, f, c);
        fmpz_poly_compose(h2, f, g);

        if (!fmpz_poly_equal(h1, h2))
        {
            flint_printf("FAIL\n");
            fmpz_poly_print(f); flint_printf("\n");
            fmpz_poly_print(g); flint_printf("\n");
            fmpz_poly_print(h1); flint_printf("\n");
            fmpz_poly_print(h2); flint_printf("\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
        fmpz_poly_clear(h1);
        fmpz_poly_clear(h2);
        fmpz_clear(c);
    }

    FLINT_TEST_CLEANUP(state);
    
    flint_printf("PASS\n");
    return 0;
}
Example #5
0
int main(int argc, char *argv[])
{
    fmpz_poly_t f, g;
    fmpz_poly_factor_t fac;
    fmpz_t t;
    slong compd, printd, i, j;

    if (argc < 2)
    {
        flint_printf("poly_roots [-refine d] [-print d] <poly>\n\n");

        flint_printf("Isolates all the complex roots of a polynomial with integer coefficients.\n\n");

        flint_printf("If -refine d is passed, the roots are refined to an absolute tolerance\n");
        flint_printf("better than 10^(-d). By default, the roots are only computed to sufficient\n");
        flint_printf("accuracy to isolate them. The refinement is not currently done efficiently.\n\n");

        flint_printf("If -print d is passed, the computed roots are printed to d decimals.\n");
        flint_printf("By default, the roots are not printed.\n\n");

        flint_printf("The polynomial can be specified by passing the following as <poly>:\n\n");

        flint_printf("a <n>          Easy polynomial 1 + 2x + ... + (n+1)x^n\n");
        flint_printf("t <n>          Chebyshev polynomial T_n\n");
        flint_printf("u <n>          Chebyshev polynomial U_n\n");
        flint_printf("p <n>          Legendre polynomial P_n\n");
        flint_printf("c <n>          Cyclotomic polynomial Phi_n\n");
        flint_printf("s <n>          Swinnerton-Dyer polynomial S_n\n");
        flint_printf("b <n>          Bernoulli polynomial B_n\n");
        flint_printf("w <n>          Wilkinson polynomial W_n\n");
        flint_printf("e <n>          Taylor series of exp(x) truncated to degree n\n");
        flint_printf("m <n> <m>      The Mignotte-like polynomial x^n + (100x+1)^m, n > m\n");
        flint_printf("coeffs <c0 c1 ... cn>        c0 + c1 x + ... + cn x^n\n\n");

        flint_printf("Concatenate to multiply polynomials, e.g.: p 5 t 6 coeffs 1 2 3\n");
        flint_printf("for P_5(x)*T_6(x)*(1+2x+3x^2)\n\n");

        return 1;
    }

    compd = 0;
    printd = 0;

    fmpz_poly_init(f);
    fmpz_poly_init(g);
    fmpz_init(t);
    fmpz_poly_one(f);

    for (i = 1; i < argc; i++)
    {
        if (!strcmp(argv[i], "-refine"))
        {
            compd = atol(argv[i+1]);
            i++;
        }
        else if (!strcmp(argv[i], "-print"))
        {
            printd = atol(argv[i+1]);
            i++;
        }
        else if (!strcmp(argv[i], "a"))
        {
            slong n = atol(argv[i+1]);
            fmpz_poly_zero(g);
            for (j = 0; j <= n; j++)
                fmpz_poly_set_coeff_ui(g, j, j+1);
            fmpz_poly_mul(f, f, g);
            i++;
        }
        else if (!strcmp(argv[i], "t"))
        {
            arith_chebyshev_t_polynomial(g, atol(argv[i+1]));
            fmpz_poly_mul(f, f, g);
            i++;
        }
        else if (!strcmp(argv[i], "u"))
        {
            arith_chebyshev_u_polynomial(g, atol(argv[i+1]));
            fmpz_poly_mul(f, f, g);
            i++;
        }
        else if (!strcmp(argv[i], "p"))
        {
            fmpq_poly_t h;
            fmpq_poly_init(h);
            arith_legendre_polynomial(h, atol(argv[i+1]));
            fmpq_poly_get_numerator(g, h);
            fmpz_poly_mul(f, f, g);
            fmpq_poly_clear(h);
            i++;
        }
        else if (!strcmp(argv[i], "c"))
        {
            arith_cyclotomic_polynomial(g, atol(argv[i+1]));
            fmpz_poly_mul(f, f, g);
            i++;
        }
        else if (!strcmp(argv[i], "s"))
        {
            arith_swinnerton_dyer_polynomial(g, atol(argv[i+1]));
            fmpz_poly_mul(f, f, g);
            i++;
        }
        else if (!strcmp(argv[i], "b"))
        {
            fmpq_poly_t h;
            fmpq_poly_init(h);
            arith_bernoulli_polynomial(h, atol(argv[i+1]));
            fmpq_poly_get_numerator(g, h);
            fmpz_poly_mul(f, f, g);
            fmpq_poly_clear(h);
            i++;
        }
        else if (!strcmp(argv[i], "w"))
        {
            slong n = atol(argv[i+1]);
            fmpz_poly_zero(g);
            fmpz_poly_fit_length(g, n+2);
            arith_stirling_number_1_vec(g->coeffs, n+1, n+2);
            _fmpz_poly_set_length(g, n+2);
            fmpz_poly_shift_right(g, g, 1);
            fmpz_poly_mul(f, f, g);
            i++;
        }
        else if (!strcmp(argv[i], "e"))
        {
            fmpq_poly_t h;
            fmpq_poly_init(h);
            fmpq_poly_set_coeff_si(h, 0, 0);
            fmpq_poly_set_coeff_si(h, 1, 1);
            fmpq_poly_exp_series(h, h, atol(argv[i+1]) + 1);
            fmpq_poly_get_numerator(g, h);
            fmpz_poly_mul(f, f, g);
            fmpq_poly_clear(h);
            i++;
        }
        else if (!strcmp(argv[i], "m"))
        {
            fmpz_poly_zero(g);
            fmpz_poly_set_coeff_ui(g, 0, 1);
            fmpz_poly_set_coeff_ui(g, 1, 100);
            fmpz_poly_pow(g, g,  atol(argv[i+2]));
            fmpz_poly_set_coeff_ui(g, atol(argv[i+1]), 1);
            fmpz_poly_mul(f, f, g);
            i += 2;
        }
        else if (!strcmp(argv[i], "coeffs"))
        {
            fmpz_poly_zero(g);
            i++;
            j = 0;
            while (i < argc)
            {
                if (fmpz_set_str(t, argv[i], 10) != 0)
                {
                    i--;
                    break;
                }

                fmpz_poly_set_coeff_fmpz(g, j, t);
                i++;
                j++;
            }
            fmpz_poly_mul(f, f, g);
        }
    }

    fmpz_poly_factor_init(fac);

    flint_printf("computing squarefree factorization...\n");
    TIMEIT_ONCE_START
    fmpz_poly_factor_squarefree(fac, f);
    TIMEIT_ONCE_STOP

    TIMEIT_ONCE_START
    for (i = 0; i < fac->num; i++)
    {
        flint_printf("roots with multiplicity %wd\n", fac->exp[i]);
        fmpz_poly_complex_roots_squarefree(fac->p + i,
                                           32, compd * 3.32193 + 2, printd);
    }
    TIMEIT_ONCE_STOP

    fmpz_poly_factor_clear(fac);
    fmpz_poly_clear(f);
    fmpz_poly_clear(g);
    fmpz_clear(t);

    flint_cleanup();
    return EXIT_SUCCESS;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
int
main(void)
{
    int i, result;
    FLINT_TEST_INIT(state);

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

    

    /* Check aliasing of the first argument */
    for (i = 0; i < 10 * flint_test_multiplier(); i++)
    {
        fmpz_poly_t f, g, h;
        slong n;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_poly_init(h);
        fmpz_poly_randtest(g, state, n_randint(state, 40), 80);
        fmpz_poly_randtest(h, state, n_randint(state, 20), 50);
        fmpz_poly_set_coeff_ui(h, 0, 0);
        n = n_randint(state, 20);

        fmpz_poly_compose_series(f, g, h, n);
        fmpz_poly_compose_series(g, g, h, n);

        result = (fmpz_poly_equal(f, g));
        if (!result)
        {
            flint_printf("FAIL (aliasing 1):\n");
            fmpz_poly_print(f), flint_printf("\n\n");
            fmpz_poly_print(g), flint_printf("\n\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
        fmpz_poly_clear(h);
    }

    /* Check aliasing of the second argument */
    for (i = 0; i < 10 * flint_test_multiplier(); i++)
    {
        fmpz_poly_t f, g, h;
        slong n;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_poly_init(h);
        fmpz_poly_randtest(g, state, n_randint(state, 40), 80);
        fmpz_poly_randtest(h, state, n_randint(state, 20), 50);
        fmpz_poly_set_coeff_ui(h, 0, 0);
        n = n_randint(state, 20);

        fmpz_poly_compose_series(f, g, h, n);
        fmpz_poly_compose_series(h, g, h, n);

        result = (fmpz_poly_equal(f, h));
        if (!result)
        {
            flint_printf("FAIL (aliasing 2):\n");
            fmpz_poly_print(f), flint_printf("\n\n");
            fmpz_poly_print(h), flint_printf("\n\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
        fmpz_poly_clear(h);
    }

    /* Compare with compose */
    for (i = 0; i < 10 * flint_test_multiplier(); i++)
    {
        fmpz_poly_t f, g, h, s, t;
        slong n;

        fmpz_poly_init(f);
        fmpz_poly_init(g);
        fmpz_poly_init(h);
        fmpz_poly_init(s);
        fmpz_poly_init(t);
        fmpz_poly_randtest(g, state, n_randint(state, 40), 80);
        fmpz_poly_randtest(h, state, n_randint(state, 20), 50);
        fmpz_poly_set_coeff_ui(h, 0, 0);
        n = n_randint(state, 10);

        fmpz_poly_compose(s, g, h);
        fmpz_poly_truncate(s, n);
        fmpz_poly_compose_series(f, g, h, n);

        result = (fmpz_poly_equal(f, s));
        if (!result)
        {
            flint_printf("FAIL (comparison):\n");
            flint_printf("n = %wd\n", n);
            flint_printf("g = "), fmpz_poly_print(g), flint_printf("\n\n");
            flint_printf("h = "), fmpz_poly_print(h), flint_printf("\n\n");
            flint_printf("f = "), fmpz_poly_print(f), flint_printf("\n\n");
            flint_printf("s = "), fmpz_poly_print(s), flint_printf("\n\n");
            abort();
        }

        fmpz_poly_clear(f);
        fmpz_poly_clear(g);
        fmpz_poly_clear(h);
        fmpz_poly_clear(s);
        fmpz_poly_clear(t);
    }

    FLINT_TEST_CLEANUP(state);
    
    flint_printf("PASS\n");
    return 0;
}
// Version Fq
void fq_poly_compose_mod_kedlaya_umans(fq_poly_t fg, const fq_poly_t f, const fq_poly_t g, const fq_poly_t h, slong d, fq_ctx_t ctx) {

	slong n, i, j, m, dm, N, Nm, degree;
	fmpz* p;
	fmpz_t q;
	fq_multi_poly_t f_prime;
	fq_struct *vect_beta, *vect_alpha, *vect_alpha2, *vect_eval;
	fq_poly_t gi;


	// Vérification des paramètres

	n = FLINT_MAX(fq_poly_length(f,ctx),fq_poly_length(g,ctx));
	i = fq_poly_length(h,ctx);

	if(n >= i) {
		printf("Erreur, f ou g n'a pas été modulé par h.\n");
		exit(1);
	}

	// Les polynômes f et g étant réduits modulo h, n vaut le nombre de coefficients de h
	n = i;

	if(d < 2) {
		printf("d < 2\n");
		exit(1);
	}

	if(d >= n) {
		printf("d >= n\n");
		exit(1);
	}

	p = fq_ctx_prime(ctx);
	degree = fq_ctx_degree(ctx);

	m = n_clog(n,d);
	dm = n_pow(d,m);
	N = n_pow(d,m)*m*d;
	Nm = N*m;


	if(fmpz_cmp_ui(p,N) < 0) {
		flint_printf("\nErreur, pas assez de points d'interpolation !\n");
		flint_printf("\np tient sur un mot machine, utilisez donc la version fq_nmod !\n");
		exit(1);
	}

	// Étape 1 //////////////////////////////

	fq_multi_poly_init(f_prime, dm, d, m, ctx);
	_fq_vec_zero(f_prime->poly, dm, ctx);

	for(i = 0 ; i < n ; i++) {
		fq_poly_get_coeff(&(f_prime->poly[i]),f,i,ctx);
	}


	// Étape 3 //////////////////////////////

	vect_beta = _fq_vec_init(N,ctx);

	for(i = 0 ; i < N ; i++) {
		fmpz_poly_set_coeff_ui(vect_beta + i, 0, i);
	}

	vect_alpha = _fq_vec_init(N*m, ctx);


	fq_poly_init(gi,ctx);
	fq_poly_set(gi,g,ctx);
	fq_poly_evaluate_fq_vec(vect_alpha, gi, vect_beta, N, ctx);
	for(i = 1 ; i < m ; i++) {

		// Étape 2 //////////////////////////////
		// Calcul du g^(d^i) avec g^(d^i) = [ (g^(d^(i-1))) ^ d ] mod h
		fq_poly_powmod_ui_binexp(gi,gi,d,h,ctx);

		fq_poly_evaluate_fq_vec(vect_alpha+i*N, gi, vect_beta, N, ctx);
	}

	fq_poly_clear(gi, ctx);


	// Transposition
	// Passe de m lignes N colonnes
	// à N lignes m colonnes ==> nécessaire pour EMM dans Fp

	vect_alpha2 = _fq_vec_init(Nm,ctx);
	for(i = 0 ; i < m ; i++) {
		for(j = 0 ; j < N ; j++) {
			fq_set(vect_alpha2 + j*m + i,vect_alpha + i*N + j,ctx);
		}
	}
	vect_alpha = vect_alpha2;


	// Étape 4 //////////////////////////////
	// EMM

	vect_eval = _fq_vec_init(N,ctx);

	fq_multi_poly_multimodular(vect_eval, N, f_prime, vect_alpha, ctx);

	_fq_vec_clear(vect_alpha,Nm,ctx);
	fq_multi_poly_clear(f_prime,ctx);

	// Étape 5 //////////////////////////////

	fq_poly_interpolate_fq_vec_fast(fg, vect_beta, vect_eval, N, ctx);


	_fq_vec_clear(vect_beta,N,ctx);

	_fq_vec_clear(vect_eval,N,ctx);

	// Étape 6 //////////////////////////////

	fq_poly_rem(fg,fg,h,ctx);

}