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 void isl_obj_bool_print(void *v
, FILE *out
)
29 if (v
== &isl_bool_true
)
31 else if (v
== &isl_bool_false
)
32 fprintf(out
, "False");
34 fprintf(out
, "Error");
37 static void *isl_obj_bool_add(void *v1
, void *v2
)
42 struct isl_obj_vtable isl_obj_bool_vtable
= {
48 #define isl_obj_bool (&isl_obj_bool_vtable)
50 int *isl_bool_from_int(int res
)
52 return res
< 0 ? &isl_bool_error
: res
? &isl_bool_true
: &isl_bool_false
;
55 int *map_is_equal(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
57 int res
= isl_map_is_equal(map1
, map2
);
60 return isl_bool_from_int(res
);
62 int *set_is_equal(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
64 return map_is_equal((isl_map
*)set1
, (isl_map
*)set2
);
67 int *map_is_subset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
69 int res
= isl_map_is_subset(map1
, map2
);
72 return isl_bool_from_int(res
);
74 int *set_is_subset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
76 return map_is_subset((isl_map
*)set1
, (isl_map
*)set2
);
79 int *map_is_strict_subset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
81 int res
= isl_map_is_strict_subset(map1
, map2
);
84 return isl_bool_from_int(res
);
86 int *set_is_strict_subset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
88 return map_is_strict_subset((isl_map
*)set1
, (isl_map
*)set2
);
91 int *map_is_superset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
93 return map_is_subset(map2
, map1
);
95 int *set_is_superset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
97 return set_is_subset(set2
, set1
);
100 int *map_is_strict_superset(__isl_take isl_map
*map1
, __isl_take isl_map
*map2
)
102 return map_is_strict_subset(map2
, map1
);
104 int *set_is_strict_superset(__isl_take isl_set
*set1
, __isl_take isl_set
*set2
)
106 return set_is_strict_subset(set2
, set1
);
109 extern struct isl_obj_vtable isl_obj_list_vtable
;
110 #define isl_obj_list (&isl_obj_list_vtable)
112 typedef void *(*isc_bin_op_fn
)(void *lhs
, void *rhs
);
114 enum isl_token_type op
;
122 isl_pw_qpolynomial
*pwqp
;
123 isl_pw_qpolynomial
*res
;
126 static int eval_at(__isl_take isl_point
*pnt
, void *user
)
128 struct iscc_at
*at
= (struct iscc_at
*) user
;
132 set
= isl_set_from_point(isl_point_copy(pnt
));
133 qp
= isl_pw_qpolynomial_eval(isl_pw_qpolynomial_copy(at
->pwqp
), pnt
);
135 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
136 isl_pw_qpolynomial_alloc(set
, qp
));
141 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_at(
142 __isl_take isl_pw_qpolynomial
*pwqp
, __isl_take isl_set
*set
)
147 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
149 isl_set_foreach_point(set
, eval_at
, &at
);
151 isl_pw_qpolynomial_free(pwqp
);
157 struct iscc_fold_at
{
158 isl_pw_qpolynomial_fold
*pwf
;
159 isl_pw_qpolynomial
*res
;
162 static int eval_fold_at(__isl_take isl_point
*pnt
, void *user
)
164 struct iscc_fold_at
*at
= (struct iscc_fold_at
*) user
;
168 set
= isl_set_from_point(isl_point_copy(pnt
));
169 qp
= isl_pw_qpolynomial_fold_eval(isl_pw_qpolynomial_fold_copy(at
->pwf
),
172 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
173 isl_pw_qpolynomial_alloc(set
, qp
));
178 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_fold_at(
179 __isl_take isl_pw_qpolynomial_fold
*pwf
, __isl_take isl_set
*set
)
181 struct iscc_fold_at at
;
184 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
186 isl_set_foreach_point(set
, eval_fold_at
, &at
);
188 isl_pw_qpolynomial_fold_free(pwf
);
194 struct isc_bin_op bin_ops
[] = {
195 { '+', isl_obj_set
, isl_obj_set
,
197 (isc_bin_op_fn
) &isl_set_union
},
198 { '+', isl_obj_map
, isl_obj_map
,
200 (isc_bin_op_fn
) &isl_map_union
},
201 { '-', isl_obj_set
, isl_obj_set
,
203 (isc_bin_op_fn
) &isl_set_subtract
},
204 { '-', isl_obj_map
, isl_obj_map
,
206 (isc_bin_op_fn
) &isl_map_subtract
},
207 { '*', isl_obj_set
, isl_obj_set
,
209 (isc_bin_op_fn
) &isl_set_intersect
},
210 { '*', isl_obj_map
, isl_obj_map
,
212 (isc_bin_op_fn
) &isl_map_intersect
},
213 { '*', isl_obj_map
, isl_obj_set
,
215 (isc_bin_op_fn
) &isl_map_intersect_domain
},
216 { '.', isl_obj_map
, isl_obj_map
,
218 (isc_bin_op_fn
) &isl_map_apply_range
},
219 { ISL_TOKEN_TO
, isl_obj_set
, isl_obj_set
, isl_obj_map
,
220 (isc_bin_op_fn
) &isl_map_from_domain_and_range
},
221 { '=', isl_obj_set
, isl_obj_set
, isl_obj_bool
,
222 (isc_bin_op_fn
) &set_is_equal
},
223 { '=', isl_obj_map
, isl_obj_map
, isl_obj_bool
,
224 (isc_bin_op_fn
) &map_is_equal
},
225 { ISL_TOKEN_LE
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
226 (isc_bin_op_fn
) &set_is_subset
},
227 { ISL_TOKEN_LE
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
228 (isc_bin_op_fn
) &map_is_subset
},
229 { ISL_TOKEN_LT
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
230 (isc_bin_op_fn
) &set_is_strict_subset
},
231 { ISL_TOKEN_LT
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
232 (isc_bin_op_fn
) &map_is_strict_subset
},
233 { ISL_TOKEN_GE
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
234 (isc_bin_op_fn
) &set_is_superset
},
235 { ISL_TOKEN_GE
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
236 (isc_bin_op_fn
) &map_is_superset
},
237 { ISL_TOKEN_GT
, isl_obj_set
, isl_obj_set
, isl_obj_bool
,
238 (isc_bin_op_fn
) &set_is_strict_superset
},
239 { ISL_TOKEN_GT
, isl_obj_map
, isl_obj_map
, isl_obj_bool
,
240 (isc_bin_op_fn
) &map_is_strict_superset
},
241 { '+', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
242 isl_obj_pw_qpolynomial
,
243 (isc_bin_op_fn
) &isl_pw_qpolynomial_add
},
244 { '-', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
245 isl_obj_pw_qpolynomial
,
246 (isc_bin_op_fn
) &isl_pw_qpolynomial_sub
},
247 { '*', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
248 isl_obj_pw_qpolynomial
,
249 (isc_bin_op_fn
) &isl_pw_qpolynomial_mul
},
250 { '*', isl_obj_pw_qpolynomial
, isl_obj_set
,
251 isl_obj_pw_qpolynomial
,
252 (isc_bin_op_fn
) &isl_pw_qpolynomial_intersect_domain
},
253 { '*', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
254 isl_obj_pw_qpolynomial_fold
,
255 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_intersect_domain
},
256 { '@', isl_obj_pw_qpolynomial
, isl_obj_set
,
257 isl_obj_pw_qpolynomial
,
258 (isc_bin_op_fn
) &isl_pw_qpolynomial_at
},
259 { '@', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
260 isl_obj_pw_qpolynomial
,
261 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_at
},
265 __isl_give isl_set
*set_sample(__isl_take isl_set
*set
)
267 return isl_set_from_basic_set(isl_set_sample(set
));
270 __isl_give isl_map
*map_sample(__isl_take isl_map
*map
)
272 return isl_map_from_basic_map(isl_map_sample(map
));
275 static __isl_give isl_set
*set_affine_hull(__isl_take isl_set
*set
)
277 return isl_set_from_basic_set(isl_set_affine_hull(set
));
280 static __isl_give isl_map
*map_affine_hull(__isl_take isl_map
*map
)
282 return isl_map_from_basic_map(isl_map_affine_hull(map
));
285 typedef void *(*isc_un_op_fn
)(void *arg
);
287 enum isl_token_type op
;
292 struct isc_named_un_op
{
296 struct isc_named_un_op named_un_ops
[] = {
297 {"aff", { -1, isl_obj_map
, isl_obj_map
,
298 (isc_un_op_fn
) &map_affine_hull
} },
299 {"aff", { -1, isl_obj_set
, isl_obj_set
,
300 (isc_un_op_fn
) &set_affine_hull
} },
301 {"card", { -1, isl_obj_set
, isl_obj_pw_qpolynomial
,
302 (isc_un_op_fn
) &isl_set_card
} },
303 {"card", { -1, isl_obj_map
, isl_obj_pw_qpolynomial
,
304 (isc_un_op_fn
) &isl_map_card
} },
305 {"dom", { -1, isl_obj_map
, isl_obj_set
,
306 (isc_un_op_fn
) &isl_map_domain
} },
307 {"dom", { -1, isl_obj_pw_qpolynomial
, isl_obj_set
,
308 (isc_un_op_fn
) &isl_pw_qpolynomial_domain
} },
309 {"dom", { -1, isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
310 (isc_un_op_fn
) &isl_pw_qpolynomial_fold_domain
} },
311 {"ran", { -1, isl_obj_map
, isl_obj_set
,
312 (isc_un_op_fn
) &isl_map_range
} },
313 {"lexmin", { -1, isl_obj_map
, isl_obj_map
,
314 (isc_un_op_fn
) &isl_map_lexmin
} },
315 {"lexmax", { -1, isl_obj_map
, isl_obj_map
,
316 (isc_un_op_fn
) &isl_map_lexmax
} },
317 {"lexmin", { -1, isl_obj_set
, isl_obj_set
,
318 (isc_un_op_fn
) &isl_set_lexmin
} },
319 {"lexmax", { -1, isl_obj_set
, isl_obj_set
,
320 (isc_un_op_fn
) &isl_set_lexmax
} },
321 {"sample", { -1, isl_obj_set
, isl_obj_set
,
322 (isc_un_op_fn
) &set_sample
} },
323 {"sample", { -1, isl_obj_map
, isl_obj_map
,
324 (isc_un_op_fn
) &map_sample
} },
325 {"sum", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
326 (isc_un_op_fn
) &isl_pw_qpolynomial_sum
} },
328 {"ub", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial_fold
,
329 (isc_un_op_fn
) &isl_pw_qpolynomial_upper_bound
} },
334 struct isl_named_obj
{
339 static void free_obj(struct isl_obj obj
)
341 obj
.type
->free(obj
.v
);
344 static int same_name(const void *entry
, const void *val
)
346 const struct isl_named_obj
*named
= (const struct isl_named_obj
*)entry
;
348 return !strcmp(named
->name
, val
);
351 static int do_assign(struct isl_ctx
*ctx
, struct isl_hash_table
*table
,
352 char *name
, struct isl_obj obj
)
354 struct isl_hash_table_entry
*entry
;
356 struct isl_named_obj
*named
;
358 name_hash
= isl_hash_string(isl_hash_init(), name
);
359 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 1);
364 free_obj(named
->obj
);
367 named
= isl_alloc_type(ctx
, struct isl_named_obj
);
382 static struct isl_obj
stored_obj(struct isl_ctx
*ctx
,
383 struct isl_hash_table
*table
, char *name
)
385 struct isl_obj obj
= { isl_obj_none
, NULL
};
386 struct isl_hash_table_entry
*entry
;
389 name_hash
= isl_hash_string(isl_hash_init(), name
);
390 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 0);
392 struct isl_named_obj
*named
;
398 obj
.v
= obj
.type
->copy(obj
.v
);
402 static struct isc_bin_op
*read_bin_op_if_available(struct isl_stream
*s
,
406 struct isl_token
*tok
;
408 tok
= isl_stream_next_token(s
);
415 if (bin_ops
[i
].op
!= tok
->type
)
417 if (bin_ops
[i
].lhs
!= lhs
)
424 isl_stream_push_token(s
, tok
);
429 static struct isc_un_op
*read_prefix_un_op_if_available(struct isl_stream
*s
)
432 struct isl_token
*tok
;
434 tok
= isl_stream_next_token(s
);
439 if (!named_un_ops
[i
].op
.op
)
441 if (named_un_ops
[i
].op
.op
!= tok
->type
)
445 return &named_un_ops
[i
].op
;
448 isl_stream_push_token(s
, tok
);
453 static struct isc_un_op
*find_matching_un_op(struct isc_un_op
*like
,
459 if (!named_un_ops
[i
].op
.op
)
461 if (named_un_ops
[i
].op
.op
!= like
->op
)
463 if (named_un_ops
[i
].op
.arg
!= arg
)
466 return &named_un_ops
[i
].op
;
472 static int is_assign(struct isl_stream
*s
)
474 struct isl_token
*tok
;
475 struct isl_token
*tok2
;
478 tok
= isl_stream_next_token(s
);
481 if (tok
->type
!= ISL_TOKEN_IDENT
) {
482 isl_stream_push_token(s
, tok
);
486 tok2
= isl_stream_next_token(s
);
488 isl_stream_push_token(s
, tok
);
491 assign
= tok2
->type
== ISL_TOKEN_DEF
;
492 isl_stream_push_token(s
, tok2
);
493 isl_stream_push_token(s
, tok
);
498 static struct isl_obj
read_obj(struct isl_stream
*s
,
499 struct isl_hash_table
*table
);
500 static struct isl_obj
read_expr(struct isl_stream
*s
,
501 struct isl_hash_table
*table
);
503 static struct isl_obj
read_un_op_expr(struct isl_stream
*s
,
504 struct isl_hash_table
*table
, struct isc_un_op
*op
)
506 struct isl_obj obj
= { isl_obj_none
, NULL
};
508 obj
= read_obj(s
, table
);
510 op
= find_matching_un_op(op
, obj
.type
);
512 isl_assert(s
->ctx
, op
, goto error
);
513 obj
.v
= op
->fn(obj
.v
);
519 obj
.type
= isl_obj_none
;
524 static struct isl_obj
transitive_closure(struct isl_ctx
*ctx
, struct isl_obj obj
)
526 struct isl_list
*list
;
529 isl_assert(ctx
, obj
.type
== isl_obj_map
, goto error
);
530 list
= isl_list_alloc(ctx
, 2);
534 list
->obj
[0].type
= isl_obj_map
;
535 list
->obj
[0].v
= isl_map_transitive_closure(obj
.v
, &exact
);
536 list
->obj
[1].type
= isl_obj_bool
;
537 list
->obj
[1].v
= exact
? &isl_bool_true
: &isl_bool_false
;
539 obj
.type
= isl_obj_list
;
540 if (exact
< 0 || !list
->obj
[0].v
)
546 obj
.type
= isl_obj_none
;
551 static struct isl_obj
obj_at_index(struct isl_stream
*s
, struct isl_obj obj
)
553 struct isl_list
*list
= obj
.v
;
554 struct isl_token
*tok
;
557 tok
= isl_stream_next_token(s
);
558 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
559 isl_stream_error(s
, tok
, "expecting index");
561 isl_stream_push_token(s
, tok
);
564 i
= isl_int_get_si(tok
->u
.v
);
566 isl_assert(s
, i
< list
->n
, goto error
);
567 if (isl_stream_eat(s
, ']'))
571 obj
.v
= obj
.type
->copy(obj
.v
);
578 obj
.type
= isl_obj_none
;
583 static struct isl_obj
power(struct isl_stream
*s
, struct isl_obj obj
)
585 struct isl_token
*tok
;
587 if (isl_stream_eat_if_available(s
, '+'))
588 return transitive_closure(s
->ctx
, obj
);
590 tok
= isl_stream_next_token(s
);
591 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
|| isl_int_cmp_si(tok
->u
.v
, -1)) {
592 isl_stream_error(s
, tok
, "expecting -1");
594 isl_stream_push_token(s
, tok
);
598 isl_assert(s
->ctx
, obj
.type
== isl_obj_map
, goto error
);
600 obj
.v
= isl_map_reverse(obj
.v
);
607 obj
.type
= isl_obj_none
;
612 static struct isl_obj
read_obj(struct isl_stream
*s
,
613 struct isl_hash_table
*table
)
615 struct isl_obj obj
= { isl_obj_none
, NULL
};
617 struct isc_un_op
*op
= NULL
;
619 if (isl_stream_eat_if_available(s
, '(')) {
620 obj
= read_expr(s
, table
);
621 if (isl_stream_eat(s
, ')'))
624 op
= read_prefix_un_op_if_available(s
);
626 return read_un_op_expr(s
, table
, op
);
628 name
= isl_stream_read_ident_if_available(s
);
630 obj
= stored_obj(s
->ctx
, table
, name
);
632 obj
= isl_stream_read_obj(s
);
637 if (isl_stream_eat_if_available(s
, '^'))
639 else if (obj
.type
== isl_obj_list
&& isl_stream_eat_if_available(s
, '['))
640 obj
= obj_at_index(s
, obj
);
645 obj
.type
= isl_obj_none
;
650 static struct isc_bin_op
*find_matching_bin_op(struct isc_bin_op
*like
,
651 isl_obj_type lhs
, isl_obj_type rhs
)
658 if (bin_ops
[i
].op
!= like
->op
)
660 if (bin_ops
[i
].lhs
!= lhs
)
662 if (bin_ops
[i
].rhs
!= rhs
)
671 static struct isl_obj
read_expr(struct isl_stream
*s
,
672 struct isl_hash_table
*table
)
674 struct isl_obj obj
= { isl_obj_none
, NULL
};
675 struct isl_obj right_obj
= { isl_obj_none
, NULL
};
677 obj
= read_obj(s
, table
);
679 struct isc_bin_op
*op
= NULL
;
681 op
= read_bin_op_if_available(s
, obj
.type
);
685 right_obj
= read_obj(s
, table
);
687 op
= find_matching_bin_op(op
, obj
.type
, right_obj
.type
);
689 isl_assert(s
->ctx
, op
, goto error
);
690 obj
.v
= op
->fn(obj
.v
, right_obj
.v
);
698 obj
.type
= isl_obj_none
;
703 static void read_line(struct isl_stream
*s
, struct isl_hash_table
*table
)
705 struct isl_obj obj
= { isl_obj_none
, NULL
};
708 struct isc_bin_op
*op
= NULL
;
710 if (isl_stream_is_empty(s
))
713 assign
= is_assign(s
);
715 lhs
= isl_stream_read_ident_if_available(s
);
716 if (isl_stream_eat(s
, ISL_TOKEN_DEF
))
720 obj
= read_expr(s
, table
);
721 if (obj
.type
== isl_obj_none
|| obj
.v
== NULL
)
723 if (isl_stream_eat(s
, ';'))
727 if (do_assign(s
->ctx
, table
, lhs
, obj
))
730 obj
.type
->print(obj
.v
, stdout
);
741 int free_cb(void *entry
)
743 struct isl_named_obj
*named
= entry
;
745 free_obj(named
->obj
);
752 static void register_named_ops(struct isl_stream
*s
)
757 if (!named_un_ops
[i
].name
)
759 named_un_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
760 named_un_ops
[i
].name
);
761 assert(named_un_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
765 int main(int argc
, char **argv
)
768 struct isl_stream
*s
;
769 struct isl_hash_table
*table
;
771 ctx
= isl_ctx_alloc();
772 s
= isl_stream_new_file(ctx
, stdin
);
774 table
= isl_hash_table_alloc(ctx
, 10);
777 register_named_ops(s
);
779 while (!feof(stdin
)) {
783 isl_hash_table_foreach(ctx
, table
, free_cb
);
784 isl_hash_table_free(ctx
, table
);