#include "fmpz_vec.h"
#include "fmpz_poly.h"
#include "fq.h"
#include "fq_poly.h"
void
_fq_poly_mullow_univariate (fq_struct * rop,
const fq_struct * op1, slong len1,
const fq_struct * op2, slong len2,
slong n, const fq_ctx_t ctx)
{
const slong fqlen = ctx->modulus->length - 1;
const slong pfqlen = 2*fqlen - 1;
const slong rlen = len1 + len2 - 1;
const slong m = FLINT_MIN(n, rlen);
const slong cmlen = pfqlen*m;
const slong clen1 = pfqlen*len1;
const slong clen2 = pfqlen*len2;
slong i;
slong len;
fmpz *cop1, *cop2, *crop;
if (!len1 || !len2)
{
_fq_poly_zero(rop, n, ctx);
return;
}
cop1 = _fmpz_vec_init(clen1);
for (i = 0; i < len1; i++)
{
_fmpz_vec_set(cop1 + pfqlen*i, (op1 + i)->coeffs, (op1 + i)->length);
_fmpz_vec_zero(cop1 + pfqlen*i + (op1 + i)->length, pfqlen - (op1 + i)->length);
}
if (op2 != op1)
{
cop2 = _fmpz_vec_init(clen2);
for (i = 0; i < len2; i++)
{
_fmpz_vec_set(cop2 + pfqlen*i, (op2 + i)->coeffs,(op2 + i)->length);
_fmpz_vec_zero(cop2 + pfqlen*i + (op2 + i)->length, pfqlen - (op2 + i)->length);
}
}
else
{
cop2 = cop1;
}
crop = _fmpz_vec_init(cmlen);
if (clen1 >= clen2)
_fmpz_poly_mullow(crop, cop1, clen1, cop2, clen2, cmlen);
else
_fmpz_poly_mullow(crop, cop2, clen2, cop1, clen1, cmlen);
for (i = 0; i < m; i++)
{
_fq_reduce(crop + pfqlen*i, pfqlen, ctx);
len = fqlen;
while (len && !(*(crop + pfqlen*i + len - 1))) len--;
fmpz_poly_fit_length(rop + i, len);
(rop + i)->length = len;
_fmpz_vec_set((rop + i)->coeffs, crop + pfqlen*i, len);
}
for (; i < n; i++)
{
(rop + i)->length = 0;
}
_fmpz_vec_clear(cop1, clen1);
if (op2 != op1)
{
_fmpz_vec_clear(cop2, clen2);
}
_fmpz_vec_clear(crop, cmlen);
}
void
fq_poly_mullow_univariate (fq_poly_t rop,
const fq_poly_t op1,
const fq_poly_t op2,
slong n, const fq_ctx_t ctx)
{
const slong len1 = op1->length;
const slong len2 = op2->length;
const slong rlen = op1->length + op2->length - 1;
const slong m = FLINT_MIN(n, rlen);
if (len1 == 0 || len2 == 0 || n == 0)
{
fq_poly_zero(rop, ctx);
return;
}
else
{
fq_poly_fit_length(rop, m, ctx);
_fq_poly_mullow_univariate(rop->coeffs, op1->coeffs, len1,
op2->coeffs, len2, m, ctx);
_fq_poly_set_length(rop, m, ctx);
_fq_poly_normalise(rop, ctx);
}
}