2 #include "conversion.h"
3 #include "evalue_convert.h"
4 #include "lattice_point.h"
16 static struct argp_option argp_options
[] = {
17 { "convert", 'c', 0, 0, "convert fractionals to periodics" },
18 { "combine", 'C', 0, 0 },
19 { "floor", 'f', 0, 0, "convert fractionals to floorings" },
20 { "list", 'l', 0, 0 },
21 { "latex", 'L', 0, 0 },
22 { "range-reduction", 'R', 0, 0 },
26 static error_t
parse_opt(int key
, char *arg
, struct argp_state
*state
)
28 struct convert_options
*options
= (struct convert_options
*)state
->input
;
60 return ARGP_ERR_UNKNOWN
;
65 struct argp convert_argp
= {
66 argp_options
, parse_opt
, 0, 0
69 static int type_offset(enode
*p
)
71 return p
->type
== fractional
? 1 :
72 p
->type
== flooring
? 1 : 0;
75 static Lattice
*extract_lattice(evalue
*e
, int nparam
)
81 /* For some mysterious reason, SolveDiophantine expects an extra
82 * [0 0 0 1] row in its input matrix.
84 Matrix
*M
= Matrix_Alloc(2, nparam
+1+1);
85 value_set_si(M
->p
[1][nparam
+1], 1);
86 evalue_extract_affine(e
, M
->p
[0], M
->p
[0]+nparam
+1, M
->p
[0]+nparam
);
88 value_set_si(M
->p
[0][nparam
+1], 0);
89 SolveDiophantine(M
, &U
, &X
);
92 L
= Matrix_Alloc(nparam
+1, nparam
+1);
93 for (i
= 0; i
< nparam
; ++i
)
94 Vector_Copy(U
->p
[i
], L
->p
[i
], nparam
);
95 value_set_si(L
->p
[nparam
][nparam
], 1);
100 /* Returns a lattice such that the quasi-polynomial e can be represented
101 * by a list of polynomials, one for each point in the fundamental
102 * parallelepiped of the lattice.
103 * If e is a polynomial, then this function returns NULL.
105 static Lattice
*extract_common_lattice(evalue
*e
, Lattice
*L
, int nparam
)
109 if (value_notzero_p(e
->d
))
112 assert(e
->x
.p
->type
!= partition
);
114 if (e
->x
.p
->type
== fractional
) {
115 Lattice
*L2
= extract_lattice(&e
->x
.p
->arr
[0], nparam
);
119 Lattice
*L3
= LatticeIntersection(L
, L2
);
126 offset
= type_offset(e
->x
.p
);
127 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
128 L
= extract_common_lattice(&e
->x
.p
->arr
[i
], L
, nparam
);
132 /* Construct an evalue dst from src corresponding to the coset represented
133 * by coset, a vector of size number of parameters plus one.
134 * The final value in this vector should be 1.
136 static void evalue_coset(const evalue
*src
, const Vector
*coset
, evalue
*dst
)
138 if (value_notzero_p(src
->d
)) {
139 value_assign(dst
->d
, src
->d
);
140 value_init(dst
->x
.n
);
141 value_assign(dst
->x
.n
, src
->x
.n
);
145 if (src
->x
.p
->type
== fractional
) {
148 Vector
*c
= Vector_Alloc(coset
->Size
);
151 evalue_extract_affine(&src
->x
.p
->arr
[0], c
->p
, c
->p
+c
->Size
-1, &f
.d
);
152 Inner_Product(coset
->p
, c
->p
, c
->Size
, &f
.x
.n
);
154 mpz_fdiv_r(f
.x
.n
, f
.x
.n
, f
.d
);
156 evalue_set_si(dst
, 0, 1);
157 for (int i
= src
->x
.p
->size
-1; i
>= 1; --i
) {
160 evalue_coset(&src
->x
.p
->arr
[i
], coset
, &t
);
162 free_evalue_refs(&t
);
164 free_evalue_refs(&f
);
168 if (src
->x
.p
->type
== relation
) {
169 evalue
*arg
= evalue_eval(&src
->x
.p
->arr
[0], coset
->p
);
170 if (value_zero_p(arg
->x
.n
))
171 evalue_coset(&src
->x
.p
->arr
[1], coset
, dst
);
172 else if (src
->x
.p
->size
> 2)
173 evalue_coset(&src
->x
.p
->arr
[2], coset
, dst
);
175 evalue_set_si(dst
, 0, 1);
176 free_evalue_refs(arg
);
181 assert(src
->x
.p
->type
== polynomial
);
182 value_set_si(dst
->d
, 0);
183 dst
->x
.p
= new_enode(src
->x
.p
->type
, src
->x
.p
->size
, src
->x
.p
->pos
);
184 for (int i
= 0; i
< src
->x
.p
->size
; ++i
)
185 evalue_coset(&src
->x
.p
->arr
[i
], coset
, &dst
->x
.p
->arr
[i
]);
189 static void evalue_print_list_evalue(FILE *out
, evalue
*e
, int nparam
,
192 cerr
<< "not supported" << endl
;
195 static void evalue_print_list_evalue(FILE *out
, evalue
*e
, int nparam
,
199 L
= extract_common_lattice(e
, NULL
, nparam
);
201 print_evalue(out
, e
, params
);
203 fdostream
os(dup(fileno(out
)));
204 Vector
*coset
= Vector_Alloc(nparam
+1);
205 value_set_si(coset
->p
[nparam
], 1);
208 matrix2zz(L
, RT
, nparam
, nparam
);
210 fprintf(out
, "Lattice:\n");
213 lattice_point(coset
->p
, R
, vertices
, to_ulong(abs(determinant(R
))), NULL
);
215 for (int i
= 0; i
< vertices
.NumRows(); ++i
) {
217 os
<< vertices
[i
] << endl
;
218 zz2values(vertices
[i
], coset
->p
);
220 evalue_coset(e
, coset
, &t
);
221 print_evalue(out
, &t
, params
);
222 free_evalue_refs(&t
);
229 static void evalue_print_list(FILE *out
, evalue
*e
, int nparam
, char **params
)
232 assert(value_zero_p(e
->d
));
233 assert(e
->x
.p
->type
== partition
);
235 for (i
= 0; i
< e
->x
.p
->size
/2; i
++) {
236 Print_Domain(out
, EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), params
);
237 evalue_print_list_evalue(out
, &e
->x
.p
->arr
[2*i
+1], nparam
, params
);
241 static void print_domain_latex(std::ostream
& o
, Polyhedron
*D
, int nparam
,
245 for (int i
= 0; i
< D
->NbConstraints
; ++i
) {
246 if (First_Non_Zero(D
->Constraint
[i
]+1, D
->Dimension
) == -1)
251 for (int j
= 0; j
< D
->Dimension
; ++j
) {
252 if (value_zero_p(D
->Constraint
[i
][1+j
]))
255 if (!fc
&& value_pos_p(D
->Constraint
[i
][1+j
]))
257 if (value_mone_p(D
->Constraint
[i
][1+j
]))
259 else if (!value_one_p(D
->Constraint
[i
][1+j
]))
260 o
<< VALUE_TO_INT(D
->Constraint
[i
][1+j
]);
261 o
<< " " << params
[j
];
264 if (!fc
&& value_pos_p(D
->Constraint
[i
][1+D
->Dimension
]))
266 if (value_notzero_p(D
->Constraint
[i
][1+D
->Dimension
]))
267 o
<< VALUE_TO_INT(D
->Constraint
[i
][1+D
->Dimension
]);
268 if (value_zero_p(D
->Constraint
[i
][0]))
276 static void evalue_print_latex(std::ostream
& o
, const evalue
*e
,
277 int first
, int nested
,
278 const string
& suffix1
, const string
& suffix2
,
279 int nparam
, char **params
);
281 static void evalue_print_poly_latex1(std::ostream
& o
, const evalue
*e
,
282 int first
, int nested
, const string
& base
,
283 const string
& suffix1
, const string
& suffix2
,
284 int nparam
, char **params
)
286 int offset
= type_offset(e
->x
.p
);
287 for (int i
= e
->x
.p
->size
-1; i
>= offset
; --i
) {
288 std::ostringstream strm
;
293 strm
<< "^" << (i
-offset
);
294 evalue_print_latex(o
, &e
->x
.p
->arr
[i
], first
, nested
,
295 strm
.str(), suffix2
, nparam
, params
);
300 static void evalue_print_poly_latex2(std::ostream
& o
, const evalue
*e
,
301 int first
, int nested
, const string
& base
,
302 const string
& suffix1
, const string
& suffix2
,
303 int nparam
, char **params
)
305 int offset
= type_offset(e
->x
.p
);
306 for (int i
= e
->x
.p
->size
-1; i
>= offset
; --i
) {
307 std::ostringstream strm
;
312 strm
<< "^" << (i
-offset
);
313 evalue_print_latex(o
, &e
->x
.p
->arr
[i
], first
, nested
,
314 suffix1
, strm
.str(), nparam
, params
);
319 static void evalue_print_latex(std::ostream
& o
, const evalue
*e
,
320 int first
, int nested
,
321 const string
& suffix1
, const string
&suffix2
,
322 int nparam
, char **params
)
324 if (value_notzero_p(e
->d
)) {
325 if (value_zero_p(e
->x
.n
)) {
332 value_absolute(tmp
, e
->x
.n
);
333 if (!first
&& value_pos_p(e
->x
.n
))
335 if (value_neg_p(e
->x
.n
))
337 if (value_one_p(e
->d
)) {
338 if (!value_one_p(tmp
) ||
339 (suffix1
.length() == 0 && suffix2
.length() == 0))
340 o
<< VALUE_TO_INT(tmp
);
343 if (value_one_p(tmp
) && suffix1
.length() != 0)
346 o
<< VALUE_TO_INT(tmp
);
348 << VALUE_TO_INT(e
->d
) << "}";
350 if (!value_one_p(tmp
)) {
360 switch (e
->x
.p
->type
) {
362 o
<< "\\begin{cases}\n";
363 for (int i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
366 evalue_print_latex(o
, &e
->x
.p
->arr
[2*i
+1], 1, 0,
367 suffix1
, suffix2
, nparam
, params
);
368 o
<< "& \\text{if $";
369 print_domain_latex(o
, EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), nparam
, params
);
372 o
<< "\\end{cases}\n";
375 evalue_print_poly_latex1(o
, e
, first
, nested
, params
[e
->x
.p
->pos
-1],
376 suffix1
, suffix2
, nparam
, params
);
379 std::ostringstream strm
;
380 strm
<< "\\fractional{";
381 evalue_print_latex(strm
, &e
->x
.p
->arr
[0], 1, 1, "", "", nparam
, params
);
383 evalue_print_poly_latex2(o
, e
, first
, nested
,
384 strm
.str(), suffix1
, suffix2
, nparam
, params
);
393 static void evalue_print_latex(FILE *out
, const evalue
*e
, int nparam
,
396 cerr
<< "not supported" << endl
;
399 static void evalue_print_latex(FILE *out
, const evalue
*e
, int nparam
,
402 fdostream
os(dup(fileno(out
)));
403 evalue_print_latex(os
, e
, 1, 0, "", "", nparam
, params
);
407 int evalue_convert(evalue
*EP
, struct convert_options
*options
,
408 int verbose
, unsigned nparam
, char **params
)
411 if (options
->combine
)
414 evalue_range_reduction(EP
);
416 print_evalue(stdout
, EP
, params
);
419 if (options
->floor
) {
420 fprintf(stderr
, "WARNING: floor conversion not supported\n");
421 evalue_frac2floor2(EP
, 0);
423 print_evalue(stdout
, EP
, params
);
424 } else if (options
->list
&& params
) {
425 evalue_print_list(stdout
, EP
, nparam
, params
);
427 } else if (options
->latex
&& params
) {
428 evalue_print_latex(stdout
, EP
, nparam
, params
);
430 } else if (options
->convert
) {
431 evalue_mod2table(EP
, nparam
);
433 print_evalue(stdout
, EP
, params
);