add isl_union_map_involves_dims
[isl.git] / isl_union_templ.c
blob4cd1d9dd183c63527bc5e50ffab258ed7083f56d
1 /*
2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8 * 91893 Orsay, France
9 */
11 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
12 #define FN(TYPE,NAME) xFN(TYPE,NAME)
13 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
14 #define S(TYPE,NAME) xS(TYPE,NAME)
16 struct UNION {
17 int ref;
18 #ifdef HAS_TYPE
19 enum isl_fold type;
20 #endif
21 isl_space *space;
23 struct isl_hash_table table;
26 __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u);
28 isl_ctx *FN(UNION,get_ctx)(__isl_keep UNION *u)
30 return u ? u->space->ctx : NULL;
33 __isl_give isl_space *FN(UNION,get_space)(__isl_keep UNION *u)
35 if (!u)
36 return NULL;
37 return isl_space_copy(u->space);
40 /* Return the number of parameters of "u", where "type"
41 * is required to be set to isl_dim_param.
43 unsigned FN(UNION,dim)(__isl_keep UNION *u, enum isl_dim_type type)
45 if (!u)
46 return 0;
48 if (type != isl_dim_param)
49 isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
50 "can only reference parameters", return 0);
52 return isl_space_dim(u->space, type);
55 /* Return the position of the parameter with the given name
56 * in "u".
57 * Return -1 if no such dimension can be found.
59 int FN(UNION,find_dim_by_name)(__isl_keep UNION *u, enum isl_dim_type type,
60 const char *name)
62 if (!u)
63 return -1;
64 return isl_space_find_dim_by_name(u->space, type, name);
67 #ifdef HAS_TYPE
68 static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *dim,
69 enum isl_fold type, int size)
70 #else
71 static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *dim, int size)
72 #endif
74 UNION *u;
76 dim = isl_space_params(dim);
77 if (!dim)
78 return NULL;
80 u = isl_calloc_type(dim->ctx, UNION);
81 if (!u)
82 goto error;
84 u->ref = 1;
85 #ifdef HAS_TYPE
86 u->type = type;
87 #endif
88 u->space = dim;
89 if (isl_hash_table_init(dim->ctx, &u->table, size) < 0)
90 return FN(UNION,free)(u);
92 return u;
93 error:
94 isl_space_free(dim);
95 return NULL;
98 #ifdef HAS_TYPE
99 __isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *dim, enum isl_fold type)
101 return FN(UNION,alloc)(dim, type, 16);
103 #else
104 __isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *dim)
106 return FN(UNION,alloc)(dim, 16);
108 #endif
110 __isl_give UNION *FN(UNION,copy)(__isl_keep UNION *u)
112 if (!u)
113 return NULL;
115 u->ref++;
116 return u;
119 S(UNION,foreach_data)
121 int (*fn)(__isl_take PART *part, void *user);
122 void *user;
125 static int call_on_copy(void **entry, void *user)
127 PART *part = *entry;
128 S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
130 return data->fn(FN(PART,copy)(part), data->user);
133 int FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
134 int (*fn)(__isl_take PART *part, void *user), void *user)
136 S(UNION,foreach_data) data = { fn, user };
138 if (!u)
139 return -1;
141 return isl_hash_table_foreach(u->space->ctx, &u->table,
142 &call_on_copy, &data);
145 /* Is the space of "entry" equal to "space"?
147 static int has_space(const void *entry, const void *val)
149 PART *part = (PART *)entry;
150 isl_space *space = (isl_space *) val;
152 return isl_space_is_equal(part->dim, space);
155 /* This function is not currently used by isl_aff.c.
157 static int has_domain_space(const void *entry, const void *val)
158 __attribute__ ((unused));
160 /* Is the domain space of "entry" equal to "space"?
162 static int has_domain_space(const void *entry, const void *val)
164 PART *part = (PART *)entry;
165 isl_space *space = (isl_space *) val;
167 if (isl_space_is_params(space))
168 return isl_space_is_set(part->dim);
170 return isl_space_tuple_is_equal(part->dim, isl_dim_in,
171 space, isl_dim_set);
174 /* Is the domain space of "entry" equal to the domain of "space"?
176 static int has_same_domain_space(const void *entry, const void *val)
178 PART *part = (PART *)entry;
179 isl_space *space = (isl_space *) val;
181 if (isl_space_is_set(space))
182 return isl_space_is_set(part->dim);
184 return isl_space_tuple_is_equal(part->dim, isl_dim_in,
185 space, isl_dim_in);
188 /* Extract the element of "u" living in "space" (ignoring parameters).
190 * Return the ZERO element if "u" does not contain any element
191 * living in "space".
193 __isl_give PART *FN(FN(UNION,extract),PARTS)(__isl_keep UNION *u,
194 __isl_take isl_space *space)
196 uint32_t hash;
197 struct isl_hash_table_entry *entry;
199 if (!u || !space)
200 goto error;
201 if (!isl_space_match(u->space, isl_dim_param, space, isl_dim_param)) {
202 space = isl_space_drop_dims(space, isl_dim_param,
203 0, isl_space_dim(space, isl_dim_param));
204 space = isl_space_align_params(space,
205 FN(UNION,get_space)(u));
206 if (!space)
207 goto error;
210 hash = isl_space_get_hash(space);
211 entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
212 &has_space, space, 0);
213 if (!entry)
214 #ifdef HAS_TYPE
215 return FN(PART,ZERO)(space, u->type);
216 #else
217 return FN(PART,ZERO)(space);
218 #endif
219 isl_space_free(space);
220 return FN(PART,copy)(entry->data);
221 error:
222 isl_space_free(space);
223 return NULL;
226 /* Add "part" to "u".
227 * If "disjoint" is set, then "u" is not allowed to already have
228 * a part that is defined on the same space as "part".
229 * Otherwise, compute the union sum of "part" and the part in "u"
230 * defined on the same space.
232 static __isl_give UNION *FN(UNION,add_part_generic)(__isl_take UNION *u,
233 __isl_take PART *part, int disjoint)
235 int empty;
236 uint32_t hash;
237 struct isl_hash_table_entry *entry;
239 if (!part)
240 goto error;
242 empty = FN(PART,IS_ZERO)(part);
243 if (empty < 0)
244 goto error;
245 if (empty) {
246 FN(PART,free)(part);
247 return u;
250 u = FN(UNION,align_params)(u, FN(PART,get_space)(part));
251 part = FN(PART,align_params)(part, FN(UNION,get_space)(u));
253 u = FN(UNION,cow)(u);
255 if (!u)
256 goto error;
258 hash = isl_space_get_hash(part->dim);
259 entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
260 &has_same_domain_space, part->dim, 1);
261 if (!entry)
262 goto error;
264 if (!entry->data)
265 entry->data = part;
266 else {
267 PART *entry_part = entry->data;
268 if (disjoint)
269 isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
270 "additional part should live on separate "
271 "space", goto error);
272 if (!isl_space_tuple_is_equal(entry_part->dim, isl_dim_out,
273 part->dim, isl_dim_out))
274 isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
275 "union expression can only contain a single "
276 "expression over a given domain", goto error);
277 entry->data = FN(PART,union_add_)(entry->data,
278 FN(PART,copy)(part));
279 if (!entry->data)
280 goto error;
281 empty = FN(PART,IS_ZERO)(part);
282 if (empty < 0)
283 goto error;
284 if (empty) {
285 FN(PART,free)(entry->data);
286 isl_hash_table_remove(u->space->ctx, &u->table, entry);
288 FN(PART,free)(part);
291 return u;
292 error:
293 FN(PART,free)(part);
294 FN(UNION,free)(u);
295 return NULL;
298 /* Add "part" to "u", where "u" is assumed not to already have
299 * a part that is defined on the same space as "part".
301 __isl_give UNION *FN(FN(UNION,add),PARTS)(__isl_take UNION *u,
302 __isl_take PART *part)
304 return FN(UNION,add_part_generic)(u, part, 1);
307 static int add_part(__isl_take PART *part, void *user)
309 UNION **u = (UNION **)user;
311 *u = FN(FN(UNION,add),PARTS)(*u, part);
313 return 0;
316 __isl_give UNION *FN(UNION,dup)(__isl_keep UNION *u)
318 UNION *dup;
320 if (!u)
321 return NULL;
323 #ifdef HAS_TYPE
324 dup = FN(UNION,ZERO)(isl_space_copy(u->space), u->type);
325 #else
326 dup = FN(UNION,ZERO)(isl_space_copy(u->space));
327 #endif
328 if (FN(FN(UNION,foreach),PARTS)(u, &add_part, &dup) < 0)
329 goto error;
330 return dup;
331 error:
332 FN(UNION,free)(dup);
333 return NULL;
336 __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u)
338 if (!u)
339 return NULL;
341 if (u->ref == 1)
342 return u;
343 u->ref--;
344 return FN(UNION,dup)(u);
347 static int free_u_entry(void **entry, void *user)
349 PART *part = *entry;
350 FN(PART,free)(part);
351 return 0;
354 __isl_null UNION *FN(UNION,free)(__isl_take UNION *u)
356 if (!u)
357 return NULL;
359 if (--u->ref > 0)
360 return NULL;
362 isl_hash_table_foreach(u->space->ctx, &u->table, &free_u_entry, NULL);
363 isl_hash_table_clear(&u->table);
364 isl_space_free(u->space);
365 free(u);
366 return NULL;
369 S(UNION,align) {
370 isl_reordering *exp;
371 UNION *res;
374 #ifdef ALIGN_DOMAIN
375 static int align_entry(__isl_take PART *part, void *user)
377 isl_reordering *exp;
378 S(UNION,align) *data = user;
380 exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
381 FN(PART,get_domain_space)(part));
383 data->res = FN(FN(UNION,add),PARTS)(data->res,
384 FN(PART,realign_domain)(part, exp));
386 return 0;
388 #else
389 static int align_entry(__isl_take PART *part, void *user)
391 isl_reordering *exp;
392 S(UNION,align) *data = user;
394 exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
395 FN(PART,get_space)(part));
397 data->res = FN(FN(UNION,add),PARTS)(data->res,
398 FN(PART,realign)(part, exp));
400 return 0;
402 #endif
404 __isl_give UNION *FN(UNION,align_params)(__isl_take UNION *u,
405 __isl_take isl_space *model)
407 S(UNION,align) data = { NULL, NULL };
409 if (!u || !model)
410 goto error;
412 if (isl_space_match(u->space, isl_dim_param, model, isl_dim_param)) {
413 isl_space_free(model);
414 return u;
417 model = isl_space_params(model);
418 data.exp = isl_parameter_alignment_reordering(u->space, model);
419 if (!data.exp)
420 goto error;
422 #ifdef HAS_TYPE
423 data.res = FN(UNION,alloc)(isl_space_copy(data.exp->dim),
424 u->type, u->table.n);
425 #else
426 data.res = FN(UNION,alloc)(isl_space_copy(data.exp->dim), u->table.n);
427 #endif
428 if (FN(FN(UNION,foreach),PARTS)(u, &align_entry, &data) < 0)
429 goto error;
431 isl_reordering_free(data.exp);
432 FN(UNION,free)(u);
433 isl_space_free(model);
434 return data.res;
435 error:
436 isl_reordering_free(data.exp);
437 FN(UNION,free)(u);
438 FN(UNION,free)(data.res);
439 isl_space_free(model);
440 return NULL;
443 /* Add "part" to *u, taking the union sum if "u" already has
444 * a part defined on the same space as "part".
446 static int union_add_part(__isl_take PART *part, void *user)
448 UNION **u = (UNION **)user;
450 *u = FN(UNION,add_part_generic)(*u, part, 0);
452 return 0;
455 /* Compute the sum of "u1" and "u2" on the union of their domains,
456 * with the actual sum on the shared domain and
457 * the defined expression on the symmetric difference of the domains.
459 * This is an internal function that is exposed under different
460 * names depending on whether the base expressions have a zero default
461 * value.
462 * If they do, then this function is called "add".
463 * Otherwise, it is called "union_add".
465 static __isl_give UNION *FN(UNION,union_add_)(__isl_take UNION *u1,
466 __isl_take UNION *u2)
468 u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
469 u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
471 u1 = FN(UNION,cow)(u1);
473 if (!u1 || !u2)
474 goto error;
476 if (FN(FN(UNION,foreach),PARTS)(u2, &union_add_part, &u1) < 0)
477 goto error;
479 FN(UNION,free)(u2);
481 return u1;
482 error:
483 FN(UNION,free)(u1);
484 FN(UNION,free)(u2);
485 return NULL;
488 __isl_give UNION *FN(FN(UNION,from),PARTS)(__isl_take PART *part)
490 isl_space *dim;
491 UNION *u;
493 if (!part)
494 return NULL;
496 dim = FN(PART,get_space)(part);
497 dim = isl_space_drop_dims(dim, isl_dim_in, 0, isl_space_dim(dim, isl_dim_in));
498 dim = isl_space_drop_dims(dim, isl_dim_out, 0, isl_space_dim(dim, isl_dim_out));
499 #ifdef HAS_TYPE
500 u = FN(UNION,ZERO)(dim, part->type);
501 #else
502 u = FN(UNION,ZERO)(dim);
503 #endif
504 u = FN(FN(UNION,add),PARTS)(u, part);
506 return u;
509 S(UNION,match_bin_data) {
510 UNION *u2;
511 UNION *res;
512 __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *);
515 /* Check if data->u2 has an element living in the same space as *entry.
516 * If so, call data->fn on the two elements and add the result to
517 * data->res.
519 static int match_bin_entry(void **entry, void *user)
521 S(UNION,match_bin_data) *data = user;
522 uint32_t hash;
523 struct isl_hash_table_entry *entry2;
524 isl_space *space;
525 PART *part = *entry;
526 PART *part2;
528 space = FN(PART,get_space)(part);
529 hash = isl_space_get_hash(space);
530 entry2 = isl_hash_table_find(data->u2->space->ctx, &data->u2->table,
531 hash, &has_same_domain_space, space, 0);
532 isl_space_free(space);
533 if (!entry2)
534 return 0;
536 part2 = entry2->data;
537 if (!isl_space_tuple_is_equal(part->dim, isl_dim_out,
538 part2->dim, isl_dim_out))
539 isl_die(FN(UNION,get_ctx)(data->u2), isl_error_invalid,
540 "entries should have the same range space",
541 return -1);
543 part = FN(PART, copy)(part);
544 part = data->fn(part, FN(PART, copy)(entry2->data));
546 data->res = FN(FN(UNION,add),PARTS)(data->res, part);
547 if (!data->res)
548 return -1;
550 return 0;
553 /* This function is currently only used from isl_polynomial.c
554 * and not from isl_fold.c.
556 static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
557 __isl_take UNION *u2,
558 __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *))
559 __attribute__ ((unused));
560 /* For each pair of elements in "u1" and "u2" living in the same space,
561 * call "fn" and collect the results.
563 static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
564 __isl_take UNION *u2,
565 __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *))
567 S(UNION,match_bin_data) data = { NULL, NULL, fn };
569 u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
570 u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
572 if (!u1 || !u2)
573 goto error;
575 data.u2 = u2;
576 #ifdef HAS_TYPE
577 data.res = FN(UNION,alloc)(isl_space_copy(u1->space), u1->type,
578 u1->table.n);
579 #else
580 data.res = FN(UNION,alloc)(isl_space_copy(u1->space), u1->table.n);
581 #endif
582 if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
583 &match_bin_entry, &data) < 0)
584 goto error;
586 FN(UNION,free)(u1);
587 FN(UNION,free)(u2);
588 return data.res;
589 error:
590 FN(UNION,free)(u1);
591 FN(UNION,free)(u2);
592 FN(UNION,free)(data.res);
593 return NULL;
596 /* Compute the sum of "u1" and "u2".
598 * If the base expressions have a default zero value, then the sum
599 * is computed on the union of the domains of "u1" and "u2".
600 * Otherwise, it is computed on their shared domains.
602 __isl_give UNION *FN(UNION,add)(__isl_take UNION *u1, __isl_take UNION *u2)
604 #if DEFAULT_IS_ZERO
605 return FN(UNION,union_add_)(u1, u2);
606 #else
607 return match_bin_op(u1, u2, &FN(PART,add));
608 #endif
611 #ifndef NO_SUB
612 /* Subtract "u2" from "u1" and return the result.
614 __isl_give UNION *FN(UNION,sub)(__isl_take UNION *u1, __isl_take UNION *u2)
616 return match_bin_op(u1, u2, &FN(PART,sub));
618 #endif
620 S(UNION,any_set_data) {
621 isl_set *set;
622 UNION *res;
623 __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
626 static int any_set_entry(void **entry, void *user)
628 S(UNION,any_set_data) *data = user;
629 PW *pw = *entry;
631 pw = FN(PW,copy)(pw);
632 pw = data->fn(pw, isl_set_copy(data->set));
634 data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
635 if (!data->res)
636 return -1;
638 return 0;
641 /* Update each element of "u" by calling "fn" on the element and "set".
643 static __isl_give UNION *any_set_op(__isl_take UNION *u,
644 __isl_take isl_set *set,
645 __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
647 S(UNION,any_set_data) data = { NULL, NULL, fn };
649 u = FN(UNION,align_params)(u, isl_set_get_space(set));
650 set = isl_set_align_params(set, FN(UNION,get_space)(u));
652 if (!u || !set)
653 goto error;
655 data.set = set;
656 #ifdef HAS_TYPE
657 data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->type,
658 u->table.n);
659 #else
660 data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
661 #endif
662 if (isl_hash_table_foreach(u->space->ctx, &u->table,
663 &any_set_entry, &data) < 0)
664 goto error;
666 FN(UNION,free)(u);
667 isl_set_free(set);
668 return data.res;
669 error:
670 FN(UNION,free)(u);
671 isl_set_free(set);
672 FN(UNION,free)(data.res);
673 return NULL;
676 /* Intersect the domain of "u" with the parameter domain "context".
678 __isl_give UNION *FN(UNION,intersect_params)(__isl_take UNION *u,
679 __isl_take isl_set *set)
681 return any_set_op(u, set, &FN(PW,intersect_params));
684 /* Compute the gist of the domain of "u" with respect to
685 * the parameter domain "context".
687 __isl_give UNION *FN(UNION,gist_params)(__isl_take UNION *u,
688 __isl_take isl_set *set)
690 return any_set_op(u, set, &FN(PW,gist_params));
693 S(UNION,match_domain_data) {
694 isl_union_set *uset;
695 UNION *res;
696 __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
699 static int set_has_dim(const void *entry, const void *val)
701 isl_set *set = (isl_set *)entry;
702 isl_space *dim = (isl_space *)val;
704 return isl_space_is_equal(set->dim, dim);
707 /* Find the set in data->uset that lives in the same space as the domain
708 * of *entry, apply data->fn to *entry and this set (if any), and add
709 * the result to data->res.
711 static int match_domain_entry(void **entry, void *user)
713 S(UNION,match_domain_data) *data = user;
714 uint32_t hash;
715 struct isl_hash_table_entry *entry2;
716 PW *pw = *entry;
717 isl_space *space;
719 space = FN(PW,get_domain_space)(pw);
720 hash = isl_space_get_hash(space);
721 entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
722 hash, &set_has_dim, space, 0);
723 isl_space_free(space);
724 if (!entry2)
725 return 0;
727 pw = FN(PW,copy)(pw);
728 pw = data->fn(pw, isl_set_copy(entry2->data));
730 data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
731 if (!data->res)
732 return -1;
734 return 0;
737 /* Apply fn to each pair of PW in u and set in uset such that
738 * the set lives in the same space as the domain of PW
739 * and collect the results.
741 static __isl_give UNION *match_domain_op(__isl_take UNION *u,
742 __isl_take isl_union_set *uset,
743 __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
745 S(UNION,match_domain_data) data = { NULL, NULL, fn };
747 u = FN(UNION,align_params)(u, isl_union_set_get_space(uset));
748 uset = isl_union_set_align_params(uset, FN(UNION,get_space)(u));
750 if (!u || !uset)
751 goto error;
753 data.uset = uset;
754 #ifdef HAS_TYPE
755 data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->type,
756 u->table.n);
757 #else
758 data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
759 #endif
760 if (isl_hash_table_foreach(u->space->ctx, &u->table,
761 &match_domain_entry, &data) < 0)
762 goto error;
764 FN(UNION,free)(u);
765 isl_union_set_free(uset);
766 return data.res;
767 error:
768 FN(UNION,free)(u);
769 isl_union_set_free(uset);
770 FN(UNION,free)(data.res);
771 return NULL;
774 /* Intersect the domain of "u" with "uset".
775 * If "uset" is a parameters domain, then intersect the parameter
776 * domain of "u" with this set.
778 __isl_give UNION *FN(UNION,intersect_domain)(__isl_take UNION *u,
779 __isl_take isl_union_set *uset)
781 if (isl_union_set_is_params(uset))
782 return FN(UNION,intersect_params)(u,
783 isl_set_from_union_set(uset));
784 return match_domain_op(u, uset, &FN(PW,intersect_domain));
787 __isl_give UNION *FN(UNION,gist)(__isl_take UNION *u,
788 __isl_take isl_union_set *uset)
790 if (isl_union_set_is_params(uset))
791 return FN(UNION,gist_params)(u, isl_set_from_union_set(uset));
792 return match_domain_op(u, uset, &FN(PW,gist));
795 #ifndef NO_EVAL
796 __isl_give isl_val *FN(UNION,eval)(__isl_take UNION *u,
797 __isl_take isl_point *pnt)
799 uint32_t hash;
800 struct isl_hash_table_entry *entry;
801 isl_space *space;
802 isl_val *v;
804 if (!u || !pnt)
805 goto error;
807 space = isl_space_copy(pnt->dim);
808 if (!space)
809 goto error;
810 hash = isl_space_get_hash(space);
811 entry = isl_hash_table_find(u->space->ctx, &u->table,
812 hash, &has_domain_space, space, 0);
813 isl_space_free(space);
814 if (!entry) {
815 v = isl_val_zero(isl_point_get_ctx(pnt));
816 isl_point_free(pnt);
817 } else {
818 v = FN(PART,eval)(FN(PART,copy)(entry->data), pnt);
820 FN(UNION,free)(u);
821 return v;
822 error:
823 FN(UNION,free)(u);
824 isl_point_free(pnt);
825 return NULL;
827 #endif
829 static int coalesce_entry(void **entry, void *user)
831 PW **pw = (PW **)entry;
833 *pw = FN(PW,coalesce)(*pw);
834 if (!*pw)
835 return -1;
837 return 0;
840 __isl_give UNION *FN(UNION,coalesce)(__isl_take UNION *u)
842 if (!u)
843 return NULL;
845 if (isl_hash_table_foreach(u->space->ctx, &u->table,
846 &coalesce_entry, NULL) < 0)
847 goto error;
849 return u;
850 error:
851 FN(UNION,free)(u);
852 return NULL;
855 static int domain(__isl_take PART *part, void *user)
857 isl_union_set **uset = (isl_union_set **)user;
859 *uset = isl_union_set_add_set(*uset, FN(PART,domain)(part));
861 return 0;
864 __isl_give isl_union_set *FN(UNION,domain)(__isl_take UNION *u)
866 isl_union_set *uset;
868 uset = isl_union_set_empty(FN(UNION,get_space)(u));
869 if (FN(FN(UNION,foreach),PARTS)(u, &domain, &uset) < 0)
870 goto error;
872 FN(UNION,free)(u);
874 return uset;
875 error:
876 isl_union_set_free(uset);
877 FN(UNION,free)(u);
878 return NULL;
881 static int mul_isl_int(void **entry, void *user)
883 PW **pw = (PW **)entry;
884 isl_int *v = user;
886 *pw = FN(PW,mul_isl_int)(*pw, *v);
887 if (!*pw)
888 return -1;
890 return 0;
893 __isl_give UNION *FN(UNION,mul_isl_int)(__isl_take UNION *u, isl_int v)
895 if (isl_int_is_one(v))
896 return u;
898 if (DEFAULT_IS_ZERO && u && isl_int_is_zero(v)) {
899 UNION *zero;
900 isl_space *dim = FN(UNION,get_space)(u);
901 #ifdef HAS_TYPE
902 zero = FN(UNION,ZERO)(dim, u->type);
903 #else
904 zero = FN(UNION,ZERO)(dim);
905 #endif
906 FN(UNION,free)(u);
907 return zero;
910 u = FN(UNION,cow)(u);
911 if (!u)
912 return NULL;
914 #ifdef HAS_TYPE
915 if (isl_int_is_neg(v))
916 u->type = isl_fold_type_negate(u->type);
917 #endif
918 if (isl_hash_table_foreach(u->space->ctx, &u->table,
919 &mul_isl_int, &v) < 0)
920 goto error;
922 return u;
923 error:
924 FN(UNION,free)(u);
925 return NULL;
928 /* Multiply *entry by the isl_val "user".
930 * Return 0 on success and -1 on error.
932 static int scale_val(void **entry, void *user)
934 PW **pw = (PW **)entry;
935 isl_val *v = user;
937 *pw = FN(PW,scale_val)(*pw, isl_val_copy(v));
938 if (!*pw)
939 return -1;
941 return 0;
944 /* Multiply "u" by "v" and return the result.
946 __isl_give UNION *FN(UNION,scale_val)(__isl_take UNION *u,
947 __isl_take isl_val *v)
949 if (!u || !v)
950 goto error;
951 if (isl_val_is_one(v)) {
952 isl_val_free(v);
953 return u;
956 if (DEFAULT_IS_ZERO && u && isl_val_is_zero(v)) {
957 UNION *zero;
958 isl_space *space = FN(UNION,get_space)(u);
959 #ifdef HAS_TYPE
960 zero = FN(UNION,ZERO)(space, u->type);
961 #else
962 zero = FN(UNION,ZERO)(space);
963 #endif
964 FN(UNION,free)(u);
965 isl_val_free(v);
966 return zero;
969 if (!isl_val_is_rat(v))
970 isl_die(isl_val_get_ctx(v), isl_error_invalid,
971 "expecting rational factor", goto error);
973 u = FN(UNION,cow)(u);
974 if (!u)
975 return NULL;
977 #ifdef HAS_TYPE
978 if (isl_val_is_neg(v))
979 u->type = isl_fold_type_negate(u->type);
980 #endif
981 if (isl_hash_table_foreach(u->space->ctx, &u->table, &scale_val, v) < 0)
982 goto error;
984 isl_val_free(v);
985 return u;
986 error:
987 isl_val_free(v);
988 FN(UNION,free)(u);
989 return NULL;
992 /* Divide *entry by the isl_val "user".
994 * Return 0 on success and -1 on error.
996 static int FN(UNION,scale_down_val_entry)(void **entry, void *user)
998 PW **pw = (PW **)entry;
999 isl_val *v = user;
1001 *pw = FN(PW,scale_down_val)(*pw, isl_val_copy(v));
1002 if (!*pw)
1003 return -1;
1005 return 0;
1008 /* Divide "u" by "v" and return the result.
1010 __isl_give UNION *FN(UNION,scale_down_val)(__isl_take UNION *u,
1011 __isl_take isl_val *v)
1013 if (!u || !v)
1014 goto error;
1015 if (isl_val_is_one(v)) {
1016 isl_val_free(v);
1017 return u;
1020 if (!isl_val_is_rat(v))
1021 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1022 "expecting rational factor", goto error);
1023 if (isl_val_is_zero(v))
1024 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1025 "cannot scale down by zero", goto error);
1027 u = FN(UNION,cow)(u);
1028 if (!u)
1029 return NULL;
1031 #ifdef HAS_TYPE
1032 if (isl_val_is_neg(v))
1033 u->type = isl_fold_type_negate(u->type);
1034 #endif
1035 if (isl_hash_table_foreach(FN(UNION,get_ctx)(u), &u->table,
1036 &FN(UNION,scale_down_val_entry), v) < 0)
1037 goto error;
1039 isl_val_free(v);
1040 return u;
1041 error:
1042 isl_val_free(v);
1043 FN(UNION,free)(u);
1044 return NULL;
1047 S(UNION,plain_is_equal_data)
1049 UNION *u2;
1050 int is_equal;
1053 static int plain_is_equal_entry(void **entry, void *user)
1055 S(UNION,plain_is_equal_data) *data = user;
1056 uint32_t hash;
1057 struct isl_hash_table_entry *entry2;
1058 PW *pw = *entry;
1060 hash = isl_space_get_hash(pw->dim);
1061 entry2 = isl_hash_table_find(data->u2->space->ctx, &data->u2->table,
1062 hash, &has_same_domain_space, pw->dim, 0);
1063 if (!entry2) {
1064 data->is_equal = 0;
1065 return -1;
1068 data->is_equal = FN(PW,plain_is_equal)(pw, entry2->data);
1069 if (data->is_equal < 0 || !data->is_equal)
1070 return -1;
1072 return 0;
1075 int FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
1077 S(UNION,plain_is_equal_data) data = { NULL, 1 };
1079 if (!u1 || !u2)
1080 return -1;
1081 if (u1 == u2)
1082 return 1;
1083 if (u1->table.n != u2->table.n)
1084 return 0;
1086 u1 = FN(UNION,copy)(u1);
1087 u2 = FN(UNION,copy)(u2);
1088 u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
1089 u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
1090 if (!u1 || !u2)
1091 goto error;
1093 data.u2 = u2;
1094 if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
1095 &plain_is_equal_entry, &data) < 0 &&
1096 data.is_equal)
1097 goto error;
1099 FN(UNION,free)(u1);
1100 FN(UNION,free)(u2);
1102 return data.is_equal;
1103 error:
1104 FN(UNION,free)(u1);
1105 FN(UNION,free)(u2);
1106 return -1;