Example #1
0
int main(void)
{
    fmpz_t p;
    long d, i;
    fq_ctx_t ctx;
    clock_t c0, c1;
    double c;
    fq_poly_t f, g, h;

    FLINT_TEST_INIT(state);

    fq_poly_init(f, ctx);
    fq_poly_init(g, ctx);
    fq_poly_init(h, ctx);

    printf("Polynomial multiplication over GF(q)\n");
    printf("------------------------------------\n");

    {
        printf("1)  Two length-10,000 polynomials over GF(3^2)\n");

        fmpz_init_set_ui(p, 3);
        d = 2;
        fq_ctx_init_conway(ctx, p, d, "X");

        fq_poly_randtest(g, state, 10000, ctx);
        fq_poly_randtest(h, state, 10000, ctx);

        c0 = clock();
        fq_poly_mul_classical(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("Classical: %fs\n", c);

        c0 = clock();
        for (i = 0; i < 100; i++)
            fq_poly_mul_reorder(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("Reorder: %fms\n", 10 * c);

        c0 = clock();
        for (i = 0; i < 100; i++)
            fq_poly_mul_KS(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("KS: %fms\n", 10 * c);

        fq_ctx_clear(ctx);
        fmpz_clear(p);
    }
    {
        printf("2)  Two length-500 polynomials over GF(3^263)\n");

        fmpz_init_set_ui(p, 3);
        d = 263;
        fq_ctx_init_conway(ctx, p, d, "X");

        fq_poly_randtest(g, state, 500, ctx);
        fq_poly_randtest(h, state, 500, ctx);

        c0 = clock();
        fq_poly_mul_classical(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("Classical: %fs\n", c);

        c0 = clock();
        fq_poly_mul_reorder(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("Reorder: %fs\n", c);

        c0 = clock();
        for (i = 0; i < 100; i++)
            fq_poly_mul_KS(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("KS: %fms\n", 10 * c);

        fq_ctx_clear(ctx);
        fmpz_clear(p);
    }
    {
        printf("3)  Two length-5 polynomials over GF(109987^4)\n");

        fmpz_init_set_ui(p, 109987);
        d = 4;
        fq_ctx_init_conway(ctx, p, d, "X");

        fq_poly_randtest(g, state, 4, ctx);
        fq_poly_randtest(h, state, 4, ctx);

        c0 = clock();
        for (i = 0; i < 1000 * 100; i++)
            fq_poly_mul_classical(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("Classical: %f\xb5s\n", 10 * c);

        c0 = clock();
        for (i = 0; i < 1000 * 100; i++)
            fq_poly_mul_reorder(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("Reorder: %f\xb5s\n", 10 * c);

        c0 = clock();
        for (i = 0; i < 1000 * 100; i++)
            fq_poly_mul_KS(f, g, h, ctx);
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        printf("KS: %f\xb5s\n", 10 * c);

        fq_ctx_clear(ctx);
        fmpz_clear(p);
    }

    fq_poly_clear(f, ctx);
    fq_poly_clear(g, ctx);
    fq_poly_clear(h, ctx);
    FLINT_TEST_CLEANUP(state);

    return EXIT_SUCCESS;
}
// 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);

}