5 #include <isl_stream.h>
6 #include <isl_obj_list.h>
7 #include <barvinok/barvinok.h>
11 #include <barvinok/bernstein.h>
14 static int isl_bool_false
= 0;
15 static int isl_bool_true
= 1;
16 static int isl_bool_error
= -1;
18 static void *isl_obj_bool_copy(void *v
)
23 static void isl_obj_bool_free(void *v
)
27 static __isl_give isl_printer
*isl_obj_bool_print(__isl_take isl_printer
*p
,
30 if (v
== &isl_bool_true
)
31 return isl_printer_print_str(p
, "True");
32 else if (v
== &isl_bool_false
)
33 return isl_printer_print_str(p
, "False");
35 return isl_printer_print_str(p
, "Error");
38 static void *isl_obj_bool_add(void *v1
, void *v2
)
43 struct isl_obj_vtable isl_obj_bool_vtable
= {
49 #define isl_obj_bool (&isl_obj_bool_vtable)
51 int *isl_bool_from_int(int res
)
53 return res
< 0 ? &isl_bool_error
: res
? &isl_bool_true
: &isl_bool_false
;
56 int *map_is_equal(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
58 int res
= isl_map_is_equal(map1
, map2
);
61 return isl_bool_from_int(res
);
63 int *set_is_equal(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
65 return map_is_equal((isl_map
*)set1
, (isl_map
*)set2
);
68 int *map_is_subset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
70 int res
= isl_map_is_subset(map1
, map2
);
73 return isl_bool_from_int(res
);
75 int *set_is_subset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
77 return map_is_subset((isl_map
*)set1
, (isl_map
*)set2
);
80 int *map_is_strict_subset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
82 int res
= isl_map_is_strict_subset(map1
, map2
);
85 return isl_bool_from_int(res
);
87 int *set_is_strict_subset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
89 return map_is_strict_subset((isl_map
*)set1
, (isl_map
*)set2
);
92 int *map_is_superset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
94 return map_is_subset(map2
, map1
);
96 int *set_is_superset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
98 return set_is_subset(set2
, set1
);
101 int *map_is_strict_superset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
103 return map_is_strict_subset(map2
, map1
);
105 int *set_is_strict_superset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
107 return set_is_strict_subset(set2
, set1
);
110 extern struct isl_obj_vtable isl_obj_list_vtable
;
111 #define isl_obj_list (&isl_obj_list_vtable)
113 typedef void *(*isc_bin_op_fn
)(void *lhs
, void *rhs
);
115 enum isl_token_type op
;
123 isl_pw_qpolynomial
*pwqp
;
124 isl_pw_qpolynomial
*res
;
127 static int eval_at(__isl_take isl_point
*pnt
, void *user
)
129 struct iscc_at
*at
= (struct iscc_at
*) user
;
133 set
= isl_set_from_point(isl_point_copy(pnt
));
134 qp
= isl_pw_qpolynomial_eval(isl_pw_qpolynomial_copy(at
->pwqp
), pnt
);
136 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
137 isl_pw_qpolynomial_alloc(set
, qp
));
142 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_at(
143 __isl_take isl_pw_qpolynomial
*pwqp
, __isl_take isl_set
*set
)
148 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
150 isl_set_foreach_point(set
, eval_at
, &at
);
152 isl_pw_qpolynomial_free(pwqp
);
158 struct iscc_fold_at
{
159 isl_pw_qpolynomial_fold
*pwf
;
160 isl_pw_qpolynomial
*res
;
163 static int eval_fold_at(__isl_take isl_point
*pnt
, void *user
)
165 struct iscc_fold_at
*at
= (struct iscc_fold_at
*) user
;
169 set
= isl_set_from_point(isl_point_copy(pnt
));
170 qp
= isl_pw_qpolynomial_fold_eval(isl_pw_qpolynomial_fold_copy(at
->pwf
),
173 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
174 isl_pw_qpolynomial_alloc(set
, qp
));
179 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_fold_at(
180 __isl_take isl_pw_qpolynomial_fold
*pwf
, __isl_take isl_set
*set
)
182 struct iscc_fold_at at
;
185 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
187 isl_set_foreach_point(set
, eval_fold_at
, &at
);
189 isl_pw_qpolynomial_fold_free(pwf
);
195 static __isl_give isl_set
*set_gist(__isl_take isl_set
*set
,
196 __isl_take isl_set
*context
)
198 return isl_set_gist(set
, isl_set_convex_hull(context
));
201 static __isl_give isl_map
*map_gist(__isl_take isl_map
*map
,
202 __isl_take isl_map
*context
)
204 return isl_map_gist(map
, isl_map_convex_hull(context
));
207 struct isc_bin_op bin_ops
[] = {
208 { '+', isl_obj_set
, isl_obj_set
,
210 (isc_bin_op_fn
) &isl_set_union
},
211 { '+', isl_obj_map
, isl_obj_map
,
213 (isc_bin_op_fn
) &isl_map_union
},
214 { '-', isl_obj_set
, isl_obj_set
,
216 (isc_bin_op_fn
) &isl_set_subtract
},
217 { '-', isl_obj_map
, isl_obj_map
,
219 (isc_bin_op_fn
) &isl_map_subtract
},
220 { '*', isl_obj_set
, isl_obj_set
,
222 (isc_bin_op_fn
) &isl_set_intersect
},
223 { '*', isl_obj_map
, isl_obj_map
,
225 (isc_bin_op_fn
) &isl_map_intersect
},
226 { '*', isl_obj_map
, isl_obj_set
,
228 (isc_bin_op_fn
) &isl_map_intersect_domain
},
229 { '.', isl_obj_map
, isl_obj_map
,
231 (isc_bin_op_fn
) &isl_map_apply_range
},
232 { ISL_TOKEN_TO
, isl_obj_set
, isl_obj_set
, isl_obj_map
,
233 (isc_bin_op_fn
) &isl_map_from_domain_and_range
},
234 { '=', isl_obj_set
, isl_obj_set
, isl_obj_bool
,
235 (isc_bin_op_fn
) &set_is_equal
},
236 { '=', isl_obj_map
, isl_obj_map
, isl_obj_bool
,
237 (isc_bin_op_fn
) &map_is_equal
},
238 { ISL_TOKEN_LE
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
239 (isc_bin_op_fn
) &set_is_subset
},
240 { ISL_TOKEN_LE
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
241 (isc_bin_op_fn
) &map_is_subset
},
242 { ISL_TOKEN_LT
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
243 (isc_bin_op_fn
) &set_is_strict_subset
},
244 { ISL_TOKEN_LT
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
245 (isc_bin_op_fn
) &map_is_strict_subset
},
246 { ISL_TOKEN_GE
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
247 (isc_bin_op_fn
) &set_is_superset
},
248 { ISL_TOKEN_GE
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
249 (isc_bin_op_fn
) &map_is_superset
},
250 { ISL_TOKEN_GT
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
251 (isc_bin_op_fn
) &set_is_strict_superset
},
252 { ISL_TOKEN_GT
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
253 (isc_bin_op_fn
) &map_is_strict_superset
},
254 { '+', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
255 isl_obj_pw_qpolynomial
,
256 (isc_bin_op_fn
) &isl_pw_qpolynomial_add
},
257 { '-', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
258 isl_obj_pw_qpolynomial
,
259 (isc_bin_op_fn
) &isl_pw_qpolynomial_sub
},
260 { '*', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
261 isl_obj_pw_qpolynomial
,
262 (isc_bin_op_fn
) &isl_pw_qpolynomial_mul
},
263 { '*', isl_obj_pw_qpolynomial
, isl_obj_set
,
264 isl_obj_pw_qpolynomial
,
265 (isc_bin_op_fn
) &isl_pw_qpolynomial_intersect_domain
},
266 { '*', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
267 isl_obj_pw_qpolynomial_fold
,
268 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_intersect_domain
},
269 { '@', isl_obj_pw_qpolynomial
, isl_obj_set
,
270 isl_obj_pw_qpolynomial
,
271 (isc_bin_op_fn
) &isl_pw_qpolynomial_at
},
272 { '@', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
273 isl_obj_pw_qpolynomial
,
274 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_at
},
275 { '%', isl_obj_set
, isl_obj_set
,
277 (isc_bin_op_fn
) &set_gist
},
278 { '%', isl_obj_map
, isl_obj_map
,
280 (isc_bin_op_fn
) &map_gist
},
281 { '%', isl_obj_pw_qpolynomial
, isl_obj_set
,
282 isl_obj_pw_qpolynomial
,
283 (isc_bin_op_fn
) &isl_pw_qpolynomial_gist
},
284 { '%', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
285 isl_obj_pw_qpolynomial_fold
,
286 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_gist
},
290 __isl_give isl_set
*set_sample(__isl_take isl_set
*set
)
292 return isl_set_from_basic_set(isl_set_sample(set
));
295 __isl_give isl_map
*map_sample(__isl_take isl_map
*map
)
297 return isl_map_from_basic_map(isl_map_sample(map
));
300 static __isl_give isl_set
*set_affine_hull(__isl_take isl_set
*set
)
302 return isl_set_from_basic_set(isl_set_affine_hull(set
));
305 static __isl_give isl_map
*map_affine_hull(__isl_take isl_map
*map
)
307 return isl_map_from_basic_map(isl_map_affine_hull(map
));
310 typedef void *(*isc_un_op_fn
)(void *arg
);
312 enum isl_token_type op
;
317 struct isc_named_un_op
{
321 struct isc_named_un_op named_un_ops
[] = {
322 {"aff", { -1, isl_obj_map
, isl_obj_map
,
323 (isc_un_op_fn
) &map_affine_hull
} },
324 {"aff", { -1, isl_obj_set
, isl_obj_set
,
325 (isc_un_op_fn
) &set_affine_hull
} },
326 {"card", { -1, isl_obj_set
, isl_obj_pw_qpolynomial
,
327 (isc_un_op_fn
) &isl_set_card
} },
328 {"card", { -1, isl_obj_map
, isl_obj_pw_qpolynomial
,
329 (isc_un_op_fn
) &isl_map_card
} },
330 {"coalesce", { -1, isl_obj_set
, isl_obj_set
,
331 (isc_un_op_fn
) &isl_set_coalesce
} },
332 {"coalesce", { -1, isl_obj_map
, isl_obj_map
,
333 (isc_un_op_fn
) &isl_map_coalesce
} },
334 {"coalesce", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
335 (isc_un_op_fn
) &isl_pw_qpolynomial_coalesce
} },
336 {"coalesce", { -1, isl_obj_pw_qpolynomial_fold
,
337 isl_obj_pw_qpolynomial_fold
,
338 (isc_un_op_fn
) &isl_pw_qpolynomial_fold_coalesce
} },
339 {"dom", { -1, isl_obj_map
, isl_obj_set
,
340 (isc_un_op_fn
) &isl_map_domain
} },
341 {"dom", { -1, isl_obj_pw_qpolynomial
, isl_obj_set
,
342 (isc_un_op_fn
) &isl_pw_qpolynomial_domain
} },
343 {"dom", { -1, isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
344 (isc_un_op_fn
) &isl_pw_qpolynomial_fold_domain
} },
345 {"ran", { -1, isl_obj_map
, isl_obj_set
,
346 (isc_un_op_fn
) &isl_map_range
} },
347 {"lexmin", { -1, isl_obj_map
, isl_obj_map
,
348 (isc_un_op_fn
) &isl_map_lexmin
} },
349 {"lexmax", { -1, isl_obj_map
, isl_obj_map
,
350 (isc_un_op_fn
) &isl_map_lexmax
} },
351 {"lexmin", { -1, isl_obj_set
, isl_obj_set
,
352 (isc_un_op_fn
) &isl_set_lexmin
} },
353 {"lexmax", { -1, isl_obj_set
, isl_obj_set
,
354 (isc_un_op_fn
) &isl_set_lexmax
} },
355 {"sample", { -1, isl_obj_set
, isl_obj_set
,
356 (isc_un_op_fn
) &set_sample
} },
357 {"sample", { -1, isl_obj_map
, isl_obj_map
,
358 (isc_un_op_fn
) &map_sample
} },
359 {"sum", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
360 (isc_un_op_fn
) &isl_pw_qpolynomial_sum
} },
362 {"ub", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial_fold
,
363 (isc_un_op_fn
) &isl_pw_qpolynomial_upper_bound
} },
368 struct isl_named_obj
{
373 static void free_obj(struct isl_obj obj
)
375 obj
.type
->free(obj
.v
);
378 static int same_name(const void *entry
, const void *val
)
380 const struct isl_named_obj
*named
= (const struct isl_named_obj
*)entry
;
382 return !strcmp(named
->name
, val
);
385 static int do_assign(struct isl_ctx
*ctx
, struct isl_hash_table
*table
,
386 char *name
, struct isl_obj obj
)
388 struct isl_hash_table_entry
*entry
;
390 struct isl_named_obj
*named
;
392 name_hash
= isl_hash_string(isl_hash_init(), name
);
393 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 1);
398 free_obj(named
->obj
);
401 named
= isl_alloc_type(ctx
, struct isl_named_obj
);
416 static struct isl_obj
stored_obj(struct isl_ctx
*ctx
,
417 struct isl_hash_table
*table
, char *name
)
419 struct isl_obj obj
= { isl_obj_none
, NULL
};
420 struct isl_hash_table_entry
*entry
;
423 name_hash
= isl_hash_string(isl_hash_init(), name
);
424 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 0);
426 struct isl_named_obj
*named
;
432 obj
.v
= obj
.type
->copy(obj
.v
);
436 static struct isc_bin_op
*read_bin_op_if_available(struct isl_stream
*s
,
440 struct isl_token
*tok
;
442 tok
= isl_stream_next_token(s
);
449 if (bin_ops
[i
].op
!= tok
->type
)
451 if (bin_ops
[i
].lhs
!= lhs
)
458 isl_stream_push_token(s
, tok
);
463 static struct isc_un_op
*read_prefix_un_op_if_available(struct isl_stream
*s
)
466 struct isl_token
*tok
;
468 tok
= isl_stream_next_token(s
);
473 if (!named_un_ops
[i
].op
.op
)
475 if (named_un_ops
[i
].op
.op
!= tok
->type
)
479 return &named_un_ops
[i
].op
;
482 isl_stream_push_token(s
, tok
);
487 static struct isc_un_op
*find_matching_un_op(struct isc_un_op
*like
,
493 if (!named_un_ops
[i
].op
.op
)
495 if (named_un_ops
[i
].op
.op
!= like
->op
)
497 if (named_un_ops
[i
].op
.arg
!= arg
)
500 return &named_un_ops
[i
].op
;
506 static int is_assign(struct isl_stream
*s
)
508 struct isl_token
*tok
;
509 struct isl_token
*tok2
;
512 tok
= isl_stream_next_token(s
);
515 if (tok
->type
!= ISL_TOKEN_IDENT
) {
516 isl_stream_push_token(s
, tok
);
520 tok2
= isl_stream_next_token(s
);
522 isl_stream_push_token(s
, tok
);
525 assign
= tok2
->type
== ISL_TOKEN_DEF
;
526 isl_stream_push_token(s
, tok2
);
527 isl_stream_push_token(s
, tok
);
532 static struct isl_obj
read_obj(struct isl_stream
*s
,
533 struct isl_hash_table
*table
);
534 static struct isl_obj
read_expr(struct isl_stream
*s
,
535 struct isl_hash_table
*table
);
537 static struct isl_obj
read_un_op_expr(struct isl_stream
*s
,
538 struct isl_hash_table
*table
, struct isc_un_op
*op
)
540 struct isl_obj obj
= { isl_obj_none
, NULL
};
542 obj
= read_obj(s
, table
);
544 op
= find_matching_un_op(op
, obj
.type
);
546 isl_assert(s
->ctx
, op
, goto error
);
547 obj
.v
= op
->fn(obj
.v
);
553 obj
.type
= isl_obj_none
;
558 static struct isl_obj
transitive_closure(struct isl_ctx
*ctx
, struct isl_obj obj
)
560 struct isl_list
*list
;
563 isl_assert(ctx
, obj
.type
== isl_obj_map
, goto error
);
564 list
= isl_list_alloc(ctx
, 2);
568 list
->obj
[0].type
= isl_obj_map
;
569 list
->obj
[0].v
= isl_map_transitive_closure(obj
.v
, &exact
);
570 list
->obj
[1].type
= isl_obj_bool
;
571 list
->obj
[1].v
= exact
? &isl_bool_true
: &isl_bool_false
;
573 obj
.type
= isl_obj_list
;
574 if (exact
< 0 || !list
->obj
[0].v
)
580 obj
.type
= isl_obj_none
;
585 static struct isl_obj
obj_at_index(struct isl_stream
*s
, struct isl_obj obj
)
587 struct isl_list
*list
= obj
.v
;
588 struct isl_token
*tok
;
591 tok
= isl_stream_next_token(s
);
592 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
593 isl_stream_error(s
, tok
, "expecting index");
595 isl_stream_push_token(s
, tok
);
598 i
= isl_int_get_si(tok
->u
.v
);
600 isl_assert(s
, i
< list
->n
, goto error
);
601 if (isl_stream_eat(s
, ']'))
605 obj
.v
= obj
.type
->copy(obj
.v
);
612 obj
.type
= isl_obj_none
;
617 static struct isl_obj
power(struct isl_stream
*s
, struct isl_obj obj
)
619 struct isl_token
*tok
;
621 if (isl_stream_eat_if_available(s
, '+'))
622 return transitive_closure(s
->ctx
, obj
);
624 tok
= isl_stream_next_token(s
);
625 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
|| isl_int_cmp_si(tok
->u
.v
, -1)) {
626 isl_stream_error(s
, tok
, "expecting -1");
628 isl_stream_push_token(s
, tok
);
632 isl_assert(s
->ctx
, obj
.type
== isl_obj_map
, goto error
);
634 obj
.v
= isl_map_reverse(obj
.v
);
641 obj
.type
= isl_obj_none
;
646 static struct isl_obj
read_obj(struct isl_stream
*s
,
647 struct isl_hash_table
*table
)
649 struct isl_obj obj
= { isl_obj_none
, NULL
};
651 struct isc_un_op
*op
= NULL
;
653 if (isl_stream_eat_if_available(s
, '(')) {
654 obj
= read_expr(s
, table
);
655 if (isl_stream_eat(s
, ')'))
658 op
= read_prefix_un_op_if_available(s
);
660 return read_un_op_expr(s
, table
, op
);
662 name
= isl_stream_read_ident_if_available(s
);
664 obj
= stored_obj(s
->ctx
, table
, name
);
666 obj
= isl_stream_read_obj(s
);
671 if (isl_stream_eat_if_available(s
, '^'))
673 else if (obj
.type
== isl_obj_list
&& isl_stream_eat_if_available(s
, '['))
674 obj
= obj_at_index(s
, obj
);
679 obj
.type
= isl_obj_none
;
684 static struct isc_bin_op
*find_matching_bin_op(struct isc_bin_op
*like
,
685 isl_obj_type lhs
, isl_obj_type rhs
)
692 if (bin_ops
[i
].op
!= like
->op
)
694 if (bin_ops
[i
].lhs
!= lhs
)
696 if (bin_ops
[i
].rhs
!= rhs
)
705 static struct isl_obj
read_expr(struct isl_stream
*s
,
706 struct isl_hash_table
*table
)
708 struct isl_obj obj
= { isl_obj_none
, NULL
};
709 struct isl_obj right_obj
= { isl_obj_none
, NULL
};
711 obj
= read_obj(s
, table
);
713 struct isc_bin_op
*op
= NULL
;
715 op
= read_bin_op_if_available(s
, obj
.type
);
719 right_obj
= read_obj(s
, table
);
721 op
= find_matching_bin_op(op
, obj
.type
, right_obj
.type
);
723 isl_assert(s
->ctx
, op
, goto error
);
724 obj
.v
= op
->fn(obj
.v
, right_obj
.v
);
732 obj
.type
= isl_obj_none
;
737 static __isl_give isl_printer
*read_line(struct isl_stream
*s
,
738 struct isl_hash_table
*table
, __isl_take isl_printer
*p
)
740 struct isl_obj obj
= { isl_obj_none
, NULL
};
743 struct isc_bin_op
*op
= NULL
;
747 if (isl_stream_is_empty(s
))
750 assign
= is_assign(s
);
752 lhs
= isl_stream_read_ident_if_available(s
);
753 if (isl_stream_eat(s
, ISL_TOKEN_DEF
))
757 obj
= read_expr(s
, table
);
758 if (obj
.type
== isl_obj_none
|| obj
.v
== NULL
)
760 if (isl_stream_eat(s
, ';'))
764 if (do_assign(s
->ctx
, table
, lhs
, obj
))
767 p
= obj
.type
->print(p
, obj
.v
);
768 p
= isl_printer_end_line(p
);
779 int free_cb(void *entry
)
781 struct isl_named_obj
*named
= entry
;
783 free_obj(named
->obj
);
790 static void register_named_ops(struct isl_stream
*s
)
795 if (!named_un_ops
[i
].name
)
797 named_un_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
798 named_un_ops
[i
].name
);
799 assert(named_un_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
803 int main(int argc
, char **argv
)
806 struct isl_stream
*s
;
807 struct isl_hash_table
*table
;
810 ctx
= isl_ctx_alloc();
811 s
= isl_stream_new_file(ctx
, stdin
);
813 table
= isl_hash_table_alloc(ctx
, 10);
815 p
= isl_printer_to_file(ctx
, stdout
);
818 register_named_ops(s
);
820 while (!feof(stdin
)) {
821 p
= read_line(s
, table
, p
);
825 isl_hash_table_foreach(ctx
, table
, free_cb
);
826 isl_hash_table_free(ctx
, table
);