1 /*
2 Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.
10 */
11
12 #include "nmod_mpoly.h"
13 #include "fq_nmod_mpoly.h"
14
15
fq_nmod_mpolyun_init(fq_nmod_mpolyun_t A,flint_bitcnt_t bits,const fq_nmod_mpoly_ctx_t ctx)16 void fq_nmod_mpolyun_init(
17 fq_nmod_mpolyun_t A,
18 flint_bitcnt_t bits,
19 const fq_nmod_mpoly_ctx_t ctx)
20 {
21 A->coeffs = NULL;
22 A->exps = NULL;
23 A->alloc = 0;
24 A->length = 0;
25 A->bits = bits;
26 }
27
28
fq_nmod_mpolyun_clear(fq_nmod_mpolyun_t A,const fq_nmod_mpoly_ctx_t ctx)29 void fq_nmod_mpolyun_clear(
30 fq_nmod_mpolyun_t A,
31 const fq_nmod_mpoly_ctx_t ctx)
32 {
33 slong i;
34 for (i = 0; i < A->alloc; i++)
35 fq_nmod_mpolyn_clear(A->coeffs + i, ctx);
36 flint_free(A->coeffs);
37 flint_free(A->exps);
38 }
39
40
fq_nmod_mpolyun_is_canonical(const fq_nmod_mpolyun_t A,const fq_nmod_mpoly_ctx_t ctx)41 int fq_nmod_mpolyun_is_canonical(
42 const fq_nmod_mpolyun_t A,
43 const fq_nmod_mpoly_ctx_t ctx)
44 {
45 slong i;
46
47 if (A->length > A->alloc)
48 {
49 return 0;
50 }
51
52 for (i = 0; i < A->length; i++)
53 {
54 if (!fq_nmod_mpolyn_is_canonical(A->coeffs + i, ctx))
55 {
56 return 0;
57 }
58
59 if (i > 0 && A->exps[i - 1] <= A->exps[i])
60 {
61 return 0;
62 }
63 }
64
65 return 1;
66 }
67
68
fq_nmod_mpolyun_print_pretty(const fq_nmod_mpolyun_t poly,const char ** x,const fq_nmod_mpoly_ctx_t ctx)69 void fq_nmod_mpolyun_print_pretty(
70 const fq_nmod_mpolyun_t poly,
71 const char ** x,
72 const fq_nmod_mpoly_ctx_t ctx)
73 {
74 slong i;
75 if (poly->length == 0)
76 flint_printf("0");
77 for (i = 0; i < poly->length; i++)
78 {
79 if (i != 0)
80 flint_printf(" + ");
81 flint_printf("(");
82 fq_nmod_mpolyn_print_pretty(poly->coeffs + i,x,ctx);
83 flint_printf(")*X^%wd",poly->exps[i]);
84 }
85 }
86
87
fq_nmod_mpolyun_swap(fq_nmod_mpolyun_t A,fq_nmod_mpolyun_t B)88 void fq_nmod_mpolyun_swap(
89 fq_nmod_mpolyun_t A,
90 fq_nmod_mpolyun_t B)
91 {
92 fq_nmod_mpolyun_struct t = *A;
93 *A = *B;
94 *B = t;
95 }
96
97
fq_nmod_mpolyun_zero(fq_nmod_mpolyun_t A,const fq_nmod_mpoly_ctx_t ctx)98 void fq_nmod_mpolyun_zero(
99 fq_nmod_mpolyun_t A,
100 const fq_nmod_mpoly_ctx_t ctx)
101 {
102 slong i;
103 for (i = 0; i < A->alloc; i++) {
104 fq_nmod_mpolyn_clear(A->coeffs + i, ctx);
105 fq_nmod_mpolyn_init(A->coeffs + i, A->bits, ctx);
106 }
107 A->length = 0;
108 }
109
110
fq_nmod_mpolyun_fit_length(fq_nmod_mpolyun_t A,slong length,const fq_nmod_mpoly_ctx_t ctx)111 void fq_nmod_mpolyun_fit_length(
112 fq_nmod_mpolyun_t A,
113 slong length,
114 const fq_nmod_mpoly_ctx_t ctx)
115 {
116 slong i;
117 slong old_alloc = A->alloc;
118 slong new_alloc = FLINT_MAX(length, 2*A->alloc);
119
120 if (length > old_alloc)
121 {
122 if (old_alloc == 0)
123 {
124 A->exps = (ulong *) flint_malloc(new_alloc*sizeof(ulong));
125 A->coeffs = (fq_nmod_mpolyn_struct *) flint_malloc(
126 new_alloc*sizeof(fq_nmod_mpolyn_struct));
127 }
128 else
129 {
130 A->exps = (ulong *) flint_realloc(A->exps,
131 new_alloc*sizeof(ulong));
132 A->coeffs = (fq_nmod_mpolyn_struct *) flint_realloc(A->coeffs,
133 new_alloc*sizeof(fq_nmod_mpolyn_struct));
134 }
135
136 for (i = old_alloc; i < new_alloc; i++)
137 {
138 fq_nmod_mpolyn_init(A->coeffs + i, A->bits, ctx);
139 }
140 A->alloc = new_alloc;
141 }
142 }
143
144
fq_nmod_mpolyun_one(fq_nmod_mpolyun_t A,const fq_nmod_mpoly_ctx_t ctx)145 void fq_nmod_mpolyun_one(
146 fq_nmod_mpolyun_t A,
147 const fq_nmod_mpoly_ctx_t ctx)
148 {
149 fq_nmod_mpolyun_fit_length(A, 1, ctx);
150 fq_nmod_mpolyn_one(A->coeffs + 0, ctx);
151 A->exps[0] = 0;
152 A->length = 1;
153 }
154
155
fq_nmod_mpolyn_is_nonzero_fq_nmod(const fq_nmod_mpolyn_t A,const fq_nmod_mpoly_ctx_t ctx)156 int fq_nmod_mpolyn_is_nonzero_fq_nmod(
157 const fq_nmod_mpolyn_t A,
158 const fq_nmod_mpoly_ctx_t ctx)
159 {
160 slong N;
161
162 if (A->length != WORD(1))
163 {
164 return 0;
165 }
166
167 if (fq_nmod_poly_degree(A->coeffs + 0, ctx->fqctx) != 0)
168 {
169 return 0;
170 }
171
172 N = mpoly_words_per_exp(A->bits, ctx->minfo);
173 return mpoly_monomial_is_zero(A->exps + N*0, N);
174 }
175
176
fq_nmod_mpolyun_is_nonzero_fq_nmod(const fq_nmod_mpolyun_t A,const fq_nmod_mpoly_ctx_t ctx)177 int fq_nmod_mpolyun_is_nonzero_fq_nmod(
178 const fq_nmod_mpolyun_t A,
179 const fq_nmod_mpoly_ctx_t ctx)
180 {
181 if (A->length != 1 || A->exps[0] != 0)
182 {
183 return 0;
184 }
185
186 return fq_nmod_mpolyn_is_nonzero_fq_nmod(A->coeffs + 0, ctx);
187 }
188
189
fq_nmod_mpolyn_scalar_mul_fq_nmod(fq_nmod_mpolyn_t A,const fq_nmod_t c,const fq_nmod_mpoly_ctx_t ctx)190 void fq_nmod_mpolyn_scalar_mul_fq_nmod(
191 fq_nmod_mpolyn_t A,
192 const fq_nmod_t c,
193 const fq_nmod_mpoly_ctx_t ctx)
194 {
195 slong i;
196
197 FLINT_ASSERT(!fq_nmod_is_zero(c, ctx->fqctx));
198
199 if (fq_nmod_is_one(c, ctx->fqctx))
200 return;
201
202 for (i = 0; i < A->length; i++)
203 {
204 fq_nmod_poly_scalar_mul_fq_nmod(A->coeffs + i,
205 A->coeffs + i, c, ctx->fqctx);
206 }
207 }
208
fq_nmod_mpolyun_scalar_mul_fq_nmod(fq_nmod_mpolyun_t A,const fq_nmod_t c,const fq_nmod_mpoly_ctx_t ctx)209 void fq_nmod_mpolyun_scalar_mul_fq_nmod(
210 fq_nmod_mpolyun_t A,
211 const fq_nmod_t c,
212 const fq_nmod_mpoly_ctx_t ctx)
213 {
214 slong i, j;
215 FLINT_ASSERT(!fq_nmod_is_zero(c, ctx->fqctx));
216 for (i = 0; i < A->length; i++)
217 {
218 fq_nmod_mpolyn_struct * Ai = A->coeffs + i;
219 for (j = 0; j < Ai->length; j++)
220 {
221 fq_nmod_poly_scalar_mul_fq_nmod(Ai->coeffs + j,
222 Ai->coeffs + j, c, ctx->fqctx);
223 }
224 }
225 }
226
227
fq_nmod_mpolyun_shift_right(fq_nmod_mpolyun_t A,ulong s)228 void fq_nmod_mpolyun_shift_right(
229 fq_nmod_mpolyun_t A,
230 ulong s)
231 {
232 slong i;
233 for (i = 0; i < A->length; i++)
234 {
235 FLINT_ASSERT(A->exps[i] >= s);
236 A->exps[i] -= s;
237 }
238 }
239
240
fq_nmod_mpolyun_shift_left(fq_nmod_mpolyun_t A,ulong s)241 void fq_nmod_mpolyun_shift_left(
242 fq_nmod_mpolyun_t A,
243 ulong s)
244 {
245 slong i;
246 for (i = 0; i < A->length; i++)
247 {
248 A->exps[i] += s;
249 FLINT_ASSERT(A->exps[i] >= s);
250 }
251 }
252
253
fq_nmod_mpolyn_mul_poly(fq_nmod_mpolyn_t A,const fq_nmod_mpolyn_t B,const fq_nmod_poly_t c,const fq_nmod_mpoly_ctx_t ctx,fq_nmod_poly_t t)254 void fq_nmod_mpolyn_mul_poly(
255 fq_nmod_mpolyn_t A,
256 const fq_nmod_mpolyn_t B,
257 const fq_nmod_poly_t c,
258 const fq_nmod_mpoly_ctx_t ctx,
259 fq_nmod_poly_t t /* temp */)
260 {
261 slong i;
262 fq_nmod_poly_struct * Acoeff, * Bcoeff;
263 ulong * Aexp, * Bexp;
264 slong Blen = B->length;
265 slong N;
266
267 FLINT_ASSERT(A->bits == B->bits);
268 FLINT_ASSERT(A->bits <= FLINT_BITS);
269 FLINT_ASSERT(!fq_nmod_poly_is_zero(c, ctx->fqctx));
270
271 if (A == B)
272 {
273 Acoeff = A->coeffs;
274 for (i = 0; i < Blen; i++)
275 {
276 fq_nmod_poly_mul(t, Acoeff + i, c, ctx->fqctx);
277 fq_nmod_poly_swap(t, Acoeff + i, ctx->fqctx);
278 }
279 }
280 else
281 {
282 fq_nmod_mpolyn_fit_length(A, Blen, ctx);
283 Acoeff = A->coeffs;
284 Bcoeff = B->coeffs;
285 Aexp = A->exps;
286 Bexp = B->exps;
287
288 N = mpoly_words_per_exp_sp(B->bits, ctx->minfo);
289
290 for (i = 0; i < Blen; i++)
291 {
292 fq_nmod_poly_mul(Acoeff + i, Bcoeff + i, c, ctx->fqctx);
293 mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N);
294 }
295 A->length = Blen;
296 }
297 }
298
fq_nmod_mpolyun_mul_poly(fq_nmod_mpolyun_t A,const fq_nmod_mpolyun_t B,const fq_nmod_poly_t c,const fq_nmod_mpoly_ctx_t ctx)299 void fq_nmod_mpolyun_mul_poly(
300 fq_nmod_mpolyun_t A,
301 const fq_nmod_mpolyun_t B,
302 const fq_nmod_poly_t c,
303 const fq_nmod_mpoly_ctx_t ctx)
304 {
305 slong i, Blen;
306 fq_nmod_mpolyn_struct * Acoeff, * Bcoeff;
307 ulong * Aexp, * Bexp;
308 fq_nmod_poly_t t;
309
310 FLINT_ASSERT(A->bits == B->bits);
311 FLINT_ASSERT(!fq_nmod_poly_is_zero(c, ctx->fqctx));
312
313 fq_nmod_poly_init(t, ctx->fqctx);
314
315 Blen = B->length;
316 fq_nmod_mpolyun_fit_length(A, Blen, ctx);
317 Acoeff = A->coeffs;
318 Bcoeff = B->coeffs;
319 Aexp = A->exps;
320 Bexp = B->exps;
321
322 for (i = 0; i < Blen; i++)
323 {
324 fq_nmod_mpolyn_mul_poly(Acoeff + i, Bcoeff + i, c, ctx, t);
325 Aexp[i] = Bexp[i];
326 }
327 A->length = Blen;
328
329 fq_nmod_poly_clear(t, ctx->fqctx);
330 }
331
332
fq_nmod_mpolyn_divexact_poly(fq_nmod_mpolyn_t A,const fq_nmod_mpolyn_t B,const fq_nmod_poly_t c,const fq_nmod_mpoly_ctx_t ctx,fq_nmod_poly_t q,fq_nmod_poly_t r)333 void fq_nmod_mpolyn_divexact_poly(
334 fq_nmod_mpolyn_t A,
335 const fq_nmod_mpolyn_t B,
336 const fq_nmod_poly_t c,
337 const fq_nmod_mpoly_ctx_t ctx,
338 fq_nmod_poly_t q, /* temp */
339 fq_nmod_poly_t r /* temp */)
340 {
341 slong i;
342 fq_nmod_poly_struct * Acoeff, * Bcoeff;
343 ulong * Aexp, * Bexp;
344 slong Blen = B->length;
345 slong N;
346
347 FLINT_ASSERT(A->bits == B->bits);
348 FLINT_ASSERT(A->bits <= FLINT_BITS);
349 FLINT_ASSERT(!fq_nmod_poly_is_zero(c, ctx->fqctx));
350
351 if (A == B)
352 {
353 Acoeff = A->coeffs;
354 for (i = 0; i < Blen; i++)
355 {
356 fq_nmod_poly_divrem(q, r, Acoeff + i, c, ctx->fqctx);
357 FLINT_ASSERT(fq_nmod_poly_is_zero(r, ctx->fqctx));
358 fq_nmod_poly_swap(q, Acoeff + i, ctx->fqctx);
359 }
360 }
361 else
362 {
363 fq_nmod_mpolyn_fit_length(A, Blen, ctx);
364 Acoeff = A->coeffs;
365 Bcoeff = B->coeffs;
366 Aexp = A->exps;
367 Bexp = B->exps;
368
369 N = mpoly_words_per_exp_sp(B->bits, ctx->minfo);
370
371 for (i = 0; i < Blen; i++)
372 {
373 fq_nmod_poly_divrem(Acoeff + i, r, Bcoeff + i, c, ctx->fqctx);
374 FLINT_ASSERT(fq_nmod_poly_is_zero(r, ctx->fqctx));
375 mpoly_monomial_set(Aexp + N*i, Bexp + N*i, N);
376 }
377 A->length = Blen;
378 }
379 }
380
fq_nmod_mpolyun_divexact_poly(fq_nmod_mpolyun_t A,const fq_nmod_mpolyun_t B,const fq_nmod_poly_t c,const fq_nmod_mpoly_ctx_t ctx)381 void fq_nmod_mpolyun_divexact_poly(
382 fq_nmod_mpolyun_t A,
383 const fq_nmod_mpolyun_t B,
384 const fq_nmod_poly_t c,
385 const fq_nmod_mpoly_ctx_t ctx)
386 {
387 slong i, Blen;
388 fq_nmod_mpolyn_struct * Acoeff, * Bcoeff;
389 ulong * Aexp, * Bexp;
390 fq_nmod_poly_t q, r;
391
392 FLINT_ASSERT(A->bits == B->bits);
393 FLINT_ASSERT(!fq_nmod_poly_is_zero(c, ctx->fqctx));
394
395 fq_nmod_poly_init(q, ctx->fqctx);
396 fq_nmod_poly_init(r, ctx->fqctx);
397
398 Blen = B->length;
399 fq_nmod_mpolyun_fit_length(A, Blen, ctx);
400 Acoeff = A->coeffs;
401 Bcoeff = B->coeffs;
402 Aexp = A->exps;
403 Bexp = B->exps;
404
405 for (i = 0; i < Blen; i++)
406 {
407 fq_nmod_mpolyn_divexact_poly(Acoeff + i, Bcoeff + i, c, ctx, q, r);
408 Aexp[i] = Bexp[i];
409 }
410 A->length = Blen;
411
412 fq_nmod_poly_clear(q, ctx->fqctx);
413 fq_nmod_poly_clear(r, ctx->fqctx);
414 }
415
416
fq_nmod_mpolyn_content_poly(fq_nmod_poly_t g,fq_nmod_mpolyn_t B,const fq_nmod_mpoly_ctx_t ctx)417 void fq_nmod_mpolyn_content_poly(
418 fq_nmod_poly_t g,
419 fq_nmod_mpolyn_t B,
420 const fq_nmod_mpoly_ctx_t ctx)
421 {
422 slong i;
423 fq_nmod_poly_t t;
424
425 fq_nmod_poly_zero(g, ctx->fqctx);
426 fq_nmod_poly_init(t, ctx->fqctx);
427
428 for (i = 0; i < B->length; i++)
429 {
430 fq_nmod_poly_gcd(t, g, B->coeffs + i, ctx->fqctx);
431 fq_nmod_poly_swap(t, g, ctx->fqctx);
432 if (fq_nmod_poly_degree(g, ctx->fqctx) == 0)
433 break;
434 }
435
436 fq_nmod_poly_clear(t, ctx->fqctx);
437 }
438
fq_nmod_mpolyun_content_poly(fq_nmod_poly_t g,fq_nmod_mpolyun_t B,const fq_nmod_mpoly_ctx_t ctx)439 void fq_nmod_mpolyun_content_poly(
440 fq_nmod_poly_t g,
441 fq_nmod_mpolyun_t B,
442 const fq_nmod_mpoly_ctx_t ctx)
443 {
444 slong i, j;
445 fq_nmod_poly_t t;
446
447 fq_nmod_poly_zero(g, ctx->fqctx);
448 fq_nmod_poly_init(t, ctx->fqctx);
449
450 for (i = 0; i < B->length; i++)
451 {
452 for (j = 0; j < (B->coeffs + i)->length; j++)
453 {
454 fq_nmod_poly_gcd(t, g, (B->coeffs + i)->coeffs + j, ctx->fqctx);
455 fq_nmod_poly_swap(t, g, ctx->fqctx);
456 if (fq_nmod_poly_degree(g, ctx->fqctx) == 0)
457 break;
458 }
459 }
460
461 fq_nmod_poly_clear(t, ctx->fqctx);
462 }
463
464
fq_nmod_mpoly_to_mpolyn_perm_deflate(fq_nmod_mpolyn_t A,const fq_nmod_mpoly_ctx_t nctx,const fq_nmod_mpoly_t B,const fq_nmod_mpoly_ctx_t ctx,const slong * perm,const ulong * shift,const ulong * stride)465 void fq_nmod_mpoly_to_mpolyn_perm_deflate(
466 fq_nmod_mpolyn_t A,
467 const fq_nmod_mpoly_ctx_t nctx,
468 const fq_nmod_mpoly_t B,
469 const fq_nmod_mpoly_ctx_t ctx,
470 const slong * perm,
471 const ulong * shift,
472 const ulong * stride)
473 {
474 slong j, k, l;
475 slong NA = mpoly_words_per_exp_sp(A->bits, nctx->minfo);
476 slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo);
477 slong n = ctx->minfo->nvars;
478 slong m = nctx->minfo->nvars;
479 ulong * Bexps;
480 slong * offs, * shifts;
481 fq_nmod_mpoly_t T;
482 TMP_INIT;
483
484 FLINT_ASSERT(m <= n);
485
486 TMP_START;
487 Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong));
488
489 offs = (slong *) TMP_ALLOC(m*sizeof(ulong));
490 shifts = (slong *) TMP_ALLOC(m*sizeof(ulong));
491 for (k = 0; k < m; k++)
492 {
493 mpoly_gen_offset_shift_sp(offs + k, shifts + k, k, A->bits, nctx->minfo);
494 }
495
496 fq_nmod_mpoly_init3(T, B->length, A->bits, nctx);
497 T->length = B->length;
498 for (j = 0; j < B->length; j++)
499 {
500 mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo);
501 fq_nmod_set(T->coeffs + j, B->coeffs + j, ctx->fqctx);
502 mpoly_monomial_zero(T->exps + NA*j, NA);
503 for (k = 0; k < m; k++)
504 {
505 l = perm[k];
506 (T->exps + NA*j)[offs[k]] += ((Bexps[l] - shift[l]) / stride[l]) << shifts[k];
507 }
508 }
509
510 fq_nmod_mpoly_sort_terms(T, nctx);
511
512 fq_nmod_mpoly_cvtto_mpolyn(A, T, nctx->minfo->nvars - 1, nctx);
513
514 fq_nmod_mpoly_clear(T, nctx);
515
516 TMP_END;
517 }
518
fq_nmod_mpoly_from_mpolyn_perm_inflate(fq_nmod_mpoly_t A,flint_bitcnt_t Abits,const fq_nmod_mpoly_ctx_t ctx,const fq_nmod_mpolyn_t B,const fq_nmod_mpoly_ctx_t nctx,const slong * perm,const ulong * shift,const ulong * stride)519 void fq_nmod_mpoly_from_mpolyn_perm_inflate(
520 fq_nmod_mpoly_t A,
521 flint_bitcnt_t Abits,
522 const fq_nmod_mpoly_ctx_t ctx,
523 const fq_nmod_mpolyn_t B,
524 const fq_nmod_mpoly_ctx_t nctx,
525 const slong * perm,
526 const ulong * shift,
527 const ulong * stride)
528 {
529 slong n = ctx->minfo->nvars;
530 slong m = nctx->minfo->nvars;
531 slong i, h, k, l;
532 slong NA, NB;
533 slong Alen;
534 fq_nmod_struct * Acoeff;
535 ulong * Aexp;
536 slong Aalloc;
537 ulong * Bexps;
538 ulong * Aexps, * tAexp, * tAgexp;
539 TMP_INIT;
540
541 FLINT_ASSERT(B->length > 0);
542 FLINT_ASSERT(Abits <= FLINT_BITS);
543 FLINT_ASSERT(B->bits <= FLINT_BITS);
544 FLINT_ASSERT(m <= n);
545 TMP_START;
546
547 Bexps = (ulong *) TMP_ALLOC(m*sizeof(ulong));
548 Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong));
549
550 NA = mpoly_words_per_exp(Abits, ctx->minfo);
551 NB = mpoly_words_per_exp(B->bits, nctx->minfo);
552
553 tAexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong));
554 tAgexp = (ulong *) TMP_ALLOC(NA*sizeof(ulong));
555 mpoly_gen_monomial_sp(tAgexp, perm[m - 1], Abits, ctx->minfo);
556 for (i = 0; i < NA; i++)
557 tAgexp[i] *= stride[perm[m - 1]];
558
559 fq_nmod_mpoly_fit_bits(A, Abits, ctx);
560 A->bits = Abits;
561
562 Acoeff = A->coeffs;
563 Aexp = A->exps;
564 Aalloc = A->alloc;
565 Alen = 0;
566 for (i = 0; i < B->length; i++)
567 {
568 mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, nctx->minfo);
569 FLINT_ASSERT(Bexps[m - 1] == 0);
570 for (l = 0; l < n; l++)
571 {
572 Aexps[l] = shift[l];
573 }
574 for (k = 0; k < m; k++)
575 {
576 l = perm[k];
577 Aexps[l] += stride[l]*Bexps[k];
578 }
579
580 mpoly_set_monomial_ui(tAexp, Aexps, Abits, ctx->minfo);
581
582 h = (B->coeffs + i)->length;
583 _fq_nmod_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + h, NA, ctx->fqctx);
584 for (h--; h >= 0; h--)
585 {
586 fq_nmod_struct * c = (B->coeffs + i)->coeffs + h;
587 if (fq_nmod_is_zero(c, ctx->fqctx))
588 continue;
589 mpoly_monomial_madd(Aexp + NA*Alen, tAexp, h, tAgexp, NA);
590 fq_nmod_set(Acoeff + Alen, c, ctx->fqctx);
591 Alen++;
592 }
593 }
594 A->coeffs = Acoeff;
595 A->exps = Aexp;
596 A->alloc = Aalloc;
597 A->length = Alen;
598
599 fq_nmod_mpoly_sort_terms(A, ctx);
600 TMP_END;
601 }
602
603
fq_nmod_mpolyn_lastdeg(fq_nmod_mpolyn_t A,const fq_nmod_mpoly_ctx_t ctx)604 slong fq_nmod_mpolyn_lastdeg(
605 fq_nmod_mpolyn_t A,
606 const fq_nmod_mpoly_ctx_t ctx)
607 {
608 slong i;
609 slong deg = -WORD(1);
610
611 for (i = 0; i < A->length; i++)
612 {
613 deg = FLINT_MAX(deg, fq_nmod_poly_degree(A->coeffs + i, ctx->fqctx));
614 }
615
616 return deg;
617 }
618
fq_nmod_mpolyun_lastdeg(fq_nmod_mpolyun_t A,const fq_nmod_mpoly_ctx_t ctx)619 slong fq_nmod_mpolyun_lastdeg(
620 fq_nmod_mpolyun_t A,
621 const fq_nmod_mpoly_ctx_t ctx)
622 {
623 slong i, j;
624 slong deg = -WORD(1);
625
626 for (i = 0; i < A->length; i++)
627 {
628 fq_nmod_mpolyn_struct * Ai = A->coeffs + i;
629 for (j = 0; j < Ai->length; j++)
630 {
631 deg = FLINT_MAX(deg, fq_nmod_poly_degree(Ai->coeffs + j, ctx->fqctx));
632 }
633 }
634
635 return deg;
636 }
637
fq_nmod_mpolyun_set(fq_nmod_mpolyun_t A,const fq_nmod_mpolyun_t B,const fq_nmod_mpoly_ctx_t ctx)638 void fq_nmod_mpolyun_set(
639 fq_nmod_mpolyun_t A,
640 const fq_nmod_mpolyun_t B,
641 const fq_nmod_mpoly_ctx_t ctx)
642 {
643 slong i, Blen;
644 fq_nmod_mpolyn_struct * Acoeff, * Bcoeff;
645 ulong * Aexp, * Bexp;
646
647 Blen = B->length;
648 fq_nmod_mpolyun_fit_length(A, Blen, ctx);
649 Acoeff = A->coeffs;
650 Bcoeff = B->coeffs;
651 Aexp = A->exps;
652 Bexp = B->exps;
653
654 for (i = 0; i < Blen; i++)
655 {
656 fq_nmod_mpolyn_set(Acoeff + i, Bcoeff + i, ctx);
657 FLINT_ASSERT((Acoeff + i)->bits == B->bits);
658 Aexp[i] = Bexp[i];
659 }
660 A->length = Blen;
661 }
662
663 /* take the last variable of B out */
fq_nmod_mpoly_cvtto_mpolyn(fq_nmod_mpolyn_t A,fq_nmod_mpoly_t B,slong var,const fq_nmod_mpoly_ctx_t ctx)664 void fq_nmod_mpoly_cvtto_mpolyn(
665 fq_nmod_mpolyn_t A,
666 fq_nmod_mpoly_t B,
667 slong var,
668 const fq_nmod_mpoly_ctx_t ctx)
669 {
670 slong i;
671 slong k;
672 ulong * oneexp;
673 slong offset;
674 slong shift;
675 ulong mask;
676 slong N;
677 TMP_INIT;
678
679 FLINT_ASSERT(B->bits <= FLINT_BITS);
680 FLINT_ASSERT(ctx->minfo->ord == ORD_LEX);
681
682 TMP_START;
683
684 N = mpoly_words_per_exp_sp(B->bits, ctx->minfo);
685 oneexp = TMP_ALLOC(N*sizeof(ulong));
686 mask = (-UWORD(1)) >> (FLINT_BITS - B->bits);
687 mpoly_gen_monomial_offset_shift_sp(oneexp, &offset, &shift, var,
688 B->bits, ctx->minfo);
689
690 fq_nmod_mpolyn_fit_bits(A, B->bits, ctx);
691 A->bits = B->bits;
692
693 k = 0;
694 fq_nmod_mpolyn_fit_length(A, k + 1, ctx);
695 for (i = 0; i < B->length; i++)
696 {
697 ulong c = (B->exps[N*i + offset] >> shift) & mask;
698 mpoly_monomial_msub(A->exps + N*k, B->exps + N*i, c, oneexp, N);
699
700 if (k > 0 && mpoly_monomial_equal(A->exps + N*k, A->exps + N*(k - 1), N))
701 {
702 fq_nmod_poly_set_coeff(A->coeffs + k - 1, c, B->coeffs + i,
703 ctx->fqctx);
704 } else
705 {
706 fq_nmod_poly_zero(A->coeffs + k, ctx->fqctx);
707 fq_nmod_poly_set_coeff(A->coeffs + k, c, B->coeffs + i, ctx->fqctx);
708 k++;
709 fq_nmod_mpolyn_fit_length(A, k + 1, ctx);
710 }
711 }
712
713 fq_nmod_mpolyn_set_length(A, k, ctx);
714 TMP_END;
715 }
716
fq_nmod_mpolyu_cvtto_mpolyun(fq_nmod_mpolyun_t A,fq_nmod_mpolyu_t B,slong k,const fq_nmod_mpoly_ctx_t ctx)717 void fq_nmod_mpolyu_cvtto_mpolyun(
718 fq_nmod_mpolyun_t A,
719 fq_nmod_mpolyu_t B,
720 slong k,
721 const fq_nmod_mpoly_ctx_t ctx)
722 {
723 slong i, Blen;
724 fq_nmod_mpolyn_struct * Acoeff;
725 fq_nmod_mpoly_struct * Bcoeff;
726 ulong * Aexp, * Bexp;
727
728 Blen = B->length;
729 fq_nmod_mpolyun_fit_length(A, Blen, ctx);
730 Acoeff = A->coeffs;
731 Bcoeff = B->coeffs;
732 Aexp = A->exps;
733 Bexp = B->exps;
734
735 for (i = 0; i < Blen; i++)
736 {
737 fq_nmod_mpoly_cvtto_mpolyn(Acoeff + i, Bcoeff + i, k, ctx);
738 Aexp[i] = Bexp[i];
739 }
740
741 /* demote remaining coefficients */
742 for (i = Blen; i < A->length; i++)
743 {
744 fq_nmod_mpolyn_clear(Acoeff + i, ctx);
745 fq_nmod_mpolyn_init(Acoeff + i, A->bits, ctx);
746 }
747 A->length = Blen;
748 }
749
750
751 /* put the last variable of B back into A */
fq_nmod_mpoly_cvtfrom_mpolyn(fq_nmod_mpoly_t A,fq_nmod_mpolyn_t B,slong var,const fq_nmod_mpoly_ctx_t ctx)752 void fq_nmod_mpoly_cvtfrom_mpolyn(
753 fq_nmod_mpoly_t A,
754 fq_nmod_mpolyn_t B,
755 slong var,
756 const fq_nmod_mpoly_ctx_t ctx)
757 {
758 slong i, j;
759 slong k;
760 slong N;
761 ulong * oneexp;
762 TMP_INIT;
763
764 FLINT_ASSERT(B->bits == A->bits);
765 FLINT_ASSERT(B->bits <= FLINT_BITS);
766 FLINT_ASSERT(ctx->minfo->ord == ORD_LEX);
767
768 TMP_START;
769
770 N = mpoly_words_per_exp_sp(B->bits, ctx->minfo);
771 oneexp = TMP_ALLOC(N*sizeof(ulong));
772 mpoly_gen_monomial_sp(oneexp, var, B->bits, ctx->minfo);
773
774 fq_nmod_mpoly_fit_length(A, B->length, ctx);
775
776 k = 0;
777 for (i = 0; i < B->length; i++)
778 {
779 for (j = (B->coeffs + i)->length - 1; j >= 0; j--)
780 {
781 if (!fq_nmod_is_zero((B->coeffs + i)->coeffs + j, ctx->fqctx))
782 {
783 fq_nmod_mpoly_fit_length(A, k + 1, ctx);
784 fq_nmod_set(A->coeffs + k, (B->coeffs + i)->coeffs + j,
785 ctx->fqctx);
786 mpoly_monomial_madd(A->exps + N*k, B->exps + N*i, j, oneexp, N);
787 k++;
788 }
789 }
790 }
791
792 A->length = k;
793 TMP_END;
794 }
795
fq_nmod_mpolyu_cvtfrom_mpolyun(fq_nmod_mpolyu_t A,fq_nmod_mpolyun_t B,slong var,const fq_nmod_mpoly_ctx_t ctx)796 void fq_nmod_mpolyu_cvtfrom_mpolyun(
797 fq_nmod_mpolyu_t A,
798 fq_nmod_mpolyun_t B,
799 slong var,
800 const fq_nmod_mpoly_ctx_t ctx)
801 {
802 slong i;
803
804 fq_nmod_mpolyu_fit_length(A, B->length, ctx);
805
806 for (i = 0; i < B->length; i++)
807 {
808 fq_nmod_mpoly_cvtfrom_mpolyn(A->coeffs + i, B->coeffs + i, var, ctx);
809 A->exps[i] = B->exps[i];
810 }
811 A->length = B->length;
812 }
813
814