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 <http://www.gnu.org/licenses/>.
10 */
11 
12 #include "fmpz_mod_poly.h"
13 #include "qadic.h"
14 
_qadic_exp(fmpz * rop,const fmpz * op,slong v,slong len,const fmpz * a,const slong * j,slong lena,const fmpz_t p,slong N,const fmpz_t pN)15 void _qadic_exp(fmpz *rop, const fmpz *op, slong v, slong len,
16                            const fmpz *a, const slong *j, slong lena,
17                            const fmpz_t p, slong N, const fmpz_t pN)
18 {
19     if (N < (WORD(1) << 13) / (slong) fmpz_bits(p))
20     {
21         _qadic_exp_rectangular(rop, op, v, len, a, j, lena, p, N, pN);
22     }
23     else
24     {
25         const slong d = j[lena - 1];
26 
27         _qadic_exp_balanced(rop, op, v, len, a, j, lena, p, N, pN);
28         _fmpz_vec_zero(rop + d, d - 1);
29     }
30 }
31 
qadic_exp(qadic_t rop,const qadic_t op,const qadic_ctx_t ctx)32 int qadic_exp(qadic_t rop, const qadic_t op, const qadic_ctx_t ctx)
33 {
34     const slong N  = qadic_prec(rop);
35     const slong v  = op->val;
36     const fmpz *p = (&ctx->pctx)->p;
37 
38     if (padic_poly_is_zero(op))
39     {
40         padic_poly_one(rop);
41         return 1;
42     }
43 
44     if ((*p == WORD(2) && v <= 1) || (v <= 0))
45     {
46         return 0;
47     }
48     else
49     {
50         if (v < N)
51         {
52             const slong d = qadic_ctx_degree(ctx);
53 
54             fmpz *t;
55             fmpz_t pN;
56             int alloc;
57 
58             alloc = _padic_ctx_pow_ui(pN, N, &ctx->pctx);
59 
60             if (rop == op)
61             {
62                 t = _fmpz_vec_init(2 * d - 1);
63             }
64             else
65             {
66                 padic_poly_fit_length(rop, 2 * d - 1);
67                 t = rop->coeffs;
68             }
69 
70             _qadic_exp(t, op->coeffs, v, op->length,
71                        ctx->a, ctx->j, ctx->len, p, N, pN);
72             rop->val = 0;
73 
74             if (rop == op)
75             {
76                 _fmpz_vec_clear(rop->coeffs, rop->alloc);
77                 rop->coeffs = t;
78                 rop->alloc  = 2 * d - 1;
79                 rop->length = d;
80             }
81             _padic_poly_set_length(rop, d);
82             _padic_poly_normalise(rop);
83 
84             if (alloc)
85                 fmpz_clear(pN);
86         }
87         else
88         {
89             padic_poly_one(rop);
90         }
91         return 1;
92     }
93 }
94 
95