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
nmod_mpolyd_ctx_init(nmod_mpolyd_ctx_t dctx,slong nvars)15 void nmod_mpolyd_ctx_init(nmod_mpolyd_ctx_t dctx, slong nvars)
16 {
17 slong i;
18
19 dctx->nvars = nvars;
20 dctx->perm = (slong *) flint_malloc(nvars*sizeof(slong));
21 for (i = 0; i < nvars; i++)
22 {
23 dctx->perm[i] = i;
24 }
25 }
26
nmod_mpolyd_ctx_clear(nmod_mpolyd_ctx_t dctx)27 void nmod_mpolyd_ctx_clear(nmod_mpolyd_ctx_t dctx)
28 {
29 flint_free(dctx->perm);
30 }
31
nmod_mpolyd_init(nmod_mpolyd_t poly,slong nvars)32 void nmod_mpolyd_init(nmod_mpolyd_t poly, slong nvars)
33 {
34 slong i;
35
36 poly->nvars = nvars;
37 poly->degb_alloc = nvars;
38 poly->deg_bounds = (slong *) flint_malloc(poly->degb_alloc*sizeof(slong));
39 for (i = 0; i < nvars; i++)
40 {
41 poly->deg_bounds[i] = WORD(1);
42 }
43 poly->coeff_alloc = WORD(16);
44 poly->coeffs = (mp_limb_t *) flint_malloc(poly->coeff_alloc*sizeof(mp_limb_t));
45 for (i = 0; i < poly->coeff_alloc; i++)
46 {
47 poly->coeffs[i] = UWORD(0);
48 }
49 }
50
nmod_mpolyd_fit_length(nmod_mpolyd_t poly,slong len)51 void nmod_mpolyd_fit_length(nmod_mpolyd_t poly, slong len) {
52 if (poly->coeff_alloc < len) {
53 /*flint_printf("realloc %wd -> %wd\n",poly->coeff_alloc, len);*/
54 poly->coeffs = (mp_limb_t *) flint_realloc(poly->coeffs, len*sizeof(mp_limb_t));
55 poly->coeff_alloc = len;
56 }
57 }
58
nmod_mpolyd_set_nvars(nmod_mpolyd_t poly,slong nvars)59 void nmod_mpolyd_set_nvars(nmod_mpolyd_t poly, slong nvars) {
60
61 poly->nvars = nvars;
62 if (poly->degb_alloc < nvars) {
63 poly->deg_bounds = (slong *) flint_realloc(poly->deg_bounds, nvars*sizeof(slong));
64 poly->degb_alloc = nvars;
65 }
66 }
67
nmod_mpolyd_zero(nmod_mpolyd_t poly)68 void nmod_mpolyd_zero(nmod_mpolyd_t poly)
69 {
70 slong i;
71
72 for (i = 0; i < poly->nvars; i++)
73 {
74 poly->deg_bounds[i] = WORD(1);
75 }
76 poly->coeffs[0] = UWORD(0);
77 }
78
nmod_mpolyd_clear(nmod_mpolyd_t poly)79 void nmod_mpolyd_clear(nmod_mpolyd_t poly)
80 {
81 flint_free(poly->deg_bounds);
82 flint_free(poly->coeffs);
83 poly->deg_bounds = NULL;
84 poly->coeffs = NULL;
85 }
86
87
nmod_mpolyd_set_degbounds(nmod_mpolyd_t A,slong * bounds)88 int nmod_mpolyd_set_degbounds(nmod_mpolyd_t A, slong * bounds)
89 {
90 slong i;
91 int success = 0;
92 slong degb_prod;
93
94 degb_prod = 1;
95 for (i = 0; i < A->nvars; i++)
96 {
97 ulong hi;
98 A->deg_bounds[i] = bounds[i];
99 umul_ppmm(hi, degb_prod, degb_prod, A->deg_bounds[i]);
100 if (hi != WORD(0) || degb_prod < 0)
101 {
102 goto done;
103 }
104 }
105
106 success = 1;
107 nmod_mpolyd_fit_length(A, degb_prod);
108
109 done:
110 return success;
111 }
112
nmod_mpolyd_set_degbounds_perm(nmod_mpolyd_t A,const nmod_mpolyd_ctx_t dctx,slong * bounds)113 int nmod_mpolyd_set_degbounds_perm(nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx, slong * bounds)
114 {
115 slong i;
116 int success = 0;
117 const slong * perm = dctx->perm;
118 slong degb_prod;
119
120 degb_prod = 1;
121 for (i = 0; i < A->nvars; i++)
122 {
123 ulong hi;
124 A->deg_bounds[i] = bounds[perm[i]];
125 umul_ppmm(hi, degb_prod, degb_prod, A->deg_bounds[i]);
126 if (hi != WORD(0) || degb_prod < 0)
127 {
128 goto done;
129 }
130 }
131
132 success = 1;
133 nmod_mpolyd_fit_length(A, degb_prod);
134
135 done:
136 return success;
137 }
138
139
140 /*
141 m is the number of variables in A
142 */
nmod_mpoly_to_nmod_mpolyd_perm_deflate(nmod_mpolyd_t A,slong m,const nmod_mpoly_t B,const slong * perm,const ulong * shift,const ulong * stride,const ulong * degree,const nmod_mpoly_ctx_t ctx)143 void nmod_mpoly_to_nmod_mpolyd_perm_deflate(nmod_mpolyd_t A, slong m,
144 const nmod_mpoly_t B, const slong * perm, const ulong * shift,
145 const ulong * stride, const ulong * degree, const nmod_mpoly_ctx_t ctx)
146 {
147 slong n = ctx->minfo->nvars;
148 slong degb_prod;
149 slong i, k, l, N;
150 ulong * Bexp;
151 TMP_INIT;
152
153 FLINT_ASSERT(m <= n);
154 FLINT_ASSERT(B->bits <= FLINT_BITS);
155 FLINT_ASSERT(B->length > 0);
156
157 nmod_mpolyd_set_nvars(A, m);
158
159 TMP_START;
160 Bexp = (ulong *) TMP_ALLOC(n*sizeof(slong));
161
162 degb_prod = WORD(1);
163 for (k = 0; k < m; k++)
164 {
165 l = perm[k];
166 FLINT_ASSERT(stride[l] != UWORD(0));
167 FLINT_ASSERT((degree[l] - shift[l]) % stride[l] == UWORD(0));
168 A->deg_bounds[k] = (degree[l] - shift[l])/stride[l] + 1;
169 degb_prod *= A->deg_bounds[k];
170 /* we should not be converting something whose dense size overflows */
171 FLINT_ASSERT(degb_prod > 0);
172 FLINT_ASSERT(degb_prod >= A->deg_bounds[k]);
173 }
174
175 nmod_mpolyd_fit_length(A, degb_prod);
176 for (i = 0; i < degb_prod; i++)
177 {
178 A->coeffs[i] = UWORD(0);
179 }
180
181 N = mpoly_words_per_exp(B->bits, ctx->minfo);
182 for (i = 0; i < B->length; i++)
183 {
184 slong off = 0;
185 mpoly_get_monomial_ui(Bexp, B->exps + N*i, B->bits, ctx->minfo);
186 for (k = 0; k < m; k++)
187 {
188 l = perm[k];
189 FLINT_ASSERT(stride[l] != UWORD(0));
190 FLINT_ASSERT(((Bexp[l] - shift[l]) % stride[l]) == UWORD(0));
191 FLINT_ASSERT((Bexp[l] - shift[l])/stride[l] < A->deg_bounds[k]);
192 off = (Bexp[l] - shift[l])/stride[l] + A->deg_bounds[k]*off;
193 }
194 A->coeffs[off] = B->coeffs[i];
195 }
196
197 TMP_END;
198 }
199
200
nmod_mpoly_from_nmod_mpolyd_perm_inflate(nmod_mpoly_t A,flint_bitcnt_t Abits,const nmod_mpoly_ctx_t ctx,const nmod_mpolyd_t B,const slong * perm,const ulong * shift,const ulong * stride)201 void nmod_mpoly_from_nmod_mpolyd_perm_inflate(nmod_mpoly_t A,
202 flint_bitcnt_t Abits, const nmod_mpoly_ctx_t ctx, const nmod_mpolyd_t B,
203 const slong * perm, const ulong * shift, const ulong * stride)
204 {
205 slong off;
206 slong n = ctx->minfo->nvars;
207 slong m = B->nvars;
208 slong Alen;
209 slong i, j, l, k, N;
210 slong perm_nontrivial;
211 ulong topmask;
212 ulong * exps, * pcurexp, * pexps;
213 TMP_INIT;
214
215 FLINT_ASSERT(m <= n);
216 FLINT_ASSERT(Abits <= FLINT_BITS);
217
218 perm_nontrivial = n - m;
219
220 /* we are going to push back terms manually */
221 Alen = 0;
222 nmod_mpoly_zero(A, ctx);
223 nmod_mpoly_fit_bits(A, Abits, ctx);
224 A->bits = Abits;
225
226 N = mpoly_words_per_exp(Abits, ctx->minfo);
227
228 TMP_START;
229
230 /* find exponent vector for all variables in B */
231 pexps = (ulong *) TMP_ALLOC(N*m*sizeof(ulong));
232 for (k = 0; k < m; k++)
233 {
234 l = perm[k];
235 perm_nontrivial |= l - k;
236 mpoly_gen_monomial_sp(pexps + k*N, l, Abits, ctx->minfo);
237 mpoly_monomial_mul_ui(pexps + k*N, pexps + k*N, N, stride[l]);
238 }
239
240 /* get most significant exponent in pcurexp and its vector in exps */
241 pcurexp = (ulong *) TMP_ALLOC(N*sizeof(ulong));
242 exps = (ulong *) TMP_ALLOC(m*sizeof(ulong));
243 off = WORD(1);
244 for (j = 0; j < m; j++)
245 {
246 off *= B->deg_bounds[j];
247 }
248 FLINT_ASSERT(off <= B->coeff_alloc);
249 off--;
250 mpoly_set_monomial_ui(pcurexp, shift, Abits, ctx->minfo);
251 i = off;
252 for (k = m - 1; k >= 0; k--)
253 {
254 exps[k] = i % B->deg_bounds[k];
255 i = i / B->deg_bounds[k];
256 mpoly_monomial_madd(pcurexp, pcurexp, exps[k], pexps + N*k, N);
257 }
258
259 /* scan down through the exponents */
260 topmask = 0;
261
262 for (; off >= 0; off--)
263 {
264 if (B->coeffs[off] != UWORD(0))
265 {
266 _nmod_mpoly_fit_length(&A->coeffs, &A->exps, &A->alloc, Alen + 1, N);
267 A->coeffs[Alen] = B->coeffs[off];
268 mpoly_monomial_set(A->exps + N*Alen, pcurexp, N);
269 topmask |= pcurexp[N - 1];
270 Alen++;
271 }
272
273 k = m - 1;
274 do {
275 --exps[k];
276 if ((slong)(exps[k]) < WORD(0))
277 {
278 FLINT_ASSERT(off == 0 || k > 0);
279 FLINT_ASSERT(exps[k] == -UWORD(1));
280 exps[k] = B->deg_bounds[k] - 1;
281 mpoly_monomial_madd(pcurexp, pcurexp, exps[k], pexps + N*k, N);
282 }
283 else
284 {
285 mpoly_monomial_sub(pcurexp, pcurexp, pexps + N*k, N);
286 break;
287 }
288 } while (--k >= 0);
289 }
290 _nmod_mpoly_set_length(A, Alen, ctx);
291
292 /* sort the terms if needed */
293 if (ctx->minfo->ord != ORD_LEX || perm_nontrivial != WORD(0))
294 {
295 slong msb;
296 mpoly_get_cmpmask(pcurexp, N, Abits, ctx->minfo);
297 if (topmask != WORD(0))
298 {
299 count_leading_zeros(msb, topmask);
300 msb = (FLINT_BITS - 1)^msb;
301 }
302 else
303 {
304 msb = -WORD(1);
305 }
306 if (N == 1)
307 {
308 if (msb >= WORD(0))
309 {
310 _nmod_mpoly_radix_sort1(A, 0, A->length,
311 msb, pcurexp[0], topmask);
312 }
313 }
314 else
315 {
316 _nmod_mpoly_radix_sort(A, 0, A->length,
317 (N - 1)*FLINT_BITS + msb, N, pcurexp);
318 }
319 }
320
321 TMP_END;
322 }
323
324
325 /*
326 convert B to A assuming degree bounds have been set in A
327 */
nmod_mpoly_convert_to_nmod_mpolyd_degbound(nmod_mpolyd_t A,const nmod_mpolyd_ctx_t dctx,const nmod_mpoly_t B,const nmod_mpoly_ctx_t ctx)328 void nmod_mpoly_convert_to_nmod_mpolyd_degbound(nmod_mpolyd_t A,
329 const nmod_mpolyd_ctx_t dctx,
330 const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx)
331 {
332 slong degb_prod;
333 slong i, j, N;
334 ulong * exps;
335 const slong * perm = dctx->perm;
336 slong nvars = ctx->minfo->nvars;
337 TMP_INIT;
338
339 FLINT_ASSERT(A->nvars == nvars);
340 FLINT_ASSERT(B->bits <= FLINT_BITS);
341
342 degb_prod = WORD(1);
343 for (i = 0; i < nvars; i++)
344 {
345 degb_prod *= A->deg_bounds[i];
346 }
347
348 for (i = 0; i < degb_prod; i++)
349 {
350 A->coeffs[i] = UWORD(0);
351 }
352
353 TMP_START;
354 exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong));
355 N = mpoly_words_per_exp(B->bits, ctx->minfo);
356
357 for (i = 0; i < B->length; i++)
358 {
359 slong off;
360
361 mpoly_get_monomial_ui(exps, B->exps + N*i, B->bits, ctx->minfo);
362 off = 0;
363 for (j = 0; j < nvars; j++)
364 {
365 off = exps[perm[j]] + A->deg_bounds[j]*off;
366 }
367 A->coeffs[off] = B->coeffs[i];
368 }
369
370 TMP_END;
371 }
372
373 /*
374 convert B to A - sets degree bounds in A
375 */
nmod_mpoly_convert_to_nmod_mpolyd(nmod_mpolyd_t A,const nmod_mpolyd_ctx_t dctx,const nmod_mpoly_t B,const nmod_mpoly_ctx_t ctx)376 void nmod_mpoly_convert_to_nmod_mpolyd(
377 nmod_mpolyd_t A, const nmod_mpolyd_ctx_t dctx,
378 const nmod_mpoly_t B, const nmod_mpoly_ctx_t ctx)
379 {
380 slong degb_prod;
381 slong i, j, N;
382 slong * exps;
383 const slong * perm = dctx->perm;
384 slong nvars = ctx->minfo->nvars;
385 TMP_INIT;
386
387 nmod_mpolyd_set_nvars(A, ctx->minfo->nvars);
388
389 FLINT_ASSERT(B->bits <= FLINT_BITS);
390
391 if (B->length == 0)
392 {
393 nmod_mpolyd_zero(A);
394 return;
395 }
396
397 TMP_START;
398 exps = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong));
399
400 nmod_mpoly_degrees_si(exps, B, ctx);
401 degb_prod = WORD(1);
402 for (i = 0; i < nvars; i++)
403 {
404 A->deg_bounds[i] = exps[perm[i]] + 1;
405 degb_prod *= A->deg_bounds[i];
406 }
407
408 nmod_mpolyd_fit_length(A, degb_prod);
409 for (i = 0; i < degb_prod; i++)
410 {
411 A->coeffs[i] = UWORD(0);
412 }
413
414 N = mpoly_words_per_exp(B->bits, ctx->minfo);
415 for (i = 0; i < B->length; i++)
416 {
417 slong off = 0;
418
419 mpoly_get_monomial_ui((ulong *)exps, B->exps + N*i, B->bits, ctx->minfo);
420 for (j = 0; j < nvars; j++)
421 {
422 off = exps[perm[j]] + A->deg_bounds[j]*off;
423 }
424
425 A->coeffs[off] = B->coeffs[i];
426 }
427
428 TMP_END;
429 }
430
431 /*
432 Convert B to A
433 */
nmod_mpoly_convert_from_nmod_mpolyd(nmod_mpoly_t A,const nmod_mpoly_ctx_t ctx,const nmod_mpolyd_t B,const nmod_mpolyd_ctx_t dctx)434 void nmod_mpoly_convert_from_nmod_mpolyd(nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx,
435 const nmod_mpolyd_t B, const nmod_mpolyd_ctx_t dctx)
436 {
437 slong off, j, k, N;
438 slong bits, nvars = ctx->minfo->nvars;
439 slong Alen;
440 slong * perm = dctx->perm;
441 slong perm_nontrivial = 0;
442 ulong topmask;
443 ulong * exps, * pcurexp, * pexps;
444 TMP_INIT;
445
446 FLINT_ASSERT(nvars == B->nvars);
447
448 TMP_START;
449 exps = (ulong *) TMP_ALLOC(nvars*sizeof(ulong));
450
451 /* find bits needed for the result */
452 off = 1;
453 for (j = 0; j < nvars; j++)
454 {
455 off *= B->deg_bounds[j];
456 exps[perm[j]] = B->deg_bounds[j] - 1;
457 perm_nontrivial |= j ^ perm[j];
458 }
459
460 FLINT_ASSERT(off <= B->coeff_alloc);
461
462 bits = mpoly_exp_bits_required_ui(exps, ctx->minfo);
463 bits = mpoly_fix_bits(bits, ctx->minfo);
464 N = mpoly_words_per_exp(bits, ctx->minfo);
465
466 /* we are going to push back terms manually */
467 Alen = 0;
468 nmod_mpoly_zero(A, ctx);
469 nmod_mpoly_fit_bits(A, bits, ctx);
470 A->bits = bits;
471
472 /* find exponent vector for all variables */
473 pexps = (ulong *) TMP_ALLOC(N*nvars*sizeof(ulong));
474 for (k = 0; k < nvars; k++)
475 {
476 for (j = 0; j < nvars; j++)
477 exps[perm[j]] = (j == k);
478 mpoly_set_monomial_ui(pexps + k*N, exps, bits, ctx->minfo);
479 }
480
481 /* get most significant exponent in exps and its vector in ptempexp */
482 off--;
483 pcurexp = (ulong *) TMP_ALLOC(N*sizeof(ulong));
484 mpoly_monomial_zero(pcurexp, N);
485 k = off;
486 for (j = nvars - 1; j >= 0; j--)
487 {
488 exps[j] = k % B->deg_bounds[j];
489 k = k / B->deg_bounds[j];
490 mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N);
491 }
492
493 /* scan down through the exponents */
494 topmask = 0;
495 for (; off >= 0; off--)
496 {
497 if (B->coeffs[off] != UWORD(0))
498 {
499 _nmod_mpoly_fit_length(&A->coeffs, &A->exps, &A->alloc, Alen + 1, N);
500 A->coeffs[Alen] = B->coeffs[off];
501 mpoly_monomial_set(A->exps + N*Alen, pcurexp, N);
502 topmask |= (A->exps + N*Alen)[N - 1];
503 Alen++;
504 }
505
506 j = nvars - 1;
507 do {
508 --exps[j];
509 if ((slong)(exps[j]) < WORD(0))
510 {
511 FLINT_ASSERT(off == 0 || j > 0);
512 FLINT_ASSERT(exps[j] == -UWORD(1));
513 exps[j] = B->deg_bounds[j] - 1;
514 mpoly_monomial_madd_inplace_mp(pcurexp, exps[j], pexps + N*j, N);
515 } else
516 {
517 mpoly_monomial_sub_mp(pcurexp, pcurexp, pexps + N*j, N);
518 break;
519 }
520 } while (--j >= 0);
521 }
522 _nmod_mpoly_set_length(A, Alen, ctx);
523
524 /* sort the exponents if needed */
525 if (ctx->minfo->ord != ORD_LEX || perm_nontrivial != WORD(0))
526 {
527 slong msb;
528 mpoly_get_cmpmask(pcurexp, N, bits, ctx->minfo);
529 if (topmask != WORD(0))
530 {
531 count_leading_zeros(msb, topmask);
532 msb = (FLINT_BITS - 1)^msb;
533 } else
534 {
535 msb = -WORD(1);
536 }
537 if (N == 1) {
538 if (msb >= WORD(0))
539 {
540 _nmod_mpoly_radix_sort1(A, 0, A->length,
541 msb, pcurexp[0], topmask);
542 }
543 } else {
544 _nmod_mpoly_radix_sort(A, 0, A->length,
545 (N - 1)*FLINT_BITS + msb, N, pcurexp);
546 }
547 }
548
549 TMP_END;
550 }
551
552
nmod_mpolyd_print(nmod_mpolyd_t poly)553 void nmod_mpolyd_print(nmod_mpolyd_t poly)
554 {
555
556 int first = 0;
557 slong i, j;
558 slong degb_prod;
559
560 degb_prod = WORD(1);
561 for (j = 0; j < poly->nvars; j++) {
562 degb_prod *= poly->deg_bounds[j];
563 }
564
565 first = 1;
566 for (i = 0; i < degb_prod; i++) {
567 ulong k = i;
568
569 if (poly->coeffs[i] == 0)
570 continue;
571
572 if (!first)
573 printf(" + ");
574
575 flint_printf("%wu", poly->coeffs[i]);
576
577 for (j = poly->nvars - 1; j >= 0; j--)
578 {
579 ulong m = poly->deg_bounds[j];
580 ulong e = k % m;
581 k = k / m;
582 flint_printf("*x%wd^%wd", j, e);
583 }
584 FLINT_ASSERT(k == 0);
585 first = 0;
586 }
587
588 if (first)
589 flint_printf("0");
590 }
591
nmod_mpolyd_length(const nmod_mpolyd_t A)592 slong nmod_mpolyd_length(const nmod_mpolyd_t A)
593 {
594 slong i, j, degb_prod;
595
596 degb_prod = WORD(1);
597 for (j = 0; j < A->nvars; j++)
598 degb_prod *= A->deg_bounds[j];
599
600 for (i = degb_prod; i > 0; i--)
601 {
602 if (A->coeffs[i - 1] != UWORD(0))
603 break;
604 }
605
606 return i;
607 }
608
nmod_mpolyd_last_degree(const nmod_mpolyd_t A,const nmodf_ctx_t fctx)609 slong nmod_mpolyd_last_degree(const nmod_mpolyd_t A, const nmodf_ctx_t fctx)
610 {
611 slong i, j, Plen, degree;
612 slong degb_prod, degb_last=0;
613
614 degb_prod = WORD(1);
615 for (j = 0; j < A->nvars; j++) {
616 degb_last = A->deg_bounds[j];
617 degb_prod *= degb_last;
618 }
619
620 degree = -1;
621 for (i = 0; i < degb_prod; i += degb_last)
622 {
623 mp_limb_t * P = A->coeffs + i;
624 Plen = degb_last;
625 while (P[Plen-1] == 0)
626 {
627 Plen --;
628 if (Plen == 0)
629 break;
630 }
631 degree = FLINT_MAX(degree, Plen - 1);
632 if (degree + 1 == degb_last)
633 return degree;
634 }
635 return degree;
636 }
637
nmod_mpoly_convert_to_fq_nmod_mpolyd(fq_nmod_mpolyd_t poly1,const fq_nmod_mpolyd_ctx_t dctx,const nmod_mpoly_t poly2,const nmod_mpoly_ctx_t ctx)638 void nmod_mpoly_convert_to_fq_nmod_mpolyd(
639 fq_nmod_mpolyd_t poly1, const fq_nmod_mpolyd_ctx_t dctx,
640 const nmod_mpoly_t poly2, const nmod_mpoly_ctx_t ctx)
641 {
642 slong degb_prod;
643 slong i, j, N;
644 slong * exps;
645 const slong * perm = dctx->perm;
646 slong nvars = ctx->minfo->nvars;
647 TMP_INIT;
648
649 fq_nmod_mpolyd_set_nvars(poly1, ctx->minfo->nvars);
650
651 FLINT_ASSERT(poly2->bits <= FLINT_BITS);
652
653 if (poly2->length == 0)
654 {
655 fq_nmod_mpolyd_zero(poly1, dctx->fqctx);
656 return;
657 }
658
659 TMP_START;
660 exps = (slong *) TMP_ALLOC(ctx->minfo->nvars*sizeof(slong));
661
662 nmod_mpoly_degrees_si(exps, poly2, ctx);
663 degb_prod = WORD(1);
664 for (i = 0; i < nvars; i++)
665 {
666 poly1->deg_bounds[i] = exps[perm[i]] + 1;
667 degb_prod *= poly1->deg_bounds[i];
668 }
669
670 fq_nmod_mpolyd_fit_length(poly1, degb_prod, dctx->fqctx);
671 for (i = 0; i < degb_prod; i++)
672 {
673 fq_nmod_zero(poly1->coeffs + i, dctx->fqctx);
674 }
675
676 N = mpoly_words_per_exp(poly2->bits, ctx->minfo);
677 for (i = 0; i < poly2->length; i++)
678 {
679 slong off = 0;
680
681 mpoly_get_monomial_ui((ulong *)exps, poly2->exps + N*i,
682 poly2->bits, ctx->minfo);
683 for (j = 0; j < nvars; j++)
684 {
685 off = exps[perm[j]] + poly1->deg_bounds[j]*off;
686 }
687 fq_nmod_set_ui(poly1->coeffs + off, poly2->coeffs[i], dctx->fqctx);
688 }
689
690 TMP_END;
691 }
692
693
nmod_mpoly_convert_from_fq_nmod_mpolyd(nmod_mpoly_t A,const nmod_mpoly_ctx_t ctx,const fq_nmod_mpolyd_t B,const fq_nmod_mpolyd_ctx_t dctx)694 void nmod_mpoly_convert_from_fq_nmod_mpolyd(
695 nmod_mpoly_t A, const nmod_mpoly_ctx_t ctx,
696 const fq_nmod_mpolyd_t B, const fq_nmod_mpolyd_ctx_t dctx)
697 {
698 slong i, j;
699 slong degb_prod;
700 slong * perm = dctx->perm;
701 ulong * exps;
702 TMP_INIT;
703
704 FLINT_ASSERT(ctx->minfo->nvars == B->nvars);
705
706 degb_prod = WORD(1);
707 for (j = 0; j < B->nvars; j++) {
708 degb_prod *= B->deg_bounds[j];
709 }
710
711 TMP_START;
712 exps = (ulong *) TMP_ALLOC(B->nvars*sizeof(ulong));
713
714 nmod_mpoly_zero(A, ctx);
715 for (i = 0; i < degb_prod; i++) {
716 ulong k = i;
717
718 if (fq_nmod_is_zero(B->coeffs + i, dctx->fqctx))
719 continue;
720
721 for (j = B->nvars - 1; j >= 0; j--)
722 {
723 ulong m = B->deg_bounds[j];
724 ulong e = k % m;
725 k = k / m;
726 exps[perm[j]] = e;
727 }
728 FLINT_ASSERT(k == 0);
729
730 /* need special function to convert F_q element to F_p element */
731 for (j=1; j < (B->coeffs + i)->length; j++) {
732 FLINT_ASSERT((B->coeffs + i)->coeffs[j] == 0);
733 }
734 nmod_mpoly_set_term_ui_ui(A, (B->coeffs + i)->coeffs[0], exps, ctx);
735 }
736
737 TMP_END;
738 }
739