1 /*
2     Copyright (C) 2012 Sebastian Pancratz
3 
4     This file is part of FLINT.
5 
6     FLINT is free software: you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License (LGPL) as published
8     by the Free Software Foundation; either version 2.1 of the License, or
9     (at your option) any later version.  See <https://www.gnu.org/licenses/>.
10 */
11 
12 #include "qadic.h"
13 
14 /*
15     Forms the product of (op1,len1) and (op2,len2) modulo (a,j,lena) and pN.
16     Assumes that len1 >= len2 > 0.  Requires rop to be of size at least
17     len1 + len2 - 1.
18  */
19 
20 static
_qadic_mul(fmpz * rop,const fmpz * op1,slong len1,const fmpz * op2,slong len2,const fmpz * a,const slong * j,slong lena,const fmpz_t pN)21 void _qadic_mul(fmpz *rop,
22                 const fmpz *op1, slong len1, const fmpz *op2, slong len2,
23                 const fmpz *a, const slong *j, slong lena, const fmpz_t pN)
24 {
25     _fmpz_poly_mul(rop, op1, len1, op2, len2);
26     _fmpz_mod_poly_reduce(rop, len1 + len2 - 1, a, j, lena, pN);
27 }
28 
qadic_mul(qadic_t x,const qadic_t y,const qadic_t z,const qadic_ctx_t ctx)29 void qadic_mul(qadic_t x, const qadic_t y, const qadic_t z,
30                           const qadic_ctx_t ctx)
31 {
32     const slong leny = y->length;
33     const slong lenz = z->length;
34     const slong lenx = leny + lenz - 1;
35     const slong N    = qadic_prec(x);
36     const slong d    = qadic_ctx_degree(ctx);
37 
38     if (leny == 0 || lenz == 0 || y->val + z->val >= N)
39     {
40         qadic_zero(x);
41     }
42     else
43     {
44         fmpz *t;
45         fmpz_t pN;
46         int alloc;
47 
48         x->val = y->val + z->val;
49 
50         alloc = _padic_ctx_pow_ui(pN, N - x->val, &ctx->pctx);
51 
52         if (x == y || x == z)
53         {
54             t = _fmpz_vec_init(lenx);
55         }
56         else
57         {
58             padic_poly_fit_length(x, lenx);
59             t = x->coeffs;
60         }
61 
62         if (leny >= lenz)
63             _qadic_mul(t, y->coeffs, leny,
64                           z->coeffs, lenz, ctx->a, ctx->j, ctx->len, pN);
65         else
66             _qadic_mul(t, z->coeffs, lenz,
67                           y->coeffs, leny, ctx->a, ctx->j, ctx->len, pN);
68 
69         if (x == y || x == z)
70         {
71             _fmpz_vec_clear(x->coeffs, x->alloc);
72             x->coeffs = t;
73             x->alloc  = lenx;
74         }
75 
76         _padic_poly_set_length(x, FLINT_MIN(lenx, d));
77         _padic_poly_normalise(x);
78 
79         if (alloc)
80             fmpz_clear(pN);
81     }
82 }
83 
84