2 * Copyright 2010 INRIA Saclay
3 * Copyright 2013 Ecole Normale Superieure
5 * Use of this software is governed by the MIT license
7 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
8 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
10 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
13 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
14 #define FN(TYPE,NAME) xFN(TYPE,NAME)
15 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
16 #define S(TYPE,NAME) xS(TYPE,NAME)
25 struct isl_hash_table table
;
28 __isl_give UNION
*FN(UNION
,cow
)(__isl_take UNION
*u
);
30 isl_ctx
*FN(UNION
,get_ctx
)(__isl_keep UNION
*u
)
32 return u
? u
->space
->ctx
: NULL
;
35 __isl_give isl_space
*FN(UNION
,get_space
)(__isl_keep UNION
*u
)
39 return isl_space_copy(u
->space
);
42 /* Return the number of parameters of "u", where "type"
43 * is required to be set to isl_dim_param.
45 unsigned FN(UNION
,dim
)(__isl_keep UNION
*u
, enum isl_dim_type type
)
50 if (type
!= isl_dim_param
)
51 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
52 "can only reference parameters", return 0);
54 return isl_space_dim(u
->space
, type
);
57 /* Return the position of the parameter with the given name
59 * Return -1 if no such dimension can be found.
61 int FN(UNION
,find_dim_by_name
)(__isl_keep UNION
*u
, enum isl_dim_type type
,
66 return isl_space_find_dim_by_name(u
->space
, type
, name
);
70 static __isl_give UNION
*FN(UNION
,alloc
)(__isl_take isl_space
*dim
,
71 enum isl_fold type
, int size
)
73 static __isl_give UNION
*FN(UNION
,alloc
)(__isl_take isl_space
*dim
, int size
)
78 dim
= isl_space_params(dim
);
82 u
= isl_calloc_type(dim
->ctx
, UNION
);
91 if (isl_hash_table_init(dim
->ctx
, &u
->table
, size
) < 0)
92 return FN(UNION
,free
)(u
);
101 __isl_give UNION
*FN(UNION
,ZERO
)(__isl_take isl_space
*dim
, enum isl_fold type
)
103 return FN(UNION
,alloc
)(dim
, type
, 16);
106 __isl_give UNION
*FN(UNION
,ZERO
)(__isl_take isl_space
*dim
)
108 return FN(UNION
,alloc
)(dim
, 16);
112 __isl_give UNION
*FN(UNION
,copy
)(__isl_keep UNION
*u
)
121 /* Return the number of base expressions in "u".
123 int FN(FN(UNION
,n
),PARTS
)(__isl_keep UNION
*u
)
125 return u
? u
->table
.n
: 0;
128 S(UNION
,foreach_data
)
130 isl_stat (*fn
)(__isl_take PART
*part
, void *user
);
134 static isl_stat
FN(UNION
,call_on_copy
)(void **entry
, void *user
)
137 S(UNION
,foreach_data
) *data
= (S(UNION
,foreach_data
) *)user
;
139 return data
->fn(FN(PART
,copy
)(part
), data
->user
);
142 isl_stat
FN(FN(UNION
,foreach
),PARTS
)(__isl_keep UNION
*u
,
143 isl_stat (*fn
)(__isl_take PART
*part
, void *user
), void *user
)
145 S(UNION
,foreach_data
) data
= { fn
, user
};
148 return isl_stat_error
;
150 return isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
151 &FN(UNION
,call_on_copy
), &data
);
154 /* Is the space of "entry" equal to "space"?
156 static int FN(UNION
,has_space
)(const void *entry
, const void *val
)
158 PART
*part
= (PART
*)entry
;
159 isl_space
*space
= (isl_space
*) val
;
161 return isl_space_is_equal(part
->dim
, space
);
164 /* This function is not currently used by isl_aff.c.
166 static int FN(UNION
,has_domain_space
)(const void *entry
, const void *val
)
167 __attribute__ ((unused
));
169 /* Is the domain space of "entry" equal to "space"?
171 static int FN(UNION
,has_domain_space
)(const void *entry
, const void *val
)
173 PART
*part
= (PART
*)entry
;
174 isl_space
*space
= (isl_space
*) val
;
176 if (isl_space_is_params(space
))
177 return isl_space_is_set(part
->dim
);
179 return isl_space_tuple_is_equal(part
->dim
, isl_dim_in
,
183 /* Is the domain space of "entry" equal to the domain of "space"?
185 static int FN(UNION
,has_same_domain_space
)(const void *entry
, const void *val
)
187 PART
*part
= (PART
*)entry
;
188 isl_space
*space
= (isl_space
*) val
;
190 if (isl_space_is_set(space
))
191 return isl_space_is_set(part
->dim
);
193 return isl_space_tuple_is_equal(part
->dim
, isl_dim_in
,
197 /* Extract the element of "u" living in "space" (ignoring parameters).
199 * Return the ZERO element if "u" does not contain any element
202 __isl_give PART
*FN(FN(UNION
,extract
),PARTS
)(__isl_keep UNION
*u
,
203 __isl_take isl_space
*space
)
206 struct isl_hash_table_entry
*entry
;
210 if (!isl_space_match(u
->space
, isl_dim_param
, space
, isl_dim_param
)) {
211 space
= isl_space_drop_dims(space
, isl_dim_param
,
212 0, isl_space_dim(space
, isl_dim_param
));
213 space
= isl_space_align_params(space
,
214 FN(UNION
,get_space
)(u
));
219 hash
= isl_space_get_hash(space
);
220 entry
= isl_hash_table_find(u
->space
->ctx
, &u
->table
, hash
,
221 &FN(UNION
,has_space
), space
, 0);
224 return FN(PART
,ZERO
)(space
, u
->type
);
226 return FN(PART
,ZERO
)(space
);
228 isl_space_free(space
);
229 return FN(PART
,copy
)(entry
->data
);
231 isl_space_free(space
);
235 /* Add "part" to "u".
236 * If "disjoint" is set, then "u" is not allowed to already have
237 * a part that is defined on the same space as "part".
238 * Otherwise, compute the union sum of "part" and the part in "u"
239 * defined on the same space.
241 static __isl_give UNION
*FN(UNION
,add_part_generic
)(__isl_take UNION
*u
,
242 __isl_take PART
*part
, int disjoint
)
246 struct isl_hash_table_entry
*entry
;
251 empty
= FN(PART
,IS_ZERO
)(part
);
259 u
= FN(UNION
,align_params
)(u
, FN(PART
,get_space
)(part
));
260 part
= FN(PART
,align_params
)(part
, FN(UNION
,get_space
)(u
));
262 u
= FN(UNION
,cow
)(u
);
267 hash
= isl_space_get_hash(part
->dim
);
268 entry
= isl_hash_table_find(u
->space
->ctx
, &u
->table
, hash
,
269 &FN(UNION
,has_same_domain_space
),
277 PART
*entry_part
= entry
->data
;
279 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
280 "additional part should live on separate "
281 "space", goto error
);
282 if (!isl_space_tuple_is_equal(entry_part
->dim
, isl_dim_out
,
283 part
->dim
, isl_dim_out
))
284 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
285 "union expression can only contain a single "
286 "expression over a given domain", goto error
);
287 entry
->data
= FN(PART
,union_add_
)(entry
->data
,
288 FN(PART
,copy
)(part
));
291 empty
= FN(PART
,IS_ZERO
)(part
);
295 FN(PART
,free
)(entry
->data
);
296 isl_hash_table_remove(u
->space
->ctx
, &u
->table
, entry
);
308 /* Add "part" to "u", where "u" is assumed not to already have
309 * a part that is defined on the same space as "part".
311 __isl_give UNION
*FN(FN(UNION
,add
),PARTS
)(__isl_take UNION
*u
,
312 __isl_take PART
*part
)
314 return FN(UNION
,add_part_generic
)(u
, part
, 1);
317 static isl_stat
FN(UNION
,add_part
)(__isl_take PART
*part
, void *user
)
319 UNION
**u
= (UNION
**)user
;
321 *u
= FN(FN(UNION
,add
),PARTS
)(*u
, part
);
326 __isl_give UNION
*FN(UNION
,dup
)(__isl_keep UNION
*u
)
334 dup
= FN(UNION
,ZERO
)(isl_space_copy(u
->space
), u
->type
);
336 dup
= FN(UNION
,ZERO
)(isl_space_copy(u
->space
));
338 if (FN(FN(UNION
,foreach
),PARTS
)(u
, &FN(UNION
,add_part
), &dup
) < 0)
346 __isl_give UNION
*FN(UNION
,cow
)(__isl_take UNION
*u
)
354 return FN(UNION
,dup
)(u
);
357 static isl_stat
FN(UNION
,free_u_entry
)(void **entry
, void *user
)
364 __isl_null UNION
*FN(UNION
,free
)(__isl_take UNION
*u
)
372 isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
373 &FN(UNION
,free_u_entry
), NULL
);
374 isl_hash_table_clear(&u
->table
);
375 isl_space_free(u
->space
);
385 static isl_stat
FN(UNION
,align_entry
)(__isl_take PART
*part
, void *user
)
388 S(UNION
,align
) *data
= user
;
390 exp
= isl_reordering_extend_space(isl_reordering_copy(data
->exp
),
391 FN(PART
,get_domain_space
)(part
));
393 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
,
394 FN(PART
,realign_domain
)(part
, exp
));
399 /* Reorder the parameters of "u" according to the given reordering.
401 static __isl_give UNION
*FN(UNION
,realign_domain
)(__isl_take UNION
*u
,
402 __isl_take isl_reordering
*r
)
404 S(UNION
,align
) data
= { NULL
, NULL
};
410 data
.res
= FN(UNION
,alloc
)(isl_space_copy(r
->dim
), u
->type
, u
->table
.n
);
412 data
.res
= FN(UNION
,alloc
)(isl_space_copy(r
->dim
), u
->table
.n
);
415 if (FN(FN(UNION
,foreach
),PARTS
)(u
, &FN(UNION
,align_entry
), &data
) < 0)
416 data
.res
= FN(UNION
,free
)(data
.res
);
418 isl_reordering_free(data
.exp
);
423 isl_reordering_free(r
);
427 /* Align the parameters of "u" to those of "model".
429 __isl_give UNION
*FN(UNION
,align_params
)(__isl_take UNION
*u
,
430 __isl_take isl_space
*model
)
437 if (isl_space_match(u
->space
, isl_dim_param
, model
, isl_dim_param
)) {
438 isl_space_free(model
);
442 model
= isl_space_params(model
);
443 r
= isl_parameter_alignment_reordering(u
->space
, model
);
444 isl_space_free(model
);
446 return FN(UNION
,realign_domain
)(u
, r
);
448 isl_space_free(model
);
453 /* Add "part" to *u, taking the union sum if "u" already has
454 * a part defined on the same space as "part".
456 static isl_stat
FN(UNION
,union_add_part
)(__isl_take PART
*part
, void *user
)
458 UNION
**u
= (UNION
**)user
;
460 *u
= FN(UNION
,add_part_generic
)(*u
, part
, 0);
465 /* Compute the sum of "u1" and "u2" on the union of their domains,
466 * with the actual sum on the shared domain and
467 * the defined expression on the symmetric difference of the domains.
469 * This is an internal function that is exposed under different
470 * names depending on whether the base expressions have a zero default
472 * If they do, then this function is called "add".
473 * Otherwise, it is called "union_add".
475 static __isl_give UNION
*FN(UNION
,union_add_
)(__isl_take UNION
*u1
,
476 __isl_take UNION
*u2
)
478 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
479 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
481 u1
= FN(UNION
,cow
)(u1
);
486 if (FN(FN(UNION
,foreach
),PARTS
)(u2
, &FN(UNION
,union_add_part
), &u1
) < 0)
498 __isl_give UNION
*FN(FN(UNION
,from
),PARTS
)(__isl_take PART
*part
)
506 dim
= FN(PART
,get_space
)(part
);
507 dim
= isl_space_drop_dims(dim
, isl_dim_in
, 0, isl_space_dim(dim
, isl_dim_in
));
508 dim
= isl_space_drop_dims(dim
, isl_dim_out
, 0, isl_space_dim(dim
, isl_dim_out
));
510 u
= FN(UNION
,ZERO
)(dim
, part
->type
);
512 u
= FN(UNION
,ZERO
)(dim
);
514 u
= FN(FN(UNION
,add
),PARTS
)(u
, part
);
519 S(UNION
,match_bin_data
) {
522 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*);
525 /* Check if data->u2 has an element living in the same space as *entry.
526 * If so, call data->fn on the two elements and add the result to
529 static isl_stat
FN(UNION
,match_bin_entry
)(void **entry
, void *user
)
531 S(UNION
,match_bin_data
) *data
= user
;
533 struct isl_hash_table_entry
*entry2
;
538 space
= FN(PART
,get_space
)(part
);
539 hash
= isl_space_get_hash(space
);
540 entry2
= isl_hash_table_find(data
->u2
->space
->ctx
, &data
->u2
->table
,
541 hash
, &FN(UNION
,has_same_domain_space
),
543 isl_space_free(space
);
547 part2
= entry2
->data
;
548 if (!isl_space_tuple_is_equal(part
->dim
, isl_dim_out
,
549 part2
->dim
, isl_dim_out
))
550 isl_die(FN(UNION
,get_ctx
)(data
->u2
), isl_error_invalid
,
551 "entries should have the same range space",
552 return isl_stat_error
);
554 part
= FN(PART
, copy
)(part
);
555 part
= data
->fn(part
, FN(PART
, copy
)(entry2
->data
));
557 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, part
);
559 return isl_stat_error
;
564 /* This function is currently only used from isl_polynomial.c
565 * and not from isl_fold.c.
567 static __isl_give UNION
*FN(UNION
,match_bin_op
)(__isl_take UNION
*u1
,
568 __isl_take UNION
*u2
,
569 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*))
570 __attribute__ ((unused
));
571 /* For each pair of elements in "u1" and "u2" living in the same space,
572 * call "fn" and collect the results.
574 static __isl_give UNION
*FN(UNION
,match_bin_op
)(__isl_take UNION
*u1
,
575 __isl_take UNION
*u2
,
576 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*))
578 S(UNION
,match_bin_data
) data
= { NULL
, NULL
, fn
};
580 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
581 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
588 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u1
->space
), u1
->type
,
591 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u1
->space
), u1
->table
.n
);
593 if (isl_hash_table_foreach(u1
->space
->ctx
, &u1
->table
,
594 &FN(UNION
,match_bin_entry
), &data
) < 0)
603 FN(UNION
,free
)(data
.res
);
607 /* Compute the sum of "u1" and "u2".
609 * If the base expressions have a default zero value, then the sum
610 * is computed on the union of the domains of "u1" and "u2".
611 * Otherwise, it is computed on their shared domains.
613 __isl_give UNION
*FN(UNION
,add
)(__isl_take UNION
*u1
, __isl_take UNION
*u2
)
616 return FN(UNION
,union_add_
)(u1
, u2
);
618 return FN(UNION
,match_bin_op
)(u1
, u2
, &FN(PART
,add
));
623 /* Subtract "u2" from "u1" and return the result.
625 __isl_give UNION
*FN(UNION
,sub
)(__isl_take UNION
*u1
, __isl_take UNION
*u2
)
627 return FN(UNION
,match_bin_op
)(u1
, u2
, &FN(PART
,sub
));
631 S(UNION
,any_set_data
) {
634 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*);
637 static isl_stat
FN(UNION
,any_set_entry
)(void **entry
, void *user
)
639 S(UNION
,any_set_data
) *data
= user
;
642 pw
= FN(PW
,copy
)(pw
);
643 pw
= data
->fn(pw
, isl_set_copy(data
->set
));
645 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, pw
);
647 return isl_stat_error
;
652 /* Update each element of "u" by calling "fn" on the element and "set".
654 static __isl_give UNION
*FN(UNION
,any_set_op
)(__isl_take UNION
*u
,
655 __isl_take isl_set
*set
,
656 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*))
658 S(UNION
,any_set_data
) data
= { NULL
, NULL
, fn
};
660 u
= FN(UNION
,align_params
)(u
, isl_set_get_space(set
));
661 set
= isl_set_align_params(set
, FN(UNION
,get_space
)(u
));
668 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->type
,
671 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->table
.n
);
673 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
674 &FN(UNION
,any_set_entry
), &data
) < 0)
683 FN(UNION
,free
)(data
.res
);
687 /* Intersect the domain of "u" with the parameter domain "context".
689 __isl_give UNION
*FN(UNION
,intersect_params
)(__isl_take UNION
*u
,
690 __isl_take isl_set
*set
)
692 return FN(UNION
,any_set_op
)(u
, set
, &FN(PW
,intersect_params
));
695 /* Compute the gist of the domain of "u" with respect to
696 * the parameter domain "context".
698 __isl_give UNION
*FN(UNION
,gist_params
)(__isl_take UNION
*u
,
699 __isl_take isl_set
*set
)
701 return FN(UNION
,any_set_op
)(u
, set
, &FN(PW
,gist_params
));
704 S(UNION
,match_domain_data
) {
707 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*);
710 static int FN(UNION
,set_has_dim
)(const void *entry
, const void *val
)
712 isl_set
*set
= (isl_set
*)entry
;
713 isl_space
*dim
= (isl_space
*)val
;
715 return isl_space_is_equal(set
->dim
, dim
);
718 /* Find the set in data->uset that lives in the same space as the domain
719 * of *entry, apply data->fn to *entry and this set (if any), and add
720 * the result to data->res.
722 static isl_stat
FN(UNION
,match_domain_entry
)(void **entry
, void *user
)
724 S(UNION
,match_domain_data
) *data
= user
;
726 struct isl_hash_table_entry
*entry2
;
730 space
= FN(PW
,get_domain_space
)(pw
);
731 hash
= isl_space_get_hash(space
);
732 entry2
= isl_hash_table_find(data
->uset
->dim
->ctx
, &data
->uset
->table
,
733 hash
, &FN(UNION
,set_has_dim
), space
, 0);
734 isl_space_free(space
);
738 pw
= FN(PW
,copy
)(pw
);
739 pw
= data
->fn(pw
, isl_set_copy(entry2
->data
));
741 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, pw
);
743 return isl_stat_error
;
748 /* Apply fn to each pair of PW in u and set in uset such that
749 * the set lives in the same space as the domain of PW
750 * and collect the results.
752 static __isl_give UNION
*FN(UNION
,match_domain_op
)(__isl_take UNION
*u
,
753 __isl_take isl_union_set
*uset
,
754 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*))
756 S(UNION
,match_domain_data
) data
= { NULL
, NULL
, fn
};
758 u
= FN(UNION
,align_params
)(u
, isl_union_set_get_space(uset
));
759 uset
= isl_union_set_align_params(uset
, FN(UNION
,get_space
)(u
));
766 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->type
,
769 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->table
.n
);
771 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
772 &FN(UNION
,match_domain_entry
), &data
) < 0)
776 isl_union_set_free(uset
);
780 isl_union_set_free(uset
);
781 FN(UNION
,free
)(data
.res
);
785 /* Intersect the domain of "u" with "uset".
786 * If "uset" is a parameters domain, then intersect the parameter
787 * domain of "u" with this set.
789 __isl_give UNION
*FN(UNION
,intersect_domain
)(__isl_take UNION
*u
,
790 __isl_take isl_union_set
*uset
)
792 if (isl_union_set_is_params(uset
))
793 return FN(UNION
,intersect_params
)(u
,
794 isl_set_from_union_set(uset
));
795 return FN(UNION
,match_domain_op
)(u
, uset
, &FN(PW
,intersect_domain
));
798 /* Internal data structure for isl_union_*_subtract_domain.
799 * uset is the set that needs to be removed from the domain.
800 * res collects the results.
802 S(UNION
,subtract_domain_data
) {
807 /* Take the set (which may be empty) in data->uset that lives
808 * in the same space as the domain of "pw", subtract it from the domain
809 * of "pw" and add the result to data->res.
811 static isl_stat
FN(UNION
,subtract_domain_entry
)(__isl_take PW
*pw
, void *user
)
813 S(UNION
,subtract_domain_data
) *data
= user
;
817 space
= FN(PW
,get_domain_space
)(pw
);
818 set
= isl_union_set_extract_set(data
->uset
, space
);
819 pw
= FN(PW
,subtract_domain
)(pw
, set
);
820 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, pw
);
825 /* Subtract "uset' from the domain of "u".
827 __isl_give UNION
*FN(UNION
,subtract_domain
)(__isl_take UNION
*u
,
828 __isl_take isl_union_set
*uset
)
830 S(UNION
,subtract_domain_data
) data
;
837 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->type
,
840 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->table
.n
);
842 if (FN(FN(UNION
,foreach
),PARTS
)(u
,
843 &FN(UNION
,subtract_domain_entry
), &data
) < 0)
844 data
.res
= FN(UNION
,free
)(data
.res
);
847 isl_union_set_free(uset
);
851 isl_union_set_free(uset
);
855 __isl_give UNION
*FN(UNION
,gist
)(__isl_take UNION
*u
,
856 __isl_take isl_union_set
*uset
)
858 if (isl_union_set_is_params(uset
))
859 return FN(UNION
,gist_params
)(u
, isl_set_from_union_set(uset
));
860 return FN(UNION
,match_domain_op
)(u
, uset
, &FN(PW
,gist
));
864 __isl_give isl_val
*FN(UNION
,eval
)(__isl_take UNION
*u
,
865 __isl_take isl_point
*pnt
)
868 struct isl_hash_table_entry
*entry
;
875 space
= isl_space_copy(pnt
->dim
);
878 hash
= isl_space_get_hash(space
);
879 entry
= isl_hash_table_find(u
->space
->ctx
, &u
->table
,
880 hash
, &FN(UNION
,has_domain_space
),
882 isl_space_free(space
);
884 v
= isl_val_zero(isl_point_get_ctx(pnt
));
887 v
= FN(PART
,eval
)(FN(PART
,copy
)(entry
->data
), pnt
);
898 static isl_stat
FN(UNION
,coalesce_entry
)(void **entry
, void *user
)
900 PW
**pw
= (PW
**)entry
;
902 *pw
= FN(PW
,coalesce
)(*pw
);
904 return isl_stat_error
;
909 __isl_give UNION
*FN(UNION
,coalesce
)(__isl_take UNION
*u
)
914 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
915 &FN(UNION
,coalesce_entry
), NULL
) < 0)
924 static isl_stat
FN(UNION
,domain_entry
)(__isl_take PART
*part
, void *user
)
926 isl_union_set
**uset
= (isl_union_set
**)user
;
928 *uset
= isl_union_set_add_set(*uset
, FN(PART
,domain
)(part
));
933 __isl_give isl_union_set
*FN(UNION
,domain
)(__isl_take UNION
*u
)
937 uset
= isl_union_set_empty(FN(UNION
,get_space
)(u
));
938 if (FN(FN(UNION
,foreach
),PARTS
)(u
, &FN(UNION
,domain_entry
), &uset
) < 0)
945 isl_union_set_free(uset
);
950 static isl_stat
FN(UNION
,mul_isl_int_entry
)(void **entry
, void *user
)
952 PW
**pw
= (PW
**)entry
;
955 *pw
= FN(PW
,mul_isl_int
)(*pw
, *v
);
957 return isl_stat_error
;
962 __isl_give UNION
*FN(UNION
,mul_isl_int
)(__isl_take UNION
*u
, isl_int v
)
964 if (isl_int_is_one(v
))
967 if (DEFAULT_IS_ZERO
&& u
&& isl_int_is_zero(v
)) {
969 isl_space
*dim
= FN(UNION
,get_space
)(u
);
971 zero
= FN(UNION
,ZERO
)(dim
, u
->type
);
973 zero
= FN(UNION
,ZERO
)(dim
);
979 u
= FN(UNION
,cow
)(u
);
984 if (isl_int_is_neg(v
))
985 u
->type
= isl_fold_type_negate(u
->type
);
987 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
988 &FN(UNION
,mul_isl_int_entry
), &v
) < 0)
997 /* Multiply *entry by the isl_val "user".
999 * Return 0 on success and -1 on error.
1001 static isl_stat
FN(UNION
,scale_val_entry
)(void **entry
, void *user
)
1003 PW
**pw
= (PW
**)entry
;
1006 *pw
= FN(PW
,scale_val
)(*pw
, isl_val_copy(v
));
1008 return isl_stat_error
;
1013 /* Multiply "u" by "v" and return the result.
1015 __isl_give UNION
*FN(UNION
,scale_val
)(__isl_take UNION
*u
,
1016 __isl_take isl_val
*v
)
1020 if (isl_val_is_one(v
)) {
1025 if (DEFAULT_IS_ZERO
&& u
&& isl_val_is_zero(v
)) {
1027 isl_space
*space
= FN(UNION
,get_space
)(u
);
1029 zero
= FN(UNION
,ZERO
)(space
, u
->type
);
1031 zero
= FN(UNION
,ZERO
)(space
);
1038 if (!isl_val_is_rat(v
))
1039 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1040 "expecting rational factor", goto error
);
1042 u
= FN(UNION
,cow
)(u
);
1047 if (isl_val_is_neg(v
))
1048 u
->type
= isl_fold_type_negate(u
->type
);
1050 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
1051 &FN(UNION
,scale_val_entry
), v
) < 0)
1062 /* Divide *entry by the isl_val "user".
1064 * Return 0 on success and -1 on error.
1066 static isl_stat
FN(UNION
,scale_down_val_entry
)(void **entry
, void *user
)
1068 PW
**pw
= (PW
**)entry
;
1071 *pw
= FN(PW
,scale_down_val
)(*pw
, isl_val_copy(v
));
1073 return isl_stat_error
;
1078 /* Divide "u" by "v" and return the result.
1080 __isl_give UNION
*FN(UNION
,scale_down_val
)(__isl_take UNION
*u
,
1081 __isl_take isl_val
*v
)
1085 if (isl_val_is_one(v
)) {
1090 if (!isl_val_is_rat(v
))
1091 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1092 "expecting rational factor", goto error
);
1093 if (isl_val_is_zero(v
))
1094 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1095 "cannot scale down by zero", goto error
);
1097 u
= FN(UNION
,cow
)(u
);
1102 if (isl_val_is_neg(v
))
1103 u
->type
= isl_fold_type_negate(u
->type
);
1105 if (isl_hash_table_foreach(FN(UNION
,get_ctx
)(u
), &u
->table
,
1106 &FN(UNION
,scale_down_val_entry
), v
) < 0)
1117 S(UNION
,plain_is_equal_data
)
1123 static isl_stat
FN(UNION
,plain_is_equal_entry
)(void **entry
, void *user
)
1125 S(UNION
,plain_is_equal_data
) *data
= user
;
1127 struct isl_hash_table_entry
*entry2
;
1130 hash
= isl_space_get_hash(pw
->dim
);
1131 entry2
= isl_hash_table_find(data
->u2
->space
->ctx
, &data
->u2
->table
,
1132 hash
, &FN(UNION
,has_same_domain_space
),
1135 data
->is_equal
= isl_bool_false
;
1136 return isl_stat_error
;
1139 data
->is_equal
= FN(PW
,plain_is_equal
)(pw
, entry2
->data
);
1140 if (data
->is_equal
< 0 || !data
->is_equal
)
1141 return isl_stat_error
;
1146 isl_bool
FN(UNION
,plain_is_equal
)(__isl_keep UNION
*u1
, __isl_keep UNION
*u2
)
1148 S(UNION
,plain_is_equal_data
) data
= { NULL
, isl_bool_true
};
1151 return isl_bool_error
;
1153 return isl_bool_true
;
1154 if (u1
->table
.n
!= u2
->table
.n
)
1155 return isl_bool_false
;
1157 u1
= FN(UNION
,copy
)(u1
);
1158 u2
= FN(UNION
,copy
)(u2
);
1159 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
1160 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
1165 if (isl_hash_table_foreach(u1
->space
->ctx
, &u1
->table
,
1166 &FN(UNION
,plain_is_equal_entry
), &data
) < 0 &&
1173 return data
.is_equal
;
1177 return isl_bool_error
;
1181 /* Replace *entry by its opposite.
1183 * Return 0 on success and -1 on error.
1185 static isl_stat
FN(UNION
,neg_entry
)(void **entry
, void *user
)
1187 PW
**pw
= (PW
**) entry
;
1189 *pw
= FN(PW
,neg
)(*pw
);
1191 return *pw
? isl_stat_ok
: isl_stat_error
;
1194 /* Return the opposite of "u".
1196 __isl_give UNION
*FN(UNION
,neg
)(__isl_take UNION
*u
)
1198 u
= FN(UNION
,cow
)(u
);
1202 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
1203 &FN(UNION
,neg_entry
), NULL
) < 0)
1204 return FN(UNION
,free
)(u
);
1210 /* Internal data structure for isl_union_*_drop_dims.
1211 * type, first and n are passed to isl_*_drop_dims.
1212 * res collects the results.
1214 S(UNION
,drop_dims_data
) {
1215 enum isl_dim_type type
;
1222 /* Drop the parameters specified by "data" from "part" and
1223 * add the results to data->res.
1225 static isl_stat
FN(UNION
,drop_dims_entry
)(__isl_take PART
*part
, void *user
)
1227 S(UNION
,drop_dims_data
) *data
= user
;
1229 part
= FN(PART
,drop_dims
)(part
, data
->type
, data
->first
, data
->n
);
1230 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, part
);
1232 return isl_stat_error
;
1237 /* Drop the specified parameters from "u".
1238 * That is, type is required to be isl_dim_param.
1240 __isl_give UNION
*FN(UNION
,drop_dims
)( __isl_take UNION
*u
,
1241 enum isl_dim_type type
, unsigned first
, unsigned n
)
1244 S(UNION
,drop_dims_data
) data
= { type
, first
, n
};
1249 if (type
!= isl_dim_param
)
1250 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
1251 "can only project out parameters",
1252 return FN(UNION
,free
)(u
));
1254 space
= FN(UNION
,get_space
)(u
);
1255 space
= isl_space_drop_dims(space
, type
, first
, n
);
1257 data
.res
= FN(UNION
,alloc
)(space
, u
->type
, u
->table
.n
);
1259 data
.res
= FN(UNION
,alloc
)(space
, u
->table
.n
);
1261 if (FN(FN(UNION
,foreach
),PARTS
)(u
,
1262 &FN(UNION
,drop_dims_entry
), &data
) < 0)
1263 data
.res
= FN(UNION
,free
)(data
.res
);
1270 /* Internal data structure for isl_union_*_set_dim_name.
1271 * pos is the position of the parameter that needs to be renamed.
1272 * s is the new name.
1273 * res collects the results.
1275 S(UNION
,set_dim_name_data
) {
1282 /* Change the name of the parameter at position data->pos of "part" to data->s
1283 * and add the result to data->res.
1285 static isl_stat
FN(UNION
,set_dim_name_entry
)(__isl_take PART
*part
, void *user
)
1287 S(UNION
,set_dim_name_data
) *data
= user
;
1289 part
= FN(PART
,set_dim_name
)(part
, isl_dim_param
, data
->pos
, data
->s
);
1290 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, part
);
1292 return isl_stat_error
;
1297 /* Change the name of the parameter at position "pos" to "s".
1298 * That is, type is required to be isl_dim_param.
1300 __isl_give UNION
*FN(UNION
,set_dim_name
)(__isl_take UNION
*u
,
1301 enum isl_dim_type type
, unsigned pos
, const char *s
)
1303 S(UNION
,set_dim_name_data
) data
= { pos
, s
};
1309 if (type
!= isl_dim_param
)
1310 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
1311 "can only set parameter names",
1312 return FN(UNION
,free
)(u
));
1314 space
= FN(UNION
,get_space
)(u
);
1315 space
= isl_space_set_dim_name(space
, type
, pos
, s
);
1317 data
.res
= FN(UNION
,alloc
)(space
, u
->type
, u
->table
.n
);
1319 data
.res
= FN(UNION
,alloc
)(space
, u
->table
.n
);
1322 if (FN(FN(UNION
,foreach
),PARTS
)(u
,
1323 &FN(UNION
,set_dim_name_entry
), &data
) < 0)
1324 data
.res
= FN(UNION
,free
)(data
.res
);
1331 /* Reset the user pointer on all identifiers of parameters and tuples
1332 * of the space of "part" and add the result to *res.
1334 static isl_stat
FN(UNION
,reset_user_entry
)(__isl_take PART
*part
, void *user
)
1338 part
= FN(PART
,reset_user
)(part
);
1339 *res
= FN(FN(UNION
,add
),PARTS
)(*res
, part
);
1341 return isl_stat_error
;
1346 /* Reset the user pointer on all identifiers of parameters and tuples
1347 * of the spaces of "u".
1349 __isl_give UNION
*FN(UNION
,reset_user
)(__isl_take UNION
*u
)
1357 space
= FN(UNION
,get_space
)(u
);
1358 space
= isl_space_reset_user(space
);
1360 res
= FN(UNION
,alloc
)(space
, u
->type
, u
->table
.n
);
1362 res
= FN(UNION
,alloc
)(space
, u
->table
.n
);
1364 if (FN(FN(UNION
,foreach
),PARTS
)(u
,
1365 &FN(UNION
,reset_user_entry
), &res
) < 0)
1366 res
= FN(UNION
,free
)(res
);