1 #include <NTL/mat_ZZ.h>
2 #include <NTL/vec_ZZ.h>
3 #include <barvinok/barvinok.h>
4 #include <barvinok/evalue.h>
5 #include <barvinok/util.h>
7 #include "conversion.h"
8 #include "lattice_point.h"
10 #define ALLOC(type) (type*)malloc(sizeof(type))
12 /* returns an evalue that corresponds to
16 static evalue
*term(int param
, ZZ
& c
, Value
*den
= NULL
)
18 evalue
*EP
= new evalue();
20 value_set_si(EP
->d
,0);
21 EP
->x
.p
= new_enode(polynomial
, 2, param
+ 1);
22 evalue_set_si(&EP
->x
.p
->arr
[0], 0, 1);
23 value_init(EP
->x
.p
->arr
[1].x
.n
);
25 value_set_si(EP
->x
.p
->arr
[1].d
, 1);
27 value_assign(EP
->x
.p
->arr
[1].d
, *den
);
28 zz2value(c
, EP
->x
.p
->arr
[1].x
.n
);
32 /* returns an evalue that corresponds to
36 evalue
*multi_monom(vec_ZZ
& p
)
38 evalue
*X
= new evalue();
41 unsigned nparam
= p
.length()-1;
42 zz2value(p
[nparam
], X
->x
.n
);
43 value_set_si(X
->d
, 1);
44 for (int i
= 0; i
< nparam
; ++i
) {
47 evalue
*T
= term(i
, p
[i
]);
56 * Check whether mapping polyhedron P on the affine combination
57 * num yields a range that has a fixed quotient on integer
59 * If zero is true, then we are only interested in the quotient
60 * for the cases where the remainder is zero.
61 * Returns NULL if false and a newly allocated value if true.
63 static Value
*fixed_quotient(Polyhedron
*P
, vec_ZZ
& num
, Value d
, bool zero
)
66 int len
= num
.length();
67 Matrix
*T
= Matrix_Alloc(2, len
);
68 zz2values(num
, T
->p
[0]);
69 value_set_si(T
->p
[1][len
-1], 1);
70 Polyhedron
*I
= Polyhedron_Image(P
, T
, P
->NbConstraints
);
74 for (i
= 0; i
< I
->NbRays
; ++i
)
75 if (value_zero_p(I
->Ray
[i
][2])) {
83 int bounded
= line_minmax(I
, &min
, &max
);
87 mpz_cdiv_q(min
, min
, d
);
89 mpz_fdiv_q(min
, min
, d
);
90 mpz_fdiv_q(max
, max
, d
);
92 if (value_eq(min
, max
)) {
95 value_assign(*ret
, min
);
103 * Normalize linear expression coef modulo m
104 * Removes common factor and reduces coefficients
105 * Returns index of first non-zero coefficient or len
107 int normal_mod(Value
*coef
, int len
, Value
*m
)
112 Vector_Gcd(coef
, len
, &gcd
);
114 Vector_AntiScale(coef
, coef
, gcd
, len
);
116 value_division(*m
, *m
, gcd
);
123 for (j
= 0; j
< len
; ++j
)
124 mpz_fdiv_r(coef
[j
], coef
[j
], *m
);
125 for (j
= 0; j
< len
; ++j
)
126 if (value_notzero_p(coef
[j
]))
132 static bool mod_needed(Polyhedron
*PD
, vec_ZZ
& num
, Value d
, evalue
*E
)
134 Value
*q
= fixed_quotient(PD
, num
, d
, false);
139 value_oppose(*q
, *q
);
142 value_set_si(EV
.d
, 1);
144 value_multiply(EV
.x
.n
, *q
, d
);
146 free_evalue_refs(&EV
);
152 /* modifies f argument ! */
153 static void ceil_mod(Value
*coef
, int len
, Value d
, ZZ
& f
, evalue
*EP
, Polyhedron
*PD
)
159 Vector_Scale(coef
, coef
, m
, len
);
162 int j
= normal_mod(coef
, len
, &m
);
170 values2zz(coef
, num
, len
);
177 evalue_set_si(&tmp
, 0, 1);
181 while (j
< len
-1 && (num
[j
] == g
/2 || num
[j
] == 0))
183 if ((j
< len
-1 && num
[j
] > g
/2) || (j
== len
-1 && num
[j
] >= (g
+1)/2)) {
184 for (int k
= j
; k
< len
-1; ++k
)
187 num
[len
-1] = g
- 1 - num
[len
-1];
188 value_assign(tmp
.d
, m
);
190 zz2value(t
, tmp
.x
.n
);
196 ZZ t
= num
[len
-1] * f
;
197 zz2value(t
, tmp
.x
.n
);
198 value_assign(tmp
.d
, m
);
201 evalue
*E
= multi_monom(num
);
205 if (PD
&& !mod_needed(PD
, num
, m
, E
)) {
208 value_assign(EV
.d
, m
);
213 value_set_si(EV
.x
.n
, 1);
214 value_assign(EV
.d
, m
);
217 value_set_si(EV
.d
, 0);
218 EV
.x
.p
= new_enode(fractional
, 3, -1);
219 evalue_copy(&EV
.x
.p
->arr
[0], E
);
220 evalue_set_si(&EV
.x
.p
->arr
[1], 0, 1);
221 value_init(EV
.x
.p
->arr
[2].x
.n
);
222 zz2value(f
, EV
.x
.p
->arr
[2].x
.n
);
223 value_set_si(EV
.x
.p
->arr
[2].d
, 1);
228 free_evalue_refs(&EV
);
233 free_evalue_refs(&tmp
);
240 static void ceil(Value
*coef
, int len
, Value d
, ZZ
& f
,
241 evalue
*EP
, Polyhedron
*PD
) {
242 ceil_mod(coef
, len
, d
, f
, EP
, PD
);
245 static void ceil(Value
*coef
, int len
, Value d
, ZZ
& f
,
246 evalue
*EP
, Polyhedron
*PD
) {
247 ceil_mod(coef
, len
, d
, f
, EP
, PD
);
248 evalue_mod2table(EP
, len
-1);
252 evalue
* bv_ceil3(Value
*coef
, int len
, Value d
, Polyhedron
*P
)
254 Vector
*val
= Vector_Alloc(len
);
259 Vector_Scale(coef
, val
->p
, t
, len
);
260 value_absolute(t
, d
);
263 values2zz(val
->p
, num
, len
);
264 evalue
*EP
= multi_monom(num
);
269 value_set_si(tmp
.x
.n
, 1);
270 value_assign(tmp
.d
, t
);
276 ceil_mod(val
->p
, len
, t
, one
, EP
, P
);
279 /* copy EP to malloc'ed evalue */
280 evalue
*E
= ALLOC(evalue
);
284 free_evalue_refs(&tmp
);
290 void lattice_point(Value
* values
, Polyhedron
*i
, vec_ZZ
& vertex
)
292 unsigned dim
= i
->Dimension
;
293 if(!value_one_p(values
[dim
])) {
294 Matrix
* Rays
= rays(i
);
295 Matrix
*inv
= Matrix_Alloc(Rays
->NbRows
, Rays
->NbColumns
);
296 int ok
= Matrix_Inverse(Rays
, inv
);
300 Vector
*lambda
= Vector_Alloc(dim
+1);
301 Vector_Matrix_Product(values
, inv
, lambda
->p
);
303 for (int j
= 0; j
< dim
; ++j
)
304 mpz_cdiv_q(lambda
->p
[j
], lambda
->p
[j
], lambda
->p
[dim
]);
305 value_set_si(lambda
->p
[dim
], 1);
306 Vector
*A
= Vector_Alloc(dim
+1);
307 Vector_Matrix_Product(lambda
->p
, Rays
, A
->p
);
310 values2zz(A
->p
, vertex
, dim
);
313 values2zz(values
, vertex
, dim
);
316 static void vertex_period(
317 Polyhedron
*i
, vec_ZZ
& lambda
, Matrix
*T
,
318 Value lcm
, int p
, Vector
*val
,
319 evalue
*E
, evalue
* ev
,
322 unsigned nparam
= T
->NbRows
- 1;
323 unsigned dim
= i
->Dimension
;
330 Vector
* values
= Vector_Alloc(dim
+ 1);
331 Vector_Matrix_Product(val
->p
, T
, values
->p
);
332 value_assign(values
->p
[dim
], lcm
);
333 lattice_point(values
->p
, i
, vertex
);
334 num
= vertex
* lambda
;
339 zz2value(num
, ev
->x
.n
);
340 value_assign(ev
->d
, lcm
);
347 values2zz(T
->p
[p
], vertex
, dim
);
348 nump
= vertex
* lambda
;
349 if (First_Non_Zero(val
->p
, p
) == -1) {
350 value_assign(tmp
, lcm
);
351 evalue
*ET
= term(p
, nump
, &tmp
);
353 free_evalue_refs(ET
);
357 value_assign(tmp
, lcm
);
358 if (First_Non_Zero(T
->p
[p
], dim
) != -1)
359 Vector_Gcd(T
->p
[p
], dim
, &tmp
);
361 if (value_lt(tmp
, lcm
)) {
364 value_division(tmp
, lcm
, tmp
);
365 value_set_si(ev
->d
, 0);
366 ev
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
367 value2zz(tmp
, count
);
369 value_decrement(tmp
, tmp
);
371 ZZ new_offset
= offset
- count
* nump
;
372 value_assign(val
->p
[p
], tmp
);
373 vertex_period(i
, lambda
, T
, lcm
, p
+1, val
, E
,
374 &ev
->x
.p
->arr
[VALUE_TO_INT(tmp
)], new_offset
);
375 } while (value_pos_p(tmp
));
377 vertex_period(i
, lambda
, T
, lcm
, p
+1, val
, E
, ev
, offset
);
381 /* Returns the power of (t+1) in the term of a rational generating function,
382 * i.e., the scalar product of the actual lattice point and lambda.
383 * The lattice point is the unique lattice point in the fundamental parallelepiped
384 * of the unimodual cone i shifted to the parametric vertex W/lcm.
386 * The rows of W refer to the coordinates of the vertex
387 * The first nparam columns are the coefficients of the parameters
388 * and the final column is the constant term.
389 * lcm is the common denominator of all coefficients.
391 * PD is the parameter domain, which, if != NULL, may be used to simply the
392 * resulting expression.
395 evalue
* lattice_point(
396 Polyhedron
*i
, vec_ZZ
& lambda
, Matrix
*W
, Value lcm
, Polyhedron
*PD
)
398 unsigned nparam
= W
->NbColumns
- 1;
400 Matrix
* Rays
= rays2(i
);
401 Matrix
*T
= Transpose(Rays
);
402 Matrix
*T2
= Matrix_Copy(T
);
403 Matrix
*inv
= Matrix_Alloc(T2
->NbRows
, T2
->NbColumns
);
404 int ok
= Matrix_Inverse(T2
, inv
);
409 matrix2zz(W
, vertex
, W
->NbRows
, W
->NbColumns
);
412 num
= lambda
* vertex
;
414 evalue
*EP
= multi_monom(num
);
419 value_set_si(tmp
.x
.n
, 1);
420 value_assign(tmp
.d
, lcm
);
424 Matrix
*L
= Matrix_Alloc(inv
->NbRows
, W
->NbColumns
);
425 Matrix_Product(inv
, W
, L
);
428 matrix2zz(T
, RT
, T
->NbRows
, T
->NbColumns
);
431 vec_ZZ p
= lambda
* RT
;
433 for (int i
= 0; i
< L
->NbRows
; ++i
) {
434 ceil_mod(L
->p
[i
], nparam
+1, lcm
, p
[i
], EP
, PD
);
440 free_evalue_refs(&tmp
);
444 evalue
* lattice_point(
445 Polyhedron
*i
, vec_ZZ
& lambda
, Matrix
*W
, Value lcm
, Polyhedron
*PD
)
447 Matrix
*T
= Transpose(W
);
448 unsigned nparam
= T
->NbRows
- 1;
450 evalue
*EP
= new evalue();
452 evalue_set_si(EP
, 0, 1);
455 Vector
*val
= Vector_Alloc(nparam
+1);
456 value_set_si(val
->p
[nparam
], 1);
457 ZZ
offset(INIT_VAL
, 0);
459 vertex_period(i
, lambda
, T
, lcm
, 0, val
, EP
, &ev
, offset
);
462 free_evalue_refs(&ev
);
472 /* returns the unique lattice point in the fundamental parallelepiped
473 * of the unimodual cone C shifted to the parametric vertex V.
475 * The return values num and E_vertex are such that
476 * coordinate i of this lattice point is equal to
478 * num[i] + E_vertex[i]
480 void lattice_point(Param_Vertices
*V
, Polyhedron
*C
, vec_ZZ
& num
,
483 unsigned nparam
= V
->Vertex
->NbColumns
- 2;
484 unsigned dim
= C
->Dimension
;
486 vertex
.SetLength(nparam
+1);
491 value_set_si(lcm
, 1);
493 for (int j
= 0; j
< V
->Vertex
->NbRows
; ++j
) {
494 value_lcm(lcm
, V
->Vertex
->p
[j
][nparam
+1], &lcm
);
497 if (value_notone_p(lcm
)) {
498 Matrix
* mv
= Matrix_Alloc(dim
, nparam
+1);
499 for (int j
= 0 ; j
< dim
; ++j
) {
500 value_division(tmp
, lcm
, V
->Vertex
->p
[j
][nparam
+1]);
501 Vector_Scale(V
->Vertex
->p
[j
], mv
->p
[j
], tmp
, nparam
+1);
504 Matrix
* Rays
= rays2(C
);
505 Matrix
*T
= Transpose(Rays
);
506 Matrix
*T2
= Matrix_Copy(T
);
507 Matrix
*inv
= Matrix_Alloc(T2
->NbRows
, T2
->NbColumns
);
508 int ok
= Matrix_Inverse(T2
, inv
);
512 Matrix
*L
= Matrix_Alloc(inv
->NbRows
, mv
->NbColumns
);
513 Matrix_Product(inv
, mv
, L
);
522 evalue
*remainders
[dim
];
523 for (int i
= 0; i
< dim
; ++i
) {
524 remainders
[i
] = evalue_zero();
526 ceil(L
->p
[i
], nparam
+1, lcm
, one
, remainders
[i
], 0);
531 for (int i
= 0; i
< V
->Vertex
->NbRows
; ++i
) {
532 values2zz(mv
->p
[i
], vertex
, nparam
+1);
533 E_vertex
[i
] = multi_monom(vertex
);
536 value_set_si(f
.x
.n
, 1);
537 value_assign(f
.d
, lcm
);
539 emul(&f
, E_vertex
[i
]);
541 for (int j
= 0; j
< dim
; ++j
) {
542 if (value_zero_p(T
->p
[i
][j
]))
546 evalue_copy(&cp
, remainders
[j
]);
547 if (value_notone_p(T
->p
[i
][j
])) {
548 value_set_si(f
.d
, 1);
549 value_assign(f
.x
.n
, T
->p
[i
][j
]);
552 eadd(&cp
, E_vertex
[i
]);
553 free_evalue_refs(&cp
);
556 for (int i
= 0; i
< dim
; ++i
) {
557 free_evalue_refs(remainders
[i
]);
561 free_evalue_refs(&f
);
572 for (int i
= 0; i
< V
->Vertex
->NbRows
; ++i
) {
574 if (First_Non_Zero(V
->Vertex
->p
[i
], nparam
) == -1) {
576 value2zz(V
->Vertex
->p
[i
][nparam
], num
[i
]);
578 values2zz(V
->Vertex
->p
[i
], vertex
, nparam
+1);
579 E_vertex
[i
] = multi_monom(vertex
);