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
14 /*
15 set A(x_var^Bstride[var]) to B/xbar^Bshifts
16 it is asserted that the conversion is correct
17 */
_nmod_mpoly_to_nmod_poly_deflate(nmod_poly_t A,const nmod_mpoly_t B,slong var,const ulong * Bshift,const ulong * Bstride,const nmod_mpoly_ctx_t ctx)18 void _nmod_mpoly_to_nmod_poly_deflate(
19 nmod_poly_t A,
20 const nmod_mpoly_t B,
21 slong var,
22 const ulong * Bshift,
23 const ulong * Bstride,
24 const nmod_mpoly_ctx_t ctx)
25 {
26 ulong mask;
27 slong i, shift, off, N;
28 slong len = B->length;
29 mp_limb_t * coeff = B->coeffs;
30 ulong * exp = B->exps;
31 ulong var_shift, var_stride;
32 flint_bitcnt_t bits = B->bits;
33
34 FLINT_ASSERT(len > 0);
35 FLINT_ASSERT(bits <= FLINT_BITS);
36
37 N = mpoly_words_per_exp_sp(bits, ctx->minfo);
38 mpoly_gen_offset_shift_sp(&off, &shift, var, bits, ctx->minfo);
39
40 nmod_poly_zero(A);
41 mask = (-UWORD(1)) >> (FLINT_BITS - bits);
42 var_shift = Bshift[var];
43 var_stride = Bstride[var];
44 for (i = 0; i < len; i++)
45 {
46 ulong k = (exp[N*i + off] >> shift) & mask;
47 FLINT_ASSERT(k >= var_shift);
48 k -= var_shift;
49 if (k != 0)
50 {
51 k /= var_stride;
52 }
53 nmod_poly_set_coeff_ui(A, k, coeff[i]);
54 }
55
56 #if WANT_ASSERT
57 for (i = 0; i < len; i++)
58 {
59 slong v;
60 for (v = 0; v < ctx->minfo->nvars; v++)
61 {
62 ulong k;
63 mpoly_gen_offset_shift_sp(&off, &shift, v, bits, ctx->minfo);
64 k = (exp[N*i + off] >> shift) & mask;
65 FLINT_ASSERT( (v == var && k >= Bshift[v])
66 || (v != var && k == Bshift[v]));
67 }
68 }
69 #endif
70 }
71
72 /*
73 set A to B(x_var^Astride[var])*xbar^Ashift
74 A must be packed into bits = Abits
75 */
_nmod_mpoly_from_nmod_poly_inflate(nmod_mpoly_t A,flint_bitcnt_t Abits,const nmod_poly_t B,slong var,const ulong * Ashift,const ulong * Astride,const nmod_mpoly_ctx_t ctx)76 void _nmod_mpoly_from_nmod_poly_inflate(
77 nmod_mpoly_t A,
78 flint_bitcnt_t Abits,
79 const nmod_poly_t B,
80 slong var,
81 const ulong * Ashift,
82 const ulong * Astride,
83 const nmod_mpoly_ctx_t ctx)
84 {
85 slong N;
86 slong k;
87 slong Alen;
88 mp_limb_t * Acoeff;
89 ulong * Aexp;
90 slong Aalloc;
91 ulong * shiftexp;
92 ulong * strideexp;
93 slong Bdeg = nmod_poly_degree(B);
94 TMP_INIT;
95
96 TMP_START;
97
98 FLINT_ASSERT(Abits <= FLINT_BITS);
99 FLINT_ASSERT(!nmod_poly_is_zero(B));
100
101 /* must have at least space for the highest exponent of var */
102 FLINT_ASSERT(1 + FLINT_BIT_COUNT(Ashift[var] + Bdeg*Astride[var]) <= Abits);
103
104 N = mpoly_words_per_exp_sp(Abits, ctx->minfo);
105 strideexp = (ulong*) TMP_ALLOC(N*sizeof(ulong));
106 shiftexp = (ulong*) TMP_ALLOC(N*sizeof(ulong));
107 mpoly_set_monomial_ui(shiftexp, Ashift, Abits, ctx->minfo);
108 mpoly_gen_monomial_sp(strideexp, var, Abits, ctx->minfo);
109 mpoly_monomial_mul_ui(strideexp, strideexp, N, Astride[var]);
110
111 nmod_mpoly_fit_bits(A, Abits, ctx);
112 A->bits = Abits;
113
114 Acoeff = A->coeffs;
115 Aexp = A->exps;
116 Aalloc = A->alloc;
117 Alen = 0;
118 for (k = Bdeg; k >= 0; k--)
119 {
120 _nmod_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, N);
121 Acoeff[Alen] = nmod_poly_get_coeff_ui(B, k);
122 if (Acoeff[Alen] != UWORD(0))
123 {
124 mpoly_monomial_madd(Aexp + N*Alen, shiftexp, k, strideexp, N);
125 Alen++;
126 }
127 }
128
129 A->coeffs = Acoeff;
130 A->exps = Aexp;
131 A->alloc = Aalloc;
132 _nmod_mpoly_set_length(A, Alen, ctx);
133
134 TMP_END;
135 }
136