5 #include <NTL/vec_ZZ.h>
6 #include <NTL/mat_ZZ.h>
7 #include <barvinok/polylib.h>
8 #include <barvinok/util.h>
10 #include "lattice_point.h"
16 struct OrthogonalException Orthogonal
;
18 void np_base::handle(const signed_cone
& sc
, barvinok_options
*options
)
20 assert(sc
.rays
.NumRows() == dim
);
22 handle(sc
.rays
, current_vertex
, factor
, sc
.det
, options
);
26 void np_base::start(Polyhedron
*P
, barvinok_options
*options
)
33 for (int i
= 0; i
< P
->NbRays
; ++i
) {
34 if (!value_pos_p(P
->Ray
[i
][dim
+1]))
37 Polyhedron
*C
= supporting_cone(P
, i
);
38 do_vertex_cone(factor
, C
, P
->Ray
[i
]+1, options
);
41 } catch (OrthogonalException
&e
) {
49 * f: the powers in the denominator for the remaining vars
50 * each row refers to a factor
51 * den_s: for each factor, the power of (s+1)
53 * num_s: powers in the numerator corresponding to the summed vars
54 * num_p: powers in the numerator corresponding to the remaining vars
55 * number of rays in cone: "dim" = "k"
56 * length of each ray: "dim" = "d"
57 * for now, it is assumed: k == d
59 * den_p: for each factor
60 * 0: independent of remaining vars
61 * 1: power corresponds to corresponding row in f
63 * all inputs are subject to change
65 void normalize(ZZ
& sign
, vec_ZZ
& num_s
, mat_ZZ
& num_p
, vec_ZZ
& den_s
, vec_ZZ
& den_p
,
68 unsigned nparam
= num_p
.NumCols();
71 for (int j
= 0; j
< den_s
.length(); ++j
) {
77 for (k
= 0; k
< nparam
; ++k
)
84 for (int i
= 0; i
< num_p
.NumRows(); ++i
)
92 den_s
[j
] = abs(den_s
[j
]);
93 for (int i
= 0; i
< num_p
.NumRows(); ++i
)
102 void reducer::base(const vec_QQ
& c
, const mat_ZZ
& num
, const mat_ZZ
& den_f
)
104 for (int i
= 0; i
< num
.NumRows(); ++i
)
105 base(c
[i
], num
[i
], den_f
);
108 struct dpoly_r_scanner
{
110 const dpoly
* const *num
;
113 dpoly_r_term_list::iterator
*iter
;
117 dpoly_r_scanner(const dpoly
* const *num
, int n
, const dpoly_r
*rc
, int dim
)
118 : rc(rc
), num(num
), n(n
), dim(dim
), powers(dim
, 0) {
120 iter
= new dpoly_r_term_list::iterator
[rc
->len
];
121 for (int i
= 0; i
< rc
->len
; ++i
) {
123 for (k
= 0; k
< n
; ++k
)
124 if (value_notzero_p(num
[k
]->coeff
->p
[rc
->len
-1-i
]))
127 iter
[i
] = rc
->c
[i
].begin();
129 iter
[i
] = rc
->c
[i
].end();
136 for (int i
= 0; i
< rc
->len
; ++i
) {
137 if (iter
[i
] == rc
->c
[i
].end())
140 pos
= new int[rc
->len
];
143 if ((*iter
[i
])->powers
< (*iter
[pos
[0]])->powers
) {
146 } else if ((*iter
[i
])->powers
== (*iter
[pos
[0]])->powers
)
154 powers
= (*iter
[pos
[0]])->powers
;
155 for (int k
= 0; k
< n
; ++k
) {
156 value2zz(num
[k
]->coeff
->p
[rc
->len
-1-pos
[0]], tmp
);
157 mul(coeff
[k
], (*iter
[pos
[0]])->coeff
, tmp
);
160 for (int i
= 1; i
< len
; ++i
) {
161 for (int k
= 0; k
< n
; ++k
) {
162 value2zz(num
[k
]->coeff
->p
[rc
->len
-1-pos
[i
]], tmp
);
163 mul(tmp
, (*iter
[pos
[i
]])->coeff
, tmp
);
164 add(coeff
[k
], coeff
[k
], tmp
);
179 void reducer::reduce_canonical(const vec_QQ
& c
, const mat_ZZ
& num
,
185 for (int i
= 0; i
< c2
.length(); ++i
) {
186 c2
[i
].canonicalize();
190 if (i
< c2
.length()-1) {
191 num2
[i
] = num2
[c2
.length()-1];
192 c2
[i
] = c2
[c2
.length()-1];
194 num2
.SetDims(num2
.NumRows()-1, num2
.NumCols());
195 c2
.SetLength(c2
.length()-1);
198 reduce(c2
, num2
, den_f
);
201 void reducer::reduce(const vec_QQ
& c
, const mat_ZZ
& num
, const mat_ZZ
& den_f
)
203 assert(c
.length() == num
.NumRows());
204 unsigned len
= den_f
.NumRows(); // number of factors in den
207 if (num
.NumCols() == lower
) {
211 assert(num
.NumCols() > 1);
212 assert(num
.NumRows() > 0);
219 split(num
, num_s
, num_p
, den_f
, den_s
, den_r
);
222 den_p
.SetLength(len
);
224 ZZ
sign(INIT_VAL
, 1);
225 normalize(sign
, num_s
, num_p
, den_s
, den_p
, den_r
);
228 int only_param
= 0; // k-r-s from text
229 int no_param
= 0; // r from text
230 for (int k
= 0; k
< len
; ++k
) {
233 else if (den_s
[k
] == 0)
237 reduce(c2
, num_p
, den_r
);
241 pden
.SetDims(only_param
, den_r
.NumCols());
243 for (k
= 0, l
= 0; k
< len
; ++k
)
245 pden
[l
++] = den_r
[k
];
247 for (k
= 0; k
< len
; ++k
)
251 dpoly
**n
= new dpoly
*[num_s
.length()];
252 for (int i
= 0; i
< num_s
.length(); ++i
) {
253 zz2value(num_s
[i
], tz
);
254 n
[i
] = new dpoly(no_param
, tz
);
255 /* Search for other numerator (j) with same num_p.
256 * If found, replace a[j]/b[j] * n[j] and a[i]/b[i] * n[i]
257 * by 1/(b[j]*b[i]/g) * (a[j]*b[i]/g * n[j] + a[i]*b[j]/g * n[i])
258 * where g = gcd(b[i], b[j].
260 for (int j
= 0; j
< i
; ++j
) {
261 if (num_p
[i
] != num_p
[j
])
263 ZZ g
= GCD(c2
[i
].d
, c2
[j
].d
);
264 zz2value(c2
[j
].n
* c2
[i
].d
/g
, tz
);
266 zz2value(c2
[i
].n
* c2
[j
].d
/g
, tz
);
270 c2
[j
].d
*= c2
[i
].d
/g
;
272 if (i
< num_s
.length()-1) {
273 num_s
[i
] = num_s
[num_s
.length()-1];
274 num_p
[i
] = num_p
[num_s
.length()-1];
275 c2
[i
] = c2
[num_s
.length()-1];
277 num_s
.SetLength(num_s
.length()-1);
278 c2
.SetLength(c2
.length()-1);
279 num_p
.SetDims(num_p
.NumRows()-1, num_p
.NumCols());
284 zz2value(den_s
[k
], tz
);
285 dpoly
D(no_param
, tz
, 1);
288 zz2value(den_s
[k
], tz
);
289 dpoly
fact(no_param
, tz
, 1);
293 if (no_param
+ only_param
== len
) {
295 q
.SetLength(num_s
.length());
296 for (int i
= 0; i
< num_s
.length(); ++i
) {
297 mpq_set_si(tcount
, 0, 1);
298 n
[i
]->div(D
, tcount
, 1);
300 value2zz(mpq_numref(tcount
), q
[i
].n
);
301 value2zz(mpq_denref(tcount
), q
[i
].d
);
304 for (int i
= q
.length()-1; i
>= 0; --i
) {
306 q
[i
] = q
[q
.length()-1];
307 num_p
[i
] = num_p
[q
.length()-1];
308 q
.SetLength(q
.length()-1);
309 num_p
.SetDims(num_p
.NumRows()-1, num_p
.NumCols());
314 reduce(q
, num_p
, pden
);
317 dpoly
one(no_param
, tz
);
320 for (k
= 0; k
< len
; ++k
) {
321 if (den_s
[k
] == 0 || den_p
[k
] == 0)
324 zz2value(den_s
[k
], tz
);
325 dpoly
pd(no_param
-1, tz
, 1);
328 for (l
= 0; l
< k
; ++l
)
329 if (den_r
[l
] == den_r
[k
])
333 r
= new dpoly_r(one
, pd
, l
, len
);
335 dpoly_r
*nr
= new dpoly_r(r
, pd
, l
, len
);
342 factor
.SetLength(c2
.length());
343 int common
= pden
.NumRows();
344 dpoly_r
*rc
= r
->div(D
);
345 for (int i
= 0; i
< num_s
.length(); ++i
) {
346 factor
[i
].d
= c2
[i
].d
;
347 factor
[i
].d
*= rc
->denom
;
350 dpoly_r_scanner
scanner(n
, num_s
.length(), rc
, len
);
352 while (scanner
.next()) {
354 for (i
= 0; i
< num_s
.length(); ++i
)
355 if (scanner
.coeff
[i
] != 0)
357 if (i
== num_s
.length())
360 pden
.SetDims(rows
, pden
.NumCols());
361 for (int k
= 0; k
< rc
->dim
; ++k
) {
362 int n
= scanner
.powers
[k
];
365 pden
.SetDims(rows
+n
, pden
.NumCols());
366 for (int l
= 0; l
< n
; ++l
)
367 pden
[rows
+l
] = den_r
[k
];
370 /* The denominators in factor are kept constant
371 * over all iterations of the enclosing while loop.
372 * The rational numbers in factor may therefore not be
373 * canonicalized. Some may even be zero.
375 for (int i
= 0; i
< num_s
.length(); ++i
) {
376 factor
[i
].n
= c2
[i
].n
;
377 factor
[i
].n
*= scanner
.coeff
[i
];
379 reduce_canonical(factor
, num_p
, pden
);
385 for (int i
= 0; i
< num_s
.length(); ++i
)
391 void reducer::handle(const mat_ZZ
& den
, Value
*V
, const QQ
& c
,
392 unsigned long det
, barvinok_options
*options
)
396 Matrix
*points
= Matrix_Alloc(det
, dim
);
397 Matrix
* Rays
= zz2matrix(den
);
398 lattice_points_fixed(V
, V
, Rays
, Rays
, points
, det
);
400 matrix2zz(points
, vertex
, points
->NbRows
, points
->NbColumns
);
403 vc
.SetLength(vertex
.NumRows());
404 for (int i
= 0; i
< vc
.length(); ++i
)
407 reduce(vc
, vertex
, den
);
410 void split_one(const mat_ZZ
& num
, vec_ZZ
& num_s
, mat_ZZ
& num_p
,
411 const mat_ZZ
& den_f
, vec_ZZ
& den_s
, mat_ZZ
& den_r
)
413 unsigned len
= den_f
.NumRows(); // number of factors in den
414 unsigned d
= num
.NumCols() - 1;
416 den_s
.SetLength(len
);
417 den_r
.SetDims(len
, d
);
419 for (int r
= 0; r
< len
; ++r
) {
420 den_s
[r
] = den_f
[r
][0];
421 for (int k
= 1; k
<= d
; ++k
)
422 den_r
[r
][k
-1] = den_f
[r
][k
];
425 num_s
.SetLength(num
.NumRows());
426 num_p
.SetDims(num
.NumRows(), d
);
427 for (int i
= 0; i
< num
.NumRows(); ++i
) {
428 num_s
[i
] = num
[i
][0];
429 for (int k
= 1 ; k
<= d
; ++k
)
430 num_p
[i
][k
-1] = num
[i
][k
];
434 void icounter::base(const QQ
& c
, const vec_ZZ
& num
, const mat_ZZ
& den_f
)
439 unsigned len
= den_f
.NumRows(); // number of factors in den
444 den_s
.SetLength(len
);
445 assert(num
.length() == 1);
447 for (r
= 0; r
< len
; ++r
)
448 den_s
[r
] = den_f
[r
][0];
449 int sign
= (len
% 2) ? -1 : 1;
453 zz2value(den_s
[0], tz
);
455 for (int k
= 1; k
< len
; ++k
) {
456 zz2value(den_s
[k
], tz
);
457 dpoly
fact(len
, tz
, 1);
460 mpq_set_si(tcount
, 0, 1);
463 value_oppose(tn
, tn
);
465 mpz_mul(mpq_numref(tcount
), mpq_numref(tcount
), tn
);
466 mpz_mul(mpq_denref(tcount
), mpq_denref(tcount
), td
);
467 mpq_canonicalize(tcount
);
469 value_assign(mpq_numref(tcount
), tn
);
470 value_assign(mpq_denref(tcount
), td
);
472 mpq_add(count
, count
, tcount
);