5 #include <barvinok/util.h>
6 #include "conversion.h"
7 #include "evalue_convert.h"
8 #include "lattice_point.h"
20 static int type_offset(enode
*p
)
22 return p
->type
== fractional
? 1 :
23 p
->type
== flooring
? 1 : 0;
26 static Lattice
*extract_lattice(evalue
*e
, int nparam
)
32 /* For some mysterious reason, SolveDiophantine expects an extra
33 * [0 0 0 1] row in its input matrix.
35 Matrix
*M
= Matrix_Alloc(2, nparam
+1+1);
36 value_set_si(M
->p
[1][nparam
+1], 1);
37 evalue_extract_affine(e
, M
->p
[0], M
->p
[0]+nparam
+1, M
->p
[0]+nparam
);
39 value_set_si(M
->p
[0][nparam
+1], 0);
40 SolveDiophantine(M
, &U
, &X
);
43 L
= Matrix_Alloc(nparam
+1, nparam
+1);
44 for (i
= 0; i
< nparam
; ++i
)
45 Vector_Copy(U
->p
[i
], L
->p
[i
], nparam
);
46 value_set_si(L
->p
[nparam
][nparam
], 1);
51 /* Returns a lattice such that the quasi-polynomial e can be represented
52 * by a list of polynomials, one for each point in the fundamental
53 * parallelepiped of the lattice.
54 * If e is a polynomial, then this function returns NULL.
56 static Lattice
*extract_common_lattice(evalue
*e
, Lattice
*L
, int nparam
)
60 if (value_notzero_p(e
->d
))
63 assert(e
->x
.p
->type
!= partition
);
65 if (e
->x
.p
->type
== fractional
) {
66 Lattice
*L2
= extract_lattice(&e
->x
.p
->arr
[0], nparam
);
70 Lattice
*L3
= LatticeIntersection(L
, L2
);
77 offset
= type_offset(e
->x
.p
);
78 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
79 L
= extract_common_lattice(&e
->x
.p
->arr
[i
], L
, nparam
);
83 /* Construct an evalue dst from src corresponding to the coset represented
84 * by coset, a vector of size number of parameters plus one.
85 * The final value in this vector should be 1.
87 static void evalue_coset(const evalue
*src
, const Vector
*coset
, evalue
*dst
)
89 if (value_notzero_p(src
->d
)) {
90 value_assign(dst
->d
, src
->d
);
92 value_assign(dst
->x
.n
, src
->x
.n
);
96 if (src
->x
.p
->type
== fractional
) {
99 Vector
*c
= Vector_Alloc(coset
->Size
);
102 evalue_extract_affine(&src
->x
.p
->arr
[0], c
->p
, c
->p
+c
->Size
-1, &f
.d
);
103 Inner_Product(coset
->p
, c
->p
, c
->Size
, &f
.x
.n
);
105 mpz_fdiv_r(f
.x
.n
, f
.x
.n
, f
.d
);
107 evalue_set_si(dst
, 0, 1);
108 for (int i
= src
->x
.p
->size
-1; i
>= 1; --i
) {
111 evalue_coset(&src
->x
.p
->arr
[i
], coset
, &t
);
113 free_evalue_refs(&t
);
115 free_evalue_refs(&f
);
119 if (src
->x
.p
->type
== relation
) {
120 evalue
*arg
= evalue_eval(&src
->x
.p
->arr
[0], coset
->p
);
121 if (value_zero_p(arg
->x
.n
))
122 evalue_coset(&src
->x
.p
->arr
[1], coset
, dst
);
123 else if (src
->x
.p
->size
> 2)
124 evalue_coset(&src
->x
.p
->arr
[2], coset
, dst
);
126 evalue_set_si(dst
, 0, 1);
131 assert(src
->x
.p
->type
== polynomial
);
132 value_set_si(dst
->d
, 0);
133 dst
->x
.p
= new_enode(src
->x
.p
->type
, src
->x
.p
->size
, src
->x
.p
->pos
);
134 for (int i
= 0; i
< src
->x
.p
->size
; ++i
)
135 evalue_coset(&src
->x
.p
->arr
[i
], coset
, &dst
->x
.p
->arr
[i
]);
139 static void evalue_print_list_evalue(FILE *out
, evalue
*e
, int nparam
,
142 cerr
<< "not supported" << endl
;
145 static void evalue_print_list_evalue(FILE *out
, evalue
*e
, int nparam
,
149 L
= extract_common_lattice(e
, NULL
, nparam
);
151 print_evalue(out
, e
, params
);
153 fdostream
os(dup(fileno(out
)));
154 Vector
*coset
= Vector_Alloc(nparam
+1);
155 value_set_si(coset
->p
[nparam
], 1);
157 Matrix_Transposition(L
);
158 matrix2zz(L
, R
, nparam
, nparam
);
159 fprintf(out
, "Lattice:\n");
161 unsigned long det
= to_ulong(abs(determinant(R
)));
163 Matrix
*points
= Matrix_Alloc(det
, nparam
);
164 lattice_points_fixed(coset
->p
, coset
->p
, L
, L
, points
, det
);
165 matrix2zz(points
, vertices
, points
->NbRows
, points
->NbColumns
);
168 for (int i
= 0; i
< vertices
.NumRows(); ++i
) {
170 os
<< vertices
[i
] << endl
;
171 zz2values(vertices
[i
], coset
->p
);
173 evalue_coset(e
, coset
, &t
);
174 print_evalue(out
, &t
, params
);
175 free_evalue_refs(&t
);
182 static void evalue_print_list(FILE *out
, evalue
*e
, int nparam
,
186 assert(value_zero_p(e
->d
));
187 assert(e
->x
.p
->type
== partition
);
189 for (i
= 0; i
< e
->x
.p
->size
/2; i
++) {
190 Print_Domain(out
, EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), params
);
191 evalue_print_list_evalue(out
, &e
->x
.p
->arr
[2*i
+1], nparam
, params
);
195 static void print_domain_latex(std::ostream
& o
, Polyhedron
*D
, int nparam
,
199 for (int i
= 0; i
< D
->NbConstraints
; ++i
) {
200 if (First_Non_Zero(D
->Constraint
[i
]+1, D
->Dimension
) == -1)
205 for (int j
= 0; j
< D
->Dimension
; ++j
) {
206 if (value_zero_p(D
->Constraint
[i
][1+j
]))
209 if (!fc
&& value_pos_p(D
->Constraint
[i
][1+j
]))
211 if (value_mone_p(D
->Constraint
[i
][1+j
]))
213 else if (!value_one_p(D
->Constraint
[i
][1+j
]))
214 o
<< VALUE_TO_INT(D
->Constraint
[i
][1+j
]);
215 o
<< " " << params
[j
];
218 if (!fc
&& value_pos_p(D
->Constraint
[i
][1+D
->Dimension
]))
220 if (value_notzero_p(D
->Constraint
[i
][1+D
->Dimension
]))
221 o
<< VALUE_TO_INT(D
->Constraint
[i
][1+D
->Dimension
]);
222 if (value_zero_p(D
->Constraint
[i
][0]))
230 static void evalue_print_latex(std::ostream
& o
, const evalue
*e
,
231 int first
, int nested
,
232 const string
& suffix1
, const string
& suffix2
,
233 int nparam
, const char **params
);
235 static void evalue_print_poly_latex1(std::ostream
& o
, const evalue
*e
,
236 int first
, int nested
, const string
& base
,
237 const string
& suffix1
, const string
& suffix2
,
238 int nparam
, const char **params
)
240 int offset
= type_offset(e
->x
.p
);
241 for (int i
= e
->x
.p
->size
-1; i
>= offset
; --i
) {
242 std::ostringstream strm
;
247 strm
<< "^" << (i
-offset
);
248 evalue_print_latex(o
, &e
->x
.p
->arr
[i
], first
, nested
,
249 strm
.str(), suffix2
, nparam
, params
);
254 static void evalue_print_poly_latex2(std::ostream
& o
, const evalue
*e
,
255 int first
, int nested
, const string
& base
,
256 const string
& suffix1
, const string
& suffix2
,
257 int nparam
, const char **params
)
259 int offset
= type_offset(e
->x
.p
);
260 for (int i
= e
->x
.p
->size
-1; i
>= offset
; --i
) {
261 std::ostringstream strm
;
266 strm
<< "^" << (i
-offset
);
267 evalue_print_latex(o
, &e
->x
.p
->arr
[i
], first
, nested
,
268 suffix1
, strm
.str(), nparam
, params
);
273 static void evalue_print_latex(std::ostream
& o
, const evalue
*e
,
274 int first
, int nested
,
275 const string
& suffix1
, const string
&suffix2
,
276 int nparam
, const char **params
)
278 if (value_notzero_p(e
->d
)) {
279 if (value_zero_p(e
->x
.n
)) {
286 value_absolute(tmp
, e
->x
.n
);
287 if (!first
&& value_pos_p(e
->x
.n
))
289 if (value_neg_p(e
->x
.n
))
291 if (value_one_p(e
->d
)) {
292 if (!value_one_p(tmp
) ||
293 (suffix1
.length() == 0 && suffix2
.length() == 0))
294 o
<< VALUE_TO_INT(tmp
);
297 if (value_one_p(tmp
) && suffix1
.length() != 0)
300 o
<< VALUE_TO_INT(tmp
);
302 << VALUE_TO_INT(e
->d
) << "}";
304 if (!value_one_p(tmp
)) {
314 switch (e
->x
.p
->type
) {
316 o
<< "\\begin{cases}\n";
317 for (int i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
320 evalue_print_latex(o
, &e
->x
.p
->arr
[2*i
+1], 1, 0,
321 suffix1
, suffix2
, nparam
, params
);
322 o
<< "& \\text{if $";
323 print_domain_latex(o
, EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), nparam
, params
);
326 o
<< "\\end{cases}\n";
329 evalue_print_poly_latex1(o
, e
, first
, nested
, params
[e
->x
.p
->pos
-1],
330 suffix1
, suffix2
, nparam
, params
);
333 std::ostringstream strm
;
334 strm
<< "\\fractional{";
335 evalue_print_latex(strm
, &e
->x
.p
->arr
[0], 1, 1, "", "", nparam
, params
);
337 evalue_print_poly_latex2(o
, e
, first
, nested
,
338 strm
.str(), suffix1
, suffix2
, nparam
, params
);
347 static void evalue_print_latex(FILE *out
, const evalue
*e
, int nparam
,
350 cerr
<< "not supported" << endl
;
353 static void evalue_print_latex(FILE *out
, const evalue
*e
, int nparam
,
356 fdostream
os(dup(fileno(out
)));
357 evalue_print_latex(os
, e
, 1, 0, "", "", nparam
, params
);
361 static void evalue_print_isl(FILE *out
, const evalue
*e
, int nparam
,
365 isl_ctx
*ctx
= isl_ctx_alloc();
366 isl_dim
*dim
= isl_dim_set_alloc(ctx
, nparam
, 0);
368 isl_pw_qpolynomial
*pwqp
;
370 for (i
= 0; i
< nparam
; ++i
)
371 dim
= isl_dim_set_name(dim
, isl_dim_param
, i
, params
[i
]);
373 pwqp
= isl_pw_qpolynomial_from_evalue(dim
, e
);
375 p
= isl_printer_to_file(ctx
, out
);
376 p
= isl_printer_print_pw_qpolynomial(p
, pwqp
);
377 p
= isl_printer_end_line(p
);
380 isl_pw_qpolynomial_free(pwqp
);
385 int evalue_convert(evalue
*EP
, struct convert_options
*options
,
386 int verbose
, unsigned nparam
, const char **params
)
389 if (options
->combine
)
392 evalue_range_reduction(EP
);
394 print_evalue(stdout
, EP
, params
);
397 if (options
->floor
) {
398 fprintf(stderr
, "WARNING: floor conversion not supported\n");
399 evalue_frac2floor(EP
);
401 print_evalue(stdout
, EP
, params
);
402 } else if (options
->list
&& params
) {
403 evalue_print_list(stdout
, EP
, nparam
, params
);
405 } else if (options
->latex
&& params
) {
406 evalue_print_latex(stdout
, EP
, nparam
, params
);
408 } else if (options
->isl
&& params
) {
409 evalue_print_isl(stdout
, EP
, nparam
, params
);
411 } else if (options
->convert
) {
412 evalue_mod2table(EP
, nparam
);
414 print_evalue(stdout
, EP
, params
);