void
_nmod_poly_product_roots_nmod_vec(mp_ptr poly, mp_srcptr xs, slong n, nmod_t mod)
{
    if (n == 0)
    {
        poly[0] = UWORD(1);
    }
    else if (n < 20)
    {
        slong i, j;

        poly[n] = UWORD(1);
        poly[n - 1] = nmod_neg(xs[0], mod);

        for (i = 1; i < n; i++)
        {
            poly[n-i-1] = nmod_neg(n_mulmod2_preinv(poly[n-i], xs[i],
                mod.n, mod.ninv), mod);

            for (j = 0; j < i - 1; j++)
            {
                poly[n-i+j] = nmod_sub(poly[n-i+j],
                    n_mulmod2_preinv(poly[n-i+j+1], xs[i], mod.n, mod.ninv),
                        mod);
            }

            poly[n-1] = nmod_sub(poly[n-1], xs[i], mod);
        }
    }
    else
    {
        const slong m = (n + 1) / 2;
        mp_ptr tmp;

        tmp = _nmod_vec_init(n + 2);

        _nmod_poly_product_roots_nmod_vec(tmp, xs, m, mod);
        _nmod_poly_product_roots_nmod_vec(tmp + m + 1, xs + m, n - m, mod);
        _nmod_poly_mul(poly, tmp, m + 1, tmp + m + 1, n - m + 1, mod);

        _nmod_vec_clear(tmp);
    }
}
Exemple #2
0
void
nmod_mat_solve_tril_classical(nmod_mat_t X, const nmod_mat_t L,
                                                const nmod_mat_t B, int unit)
{
    int nlimbs;
    long i, j, n, m;
    nmod_t mod;
    mp_ptr inv, tmp;

    n = L->r;
    m = B->c;
    mod = L->mod;

    if (!unit)
    {
        inv = _nmod_vec_init(n);
        for (i = 0; i < n; i++)
            inv[i] = n_invmod(nmod_mat_entry(L, i, i), mod.n);
    }
    else
        inv = NULL;

    nlimbs = _nmod_vec_dot_bound_limbs(n, mod);
    tmp = _nmod_vec_init(n);

    for (i = 0; i < m; i++)
    {
        for (j = 0; j < n; j++)
            tmp[j] = nmod_mat_entry(X, j, i);

        for (j = 0; j < n; j++)
        {
            mp_limb_t s;
            s = _nmod_vec_dot(L->rows[j], tmp, j, mod, nlimbs);
            s = nmod_sub(nmod_mat_entry(B, j, i), s, mod);
            if (!unit)
                s = n_mulmod2_preinv(s, inv[j], mod.n, mod.ninv);
            tmp[j] = s;
        }

        for (j = 0; j < n; j++)
            nmod_mat_entry(X, j, i) = tmp[j];
    }

    _nmod_vec_clear(tmp);
    if (!unit)
        _nmod_vec_clear(inv);
}
void
_nmod_poly_interpolate_nmod_vec_barycentric(mp_ptr poly,
                            mp_srcptr xs, mp_srcptr ys, slong n, nmod_t mod)
{
    mp_ptr P, Q, w;
    slong i, j;

    if (n == 1)
    {
        poly[0] = ys[0];
        return;
    }

    P = _nmod_vec_init(n + 1);
    Q = _nmod_vec_init(n);
    w = _nmod_vec_init(n);

    _nmod_poly_product_roots_nmod_vec(P, xs, n, mod);

    for (i = 0; i < n; i++)
    {
        w[i] = UWORD(1);
        for (j = 0; j < n; j++)
        {
            if (i != j)
                w[i] = nmod_mul(w[i], nmod_sub(xs[i], xs[j], mod), mod);
        }
        w[i] = n_invmod(w[i], mod.n);
    }

    _nmod_vec_zero(poly, n);

    for (i = 0; i < n; i++)
    {
        _nmod_poly_div_root(Q, P, n + 1, xs[i], mod);
        _nmod_vec_scalar_addmul_nmod(poly, Q, n,
            nmod_mul(w[i], ys[i], mod), mod);
    }

    _nmod_vec_clear(P);
    _nmod_vec_clear(Q);
    _nmod_vec_clear(w);
}