コード例 #1
0
ファイル: det.c プロジェクト: clear731/lattice
void
nmod_poly_mat_det(nmod_poly_t det, const nmod_poly_mat_t A)
{
    slong n = A->r;

    if (n == 0)
    {
        nmod_poly_one(det);
    }
    else if (n == 1)
    {
        nmod_poly_set(det, nmod_poly_mat_entry(A, 0, 0));
    }
    else if (n == 2)
    {
        nmod_poly_t tmp;
        nmod_poly_init(tmp, nmod_poly_mat_modulus(A));
        nmod_poly_mul(det, nmod_poly_mat_entry(A, 0, 0),
                           nmod_poly_mat_entry(A, 1, 1));
        nmod_poly_mul(tmp, nmod_poly_mat_entry(A, 0, 1),
                           nmod_poly_mat_entry(A, 1, 0));
        nmod_poly_sub(det, det, tmp);
        nmod_poly_clear(tmp);
    }
    else if (n < 15)  /* should be entry sensitive too */
    {
        nmod_poly_mat_det_fflu(det, A);
    }
    else
    {
        nmod_poly_mat_det_interpolate(det, A);
    }
}
コード例 #2
0
ファイル: set.c プロジェクト: clear731/lattice
void nmod_poly_factor_set(nmod_poly_factor_t res, const nmod_poly_factor_t fac)
{
    if (res != fac)
    {
        if (fac->num == 0)
        {
            nmod_poly_factor_clear(res);
            nmod_poly_factor_init(res);
        }
        else
        {
            slong i;

            nmod_poly_factor_fit_length(res, fac->num);
            for (i = 0; i < fac->num; i++)
            {
                nmod_poly_set(res->p + i, fac->p + i);
                (res->p + i)->mod = (fac->p + i)->mod;
                res->exp[i] = fac->exp[i];
            }
            for ( ; i < res->num; i++)
            {
                nmod_poly_zero(res->p + i);
                res->exp[i] = 0;
            }
            res->num = fac->num;
        }
    }
}
コード例 #3
0
ファイル: divrem_newton.c プロジェクト: goens/flint2
void nmod_poly_divrem_newton(nmod_poly_t Q, nmod_poly_t R, 
                             const nmod_poly_t A, const nmod_poly_t B)
{
    const long lenA = A->length, lenB = B->length;
    mp_ptr q, r;

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

    if (lenA < lenB)
    {
        nmod_poly_set(R, A);
        nmod_poly_zero(Q);
        return;
    }

    if (Q == A || Q == B)
    {
        q = _nmod_vec_init(lenA - lenB + 1);
    }
    else
    {
        nmod_poly_fit_length(Q, lenA - lenB + 1);
        q = Q->coeffs;
    }
    if (R == A || R == B)
    {
        r = _nmod_vec_init(lenB - 1);
    }
    else
    {
        nmod_poly_fit_length(R, lenB - 1);
        r = R->coeffs;
    }

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

    if (Q == A || Q == B)
    {
        _nmod_vec_clear(Q->coeffs);
        Q->coeffs = q;
        Q->alloc  = lenA - lenB + 1;
    }
    if (R == A || R == B)
    {
        _nmod_vec_clear(R->coeffs);
        R->coeffs = r;
        R->alloc  = lenB - 1;
    }
    Q->length = lenA - lenB + 1;
    R->length = lenB - 1;

    _nmod_poly_normalise(R);
}
コード例 #4
0
void
nmod_poly_taylor_shift_convolution(nmod_poly_t g, const nmod_poly_t f,
    mp_limb_t c)
{
    if (f != g)
        nmod_poly_set(g, f);

    _nmod_poly_taylor_shift_convolution(g->coeffs, c, g->length, g->mod);
}
コード例 #5
0
ファイル: set.c プロジェクト: goens/flint2
void
nmod_poly_mat_set(nmod_poly_mat_t B, const nmod_poly_mat_t A)
{
    if (A != B)
    {
        long i, j;

        for (i = 0; i < A->r; i++)
            for (j = 0; j < A->c; j++)
                nmod_poly_set(nmod_poly_mat_entry(B, i, j),
                              nmod_poly_mat_entry(A, i, j));
    }
}
コード例 #6
0
ファイル: pow.c プロジェクト: clear731/lattice
void
nmod_poly_pow(nmod_poly_t res, const nmod_poly_t poly, ulong e)
{
    const slong len = poly->length;
    slong rlen;

    if ((len < 2) | (e < UWORD(3)))
    {
        if (len == 0)
            nmod_poly_zero(res);
        else if (len == 1)
        {
            nmod_poly_fit_length(res, 1);
            res->coeffs[0] = n_powmod2_ui_preinv(poly->coeffs[0], e,
                poly->mod.n, poly->mod.ninv);
            res->length = 1;
            _nmod_poly_normalise(res);
        }
        else if (e == UWORD(0))
        {
            nmod_poly_set_coeff_ui(res, 0, UWORD(1));
            res->length = 1;
            _nmod_poly_normalise(res);
        }
        else if (e == UWORD(1))
            nmod_poly_set(res, poly);
        else  /* e == UWORD(2) */
            nmod_poly_mul(res, poly, poly);

        return;
    }

    rlen = (slong) e * (len - 1) + 1;

    if (res != poly)
    {
        nmod_poly_fit_length(res, rlen);
        _nmod_poly_pow(res->coeffs, poly->coeffs, len, e, poly->mod);
    }
    else
    {
        nmod_poly_t t;
        nmod_poly_init2(t, poly->mod.n, rlen);
        _nmod_poly_pow(t->coeffs, poly->coeffs, len, e, poly->mod);
        nmod_poly_swap(res, t);
        nmod_poly_clear(t);
    }

    res->length = rlen;
    _nmod_poly_normalise(res);
}
コード例 #7
0
ファイル: rem_basecase.c プロジェクト: goens/flint2
void 
nmod_poly_rem_basecase(nmod_poly_t R, const nmod_poly_t A, const nmod_poly_t B)
{
    const long lenA = A->length, lenB = B->length;
    mp_ptr r, W;
    nmod_poly_t t;

    if (lenB == 0)
    {
        printf("Exception: division by zero in nmod_poly_rem_basecase\n");
        abort();
    }
    if (lenA < lenB)
    {
        nmod_poly_set(R, A);
        return;
    }

    if (R == A || R == B)
    {
        nmod_poly_init2_preinv(t, B->mod.n, B->mod.ninv, lenB - 1);
        r = t->coeffs;
    }
    else
    {
        nmod_poly_fit_length(R, lenB - 1);
        r = R->coeffs;
    }

    W = _nmod_vec_init(NMOD_DIVREM_BC_ITCH(lenA, lenB, A->mod));

    _nmod_poly_rem_basecase(r, W, A->coeffs, lenA,
                                  B->coeffs, lenB, B->mod);

    if (R == A || R == B)
    {
        nmod_poly_swap(R, t);
        nmod_poly_clear(t);
    }
    R->length = lenB - 1;

    _nmod_vec_clear(W);
    _nmod_poly_normalise(R);
}
コード例 #8
0
ファイル: nullspace.c プロジェクト: goens/flint2
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;
}
コード例 #9
0
ファイル: divrem_basecase.c プロジェクト: clear731/lattice
void
nmod_poly_divrem_basecase(nmod_poly_t Q, nmod_poly_t R, const nmod_poly_t A,
                          const nmod_poly_t B)
{
    const slong lenA = A->length, lenB = B->length;
    mp_ptr Q_coeffs, R_coeffs, W;
    nmod_poly_t t1, t2;
    TMP_INIT;

    if (lenB == 0)
    {
        flint_printf("Exception (nmod_poly_divrem). Division by zero.\n");
        abort();
    }

    if (lenA < lenB)
    {
        nmod_poly_set(R, A);
        nmod_poly_zero(Q);
        return;
    }

    if (Q == A || Q == B)
    {
        nmod_poly_init2_preinv(t1, B->mod.n, B->mod.ninv, lenA - lenB + 1);
        Q_coeffs = t1->coeffs;
    }
    else
    {
        nmod_poly_fit_length(Q, lenA - lenB + 1);
        Q_coeffs = Q->coeffs;
    }

    if (R == A || R == B)
    {
        nmod_poly_init2_preinv(t2, B->mod.n, B->mod.ninv, lenB - 1);
        R_coeffs = t2->coeffs;
    }
    else
    {
        nmod_poly_fit_length(R, lenB - 1);
        R_coeffs = R->coeffs;
    }

    TMP_START;
    W = TMP_ALLOC(NMOD_DIVREM_BC_ITCH(lenA, lenB, A->mod)*sizeof(mp_limb_t));
    
    _nmod_poly_divrem_basecase(Q_coeffs, R_coeffs, W, A->coeffs, lenA,
                               B->coeffs, lenB, B->mod);

    if (Q == A || Q == B)
    {
        nmod_poly_swap(Q, t1);
        nmod_poly_clear(t1);
    }
    if (R == A || R == B)
    {
        nmod_poly_swap(R, t2);
        nmod_poly_clear(t2);
    }
    Q->length = lenA - lenB + 1;
    R->length = lenB - 1;

    TMP_END;
    _nmod_poly_normalise(R);
}
コード例 #10
0
ファイル: t-shift_left_right.c プロジェクト: goens/flint2
int
main(void)
{
    int i, result;
    flint_rand_t state;
    flint_randinit(state);

    printf("shift_left_right....");
    fflush(stdout);

    /* Check a << shift >> shift == a */
    for (i = 0; i < 10000; i++)
    {
        nmod_poly_t a, b;
        mp_limb_t n = n_randtest_not_zero(state);
        long shift = n_randint(state, 100);
  
        nmod_poly_init(a, n);
        nmod_poly_init(b, n);
        nmod_poly_randtest(a, state, n_randint(state, 100));
        
        nmod_poly_shift_left(b, a, shift);
        nmod_poly_shift_right(b, b, shift);
        
        result = (nmod_poly_equal(a, b));
        if (!result)
        {
            printf("FAIL:\n");
            printf("shift = %ld, a->length = %ld, n = %lu\n", 
                shift, a->length, a->mod.n);
            nmod_poly_print(a), printf("\n\n");
            nmod_poly_print(b), printf("\n\n");
            abort();
        }

        nmod_poly_clear(a);
        nmod_poly_clear(b);
    }
    
    /* Check a << shift >> shift == a aliasing the other way */
    for (i = 0; i < 10000; i++)
    {
        nmod_poly_t a, b, c;
        mp_limb_t n = n_randtest_not_zero(state);
        long shift = n_randint(state, 100);

        nmod_poly_init(a, n);
        nmod_poly_init(b, n);
        nmod_poly_init(c, n);
        nmod_poly_randtest(c, state, n_randint(state, 100));
        
        nmod_poly_set(a, c);
        nmod_poly_shift_left(c, c, shift);
        nmod_poly_shift_right(b, c, shift);

        result = (nmod_poly_equal(a, b));
        if (!result)
        {
            printf("FAIL:\n");
            printf("shift = %ld, c->length = %ld, n = %lu\n", 
                shift, c->length, a->mod.n);
            nmod_poly_print(a), printf("\n\n");
            nmod_poly_print(b), printf("\n\n");
            abort();
        }

        nmod_poly_clear(a);
        nmod_poly_clear(b);
        nmod_poly_clear(c);
    }

    flint_randclear(state);

    printf("PASS\n");
    return 0;
}
コード例 #11
0
ファイル: factor_squarefree.c プロジェクト: clear731/lattice
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);
}
コード例 #12
0
ファイル: compose_mod_horner.c プロジェクト: goens/flint2
void
nmod_poly_compose_mod_horner(nmod_poly_t res, 
                    const nmod_poly_t poly1, const nmod_poly_t poly2,
                    const nmod_poly_t poly3)
{
    long len1 = poly1->length;
    long len2 = poly2->length;
    long len3 = poly3->length;
    long len = len3 - 1;

    mp_ptr ptr2;

    if (len3 == 0)
    {
        printf("exception: division by zero in nmod_poly_compose_mod_horner\n");
        abort();
    }

    if (len1 == 0 || len3 == 1)
    {
        nmod_poly_zero(res);
        return;
    }

    if (len1 == 1)
    {
        nmod_poly_set(res, poly1);
        return;
    }

    if (res == poly3 || res == poly1)
    {
        nmod_poly_t tmp;
        nmod_poly_init_preinv(tmp, res->mod.n, res->mod.ninv);
        nmod_poly_compose_mod_horner(tmp, poly1, poly2, poly3);
        nmod_poly_swap(tmp, res);
        nmod_poly_clear(tmp);
        return;
    }

    ptr2 = _nmod_vec_init(len);

    if (len2 <= len)
    {
        mpn_copyi(ptr2, poly2->coeffs, len2);
        mpn_zero(ptr2 + len2, len - len2);
    }
    else
    {
        _nmod_poly_rem(ptr2, poly2->coeffs, len2,
                             poly3->coeffs, len3, res->mod);
    }

    nmod_poly_fit_length(res, len);
    _nmod_poly_compose_mod_horner(res->coeffs,
        poly1->coeffs, len1, ptr2, poly3->coeffs, len3, res->mod);
    res->length = len;
    _nmod_poly_normalise(res);

    _nmod_vec_clear(ptr2);
}
コード例 #13
0
ファイル: elements.c プロジェクト: defeo/ff_compositum
void pq_nmod_elt_set_mono(pq_nmod_elt_t x, const nmod_poly_t val) {
  nmod_poly_set(x->mono, val);
  nmod_poly_zero(x->dual);
}
コード例 #14
0
ファイル: elements.c プロジェクト: defeo/ff_compositum
void _pq_nmod_elt_set_dual(pq_nmod_elt_t x, const nmod_poly_t val) {
  nmod_poly_zero(x->mono);
  nmod_poly_set(x->dual, val);
}
コード例 #15
0
ファイル: elements.c プロジェクト: defeo/ff_compositum
void pq_nmod_elt_set(pq_nmod_elt_t x, const pq_nmod_elt_t y) {
  nmod_poly_set(x->mono, y->mono);
  nmod_poly_set(x->dual, y->dual);
}
コード例 #16
0
ファイル: rref.c プロジェクト: clear731/lattice
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;
}
コード例 #17
0
ファイル: inv.c プロジェクト: clear731/lattice
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;
    }
}
コード例 #18
0
ファイル: compose_mod_brent_kung.c プロジェクト: goens/flint2
void
nmod_poly_compose_mod_brent_kung(nmod_poly_t res, 
                    const nmod_poly_t poly1, const nmod_poly_t poly2,
                    const nmod_poly_t poly3)
{
    long len1 = poly1->length;
    long len2 = poly2->length;
    long len3 = poly3->length;
    long len = len3 - 1;

    mp_ptr ptr2;

    if (len3 == 0)
    {
        printf("exception: division by zero in "
                "nmod_poly_compose_mod_brent_kung\n");
        abort();
    }

    if (len1 >= len3)
    {
        printf("exception: nmod_poly_compose_brent_kung: the degree of the"
                " first polynomial must be smaller than that of the modulus\n");
        abort();
    }

    if (len1 == 0 || len3 == 1)
    {
        nmod_poly_zero(res);
        return;
    }

    if (len1 == 1)
    {
        nmod_poly_set(res, poly1);
        return;
    }

    if (res == poly3 || res == poly1)
    {
        nmod_poly_t tmp;
        nmod_poly_init_preinv(tmp, res->mod.n, res->mod.ninv);
        nmod_poly_compose_mod_brent_kung(tmp, poly1, poly2, poly3);
        nmod_poly_swap(tmp, res);
        nmod_poly_clear(tmp);
        return;
    }

    ptr2 = _nmod_vec_init(len);

    if (len2 <= len)
    {
        mpn_copyi(ptr2, poly2->coeffs, len2);
        mpn_zero(ptr2 + len2, len - len2);
    }
    else
    {
        _nmod_poly_rem(ptr2, poly2->coeffs, len2,
                             poly3->coeffs, len3, res->mod);
    }

    nmod_poly_fit_length(res, len);
    _nmod_poly_compose_mod_brent_kung(res->coeffs,
        poly1->coeffs, len1, ptr2, poly3->coeffs, len3, res->mod);
    res->length = len;
    _nmod_poly_normalise(res);

    _nmod_vec_clear(ptr2);
}