Esempio n. 1
0
void
nmod_poly_div_divconquer(nmod_poly_t Q,
                            const nmod_poly_t A, const nmod_poly_t B)
{
    nmod_poly_t tQ;
    mp_ptr q;
    long Alen, Blen;

    Blen = B->length;

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

    Alen = A->length;

    if (Alen < Blen)
    {
        nmod_poly_zero(Q);
        return;
    }

    if (Q == A || Q == B)
    {
        nmod_poly_init2(tQ, A->mod.n, Alen - Blen + 1);
        q = tQ->coeffs;
    }
    else
    {
        nmod_poly_fit_length(Q, Alen - Blen + 1);
        q = Q->coeffs;
    }

    _nmod_poly_div_divconquer(q, A->coeffs, Alen,
                                       B->coeffs, Blen, A->mod);

    if (Q == A || Q == B)
    {
        nmod_poly_swap(tQ, Q);
        nmod_poly_clear(tQ);
    }
    
    Q->length = Alen - Blen + 1;
}
Esempio n. 2
0
void
_nmod_poly_inv_series_basecase(mp_ptr Qinv,
                               mp_srcptr Q, long n, nmod_t mod)
{
    mp_ptr X2n, Qrev;

    X2n = _nmod_vec_init(2*n);
    Qrev = X2n + n;

    _nmod_poly_reverse(Qrev, Q, n, n);

    X2n[n - 1] = 1;
    mpn_zero(X2n, n - 1);
    X2n -= (n - 1);

    _nmod_poly_div_divconquer(Qinv, X2n, 2*n - 1, Qrev, n, mod);

    _nmod_poly_reverse(Qinv, Qinv, n, n);

    _nmod_vec_free(X2n + n - 1);
}
Esempio n. 3
0
void
_nmod_poly_div_divconquer(mp_ptr Q, mp_srcptr A, long lenA, 
                             mp_srcptr B, long lenB, nmod_t mod)
{
    if (lenA < 2 * lenB - 1)
    {
        /*
           Convert unbalanced division into a 2 n1 - 1 by n1 division
         */

        const long n1 = lenA - lenB + 1;
        const long n2 = lenB - n1;

        mp_srcptr p1 = A + n2;
        mp_srcptr d1 = B + n2;
        
        mp_ptr V = _nmod_vec_init(n1 - 1 + NMOD_DIVREM_DC_ITCH(n1, mod));
        mp_ptr W = V + NMOD_DIVREM_DC_ITCH(n1, mod);

        _nmod_poly_div_divconquer_recursive(Q, W, V, p1, d1, n1, mod);

        _nmod_vec_clear(V);
    }
    else if (lenA > 2 * lenB - 1)
    {
        /*
           We shift A right until it is of length 2 lenB - 1, call this p1
         */

        const long shift = lenA - 2 * lenB + 1;
        mp_srcptr p1 = A + shift;

        mp_ptr V = _nmod_vec_init(lenA + (3 * lenB - 2) + NMOD_DIVREM_DC_ITCH(lenB, mod));
        mp_ptr R = V + NMOD_DIVREM_DC_ITCH(lenB, mod);
        mp_ptr W = R + lenB - 1;

        mp_ptr q1   = Q + shift;
        mp_ptr q2   = Q;
        mp_ptr dq1  = W;
        mp_ptr d1q1 = dq1 + shift;

        /* 
           Set q1 to p1 div B, a 2 lenB - 1 by lenB division, so q1 ends up 
           being of length lenB; set d1q1 = d1 * q1 of length 2 lenB - 1
         */

        _nmod_poly_divrem_divconquer_recursive(q1, d1q1, R, V, p1, B, lenB, mod);

        /* 
           We have dq1 = d1 * q1 * x^shift, of length lenA

           Compute R = A - dq1; the first lenB coeffs represent remainder 
           terms (zero if division is exact), leaving lenA - lenB significant 
           terms which we use in the division
         */

        mpn_copyi(dq1, A, shift);
        _nmod_vec_sub(dq1 + shift, A + shift, dq1 + shift, lenB - 1, mod);
        
        /*
           Compute q2 = trunc(R) div B; it is a smaller division than the 
           original since len(trunc(R)) = lenA - lenB
         */

        _nmod_poly_div_divconquer(q2, dq1, lenA - lenB, B, lenB, mod);

        /*
           We have Q = q1 * x^shift + q2; Q has length lenB + shift; 
           note q2 has length shift since the above division is 
           lenA - lenB by lenB
         */

        _nmod_vec_clear(V);
    }
    else  /* lenA = 2 * lenB - 1 */
    {
        mp_ptr V = _nmod_vec_init(lenB - 1 + NMOD_DIVREM_DC_ITCH(lenB, mod));
        mp_ptr W = V + NMOD_DIVREM_DC_ITCH(lenB, mod);
 
        _nmod_poly_div_divconquer_recursive(Q, W, V, A, B, lenB, mod);
        
        _nmod_vec_clear(V);
    }
}