5 #include <NTL/vec_ZZ.h>
6 #include <NTL/mat_ZZ.h>
7 #include <barvinok/polylib.h>
9 #include "lattice_point.h"
15 static int lex_cmp(vec_ZZ
& a
, vec_ZZ
& b
)
17 assert(a
.length() == b
.length());
19 for (int j
= 0; j
< a
.length(); ++j
)
21 return a
[j
] < b
[j
] ? -1 : 1;
25 void bf_base::add_term(bfc_term_base
*t
, vec_ZZ
& num_orig
, vec_ZZ
& extra_num
)
28 int d
= num_orig
.length();
30 for (int l
= 0; l
< d
-1; ++l
)
31 num
[l
] = num_orig
[l
+1] + extra_num
[l
];
36 void bf_base::add_term(bfc_term_base
*t
, vec_ZZ
& num
)
38 int len
= t
->terms
.NumRows();
40 for (i
= 0; i
< len
; ++i
) {
41 r
= lex_cmp(t
->terms
[i
], num
);
45 if (i
== len
|| r
> 0) {
46 t
->terms
.SetDims(len
+1, num
.length());
55 bfc_term_base
* bf_base::find_bfc_term(bfc_vec
& v
, int *powers
, int len
)
58 for (i
= v
.begin(); i
!= v
.end(); ++i
) {
60 for (j
= 0; j
< len
; ++j
)
61 if ((*i
)->powers
[j
] != powers
[j
])
65 if ((*i
)->powers
[j
] > powers
[j
])
69 bfc_term_base
* t
= new_bf_term(len
);
71 memcpy(t
->powers
, powers
, len
* sizeof(int));
76 void bf_base::reduce(mat_ZZ
& factors
, bfc_vec
& v
, barvinok_options
*options
)
79 unsigned d
= factors
.NumCols();
82 return base(factors
, v
);
84 bf_reducer
bfr(factors
, v
, this);
88 if (bfr
.vn
.size() > 0)
89 reduce(bfr
.nfactors
, bfr
.vn
, options
);
92 int bf_base::setup_factors(const mat_ZZ
& rays
, mat_ZZ
& factors
,
93 bfc_term_base
* t
, int s
)
95 factors
.SetDims(dim
, dim
);
99 for (r
= 0; r
< dim
; ++r
)
102 for (r
= 0; r
< dim
; ++r
) {
103 factors
[r
] = rays
[r
];
105 for (k
= 0; k
< dim
; ++k
)
106 if (factors
[r
][k
] != 0)
108 if (factors
[r
][k
] < 0) {
109 factors
[r
] = -factors
[r
];
110 for (int i
= 0; i
< t
->terms
.NumRows(); ++i
)
111 t
->terms
[i
] += factors
[r
];
119 void bf_base::handle(const mat_ZZ
& rays
, Value
*vertex
, const QQ
& c
,
120 unsigned long det
, barvinok_options
*options
)
122 bfc_term
* t
= new bfc_term(dim
);
123 vector
< bfc_term_base
* > v
;
126 Matrix
*points
= Matrix_Alloc(det
, dim
);
127 Matrix
* Rays
= zz2matrix(rays
);
128 lattice_points_fixed(vertex
, vertex
, Rays
, Rays
, points
, det
);
130 matrix2zz(points
, t
->terms
, points
->NbRows
, points
->NbColumns
);
133 // the elements of factors are always lexpositive
135 int s
= setup_factors(rays
, factors
, t
, 1);
137 t
->c
.SetLength(t
->terms
.NumRows());
139 for (int i
= 0; i
< t
->c
.length(); ++i
) {
144 reduce(factors
, v
, options
);
147 bfc_term_base
* bfcounter_base::new_bf_term(int len
)
149 bfc_term
* t
= new bfc_term(len
);
154 void bfcounter_base::set_factor(bfc_term_base
*t
, int k
, int change
)
156 bfc_term
* bfct
= static_cast<bfc_term
*>(t
);
162 void bfcounter_base::set_factor(bfc_term_base
*t
, int k
, mpq_t
&f
, int change
)
164 bfc_term
* bfct
= static_cast<bfc_term
*>(t
);
165 value2zz(mpq_numref(f
), c
.n
);
166 value2zz(mpq_denref(f
), c
.d
);
172 void bfcounter_base::set_factor(bfc_term_base
*t
, int k
, const QQ
& c_factor
,
175 bfc_term
* bfct
= static_cast<bfc_term
*>(t
);
182 void bfcounter_base::insert_term(bfc_term_base
*t
, int i
)
184 bfc_term
* bfct
= static_cast<bfc_term
*>(t
);
185 int len
= t
->terms
.NumRows()-1; // already increased by one
187 bfct
->c
.SetLength(len
+1);
188 for (int j
= len
; j
> i
; --j
) {
189 bfct
->c
[j
] = bfct
->c
[j
-1];
190 t
->terms
[j
] = t
->terms
[j
-1];
195 void bfcounter_base::update_term(bfc_term_base
*t
, int i
)
197 bfc_term
* bfct
= static_cast<bfc_term
*>(t
);
202 void bf_reducer::compute_extra_num(int i
)
206 no_param
= 0; // r from text
207 only_param
= 0; // k-r-s from text
208 total_power
= 0; // k from text
210 for (int j
= 0; j
< nf
; ++j
) {
211 if (v
[i
]->powers
[j
] == 0)
214 total_power
+= v
[i
]->powers
[j
];
215 if (factors
[j
][0] == 0) {
216 only_param
+= v
[i
]->powers
[j
];
220 if (old2new
[j
] == -1)
221 no_param
+= v
[i
]->powers
[j
];
223 extra_num
+= -sign
[j
] * v
[i
]->powers
[j
] * nfactors
[old2new
[j
]];
224 changes
+= v
[i
]->powers
[j
];
228 void bf_reducer::update_powers(const std::vector
<int>& powers
)
230 for (int l
= 0; l
< nnf
; ++l
)
231 npowers
[l
] = bpowers
[l
];
233 l_extra_num
= extra_num
;
236 for (int l
= 0; l
< powers
.size(); ++l
) {
240 assert(old2new
[l
] != -1);
242 npowers
[old2new
[l
]] += n
;
243 // interpretation of sign has been inverted
244 // since we inverted the power for specialization
246 l_extra_num
+= n
* nfactors
[old2new
[l
]];
253 void bf_reducer::compute_reduced_factors()
255 unsigned nf
= factors
.NumRows();
256 unsigned d
= factors
.NumCols();
258 nfactors
.SetDims(nnf
, d
-1);
260 for (int i
= 0; i
< nf
; ++i
) {
263 for (j
= 0; j
< nnf
; ++j
) {
265 for (k
= 1; k
< d
; ++k
)
266 if (factors
[i
][k
] != 0 || nfactors
[j
][k
-1] != 0)
268 if (k
< d
&& factors
[i
][k
] == -nfactors
[j
][k
-1])
271 if (factors
[i
][k
] != s
* nfactors
[j
][k
-1])
279 for (k
= 1; k
< d
; ++k
)
280 if (factors
[i
][k
] != 0)
283 if (factors
[i
][k
] < 0)
285 nfactors
.SetDims(++nnf
, d
-1);
286 for (int k
= 1; k
< d
; ++k
)
287 nfactors
[j
][k
-1] = s
* factors
[i
][k
];
293 npowers
= new int[nnf
];
294 bpowers
= new int[nnf
];
297 void bf_reducer::reduce(barvinok_options
*options
)
299 compute_reduced_factors();
303 for (int i
= 0; i
< v
.size(); ++i
) {
304 compute_extra_num(i
);
308 extra_num
.SetLength(d
-1);
310 int *npowers
= new int[nnf
];
311 for (int k
= 0; k
< nnf
; ++k
)
313 for (int k
= 0; k
< nf
; ++k
) {
314 assert(old2new
[k
] != -1);
315 npowers
[old2new
[k
]] += v
[i
]->powers
[k
];
317 extra_num
+= v
[i
]->powers
[k
] * nfactors
[old2new
[k
]];
318 changes
+= v
[i
]->powers
[k
];
322 bfc_term_base
* t
= bf
->find_bfc_term(vn
, npowers
, nnf
);
323 for (int k
= 0; k
< v
[i
]->terms
.NumRows(); ++k
) {
324 bf
->set_factor(v
[i
], k
, changes
% 2);
325 bf
->add_term(t
, v
[i
]->terms
[k
], extra_num
);
329 // powers of "constant" part
330 for (int k
= 0; k
< nnf
; ++k
)
332 for (int k
= 0; k
< nf
; ++k
) {
333 if (factors
[k
][0] != 0)
335 assert(old2new
[k
] != -1);
336 bpowers
[old2new
[k
]] += v
[i
]->powers
[k
];
338 extra_num
+= v
[i
]->powers
[k
] * nfactors
[old2new
[k
]];
339 changes
+= v
[i
]->powers
[k
];
344 for (j
= 0; j
< nf
; ++j
)
345 if (old2new
[j
] == -1 && v
[i
]->powers
[j
] > 0)
348 zz2value(factors
[j
][0], tmp
);
349 dpoly
D(no_param
, tmp
, 1);
350 for (int k
= 1; k
< v
[i
]->powers
[j
]; ++k
) {
351 dpoly
fact(no_param
, tmp
, 1);
355 if (old2new
[j
] == -1) {
356 zz2value(factors
[j
][0], tmp
);
357 for (int k
= 0; k
< v
[i
]->powers
[j
]; ++k
) {
358 dpoly
fact(no_param
, tmp
, 1);
363 if (no_param
+ only_param
== total_power
&&
364 bf
->constant_vertex(d
)) {
365 bfc_term_base
* t
= NULL
;
366 for (int k
= 0; k
< v
[i
]->terms
.NumRows(); ++k
) {
367 zz2value(v
[i
]->terms
[k
][0], tmp
);
368 dpoly
n(no_param
, tmp
);
369 mpq_set_si(bf
->tcount
, 0, 1);
370 n
.div(D
, bf
->tcount
, 1);
372 if (value_zero_p(mpq_numref(bf
->tcount
)))
376 t
= bf
->find_bfc_term(vn
, bpowers
, nnf
);
377 bf
->set_factor(v
[i
], k
, bf
->tcount
, changes
% 2);
378 bf
->add_term(t
, v
[i
]->terms
[k
], extra_num
);
381 for (int j
= 0; j
< v
[i
]->terms
.NumRows(); ++j
) {
382 zz2value(v
[i
]->terms
[j
][0], tmp
);
383 dpoly
n(no_param
, tmp
);
386 if (no_param
+ only_param
== total_power
)
387 r
= new dpoly_r(n
, nf
);
389 for (int k
= 0; k
< nf
; ++k
) {
390 if (v
[i
]->powers
[k
] == 0)
392 if (factors
[k
][0] == 0 || old2new
[k
] == -1)
395 zz2value(factors
[k
][0], tmp
);
396 dpoly
pd(no_param
-1, tmp
, 1);
398 for (int l
= 0; l
< v
[i
]->powers
[k
]; ++l
) {
400 for (q
= 0; q
< k
; ++q
)
401 if (old2new
[q
] == old2new
[k
] &&
406 r
= new dpoly_r(n
, pd
, q
, nf
);
408 dpoly_r
*nr
= new dpoly_r(r
, pd
, q
, nf
);
415 dpoly_r
*rc
= r
->div(D
);
418 factor
.d
= rc
->denom
;
420 if (bf
->constant_vertex(d
)) {
421 dpoly_r_term_list
& final
= rc
->c
[rc
->len
-1];
423 dpoly_r_term_list::iterator k
;
424 for (k
= final
.begin(); k
!= final
.end(); ++k
) {
425 if ((*k
)->coeff
== 0)
428 update_powers((*k
)->powers
);
430 bfc_term_base
* t
= bf
->find_bfc_term(vn
, npowers
, nnf
);
431 factor
.n
= (*k
)->coeff
;
432 bf
->set_factor(v
[i
], j
, factor
, l_changes
% 2);
433 bf
->add_term(t
, v
[i
]->terms
[j
], l_extra_num
);
436 bf
->cum(this, v
[i
], j
, rc
, options
);