1 /*
2     Copyright (C) 2020 Daniel Schultz
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 "n_poly.h"
13 
14 
n_fq_bpoly_is_canonical(const n_fq_bpoly_t A,const fq_nmod_ctx_t ctx)15 int n_fq_bpoly_is_canonical(const n_fq_bpoly_t A, const fq_nmod_ctx_t ctx)
16 {
17     slong i;
18 
19     if (A->length < 0)
20         return 0;
21 
22     if (A->length > A->alloc)
23         return 0;
24 
25     for (i = 0; i < A->length; i++)
26     {
27         if (!n_fq_poly_is_canonical(A->coeffs + i, ctx))
28             return 0;
29         if (i + 1 == A->length && n_fq_poly_is_zero(A->coeffs + i))
30             return 0;
31     }
32 
33     return 1;
34 }
35 
36 
n_fq_bpoly_print_pretty(const n_fq_bpoly_t A,const char * xvar,const char * yvar,const fq_nmod_ctx_t ctx)37 void n_fq_bpoly_print_pretty(
38     const n_fq_bpoly_t A,
39     const char * xvar,
40     const char * yvar,
41     const fq_nmod_ctx_t ctx)
42 {
43     slong i;
44     int first;
45 
46     first = 1;
47     for (i = A->length - 1; i >= 0; i--)
48     {
49         if (i + 1 != A->length && n_fq_poly_is_zero(A->coeffs + i))
50             continue;
51 
52         if (!first)
53             flint_printf(" + ");
54 
55         first = 0;
56 
57         flint_printf("(");
58         n_fq_poly_print_pretty(A->coeffs + i, yvar, ctx);
59         flint_printf(")*%s^%wd", xvar, i);
60     }
61 
62     if (first)
63         flint_printf("0");
64 }
65 
66 
n_fq_bpoly_one(n_fq_bpoly_t A,const fq_nmod_ctx_t ctx)67 void n_fq_bpoly_one(n_fq_bpoly_t A, const fq_nmod_ctx_t ctx)
68 {
69     n_fq_bpoly_fit_length(A, 1);
70     A->length = 1;
71     n_fq_poly_one(A->coeffs + 0, ctx);
72 }
73 
n_fq_bpoly_set(n_fq_bpoly_t A,const n_fq_bpoly_t B,const fq_nmod_ctx_t ctx)74 void n_fq_bpoly_set(
75     n_fq_bpoly_t A,
76     const n_fq_bpoly_t B,
77     const fq_nmod_ctx_t ctx)
78 {
79     slong i;
80 
81     if (A == B)
82         return;
83 
84     n_fq_bpoly_fit_length(A, B->length);
85     A->length = B->length;
86     for (i = 0; i < B->length; i++)
87         n_fq_poly_set(A->coeffs + i, B->coeffs + i, ctx);
88 }
89 
n_fq_bpoly_equal(const n_bpoly_t A,const n_bpoly_t B,const fq_nmod_ctx_t ctx)90 int n_fq_bpoly_equal(
91     const n_bpoly_t A,
92     const n_bpoly_t B,
93     const fq_nmod_ctx_t ctx)
94 {
95     slong i;
96 
97     if (A->length != B->length)
98         return 0;
99 
100     for (i = 0; i < A->length; i++)
101     {
102         if (!n_fq_poly_equal(A->coeffs + i, B->coeffs + i, ctx))
103             return 0;
104     }
105 
106     return 1;
107 }
108 
109 
n_fq_bpoly_get_coeff_n_fq(mp_limb_t * c,const n_bpoly_t A,slong e0,slong e1,const fq_nmod_ctx_t ctx)110 void n_fq_bpoly_get_coeff_n_fq(
111     mp_limb_t * c,
112     const n_bpoly_t A,
113     slong e0,
114     slong e1,
115     const fq_nmod_ctx_t ctx)
116 {
117     if (e0 >= A->length)
118         _n_fq_zero(c, fq_nmod_ctx_degree(ctx));
119     else
120         n_fq_poly_get_coeff_n_fq(c, A->coeffs + e0, e1, ctx);
121 }
122 
n_fq_bpoly_set_coeff_n_fq(n_bpoly_t A,slong e0,slong e1,const mp_limb_t * c,const fq_nmod_ctx_t ctx)123 void n_fq_bpoly_set_coeff_n_fq(
124     n_bpoly_t A,
125     slong e0,
126     slong e1,
127     const mp_limb_t * c,
128     const fq_nmod_ctx_t ctx)
129 {
130     slong i;
131 
132     if (e0 >= A->length)
133     {
134         n_fq_bpoly_fit_length(A, e0 + 1);
135         for (i = A->length; i <= e0; i++)
136             n_fq_poly_zero(A->coeffs + i);
137         A->length = e0 + 1;
138     }
139 
140     n_fq_poly_set_coeff_n_fq(A->coeffs + e0, e1, c, ctx);
141 
142     n_fq_bpoly_normalise(A);
143 
144     FLINT_ASSERT(n_fq_bpoly_is_canonical(A, ctx));
145 }
146 
147 
n_fq_bpoly_get_coeff_fq_nmod(fq_nmod_t c,const n_bpoly_t A,slong e0,slong e1,const fq_nmod_ctx_t ctx)148 void n_fq_bpoly_get_coeff_fq_nmod(
149     fq_nmod_t c,
150     const n_bpoly_t A,
151     slong e0,
152     slong e1,
153     const fq_nmod_ctx_t ctx)
154 {
155     if (e0 >= A->length)
156         fq_nmod_zero(c, ctx);
157     else
158         n_fq_poly_get_coeff_fq_nmod(c, A->coeffs + e0, e1, ctx);
159 }
160 
161 
n_fq_bpoly_set_fq_nmod_poly_gen0(n_fq_bpoly_t A,const fq_nmod_poly_t B,const fq_nmod_ctx_t ctx)162 void n_fq_bpoly_set_fq_nmod_poly_gen0(
163     n_fq_bpoly_t A,
164     const fq_nmod_poly_t B,
165     const fq_nmod_ctx_t ctx)
166 {
167     slong i;
168     n_bpoly_fit_length(A, B->length);
169     A->length = 0;
170     for (i = 0; i < B->length; i++)
171         n_fq_poly_set_fq_nmod(A->coeffs + i, B->coeffs + i, ctx);
172     A->length = B->length;
173     n_bpoly_normalise(A);
174 }
175 
n_fq_bpoly_set_n_fq_poly_gen0(n_fq_bpoly_t A,const n_fq_poly_t B,const fq_nmod_ctx_t ctx)176 void n_fq_bpoly_set_n_fq_poly_gen0(
177     n_fq_bpoly_t A,
178     const n_fq_poly_t B,
179     const fq_nmod_ctx_t ctx)
180 {
181     slong d = fq_nmod_ctx_degree(ctx);
182     slong i;
183     n_bpoly_fit_length(A, B->length);
184     for (i = 0; i < B->length; i++)
185         n_fq_poly_set_n_fq(A->coeffs + i, B->coeffs + d*i, ctx);
186     A->length = B->length;
187     n_bpoly_normalise(A);
188 }
189 
n_fq_bpoly_set_n_fq_poly_gen1(n_fq_bpoly_t A,const n_fq_poly_t B,const fq_nmod_ctx_t ctx)190 void n_fq_bpoly_set_n_fq_poly_gen1(
191     n_fq_bpoly_t A,
192     const n_fq_poly_t B,
193     const fq_nmod_ctx_t ctx)
194 {
195     n_bpoly_fit_length(A, 1);
196 	n_fq_poly_set(A->coeffs + 0, B, ctx);
197 	A->length = !n_poly_is_zero(A->coeffs + 0);
198 }
199 
200 
n_fq_bpoly_derivative_gen0(n_bpoly_t A,const n_bpoly_t B,const fq_nmod_ctx_t ctx)201 void n_fq_bpoly_derivative_gen0(
202     n_bpoly_t A,
203     const n_bpoly_t B,
204     const fq_nmod_ctx_t ctx)
205 {
206     slong i;
207     slong Blen = B->length;
208 
209     if (Blen < 2)
210     {
211         n_bpoly_zero(A);
212         return;
213     }
214 
215     n_bpoly_fit_length(A, Blen - 1);
216 
217     for (i = 1; i < Blen; i++)
218         n_fq_poly_scalar_mul_ui(A->coeffs + i - 1, B->coeffs + i, i, ctx);
219 
220     A->length = Blen - 1;
221     n_bpoly_normalise(A);
222 }
223 
224 
n_fq_bpoly_scalar_mul_n_fq(n_fq_bpoly_t A,const mp_limb_t * c,const fq_nmod_ctx_t ctx)225 void n_fq_bpoly_scalar_mul_n_fq(
226     n_fq_bpoly_t A,
227     const mp_limb_t * c,
228     const fq_nmod_ctx_t ctx)
229 {
230     slong d = fq_nmod_ctx_degree(ctx);
231     slong i;
232 
233     if (_n_fq_is_zero(c, d))
234     {
235         A->length = 0;
236         return;
237     }
238 
239     if (_n_fq_is_one(c, d))
240     {
241         return;
242     }
243 
244     for (i = 0; i < A->length; i++)
245         n_fq_poly_scalar_mul_n_fq(A->coeffs + i, A->coeffs + i, c, ctx);
246 }
247