5 #include <isl_stream.h>
6 #include <isl_vertices.h>
7 #include <isl_obj_list.h>
8 #include <isl_obj_str.h>
9 #include <barvinok/barvinok.h>
14 #include <cloog/isl/cloog.h>
17 static int isl_bool_false
= 0;
18 static int isl_bool_true
= 1;
19 static int isl_bool_error
= -1;
21 static enum isl_token_type read_op
;
22 static enum isl_token_type source_op
;
23 static enum isl_token_type vertices_op
;
25 struct isl_arg_choice iscc_format
[] = {
26 {"isl", ISL_FORMAT_ISL
},
27 {"omega", ISL_FORMAT_OMEGA
},
28 {"polylib", ISL_FORMAT_POLYLIB
},
29 {"latex", ISL_FORMAT_LATEX
},
35 struct barvinok_options
*barvinok
;
39 struct isl_arg iscc_options_arg
[] = {
40 ISL_ARG_CHILD(struct iscc_options
, barvinok
, "barvinok", barvinok_options_arg
,
42 ISL_ARG_CHOICE(struct iscc_options
, format
, 0, "format", \
43 iscc_format
, ISL_FORMAT_ISL
, "output format")
47 ISL_ARG_DEF(iscc_options
, struct iscc_options
, iscc_options_arg
)
49 static void *isl_obj_bool_copy(void *v
)
54 static void isl_obj_bool_free(void *v
)
58 static __isl_give isl_printer
*isl_obj_bool_print(__isl_take isl_printer
*p
,
61 if (v
== &isl_bool_true
)
62 return isl_printer_print_str(p
, "True");
63 else if (v
== &isl_bool_false
)
64 return isl_printer_print_str(p
, "False");
66 return isl_printer_print_str(p
, "Error");
69 static void *isl_obj_bool_add(void *v1
, void *v2
)
74 struct isl_obj_vtable isl_obj_bool_vtable
= {
80 #define isl_obj_bool (&isl_obj_bool_vtable)
82 int *isl_bool_from_int(int res
)
84 return res
< 0 ? &isl_bool_error
: res
? &isl_bool_true
: &isl_bool_false
;
87 int *union_map_is_equal(__isl_take isl_union_map
*map1
,
88 __isl_take isl_union_map
*map2
)
90 int res
= isl_union_map_is_equal(map1
, map2
);
91 isl_union_map_free(map1
);
92 isl_union_map_free(map2
);
93 return isl_bool_from_int(res
);
95 int *union_set_is_equal(__isl_take isl_union_set
*set1
,
96 __isl_take isl_union_set
*set2
)
98 return union_map_is_equal((isl_union_map
*)set1
, (isl_union_map
*)set2
);
101 int *union_map_is_subset(__isl_take isl_union_map
*map1
,
102 __isl_take isl_union_map
*map2
)
104 int res
= isl_union_map_is_subset(map1
, map2
);
105 isl_union_map_free(map1
);
106 isl_union_map_free(map2
);
107 return isl_bool_from_int(res
);
109 int *union_set_is_subset(__isl_take isl_union_set
*set1
,
110 __isl_take isl_union_set
*set2
)
112 return union_map_is_subset((isl_union_map
*)set1
, (isl_union_map
*)set2
);
115 int *union_map_is_strict_subset(__isl_take isl_union_map
*map1
,
116 __isl_take isl_union_map
*map2
)
118 int res
= isl_union_map_is_strict_subset(map1
, map2
);
119 isl_union_map_free(map1
);
120 isl_union_map_free(map2
);
121 return isl_bool_from_int(res
);
123 int *union_set_is_strict_subset(__isl_take isl_union_set
*set1
,
124 __isl_take isl_union_set
*set2
)
126 return union_map_is_strict_subset((isl_union_map
*)set1
,
127 (isl_union_map
*)set2
);
130 int *union_map_is_superset(__isl_take isl_union_map
*map1
,
131 __isl_take isl_union_map
*map2
)
133 return union_map_is_subset(map2
, map1
);
135 int *union_set_is_superset(__isl_take isl_union_set
*set1
,
136 __isl_take isl_union_set
*set2
)
138 return union_set_is_subset(set2
, set1
);
141 int *union_map_is_strict_superset(__isl_take isl_union_map
*map1
,
142 __isl_take isl_union_map
*map2
)
144 return union_map_is_strict_subset(map2
, map1
);
146 int *union_set_is_strict_superset(__isl_take isl_union_set
*set1
,
147 __isl_take isl_union_set
*set2
)
149 return union_set_is_strict_subset(set2
, set1
);
152 extern struct isl_obj_vtable isl_obj_list_vtable
;
153 #define isl_obj_list (&isl_obj_list_vtable)
155 typedef void *(*isc_bin_op_fn
)(void *lhs
, void *rhs
);
157 enum isl_token_type op
;
163 struct isc_named_bin_op
{
165 struct isc_bin_op op
;
169 isl_union_pw_qpolynomial
*upwqp
;
170 isl_union_pw_qpolynomial
*res
;
173 static int eval_at(__isl_take isl_point
*pnt
, void *user
)
175 struct iscc_at
*at
= (struct iscc_at
*) user
;
179 set
= isl_set_from_point(isl_point_copy(pnt
));
180 qp
= isl_union_pw_qpolynomial_eval(
181 isl_union_pw_qpolynomial_copy(at
->upwqp
), pnt
);
183 at
->res
= isl_union_pw_qpolynomial_add(at
->res
,
184 isl_union_pw_qpolynomial_from_pw_qpolynomial(
185 isl_pw_qpolynomial_alloc(set
, qp
)));
190 __isl_give isl_union_pw_qpolynomial
*isl_union_pw_qpolynomial_at(
191 __isl_take isl_union_pw_qpolynomial
*upwqp
,
192 __isl_take isl_union_set
*uset
)
197 at
.res
= isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset
));
199 isl_union_set_foreach_point(uset
, eval_at
, &at
);
201 isl_union_pw_qpolynomial_free(upwqp
);
202 isl_union_set_free(uset
);
207 struct iscc_fold_at
{
208 isl_union_pw_qpolynomial_fold
*upwf
;
209 isl_union_pw_qpolynomial
*res
;
212 static int eval_fold_at(__isl_take isl_point
*pnt
, void *user
)
214 struct iscc_fold_at
*at
= (struct iscc_fold_at
*) user
;
218 set
= isl_set_from_point(isl_point_copy(pnt
));
219 qp
= isl_union_pw_qpolynomial_fold_eval(
220 isl_union_pw_qpolynomial_fold_copy(at
->upwf
), pnt
);
222 at
->res
= isl_union_pw_qpolynomial_add(at
->res
,
223 isl_union_pw_qpolynomial_from_pw_qpolynomial(
224 isl_pw_qpolynomial_alloc(set
, qp
)));
229 __isl_give isl_union_pw_qpolynomial
*isl_union_pw_qpolynomial_fold_at(
230 __isl_take isl_union_pw_qpolynomial_fold
*upwf
,
231 __isl_take isl_union_set
*uset
)
233 struct iscc_fold_at at
;
236 at
.res
= isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset
));
238 isl_union_set_foreach_point(uset
, eval_fold_at
, &at
);
240 isl_union_pw_qpolynomial_fold_free(upwf
);
241 isl_union_set_free(uset
);
246 static __isl_give isl_union_pw_qpolynomial_fold
*union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
247 __isl_take isl_union_pw_qpolynomial
*upwqp
,
248 __isl_take isl_union_pw_qpolynomial_fold
*upwf
)
250 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf
,
254 static __isl_give
struct isl_list
*union_map_apply_union_pw_qpolynomial_fold(
255 __isl_take isl_union_map
*umap
,
256 __isl_take isl_union_pw_qpolynomial_fold
*upwf
)
259 struct isl_list
*list
;
262 ctx
= isl_union_map_get_ctx(umap
);
263 list
= isl_list_alloc(ctx
, 2);
267 list
->obj
[0].type
= isl_obj_union_pw_qpolynomial_fold
;
268 list
->obj
[0].v
= isl_union_map_apply_union_pw_qpolynomial_fold(umap
,
270 list
->obj
[1].type
= isl_obj_bool
;
271 list
->obj
[1].v
= tight
? &isl_bool_true
: &isl_bool_false
;
272 if (tight
< 0 || !list
->obj
[0].v
)
277 isl_union_map_free(umap
);
278 isl_union_pw_qpolynomial_fold_free(upwf
);
284 struct isc_bin_op bin_ops
[] = {
285 { '+', isl_obj_union_set
, isl_obj_union_set
,
287 (isc_bin_op_fn
) &isl_union_set_union
},
288 { '+', isl_obj_union_map
, isl_obj_union_map
,
290 (isc_bin_op_fn
) &isl_union_map_union
},
291 { '-', isl_obj_union_set
, isl_obj_union_set
,
293 (isc_bin_op_fn
) &isl_union_set_subtract
},
294 { '-', isl_obj_union_map
, isl_obj_union_map
,
296 (isc_bin_op_fn
) &isl_union_map_subtract
},
297 { '*', isl_obj_union_set
, isl_obj_union_set
,
299 (isc_bin_op_fn
) &isl_union_set_intersect
},
300 { '*', isl_obj_union_map
, isl_obj_union_map
,
302 (isc_bin_op_fn
) &isl_union_map_intersect
},
303 { '*', isl_obj_union_map
, isl_obj_union_set
,
305 (isc_bin_op_fn
) &isl_union_map_intersect_domain
},
306 { '.', isl_obj_union_map
, isl_obj_union_map
,
308 (isc_bin_op_fn
) &isl_union_map_apply_range
},
309 { '.', isl_obj_union_map
, isl_obj_union_pw_qpolynomial
,
310 isl_obj_union_pw_qpolynomial
,
311 (isc_bin_op_fn
) &isl_union_map_apply_union_pw_qpolynomial
},
312 { '.', isl_obj_union_map
, isl_obj_union_pw_qpolynomial_fold
,
314 (isc_bin_op_fn
) &union_map_apply_union_pw_qpolynomial_fold
},
315 { ISL_TOKEN_TO
, isl_obj_union_set
, isl_obj_union_set
,
317 (isc_bin_op_fn
) &isl_union_map_from_domain_and_range
},
318 { '=', isl_obj_union_set
, isl_obj_union_set
, isl_obj_bool
,
319 (isc_bin_op_fn
) &union_set_is_equal
},
320 { '=', isl_obj_union_map
, isl_obj_union_map
, isl_obj_bool
,
321 (isc_bin_op_fn
) &union_map_is_equal
},
322 { ISL_TOKEN_LE
, isl_obj_union_set
, isl_obj_union_set
,
323 isl_obj_bool
, (isc_bin_op_fn
) &union_set_is_subset
},
324 { ISL_TOKEN_LE
, isl_obj_union_map
, isl_obj_union_map
,
325 isl_obj_bool
, (isc_bin_op_fn
) &union_map_is_subset
},
326 { ISL_TOKEN_LT
, isl_obj_union_set
, isl_obj_union_set
,
327 isl_obj_bool
, (isc_bin_op_fn
) &union_set_is_strict_subset
},
328 { ISL_TOKEN_LT
, isl_obj_union_map
, isl_obj_union_map
,
329 isl_obj_bool
, (isc_bin_op_fn
) &union_map_is_strict_subset
},
330 { ISL_TOKEN_GE
, isl_obj_union_set
, isl_obj_union_set
,
331 isl_obj_bool
, (isc_bin_op_fn
) &union_set_is_superset
},
332 { ISL_TOKEN_GE
, isl_obj_union_map
, isl_obj_union_map
,
333 isl_obj_bool
, (isc_bin_op_fn
) &union_map_is_superset
},
334 { ISL_TOKEN_GT
, isl_obj_union_set
, isl_obj_union_set
,
335 isl_obj_bool
, (isc_bin_op_fn
) &union_set_is_strict_superset
},
336 { ISL_TOKEN_GT
, isl_obj_union_map
, isl_obj_union_map
,
337 isl_obj_bool
, (isc_bin_op_fn
) &union_map_is_strict_superset
},
338 { ISL_TOKEN_LEX_LE
, isl_obj_union_set
, isl_obj_union_set
,
340 (isc_bin_op_fn
) &isl_union_set_lex_le_union_set
},
341 { ISL_TOKEN_LEX_LT
, isl_obj_union_set
, isl_obj_union_set
,
343 (isc_bin_op_fn
) &isl_union_set_lex_lt_union_set
},
344 { ISL_TOKEN_LEX_GE
, isl_obj_union_set
, isl_obj_union_set
,
346 (isc_bin_op_fn
) &isl_union_set_lex_ge_union_set
},
347 { ISL_TOKEN_LEX_GT
, isl_obj_union_set
, isl_obj_union_set
,
349 (isc_bin_op_fn
) &isl_union_set_lex_gt_union_set
},
350 { ISL_TOKEN_LEX_LE
, isl_obj_union_map
, isl_obj_union_map
,
352 (isc_bin_op_fn
) &isl_union_map_lex_le_union_map
},
353 { ISL_TOKEN_LEX_LT
, isl_obj_union_map
, isl_obj_union_map
,
355 (isc_bin_op_fn
) &isl_union_map_lex_lt_union_map
},
356 { ISL_TOKEN_LEX_GE
, isl_obj_union_map
, isl_obj_union_map
,
358 (isc_bin_op_fn
) &isl_union_map_lex_ge_union_map
},
359 { ISL_TOKEN_LEX_GT
, isl_obj_union_map
, isl_obj_union_map
,
361 (isc_bin_op_fn
) &isl_union_map_lex_gt_union_map
},
362 { '.', isl_obj_union_pw_qpolynomial_fold
,
363 isl_obj_union_pw_qpolynomial_fold
,
364 isl_obj_union_pw_qpolynomial_fold
,
365 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_fold
},
366 { '+', isl_obj_union_pw_qpolynomial
, isl_obj_union_pw_qpolynomial
,
367 isl_obj_union_pw_qpolynomial
,
368 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_add
},
369 { '+', isl_obj_union_pw_qpolynomial
,
370 isl_obj_union_pw_qpolynomial_fold
,
371 isl_obj_union_pw_qpolynomial_fold
,
372 (isc_bin_op_fn
) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold
},
373 { '+', isl_obj_union_pw_qpolynomial_fold
,
374 isl_obj_union_pw_qpolynomial
,
375 isl_obj_union_pw_qpolynomial_fold
,
376 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial
},
377 { '-', isl_obj_union_pw_qpolynomial
, isl_obj_union_pw_qpolynomial
,
378 isl_obj_union_pw_qpolynomial
,
379 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_sub
},
380 { '*', isl_obj_union_pw_qpolynomial
, isl_obj_union_pw_qpolynomial
,
381 isl_obj_union_pw_qpolynomial
,
382 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_mul
},
383 { '*', isl_obj_union_pw_qpolynomial
, isl_obj_union_set
,
384 isl_obj_union_pw_qpolynomial
,
385 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_intersect_domain
},
386 { '*', isl_obj_union_pw_qpolynomial_fold
, isl_obj_union_set
,
387 isl_obj_union_pw_qpolynomial_fold
,
388 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_intersect_domain
},
389 { '@', isl_obj_union_pw_qpolynomial
, isl_obj_union_set
,
390 isl_obj_union_pw_qpolynomial
,
391 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_at
},
392 { '@', isl_obj_union_pw_qpolynomial_fold
, isl_obj_union_set
,
393 isl_obj_union_pw_qpolynomial
,
394 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_at
},
395 { '%', isl_obj_union_set
, isl_obj_union_set
,
397 (isc_bin_op_fn
) &isl_union_set_gist
},
398 { '%', isl_obj_union_map
, isl_obj_union_map
,
400 (isc_bin_op_fn
) &isl_union_map_gist
},
401 { '%', isl_obj_union_pw_qpolynomial
, isl_obj_union_set
,
402 isl_obj_union_pw_qpolynomial
,
403 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_gist
},
404 { '%', isl_obj_union_pw_qpolynomial_fold
, isl_obj_union_set
,
405 isl_obj_union_pw_qpolynomial_fold
,
406 (isc_bin_op_fn
) &isl_union_pw_qpolynomial_fold_gist
},
407 { '+', isl_obj_str
, isl_obj_str
, isl_obj_str
,
408 (isc_bin_op_fn
) &isl_str_concat
},
411 struct isc_named_bin_op named_bin_ops
[] = {
412 { "cross", { -1, isl_obj_union_set
, isl_obj_union_set
,
414 (isc_bin_op_fn
) &isl_union_set_product
} },
415 { "cross", { -1, isl_obj_union_map
, isl_obj_union_map
,
417 (isc_bin_op_fn
) &isl_union_map_product
} },
421 __isl_give isl_set
*union_set_sample(__isl_take isl_union_set
*uset
)
423 return isl_set_from_basic_set(isl_union_set_sample(uset
));
426 __isl_give isl_map
*union_map_sample(__isl_take isl_union_map
*umap
)
428 return isl_map_from_basic_map(isl_union_map_sample(umap
));
431 static __isl_give
struct isl_list
*union_pw_qpolynomial_upper_bound(
432 __isl_take isl_union_pw_qpolynomial
*upwqp
)
435 struct isl_list
*list
;
438 ctx
= isl_union_pw_qpolynomial_get_ctx(upwqp
);
439 list
= isl_list_alloc(ctx
, 2);
443 list
->obj
[0].type
= isl_obj_union_pw_qpolynomial_fold
;
444 list
->obj
[0].v
= isl_union_pw_qpolynomial_bound(upwqp
,
445 isl_fold_max
, &tight
);
446 list
->obj
[1].type
= isl_obj_bool
;
447 list
->obj
[1].v
= tight
? &isl_bool_true
: &isl_bool_false
;
448 if (tight
< 0 || !list
->obj
[0].v
)
453 isl_union_pw_qpolynomial_free(upwqp
);
460 void *map_codegen(void *arg
)
463 isl_union_map
*umap
= (isl_union_map
*)arg
;
464 isl_ctx
*ctx
= isl_union_map_get_ctx(umap
);
466 CloogOptions
*options
;
467 CloogDomain
*context
;
468 CloogUnionDomain
*ud
;
470 struct clast_stmt
*stmt
;
472 state
= cloog_isl_state_malloc(ctx
);
473 options
= cloog_options_malloc(state
);
474 options
->language
= LANGUAGE_C
;
475 options
->strides
= 1;
477 ud
= cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap
));
479 dim
= isl_union_map_get_dim(umap
);
480 context
= cloog_domain_from_isl_set(isl_set_universe(dim
));
482 input
= cloog_input_alloc(context
, ud
);
484 stmt
= cloog_clast_create_from_input(input
, options
);
485 clast_pprint(stdout
, stmt
, 0, options
);
486 cloog_clast_free(stmt
);
489 cloog_options_free(options
);
490 cloog_state_free(state
);
491 isl_union_map_free(umap
);
495 void *set_codegen(void *arg
)
498 isl_union_set
*uset
= (isl_union_set
*)arg
;
499 isl_ctx
*ctx
= isl_union_set_get_ctx(uset
);
501 CloogOptions
*options
;
502 CloogDomain
*context
;
503 CloogUnionDomain
*ud
;
505 struct clast_stmt
*stmt
;
507 state
= cloog_isl_state_malloc(ctx
);
508 options
= cloog_options_malloc(state
);
509 options
->language
= LANGUAGE_C
;
510 options
->strides
= 1;
512 ud
= cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset
));
514 dim
= isl_union_set_get_dim(uset
);
515 context
= cloog_domain_from_isl_set(isl_set_universe(dim
));
517 input
= cloog_input_alloc(context
, ud
);
519 stmt
= cloog_clast_create_from_input(input
, options
);
520 clast_pprint(stdout
, stmt
, 0, options
);
521 cloog_clast_free(stmt
);
524 cloog_options_free(options
);
525 cloog_state_free(state
);
526 isl_union_set_free(uset
);
531 typedef void *(*isc_un_op_fn
)(void *arg
);
533 enum isl_token_type op
;
538 struct isc_named_un_op
{
542 struct isc_named_un_op named_un_ops
[] = {
543 {"aff", { -1, isl_obj_union_map
, isl_obj_union_map
,
544 (isc_un_op_fn
) &isl_union_map_affine_hull
} },
545 {"aff", { -1, isl_obj_union_set
, isl_obj_union_set
,
546 (isc_un_op_fn
) &isl_union_set_affine_hull
} },
547 {"card", { -1, isl_obj_union_set
,
548 isl_obj_union_pw_qpolynomial
,
549 (isc_un_op_fn
) &isl_union_set_card
} },
550 {"card", { -1, isl_obj_union_map
,
551 isl_obj_union_pw_qpolynomial
,
552 (isc_un_op_fn
) &isl_union_map_card
} },
553 {"coalesce", { -1, isl_obj_union_set
, isl_obj_union_set
,
554 (isc_un_op_fn
) &isl_union_set_coalesce
} },
555 {"coalesce", { -1, isl_obj_union_map
, isl_obj_union_map
,
556 (isc_un_op_fn
) &isl_union_map_coalesce
} },
557 {"coalesce", { -1, isl_obj_union_pw_qpolynomial
,
558 isl_obj_union_pw_qpolynomial
,
559 (isc_un_op_fn
) &isl_union_pw_qpolynomial_coalesce
} },
560 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold
,
561 isl_obj_union_pw_qpolynomial_fold
,
562 (isc_un_op_fn
) &isl_union_pw_qpolynomial_fold_coalesce
} },
564 {"codegen", { -1, isl_obj_union_set
, isl_obj_none
,
566 {"codegen", { -1, isl_obj_union_map
, isl_obj_none
,
569 {"deltas", { -1, isl_obj_union_map
, isl_obj_union_set
,
570 (isc_un_op_fn
) &isl_union_map_deltas
} },
571 {"dom", { -1, isl_obj_union_map
, isl_obj_union_set
,
572 (isc_un_op_fn
) &isl_union_map_domain
} },
573 {"dom", { -1, isl_obj_union_pw_qpolynomial
, isl_obj_union_set
,
574 (isc_un_op_fn
) &isl_union_pw_qpolynomial_domain
} },
575 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold
,
577 (isc_un_op_fn
) &isl_union_pw_qpolynomial_fold_domain
} },
578 {"ran", { -1, isl_obj_union_map
, isl_obj_union_set
,
579 (isc_un_op_fn
) &isl_union_map_range
} },
580 {"lexmin", { -1, isl_obj_union_map
, isl_obj_union_map
,
581 (isc_un_op_fn
) &isl_union_map_lexmin
} },
582 {"lexmax", { -1, isl_obj_union_map
, isl_obj_union_map
,
583 (isc_un_op_fn
) &isl_union_map_lexmax
} },
584 {"lexmin", { -1, isl_obj_union_set
, isl_obj_union_set
,
585 (isc_un_op_fn
) &isl_union_set_lexmin
} },
586 {"lexmax", { -1, isl_obj_union_set
, isl_obj_union_set
,
587 (isc_un_op_fn
) &isl_union_set_lexmax
} },
588 {"sample", { -1, isl_obj_union_set
, isl_obj_set
,
589 (isc_un_op_fn
) &union_set_sample
} },
590 {"sample", { -1, isl_obj_union_map
, isl_obj_map
,
591 (isc_un_op_fn
) &union_map_sample
} },
592 {"sum", { -1, isl_obj_union_pw_qpolynomial
,
593 isl_obj_union_pw_qpolynomial
,
594 (isc_un_op_fn
) &isl_union_pw_qpolynomial_sum
} },
595 {"ub", { -1, isl_obj_union_pw_qpolynomial
, isl_obj_list
,
596 (isc_un_op_fn
) &union_pw_qpolynomial_upper_bound
} },
597 {"unwrap", { -1, isl_obj_union_set
, isl_obj_union_map
,
598 (isc_un_op_fn
) &isl_union_set_unwrap
} },
599 {"wrap", { -1, isl_obj_union_map
, isl_obj_union_set
,
600 (isc_un_op_fn
) &isl_union_map_wrap
} },
604 struct isl_named_obj
{
609 static void free_obj(struct isl_obj obj
)
611 obj
.type
->free(obj
.v
);
614 static int same_name(const void *entry
, const void *val
)
616 const struct isl_named_obj
*named
= (const struct isl_named_obj
*)entry
;
618 return !strcmp(named
->name
, val
);
621 static int do_assign(struct isl_ctx
*ctx
, struct isl_hash_table
*table
,
622 char *name
, struct isl_obj obj
)
624 struct isl_hash_table_entry
*entry
;
626 struct isl_named_obj
*named
;
628 name_hash
= isl_hash_string(isl_hash_init(), name
);
629 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 1);
634 free_obj(named
->obj
);
637 named
= isl_alloc_type(ctx
, struct isl_named_obj
);
652 static struct isl_obj
stored_obj(struct isl_ctx
*ctx
,
653 struct isl_hash_table
*table
, char *name
)
655 struct isl_obj obj
= { isl_obj_none
, NULL
};
656 struct isl_hash_table_entry
*entry
;
659 name_hash
= isl_hash_string(isl_hash_init(), name
);
660 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 0);
662 struct isl_named_obj
*named
;
666 fprintf(stderr
, "unknown identifier '%s'\n", name
);
669 obj
.v
= obj
.type
->copy(obj
.v
);
673 static int is_subtype(struct isl_obj obj
, isl_obj_type super
)
675 if (obj
.type
== super
)
677 if (obj
.type
== isl_obj_map
&& super
== isl_obj_union_map
)
679 if (obj
.type
== isl_obj_set
&& super
== isl_obj_union_set
)
681 if (obj
.type
== isl_obj_pw_qpolynomial
&&
682 super
== isl_obj_union_pw_qpolynomial
)
684 if (obj
.type
== isl_obj_pw_qpolynomial_fold
&&
685 super
== isl_obj_union_pw_qpolynomial_fold
)
687 if (obj
.type
== isl_obj_union_set
&& isl_union_set_is_empty(obj
.v
))
689 if (obj
.type
== isl_obj_list
) {
690 struct isl_list
*list
= obj
.v
;
691 if (list
->n
== 2 && list
->obj
[1].type
== isl_obj_bool
)
692 return is_subtype(list
->obj
[0], super
);
694 if (super
== isl_obj_str
)
699 static struct isl_obj
obj_at(struct isl_obj obj
, int i
)
701 struct isl_list
*list
= obj
.v
;
704 obj
.v
= obj
.type
->copy(obj
.v
);
711 static struct isl_obj
convert(isl_ctx
*ctx
, struct isl_obj obj
,
714 if (obj
.type
== type
)
716 if (obj
.type
== isl_obj_map
&& type
== isl_obj_union_map
) {
717 obj
.type
= isl_obj_union_map
;
718 obj
.v
= isl_union_map_from_map(obj
.v
);
721 if (obj
.type
== isl_obj_set
&& type
== isl_obj_union_set
) {
722 obj
.type
= isl_obj_union_set
;
723 obj
.v
= isl_union_set_from_set(obj
.v
);
726 if (obj
.type
== isl_obj_pw_qpolynomial
&&
727 type
== isl_obj_union_pw_qpolynomial
) {
728 obj
.type
= isl_obj_union_pw_qpolynomial
;
729 obj
.v
= isl_union_pw_qpolynomial_from_pw_qpolynomial(obj
.v
);
732 if (obj
.type
== isl_obj_pw_qpolynomial_fold
&&
733 type
== isl_obj_union_pw_qpolynomial_fold
) {
734 obj
.type
= isl_obj_union_pw_qpolynomial_fold
;
735 obj
.v
= isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj
.v
);
738 if (obj
.type
== isl_obj_union_set
&& isl_union_set_is_empty(obj
.v
)) {
739 if (type
== isl_obj_union_map
) {
740 obj
.type
= isl_obj_union_map
;
743 if (type
== isl_obj_union_pw_qpolynomial
) {
744 isl_dim
*dim
= isl_union_set_get_dim(obj
.v
);
745 isl_union_set_free(obj
.v
);
746 obj
.v
= isl_union_pw_qpolynomial_zero(dim
);
747 obj
.type
= isl_obj_union_pw_qpolynomial
;
750 if (type
== isl_obj_union_pw_qpolynomial_fold
) {
751 isl_dim
*dim
= isl_union_set_get_dim(obj
.v
);
752 isl_union_set_free(obj
.v
);
753 obj
.v
= isl_union_pw_qpolynomial_fold_zero(dim
,
755 obj
.type
= isl_obj_union_pw_qpolynomial_fold
;
759 if (obj
.type
== isl_obj_list
) {
760 struct isl_list
*list
= obj
.v
;
761 if (list
->n
== 2 && list
->obj
[1].type
== isl_obj_bool
)
762 return convert(ctx
, obj_at(obj
, 0), type
);
764 if (type
== isl_obj_str
) {
769 p
= isl_printer_to_str(ctx
);
772 p
= obj
.type
->print(p
, obj
.v
);
773 s
= isl_printer_get_str(p
);
776 str
= isl_str_alloc(ctx
);
784 obj
.type
= isl_obj_str
;
790 obj
.type
= isl_obj_none
;
795 static struct isc_bin_op
*read_bin_op_if_available(struct isl_stream
*s
,
799 struct isl_token
*tok
;
801 tok
= isl_stream_next_token(s
);
808 if (bin_ops
[i
].op
!= tok
->type
)
810 if (!is_subtype(lhs
, bin_ops
[i
].lhs
))
818 if (!named_bin_ops
[i
].name
)
820 if (named_bin_ops
[i
].op
.op
!= tok
->type
)
822 if (!is_subtype(lhs
, named_bin_ops
[i
].op
.lhs
))
826 return &named_bin_ops
[i
].op
;
829 isl_stream_push_token(s
, tok
);
834 static struct isc_un_op
*read_prefix_un_op_if_available(struct isl_stream
*s
)
837 struct isl_token
*tok
;
839 tok
= isl_stream_next_token(s
);
844 if (!named_un_ops
[i
].name
)
846 if (named_un_ops
[i
].op
.op
!= tok
->type
)
850 return &named_un_ops
[i
].op
;
853 isl_stream_push_token(s
, tok
);
858 static struct isc_un_op
*find_matching_un_op(struct isc_un_op
*like
,
864 if (!named_un_ops
[i
].name
)
866 if (named_un_ops
[i
].op
.op
!= like
->op
)
868 if (!is_subtype(arg
, named_un_ops
[i
].op
.arg
))
871 return &named_un_ops
[i
].op
;
877 static int is_assign(struct isl_stream
*s
)
879 struct isl_token
*tok
;
880 struct isl_token
*tok2
;
883 tok
= isl_stream_next_token(s
);
886 if (tok
->type
!= ISL_TOKEN_IDENT
) {
887 isl_stream_push_token(s
, tok
);
891 tok2
= isl_stream_next_token(s
);
893 isl_stream_push_token(s
, tok
);
896 assign
= tok2
->type
== ISL_TOKEN_DEF
;
897 isl_stream_push_token(s
, tok2
);
898 isl_stream_push_token(s
, tok
);
903 static struct isl_obj
read_obj(struct isl_stream
*s
,
904 struct isl_hash_table
*table
);
905 static struct isl_obj
read_expr(struct isl_stream
*s
,
906 struct isl_hash_table
*table
);
908 static struct isl_obj
read_un_op_expr(struct isl_stream
*s
,
909 struct isl_hash_table
*table
, struct isc_un_op
*op
)
911 struct isl_obj obj
= { isl_obj_none
, NULL
};
913 obj
= read_obj(s
, table
);
917 op
= find_matching_un_op(op
, obj
);
919 isl_assert(s
->ctx
, op
, goto error
);
920 obj
= convert(s
->ctx
, obj
, op
->arg
);
921 obj
.v
= op
->fn(obj
.v
);
927 obj
.type
= isl_obj_none
;
932 static struct isl_obj
transitive_closure(struct isl_ctx
*ctx
, struct isl_obj obj
)
934 struct isl_list
*list
;
937 if (obj
.type
!= isl_obj_union_map
)
938 obj
= convert(ctx
, obj
, isl_obj_union_map
);
939 isl_assert(ctx
, obj
.type
== isl_obj_union_map
, goto error
);
940 list
= isl_list_alloc(ctx
, 2);
944 list
->obj
[0].type
= isl_obj_union_map
;
945 list
->obj
[0].v
= isl_union_map_transitive_closure(obj
.v
, &exact
);
946 list
->obj
[1].type
= isl_obj_bool
;
947 list
->obj
[1].v
= exact
? &isl_bool_true
: &isl_bool_false
;
949 obj
.type
= isl_obj_list
;
950 if (exact
< 0 || !list
->obj
[0].v
)
956 obj
.type
= isl_obj_none
;
961 static struct isl_obj
obj_at_index(struct isl_stream
*s
, struct isl_obj obj
)
963 struct isl_list
*list
= obj
.v
;
964 struct isl_token
*tok
;
967 tok
= isl_stream_next_token(s
);
968 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
969 isl_stream_error(s
, tok
, "expecting index");
971 isl_stream_push_token(s
, tok
);
974 i
= isl_int_get_si(tok
->u
.v
);
976 isl_assert(s
->ctx
, i
< list
->n
, goto error
);
977 if (isl_stream_eat(s
, ']'))
980 return obj_at(obj
, i
);
983 obj
.type
= isl_obj_none
;
988 static struct isl_obj
apply(struct isl_stream
*s
, __isl_take isl_union_map
*umap
,
989 struct isl_hash_table
*table
)
993 obj
= read_expr(s
, table
);
994 isl_assert(s
->ctx
, is_subtype(obj
, isl_obj_union_set
) ||
995 is_subtype(obj
, isl_obj_union_map
), goto error
);
997 if (obj
.type
== isl_obj_list
) {
998 struct isl_list
*list
= obj
.v
;
999 if (list
->n
== 2 && list
->obj
[1].type
== isl_obj_bool
)
1000 obj
= obj_at(obj
, 0);
1002 if (obj
.type
== isl_obj_set
)
1003 obj
= convert(s
->ctx
, obj
, isl_obj_union_set
);
1004 else if (obj
.type
== isl_obj_map
)
1005 obj
= convert(s
->ctx
, obj
, isl_obj_union_map
);
1006 if (obj
.type
== isl_obj_union_set
) {
1007 obj
.v
= isl_union_set_apply(obj
.v
, umap
);
1009 obj
.v
= isl_union_map_apply_range(obj
.v
, umap
);
1013 if (isl_stream_eat(s
, ')'))
1018 isl_union_map_free(umap
);
1021 obj
.type
= isl_obj_none
;
1026 struct add_vertex_data
{
1027 struct isl_list
*list
;
1031 static int add_vertex(__isl_take isl_vertex
*vertex
, void *user
)
1033 struct add_vertex_data
*data
= (struct add_vertex_data
*)user
;
1034 isl_basic_set
*expr
;
1036 expr
= isl_vertex_get_expr(vertex
);
1038 data
->list
->obj
[data
->i
].type
= isl_obj_set
;
1039 data
->list
->obj
[data
->i
].v
= isl_set_from_basic_set(expr
);
1042 isl_vertex_free(vertex
);
1047 static int set_vertices(__isl_take isl_set
*set
, void *user
)
1050 isl_basic_set
*hull
;
1051 isl_vertices
*vertices
= NULL
;
1052 struct isl_list
*list
= NULL
;
1054 struct add_vertex_data
*data
= (struct add_vertex_data
*)user
;
1056 set
= isl_set_remove_divs(set
);
1057 hull
= isl_set_convex_hull(set
);
1058 vertices
= isl_basic_set_compute_vertices(hull
);
1059 isl_basic_set_free(hull
);
1063 ctx
= isl_vertices_get_ctx(vertices
);
1064 data
->list
= isl_list_alloc(ctx
, isl_vertices_get_n_vertices(vertices
));
1069 r
= isl_vertices_foreach_vertex(vertices
, &add_vertex
, user
);
1071 data
->list
= isl_list_concat(list
, data
->list
);
1073 isl_vertices_free(vertices
);
1078 isl_vertices_free(vertices
);
1082 static struct isl_obj
vertices(struct isl_stream
*s
,
1083 struct isl_hash_table
*table
)
1087 struct isl_list
*list
= NULL
;
1088 isl_union_set
*uset
;
1089 struct add_vertex_data data
= { NULL
};
1091 obj
= read_expr(s
, table
);
1092 obj
= convert(s
->ctx
, obj
, isl_obj_union_set
);
1093 isl_assert(s
->ctx
, obj
.type
== isl_obj_union_set
, goto error
);
1097 ctx
= isl_union_set_get_ctx(uset
);
1098 list
= isl_list_alloc(ctx
, 0);
1104 if (isl_union_set_foreach_set(uset
, &set_vertices
, &data
) < 0)
1107 isl_union_set_free(uset
);
1109 obj
.type
= isl_obj_list
;
1114 isl_union_set_free(uset
);
1115 isl_list_free(data
.list
);
1117 obj
.type
= isl_obj_none
;
1122 static struct isl_obj
power(struct isl_stream
*s
, struct isl_obj obj
)
1124 struct isl_token
*tok
;
1126 if (isl_stream_eat_if_available(s
, '+'))
1127 return transitive_closure(s
->ctx
, obj
);
1129 tok
= isl_stream_next_token(s
);
1130 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
|| isl_int_cmp_si(tok
->u
.v
, -1)) {
1131 isl_stream_error(s
, tok
, "expecting -1");
1133 isl_stream_push_token(s
, tok
);
1136 isl_token_free(tok
);
1137 isl_assert(s
->ctx
, is_subtype(obj
, isl_obj_union_map
), goto error
);
1138 if (obj
.type
!= isl_obj_union_map
)
1139 obj
= convert(s
->ctx
, obj
, isl_obj_union_map
);
1141 obj
.v
= isl_union_map_reverse(obj
.v
);
1148 obj
.type
= isl_obj_none
;
1153 static struct isl_obj
read_from_file(struct isl_stream
*s
)
1156 struct isl_token
*tok
;
1157 struct isl_stream
*s_file
;
1160 tok
= isl_stream_next_token(s
);
1161 if (!tok
|| tok
->type
!= ISL_TOKEN_STRING
) {
1162 isl_stream_error(s
, tok
, "expecting filename");
1163 isl_token_free(tok
);
1167 file
= fopen(tok
->u
.s
, "r");
1168 isl_token_free(tok
);
1169 isl_assert(s
->ctx
, file
, goto error
);
1171 s_file
= isl_stream_new_file(s
->ctx
, file
);
1177 obj
= isl_stream_read_obj(s_file
);
1179 isl_stream_free(s_file
);
1184 obj
.type
= isl_obj_none
;
1189 static struct isl_obj
read_string_if_available(struct isl_stream
*s
)
1191 struct isl_token
*tok
;
1192 struct isl_obj obj
= { isl_obj_none
, NULL
};
1194 tok
= isl_stream_next_token(s
);
1197 if (tok
->type
== ISL_TOKEN_STRING
) {
1199 str
= isl_str_alloc(s
->ctx
);
1202 str
->s
= strdup(tok
->u
.s
);
1203 isl_token_free(tok
);
1205 obj
.type
= isl_obj_str
;
1207 isl_stream_push_token(s
, tok
);
1210 isl_token_free(tok
);
1214 static struct isl_obj
read_obj(struct isl_stream
*s
,
1215 struct isl_hash_table
*table
)
1217 struct isl_obj obj
= { isl_obj_none
, NULL
};
1219 struct isc_un_op
*op
= NULL
;
1221 obj
= read_string_if_available(s
);
1224 if (isl_stream_eat_if_available(s
, '(')) {
1225 obj
= read_expr(s
, table
);
1226 if (!obj
.v
|| isl_stream_eat(s
, ')'))
1229 op
= read_prefix_un_op_if_available(s
);
1231 return read_un_op_expr(s
, table
, op
);
1233 if (isl_stream_eat_if_available(s
, read_op
))
1234 return read_from_file(s
);
1235 if (isl_stream_eat_if_available(s
, vertices_op
))
1236 return vertices(s
, table
);
1238 name
= isl_stream_read_ident_if_available(s
);
1240 obj
= stored_obj(s
->ctx
, table
, name
);
1242 obj
= isl_stream_read_obj(s
);
1247 if (isl_stream_eat_if_available(s
, '^'))
1248 obj
= power(s
, obj
);
1249 else if (obj
.type
== isl_obj_list
&& isl_stream_eat_if_available(s
, '['))
1250 obj
= obj_at_index(s
, obj
);
1251 else if (is_subtype(obj
, isl_obj_union_map
) &&
1252 isl_stream_eat_if_available(s
, '(')) {
1253 obj
= convert(s
->ctx
, obj
, isl_obj_union_map
);
1254 obj
= apply(s
, obj
.v
, table
);
1260 obj
.type
= isl_obj_none
;
1265 static struct isc_bin_op
*find_matching_bin_op(struct isc_bin_op
*like
,
1266 struct isl_obj lhs
, struct isl_obj rhs
)
1270 for (i
= 0; ; ++i
) {
1273 if (bin_ops
[i
].op
!= like
->op
)
1275 if (!is_subtype(lhs
, bin_ops
[i
].lhs
))
1277 if (!is_subtype(rhs
, bin_ops
[i
].rhs
))
1283 for (i
= 0; ; ++i
) {
1284 if (!named_bin_ops
[i
].name
)
1286 if (named_bin_ops
[i
].op
.op
!= like
->op
)
1288 if (!is_subtype(lhs
, named_bin_ops
[i
].op
.lhs
))
1290 if (!is_subtype(rhs
, named_bin_ops
[i
].op
.rhs
))
1293 return &named_bin_ops
[i
].op
;
1299 static struct isl_obj
read_expr(struct isl_stream
*s
,
1300 struct isl_hash_table
*table
)
1302 struct isl_obj obj
= { isl_obj_none
, NULL
};
1303 struct isl_obj right_obj
= { isl_obj_none
, NULL
};
1305 obj
= read_obj(s
, table
);
1307 struct isc_bin_op
*op
= NULL
;
1309 op
= read_bin_op_if_available(s
, obj
);
1313 right_obj
= read_obj(s
, table
);
1315 op
= find_matching_bin_op(op
, obj
, right_obj
);
1317 isl_assert(s
->ctx
, op
, goto error
);
1318 obj
= convert(s
->ctx
, obj
, op
->lhs
);
1319 right_obj
= convert(s
->ctx
, right_obj
, op
->rhs
);
1320 obj
.v
= op
->fn(obj
.v
, right_obj
.v
);
1326 free_obj(right_obj
);
1328 obj
.type
= isl_obj_none
;
1333 static __isl_give isl_printer
*source_file(struct isl_stream
*s
,
1334 struct isl_hash_table
*table
, __isl_take isl_printer
*p
);
1336 static __isl_give isl_printer
*read_line(struct isl_stream
*s
,
1337 struct isl_hash_table
*table
, __isl_take isl_printer
*p
)
1339 struct isl_obj obj
= { isl_obj_none
, NULL
};
1342 struct isc_bin_op
*op
= NULL
;
1346 if (isl_stream_is_empty(s
))
1349 if (isl_stream_eat_if_available(s
, source_op
))
1350 return source_file(s
, table
, p
);
1352 assign
= is_assign(s
);
1354 lhs
= isl_stream_read_ident_if_available(s
);
1355 if (isl_stream_eat(s
, ISL_TOKEN_DEF
))
1359 obj
= read_expr(s
, table
);
1360 if (obj
.type
== isl_obj_none
|| obj
.v
== NULL
)
1362 if (isl_stream_eat(s
, ';'))
1366 if (do_assign(s
->ctx
, table
, lhs
, obj
))
1369 p
= obj
.type
->print(p
, obj
.v
);
1370 p
= isl_printer_end_line(p
);
1376 isl_stream_flush_tokens(s
);
1377 isl_stream_skip_line(s
);
1383 int free_cb(void **entry
, void *user
)
1385 struct isl_named_obj
*named
= *entry
;
1387 free_obj(named
->obj
);
1394 static void register_named_ops(struct isl_stream
*s
)
1398 read_op
= isl_stream_register_keyword(s
, "read");
1399 assert(read_op
!= ISL_TOKEN_ERROR
);
1400 source_op
= isl_stream_register_keyword(s
, "source");
1401 assert(source_op
!= ISL_TOKEN_ERROR
);
1402 vertices_op
= isl_stream_register_keyword(s
, "vertices");
1403 assert(vertices_op
!= ISL_TOKEN_ERROR
);
1405 for (i
= 0; ; ++i
) {
1406 if (!named_un_ops
[i
].name
)
1408 named_un_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
1409 named_un_ops
[i
].name
);
1410 assert(named_un_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
1413 for (i
= 0; ; ++i
) {
1414 if (!named_bin_ops
[i
].name
)
1416 named_bin_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
1417 named_bin_ops
[i
].name
);
1418 assert(named_bin_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
1422 static __isl_give isl_printer
*source_file(struct isl_stream
*s
,
1423 struct isl_hash_table
*table
, __isl_take isl_printer
*p
)
1425 struct isl_token
*tok
;
1426 struct isl_stream
*s_file
;
1429 tok
= isl_stream_next_token(s
);
1430 if (!tok
|| tok
->type
!= ISL_TOKEN_STRING
) {
1431 isl_stream_error(s
, tok
, "expecting filename");
1432 isl_token_free(tok
);
1436 file
= fopen(tok
->u
.s
, "r");
1437 isl_token_free(tok
);
1438 isl_assert(s
->ctx
, file
, return p
);
1440 s_file
= isl_stream_new_file(s
->ctx
, file
);
1446 register_named_ops(s_file
);
1448 while (!s_file
->eof
)
1449 p
= read_line(s_file
, table
, p
);
1451 isl_stream_free(s_file
);
1454 isl_stream_eat(s
, ';');
1459 int main(int argc
, char **argv
)
1461 struct isl_ctx
*ctx
;
1462 struct isl_stream
*s
;
1463 struct isl_hash_table
*table
;
1464 struct iscc_options
*options
;
1467 options
= iscc_options_new_with_defaults();
1469 argc
= iscc_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
1471 ctx
= isl_ctx_alloc_with_options(iscc_options_arg
, options
);
1472 s
= isl_stream_new_file(ctx
, stdin
);
1474 table
= isl_hash_table_alloc(ctx
, 10);
1476 p
= isl_printer_to_file(ctx
, stdout
);
1477 p
= isl_printer_set_output_format(p
, options
->format
);
1480 register_named_ops(s
);
1483 p
= read_line(s
, table
, p
);
1486 isl_printer_free(p
);
1487 isl_hash_table_foreach(ctx
, table
, free_cb
, NULL
);
1488 isl_hash_table_free(ctx
, table
);