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 extern struct isl_obj_vtable isl_obj_list_vtable
;
51 #define isl_obj_list (&isl_obj_list_vtable)
53 typedef void *(*isc_bin_op_fn
)(void *lhs
, void *rhs
);
55 enum isl_token_type op
;
63 isl_pw_qpolynomial
*pwqp
;
64 isl_pw_qpolynomial
*res
;
67 static int eval_at(__isl_take isl_point
*pnt
, void *user
)
69 struct iscc_at
*at
= (struct iscc_at
*) user
;
73 set
= isl_set_from_point(isl_point_copy(pnt
));
74 qp
= isl_pw_qpolynomial_eval(isl_pw_qpolynomial_copy(at
->pwqp
), pnt
);
76 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
77 isl_pw_qpolynomial_alloc(set
, qp
));
82 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_at(
83 __isl_take isl_pw_qpolynomial
*pwqp
, __isl_take isl_set
*set
)
88 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
90 isl_set_foreach_point(set
, eval_at
, &at
);
92 isl_pw_qpolynomial_free(pwqp
);
99 isl_pw_qpolynomial_fold
*pwf
;
100 isl_pw_qpolynomial
*res
;
103 static int eval_fold_at(__isl_take isl_point
*pnt
, void *user
)
105 struct iscc_fold_at
*at
= (struct iscc_fold_at
*) user
;
109 set
= isl_set_from_point(isl_point_copy(pnt
));
110 qp
= isl_pw_qpolynomial_fold_eval(isl_pw_qpolynomial_fold_copy(at
->pwf
),
113 at
->res
= isl_pw_qpolynomial_add_disjoint(at
->res
,
114 isl_pw_qpolynomial_alloc(set
, qp
));
119 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_fold_at(
120 __isl_take isl_pw_qpolynomial_fold
*pwf
, __isl_take isl_set
*set
)
122 struct iscc_fold_at at
;
125 at
.res
= isl_pw_qpolynomial_zero(isl_set_get_dim(set
));
127 isl_set_foreach_point(set
, eval_fold_at
, &at
);
129 isl_pw_qpolynomial_fold_free(pwf
);
135 struct isc_bin_op bin_ops
[] = {
136 { '+', isl_obj_set
, isl_obj_set
,
138 (isc_bin_op_fn
) &isl_set_union
},
139 { '+', isl_obj_map
, isl_obj_map
,
141 (isc_bin_op_fn
) &isl_map_union
},
142 { '-', isl_obj_set
, isl_obj_set
,
144 (isc_bin_op_fn
) &isl_set_subtract
},
145 { '-', isl_obj_map
, isl_obj_map
,
147 (isc_bin_op_fn
) &isl_map_subtract
},
148 { '*', isl_obj_set
, isl_obj_set
,
150 (isc_bin_op_fn
) &isl_set_intersect
},
151 { '*', isl_obj_map
, isl_obj_map
,
153 (isc_bin_op_fn
) &isl_map_intersect
},
154 { '*', isl_obj_map
, isl_obj_set
,
156 (isc_bin_op_fn
) &isl_map_intersect_domain
},
157 { '.', isl_obj_map
, isl_obj_map
,
159 (isc_bin_op_fn
) &isl_map_apply_range
},
160 { ISL_TOKEN_TO
, isl_obj_set
, isl_obj_set
, isl_obj_map
,
161 (isc_bin_op_fn
) &isl_map_from_domain_and_range
},
162 { '+', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
163 isl_obj_pw_qpolynomial
,
164 (isc_bin_op_fn
) &isl_pw_qpolynomial_add
},
165 { '-', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
166 isl_obj_pw_qpolynomial
,
167 (isc_bin_op_fn
) &isl_pw_qpolynomial_sub
},
168 { '*', isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
169 isl_obj_pw_qpolynomial
,
170 (isc_bin_op_fn
) &isl_pw_qpolynomial_mul
},
171 { '*', isl_obj_pw_qpolynomial
, isl_obj_set
,
172 isl_obj_pw_qpolynomial
,
173 (isc_bin_op_fn
) &isl_pw_qpolynomial_intersect_domain
},
174 { '*', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
175 isl_obj_pw_qpolynomial_fold
,
176 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_intersect_domain
},
177 { '@', isl_obj_pw_qpolynomial
, isl_obj_set
,
178 isl_obj_pw_qpolynomial
,
179 (isc_bin_op_fn
) &isl_pw_qpolynomial_at
},
180 { '@', isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
181 isl_obj_pw_qpolynomial
,
182 (isc_bin_op_fn
) &isl_pw_qpolynomial_fold_at
},
186 __isl_give isl_set
*set_sample(__isl_take isl_set
*set
)
188 return isl_set_from_basic_set(isl_set_sample(set
));
191 __isl_give isl_map
*map_sample(__isl_take isl_map
*map
)
193 return isl_map_from_basic_map(isl_map_sample(map
));
196 static __isl_give isl_set
*set_affine_hull(__isl_take isl_set
*set
)
198 return isl_set_from_basic_set(isl_set_affine_hull(set
));
201 static __isl_give isl_map
*map_affine_hull(__isl_take isl_map
*map
)
203 return isl_map_from_basic_map(isl_map_affine_hull(map
));
206 typedef void *(*isc_un_op_fn
)(void *arg
);
208 enum isl_token_type op
;
213 struct isc_named_un_op
{
217 struct isc_named_un_op named_un_ops
[] = {
218 {"aff", { -1, isl_obj_map
, isl_obj_map
,
219 (isc_un_op_fn
) &map_affine_hull
} },
220 {"aff", { -1, isl_obj_set
, isl_obj_set
,
221 (isc_un_op_fn
) &set_affine_hull
} },
222 {"card", { -1, isl_obj_set
, isl_obj_pw_qpolynomial
,
223 (isc_un_op_fn
) &isl_set_card
} },
224 {"card", { -1, isl_obj_map
, isl_obj_pw_qpolynomial
,
225 (isc_un_op_fn
) &isl_map_card
} },
226 {"dom", { -1, isl_obj_map
, isl_obj_set
,
227 (isc_un_op_fn
) &isl_map_domain
} },
228 {"dom", { -1, isl_obj_pw_qpolynomial
, isl_obj_set
,
229 (isc_un_op_fn
) &isl_pw_qpolynomial_domain
} },
230 {"dom", { -1, isl_obj_pw_qpolynomial_fold
, isl_obj_set
,
231 (isc_un_op_fn
) &isl_pw_qpolynomial_fold_domain
} },
232 {"ran", { -1, isl_obj_map
, isl_obj_set
,
233 (isc_un_op_fn
) &isl_map_range
} },
234 {"lexmin", { -1, isl_obj_map
, isl_obj_map
,
235 (isc_un_op_fn
) &isl_map_lexmin
} },
236 {"lexmax", { -1, isl_obj_map
, isl_obj_map
,
237 (isc_un_op_fn
) &isl_map_lexmax
} },
238 {"lexmin", { -1, isl_obj_set
, isl_obj_set
,
239 (isc_un_op_fn
) &isl_set_lexmin
} },
240 {"lexmax", { -1, isl_obj_set
, isl_obj_set
,
241 (isc_un_op_fn
) &isl_set_lexmax
} },
242 {"sample", { -1, isl_obj_set
, isl_obj_set
,
243 (isc_un_op_fn
) &set_sample
} },
244 {"sample", { -1, isl_obj_map
, isl_obj_map
,
245 (isc_un_op_fn
) &map_sample
} },
246 {"sum", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial
,
247 (isc_un_op_fn
) &isl_pw_qpolynomial_sum
} },
249 {"ub", { -1, isl_obj_pw_qpolynomial
, isl_obj_pw_qpolynomial_fold
,
250 (isc_un_op_fn
) &isl_pw_qpolynomial_upper_bound
} },
255 struct isl_named_obj
{
260 static void free_obj(struct isl_obj obj
)
262 obj
.type
->free(obj
.v
);
265 static int same_name(const void *entry
, const void *val
)
267 const struct isl_named_obj
*named
= (const struct isl_named_obj
*)entry
;
269 return !strcmp(named
->name
, val
);
272 static int do_assign(struct isl_ctx
*ctx
, struct isl_hash_table
*table
,
273 char *name
, struct isl_obj obj
)
275 struct isl_hash_table_entry
*entry
;
277 struct isl_named_obj
*named
;
279 name_hash
= isl_hash_string(isl_hash_init(), name
);
280 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 1);
285 free_obj(named
->obj
);
288 named
= isl_alloc_type(ctx
, struct isl_named_obj
);
303 static struct isl_obj
stored_obj(struct isl_ctx
*ctx
,
304 struct isl_hash_table
*table
, char *name
)
306 struct isl_obj obj
= { isl_obj_none
, NULL
};
307 struct isl_hash_table_entry
*entry
;
310 name_hash
= isl_hash_string(isl_hash_init(), name
);
311 entry
= isl_hash_table_find(ctx
, table
, name_hash
, same_name
, name
, 0);
313 struct isl_named_obj
*named
;
319 obj
.v
= obj
.type
->copy(obj
.v
);
323 static struct isc_bin_op
*read_bin_op_if_available(struct isl_stream
*s
,
327 struct isl_token
*tok
;
329 tok
= isl_stream_next_token(s
);
336 if (bin_ops
[i
].op
!= tok
->type
)
338 if (bin_ops
[i
].lhs
!= lhs
)
345 isl_stream_push_token(s
, tok
);
350 static struct isc_un_op
*read_prefix_un_op_if_available(struct isl_stream
*s
)
353 struct isl_token
*tok
;
355 tok
= isl_stream_next_token(s
);
360 if (!named_un_ops
[i
].op
.op
)
362 if (named_un_ops
[i
].op
.op
!= tok
->type
)
366 return &named_un_ops
[i
].op
;
369 isl_stream_push_token(s
, tok
);
374 static struct isc_un_op
*find_matching_un_op(struct isc_un_op
*like
,
380 if (!named_un_ops
[i
].op
.op
)
382 if (named_un_ops
[i
].op
.op
!= like
->op
)
384 if (named_un_ops
[i
].op
.arg
!= arg
)
387 return &named_un_ops
[i
].op
;
393 static int is_assign(struct isl_stream
*s
)
395 struct isl_token
*tok
;
396 struct isl_token
*tok2
;
399 tok
= isl_stream_next_token(s
);
402 if (tok
->type
!= ISL_TOKEN_IDENT
) {
403 isl_stream_push_token(s
, tok
);
407 tok2
= isl_stream_next_token(s
);
409 isl_stream_push_token(s
, tok
);
412 assign
= tok2
->type
== ISL_TOKEN_DEF
;
413 isl_stream_push_token(s
, tok2
);
414 isl_stream_push_token(s
, tok
);
419 static struct isl_obj
read_obj(struct isl_stream
*s
,
420 struct isl_hash_table
*table
);
421 static struct isl_obj
read_expr(struct isl_stream
*s
,
422 struct isl_hash_table
*table
);
424 static struct isl_obj
read_un_op_expr(struct isl_stream
*s
,
425 struct isl_hash_table
*table
, struct isc_un_op
*op
)
427 struct isl_obj obj
= { isl_obj_none
, NULL
};
429 obj
= read_obj(s
, table
);
431 op
= find_matching_un_op(op
, obj
.type
);
433 isl_assert(s
->ctx
, op
, goto error
);
434 obj
.v
= op
->fn(obj
.v
);
440 obj
.type
= isl_obj_none
;
445 static struct isl_obj
transitive_closure(struct isl_ctx
*ctx
, struct isl_obj obj
)
447 struct isl_list
*list
;
450 isl_assert(ctx
, obj
.type
== isl_obj_map
, goto error
);
451 list
= isl_list_alloc(ctx
, 2);
455 list
->obj
[0].type
= isl_obj_map
;
456 list
->obj
[0].v
= isl_map_transitive_closure(obj
.v
, &exact
);
457 list
->obj
[1].type
= isl_obj_bool
;
458 list
->obj
[1].v
= exact
? &isl_bool_true
: &isl_bool_false
;
460 obj
.type
= isl_obj_list
;
461 if (exact
< 0 || !list
->obj
[0].v
)
467 obj
.type
= isl_obj_none
;
472 static struct isl_obj
obj_at_index(struct isl_stream
*s
, struct isl_obj obj
)
474 struct isl_list
*list
= obj
.v
;
475 struct isl_token
*tok
;
478 tok
= isl_stream_next_token(s
);
479 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
480 isl_stream_error(s
, tok
, "expecting index");
482 isl_stream_push_token(s
, tok
);
485 i
= isl_int_get_si(tok
->u
.v
);
487 isl_assert(s
, i
< list
->n
, goto error
);
488 if (isl_stream_eat(s
, ']'))
492 obj
.v
= obj
.type
->copy(obj
.v
);
499 obj
.type
= isl_obj_none
;
504 static struct isl_obj
power(struct isl_stream
*s
, struct isl_obj obj
)
506 struct isl_token
*tok
;
508 if (isl_stream_eat_if_available(s
, '+'))
509 return transitive_closure(s
->ctx
, obj
);
511 tok
= isl_stream_next_token(s
);
512 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
|| isl_int_cmp_si(tok
->u
.v
, -1)) {
513 isl_stream_error(s
, tok
, "expecting -1");
515 isl_stream_push_token(s
, tok
);
519 isl_assert(s
->ctx
, obj
.type
== isl_obj_map
, goto error
);
521 obj
.v
= isl_map_reverse(obj
.v
);
528 obj
.type
= isl_obj_none
;
533 static struct isl_obj
read_obj(struct isl_stream
*s
,
534 struct isl_hash_table
*table
)
536 struct isl_obj obj
= { isl_obj_none
, NULL
};
538 struct isc_un_op
*op
= NULL
;
540 if (isl_stream_eat_if_available(s
, '(')) {
541 obj
= read_expr(s
, table
);
542 if (isl_stream_eat(s
, ')'))
545 op
= read_prefix_un_op_if_available(s
);
547 return read_un_op_expr(s
, table
, op
);
549 name
= isl_stream_read_ident_if_available(s
);
551 obj
= stored_obj(s
->ctx
, table
, name
);
553 obj
= isl_stream_read_obj(s
);
558 if (isl_stream_eat_if_available(s
, '^'))
560 else if (obj
.type
== isl_obj_list
&& isl_stream_eat_if_available(s
, '['))
561 obj
= obj_at_index(s
, obj
);
566 obj
.type
= isl_obj_none
;
571 static struct isc_bin_op
*find_matching_bin_op(struct isc_bin_op
*like
,
572 isl_obj_type lhs
, isl_obj_type rhs
)
579 if (bin_ops
[i
].op
!= like
->op
)
581 if (bin_ops
[i
].lhs
!= lhs
)
583 if (bin_ops
[i
].rhs
!= rhs
)
592 static struct isl_obj
read_expr(struct isl_stream
*s
,
593 struct isl_hash_table
*table
)
595 struct isl_obj obj
= { isl_obj_none
, NULL
};
596 struct isl_obj right_obj
= { isl_obj_none
, NULL
};
598 obj
= read_obj(s
, table
);
600 struct isc_bin_op
*op
= NULL
;
602 op
= read_bin_op_if_available(s
, obj
.type
);
606 right_obj
= read_obj(s
, table
);
608 op
= find_matching_bin_op(op
, obj
.type
, right_obj
.type
);
610 isl_assert(s
->ctx
, op
, goto error
);
611 obj
.v
= op
->fn(obj
.v
, right_obj
.v
);
619 obj
.type
= isl_obj_none
;
624 static void read_line(struct isl_stream
*s
, struct isl_hash_table
*table
)
626 struct isl_obj obj
= { isl_obj_none
, NULL
};
629 struct isc_bin_op
*op
= NULL
;
631 if (isl_stream_is_empty(s
))
634 assign
= is_assign(s
);
636 lhs
= isl_stream_read_ident_if_available(s
);
637 if (isl_stream_eat(s
, ISL_TOKEN_DEF
))
641 obj
= read_expr(s
, table
);
642 if (obj
.type
== isl_obj_none
|| obj
.v
== NULL
)
644 if (isl_stream_eat(s
, ';'))
648 if (do_assign(s
->ctx
, table
, lhs
, obj
))
651 obj
.type
->print(obj
.v
, stdout
);
662 int free_cb(void *entry
)
664 struct isl_named_obj
*named
= entry
;
666 free_obj(named
->obj
);
673 static void register_named_ops(struct isl_stream
*s
)
678 if (!named_un_ops
[i
].name
)
680 named_un_ops
[i
].op
.op
= isl_stream_register_keyword(s
,
681 named_un_ops
[i
].name
);
682 assert(named_un_ops
[i
].op
.op
!= ISL_TOKEN_ERROR
);
686 int main(int argc
, char **argv
)
689 struct isl_stream
*s
;
690 struct isl_hash_table
*table
;
692 ctx
= isl_ctx_alloc();
693 s
= isl_stream_new_file(ctx
, stdin
);
695 table
= isl_hash_table_alloc(ctx
, 10);
698 register_named_ops(s
);
700 while (!feof(stdin
)) {
704 isl_hash_table_foreach(ctx
, table
, free_cb
);
705 isl_hash_table_free(ctx
, table
);