5 #include <barvinok/polylib.h>
12 /* Construct truncated expansion of (1+t)^(degree),
13 * computing the first 1+d coefficients
15 dpoly::dpoly(int d
, const Value degree
, int offset
)
17 coeff
= Vector_Alloc(d
+1);
19 /* For small degrees, we only need to compute some coefficients */
21 if (value_posz_p(degree
) && value_cmp_si(degree
, min
) < 0)
22 min
= VALUE_TO_INT(degree
);
29 value_assign(coeff
->p
[0], c
);
30 value_assign(tmp
, degree
);
31 for (int i
= 1; i
<= min
; ++i
) {
32 value_multiply(c
, c
, tmp
);
33 value_decrement(tmp
, tmp
);
34 mpz_divexact_ui(c
, c
, i
);
35 value_assign(coeff
->p
[i
-offset
], c
);
41 void dpoly::operator += (const dpoly
& t
)
43 assert(coeff
->Size
== t
.coeff
->Size
);
44 for (int i
= 0; i
< coeff
->Size
; ++i
)
45 value_addto(coeff
->p
[i
], coeff
->p
[i
], t
.coeff
->p
[i
]);
48 void dpoly::operator *= (const Value f
)
50 for (int i
= 0; i
< coeff
->Size
; ++i
)
51 value_multiply(coeff
->p
[i
], coeff
->p
[i
], f
);
54 void dpoly::operator *= (const dpoly
& f
)
56 assert(coeff
->Size
== f
.coeff
->Size
);
57 Vector
*old
= Vector_Alloc(coeff
->Size
);
58 Vector_Copy(coeff
->p
, old
->p
, coeff
->Size
);
59 Vector_Scale(coeff
->p
, coeff
->p
, f
.coeff
->p
[0], coeff
->Size
);
60 for (int i
= 1; i
< coeff
->Size
; ++i
)
61 for (int j
= 0; i
+j
< coeff
->Size
; ++j
)
62 value_addmul(coeff
->p
[i
+j
], f
.coeff
->p
[i
], old
->p
[j
]);
66 Vector
*dpoly::div(const dpoly
& d
)
68 int len
= coeff
->Size
;
69 Vector
*denom
= Vector_Alloc(len
);
73 /* Make sure denominators are positive */
74 if (value_neg_p(d
.coeff
->p
[0])) {
75 Vector_Oppose(d
.coeff
->p
, d
.coeff
->p
, d
.coeff
->Size
);
76 Vector_Oppose(coeff
->p
, coeff
->p
, coeff
->Size
);
78 value_assign(denom
->p
[0], d
.coeff
->p
[0]);
79 for (int i
= 1; i
< len
; ++i
) {
80 value_multiply(denom
->p
[i
], denom
->p
[i
-1], denom
->p
[0]);
81 value_multiply(coeff
->p
[i
], coeff
->p
[i
], denom
->p
[i
-1]);
83 mpz_submul(coeff
->p
[i
], d
.coeff
->p
[1], coeff
->p
[i
-1]);
84 for (int j
= 2; j
<= i
; ++j
) {
85 value_multiply(tmp
, denom
->p
[j
-2], coeff
->p
[i
-j
]);
86 mpz_submul(coeff
->p
[i
], d
.coeff
->p
[j
], tmp
);
94 void dpoly::div(const dpoly
& d
, mpq_t count
, int sign
)
96 int len
= coeff
->Size
;
97 Vector
*denom
= div(d
);
100 value_assign(mpq_numref(tmp
), coeff
->p
[len
-1]);
101 value_assign(mpq_denref(tmp
), denom
->p
[len
-1]);
102 mpq_canonicalize(tmp
);
105 mpq_sub(count
, count
, tmp
);
107 mpq_add(count
, count
, tmp
);
113 void dpoly::div(const dpoly
& d
, mpq_t
*count
, const mpq_t
& factor
)
115 int len
= coeff
->Size
;
116 Vector
*denom
= div(d
);
120 for (int i
= 0; i
< len
; ++i
) {
121 value_multiply(mpq_numref(tmp
), coeff
->p
[len
-1 - i
], mpq_numref(factor
));
122 value_multiply(mpq_denref(tmp
), denom
->p
[len
-1 - i
], mpq_denref(factor
));
123 mpq_add(count
[i
], count
[i
], tmp
);
124 mpq_canonicalize(count
[i
]);
131 void dpoly_r::add_term(int i
, const vector
<int>& powers
, const ZZ
& coeff
)
138 dpoly_r_term_list::iterator k
= c
[i
].find(&tmp
);
139 if (k
!= c
[i
].end()) {
140 (*k
)->coeff
+= coeff
;
143 dpoly_r_term
*t
= new dpoly_r_term
;
149 dpoly_r::dpoly_r(int len
, int dim
)
154 c
= new dpoly_r_term_list
[len
];
157 dpoly_r::dpoly_r(dpoly
& num
, int dim
)
160 len
= num
.coeff
->Size
;
161 c
= new dpoly_r_term_list
[len
];
163 vector
<int> powers(dim
, 0);
165 for (int i
= 0; i
< len
; ++i
) {
167 value2zz(num
.coeff
->p
[i
], coeff
);
168 add_term(i
, powers
, coeff
);
172 dpoly_r::dpoly_r(dpoly
& num
, dpoly
& den
, int pos
, int dim
)
175 len
= num
.coeff
->Size
;
176 c
= new dpoly_r_term_list
[len
];
178 int *powers
= new int[dim
];
181 for (int i
= 0; i
< len
; ++i
) {
182 vector
<int> powers(dim
, 0);
185 value2zz(num
.coeff
->p
[i
], coeff
);
186 add_term(i
, powers
, coeff
);
188 for (int j
= 1; j
<= i
; ++j
) {
189 dpoly_r_term_list::iterator k
;
190 for (k
= c
[i
-j
].begin(); k
!= c
[i
-j
].end(); ++k
) {
191 powers
= (*k
)->powers
;
193 value2zz(den
.coeff
->p
[j
-1], coeff
);
194 negate(coeff
, coeff
);
195 coeff
*= (*k
)->coeff
;
196 add_term(i
, powers
, coeff
);
204 dpoly_r::dpoly_r(const dpoly_r
* num
, dpoly
& den
, int pos
, int dim
)
208 c
= new dpoly_r_term_list
[len
];
212 for (int i
= 0 ; i
< len
; ++i
) {
213 dpoly_r_term_list::iterator k
;
214 for (k
= num
->c
[i
].begin(); k
!= num
->c
[i
].end(); ++k
) {
215 vector
<int> powers
= (*k
)->powers
;
217 add_term(i
, powers
, (*k
)->coeff
);
220 for (int j
= 1; j
<= i
; ++j
) {
221 dpoly_r_term_list::iterator k
;
222 for (k
= c
[i
-j
].begin(); k
!= c
[i
-j
].end(); ++k
) {
223 vector
<int> powers
= (*k
)->powers
;
225 value2zz(den
.coeff
->p
[j
-1], coeff
);
226 negate(coeff
, coeff
);
227 coeff
*= (*k
)->coeff
;
228 add_term(i
, powers
, coeff
);
236 for (int i
= 0 ; i
< len
; ++i
)
237 for (dpoly_r_term_list::iterator k
= c
[i
].begin(); k
!= c
[i
].end(); ++k
) {
243 dpoly_r
*dpoly_r::div(const dpoly
& d
) const
245 dpoly_r
*rc
= new dpoly_r(len
, dim
);
248 value2zz(d
.coeff
->p
[0], coeff0
);
249 rc
->denom
= power(coeff0
, len
);
250 ZZ inv_d
= rc
->denom
/ coeff0
;
252 for (int i
= 0; i
< len
; ++i
) {
253 for (dpoly_r_term_list::iterator k
= c
[i
].begin(); k
!= c
[i
].end(); ++k
) {
254 coeff
= (*k
)->coeff
* inv_d
;
255 rc
->add_term(i
, (*k
)->powers
, coeff
);
258 for (int j
= 1; j
<= i
; ++j
) {
259 dpoly_r_term_list::iterator k
;
260 for (k
= rc
->c
[i
-j
].begin(); k
!= rc
->c
[i
-j
].end(); ++k
) {
261 value2zz(d
.coeff
->p
[j
], coeff
);
262 coeff
= - coeff
* (*k
)->coeff
/ coeff0
;
263 rc
->add_term(i
, (*k
)->powers
, coeff
);
270 void dpoly_r::dump(void)
272 for (int i
= 0; i
< len
; ++i
) {
275 cerr
<< c
[i
].size() << endl
;
276 for (dpoly_r_term_list::iterator j
= c
[i
].begin(); j
!= c
[i
].end(); ++j
) {
277 for (int k
= 0; k
< dim
; ++k
) {
278 cerr
<< (*j
)->powers
[k
] << " ";
280 cerr
<< ": " << (*j
)->coeff
<< "/" << denom
<< endl
;