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 int (*fn
)(__isl_take PART
*part
, void *user
);
134 static int 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 int FN(FN(UNION
,foreach
),PARTS
)(__isl_keep UNION
*u
,
143 int (*fn
)(__isl_take PART
*part
, void *user
), void *user
)
145 S(UNION
,foreach_data
) data
= { fn
, user
};
150 return isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
151 &call_on_copy
, &data
);
154 /* Is the space of "entry" equal to "space"?
156 static int 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 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 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 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 &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 &has_same_domain_space
, part
->dim
, 1);
276 PART
*entry_part
= entry
->data
;
278 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
279 "additional part should live on separate "
280 "space", goto error
);
281 if (!isl_space_tuple_is_equal(entry_part
->dim
, isl_dim_out
,
282 part
->dim
, isl_dim_out
))
283 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
284 "union expression can only contain a single "
285 "expression over a given domain", goto error
);
286 entry
->data
= FN(PART
,union_add_
)(entry
->data
,
287 FN(PART
,copy
)(part
));
290 empty
= FN(PART
,IS_ZERO
)(part
);
294 FN(PART
,free
)(entry
->data
);
295 isl_hash_table_remove(u
->space
->ctx
, &u
->table
, entry
);
307 /* Add "part" to "u", where "u" is assumed not to already have
308 * a part that is defined on the same space as "part".
310 __isl_give UNION
*FN(FN(UNION
,add
),PARTS
)(__isl_take UNION
*u
,
311 __isl_take PART
*part
)
313 return FN(UNION
,add_part_generic
)(u
, part
, 1);
316 static int add_part(__isl_take PART
*part
, void *user
)
318 UNION
**u
= (UNION
**)user
;
320 *u
= FN(FN(UNION
,add
),PARTS
)(*u
, part
);
325 __isl_give UNION
*FN(UNION
,dup
)(__isl_keep UNION
*u
)
333 dup
= FN(UNION
,ZERO
)(isl_space_copy(u
->space
), u
->type
);
335 dup
= FN(UNION
,ZERO
)(isl_space_copy(u
->space
));
337 if (FN(FN(UNION
,foreach
),PARTS
)(u
, &add_part
, &dup
) < 0)
345 __isl_give UNION
*FN(UNION
,cow
)(__isl_take UNION
*u
)
353 return FN(UNION
,dup
)(u
);
356 static int free_u_entry(void **entry
, void *user
)
363 __isl_null UNION
*FN(UNION
,free
)(__isl_take UNION
*u
)
371 isl_hash_table_foreach(u
->space
->ctx
, &u
->table
, &free_u_entry
, NULL
);
372 isl_hash_table_clear(&u
->table
);
373 isl_space_free(u
->space
);
384 static int align_entry(__isl_take PART
*part
, void *user
)
387 S(UNION
,align
) *data
= user
;
389 exp
= isl_reordering_extend_space(isl_reordering_copy(data
->exp
),
390 FN(PART
,get_domain_space
)(part
));
392 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
,
393 FN(PART
,realign_domain
)(part
, exp
));
398 static int align_entry(__isl_take PART
*part
, void *user
)
401 S(UNION
,align
) *data
= user
;
403 exp
= isl_reordering_extend_space(isl_reordering_copy(data
->exp
),
404 FN(PART
,get_space
)(part
));
406 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
,
407 FN(PART
,realign
)(part
, exp
));
413 __isl_give UNION
*FN(UNION
,align_params
)(__isl_take UNION
*u
,
414 __isl_take isl_space
*model
)
416 S(UNION
,align
) data
= { NULL
, NULL
};
421 if (isl_space_match(u
->space
, isl_dim_param
, model
, isl_dim_param
)) {
422 isl_space_free(model
);
426 model
= isl_space_params(model
);
427 data
.exp
= isl_parameter_alignment_reordering(u
->space
, model
);
432 data
.res
= FN(UNION
,alloc
)(isl_space_copy(data
.exp
->dim
),
433 u
->type
, u
->table
.n
);
435 data
.res
= FN(UNION
,alloc
)(isl_space_copy(data
.exp
->dim
), u
->table
.n
);
437 if (FN(FN(UNION
,foreach
),PARTS
)(u
, &align_entry
, &data
) < 0)
440 isl_reordering_free(data
.exp
);
442 isl_space_free(model
);
445 isl_reordering_free(data
.exp
);
447 FN(UNION
,free
)(data
.res
);
448 isl_space_free(model
);
452 /* Add "part" to *u, taking the union sum if "u" already has
453 * a part defined on the same space as "part".
455 static int union_add_part(__isl_take PART
*part
, void *user
)
457 UNION
**u
= (UNION
**)user
;
459 *u
= FN(UNION
,add_part_generic
)(*u
, part
, 0);
464 /* Compute the sum of "u1" and "u2" on the union of their domains,
465 * with the actual sum on the shared domain and
466 * the defined expression on the symmetric difference of the domains.
468 * This is an internal function that is exposed under different
469 * names depending on whether the base expressions have a zero default
471 * If they do, then this function is called "add".
472 * Otherwise, it is called "union_add".
474 static __isl_give UNION
*FN(UNION
,union_add_
)(__isl_take UNION
*u1
,
475 __isl_take UNION
*u2
)
477 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
478 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
480 u1
= FN(UNION
,cow
)(u1
);
485 if (FN(FN(UNION
,foreach
),PARTS
)(u2
, &union_add_part
, &u1
) < 0)
497 __isl_give UNION
*FN(FN(UNION
,from
),PARTS
)(__isl_take PART
*part
)
505 dim
= FN(PART
,get_space
)(part
);
506 dim
= isl_space_drop_dims(dim
, isl_dim_in
, 0, isl_space_dim(dim
, isl_dim_in
));
507 dim
= isl_space_drop_dims(dim
, isl_dim_out
, 0, isl_space_dim(dim
, isl_dim_out
));
509 u
= FN(UNION
,ZERO
)(dim
, part
->type
);
511 u
= FN(UNION
,ZERO
)(dim
);
513 u
= FN(FN(UNION
,add
),PARTS
)(u
, part
);
518 S(UNION
,match_bin_data
) {
521 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*);
524 /* Check if data->u2 has an element living in the same space as *entry.
525 * If so, call data->fn on the two elements and add the result to
528 static int match_bin_entry(void **entry
, void *user
)
530 S(UNION
,match_bin_data
) *data
= user
;
532 struct isl_hash_table_entry
*entry2
;
537 space
= FN(PART
,get_space
)(part
);
538 hash
= isl_space_get_hash(space
);
539 entry2
= isl_hash_table_find(data
->u2
->space
->ctx
, &data
->u2
->table
,
540 hash
, &has_same_domain_space
, space
, 0);
541 isl_space_free(space
);
545 part2
= entry2
->data
;
546 if (!isl_space_tuple_is_equal(part
->dim
, isl_dim_out
,
547 part2
->dim
, isl_dim_out
))
548 isl_die(FN(UNION
,get_ctx
)(data
->u2
), isl_error_invalid
,
549 "entries should have the same range space",
552 part
= FN(PART
, copy
)(part
);
553 part
= data
->fn(part
, FN(PART
, copy
)(entry2
->data
));
555 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, part
);
562 /* This function is currently only used from isl_polynomial.c
563 * and not from isl_fold.c.
565 static __isl_give UNION
*match_bin_op(__isl_take UNION
*u1
,
566 __isl_take UNION
*u2
,
567 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*))
568 __attribute__ ((unused
));
569 /* For each pair of elements in "u1" and "u2" living in the same space,
570 * call "fn" and collect the results.
572 static __isl_give UNION
*match_bin_op(__isl_take UNION
*u1
,
573 __isl_take UNION
*u2
,
574 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*))
576 S(UNION
,match_bin_data
) data
= { NULL
, NULL
, fn
};
578 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
579 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
586 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u1
->space
), u1
->type
,
589 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u1
->space
), u1
->table
.n
);
591 if (isl_hash_table_foreach(u1
->space
->ctx
, &u1
->table
,
592 &match_bin_entry
, &data
) < 0)
601 FN(UNION
,free
)(data
.res
);
605 /* Compute the sum of "u1" and "u2".
607 * If the base expressions have a default zero value, then the sum
608 * is computed on the union of the domains of "u1" and "u2".
609 * Otherwise, it is computed on their shared domains.
611 __isl_give UNION
*FN(UNION
,add
)(__isl_take UNION
*u1
, __isl_take UNION
*u2
)
614 return FN(UNION
,union_add_
)(u1
, u2
);
616 return match_bin_op(u1
, u2
, &FN(PART
,add
));
621 /* Subtract "u2" from "u1" and return the result.
623 __isl_give UNION
*FN(UNION
,sub
)(__isl_take UNION
*u1
, __isl_take UNION
*u2
)
625 return match_bin_op(u1
, u2
, &FN(PART
,sub
));
629 S(UNION
,any_set_data
) {
632 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*);
635 static int any_set_entry(void **entry
, void *user
)
637 S(UNION
,any_set_data
) *data
= user
;
640 pw
= FN(PW
,copy
)(pw
);
641 pw
= data
->fn(pw
, isl_set_copy(data
->set
));
643 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, pw
);
650 /* Update each element of "u" by calling "fn" on the element and "set".
652 static __isl_give UNION
*any_set_op(__isl_take UNION
*u
,
653 __isl_take isl_set
*set
,
654 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*))
656 S(UNION
,any_set_data
) data
= { NULL
, NULL
, fn
};
658 u
= FN(UNION
,align_params
)(u
, isl_set_get_space(set
));
659 set
= isl_set_align_params(set
, FN(UNION
,get_space
)(u
));
666 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->type
,
669 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->table
.n
);
671 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
672 &any_set_entry
, &data
) < 0)
681 FN(UNION
,free
)(data
.res
);
685 /* Intersect the domain of "u" with the parameter domain "context".
687 __isl_give UNION
*FN(UNION
,intersect_params
)(__isl_take UNION
*u
,
688 __isl_take isl_set
*set
)
690 return any_set_op(u
, set
, &FN(PW
,intersect_params
));
693 /* Compute the gist of the domain of "u" with respect to
694 * the parameter domain "context".
696 __isl_give UNION
*FN(UNION
,gist_params
)(__isl_take UNION
*u
,
697 __isl_take isl_set
*set
)
699 return any_set_op(u
, set
, &FN(PW
,gist_params
));
702 S(UNION
,match_domain_data
) {
705 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*);
708 static int set_has_dim(const void *entry
, const void *val
)
710 isl_set
*set
= (isl_set
*)entry
;
711 isl_space
*dim
= (isl_space
*)val
;
713 return isl_space_is_equal(set
->dim
, dim
);
716 /* Find the set in data->uset that lives in the same space as the domain
717 * of *entry, apply data->fn to *entry and this set (if any), and add
718 * the result to data->res.
720 static int match_domain_entry(void **entry
, void *user
)
722 S(UNION
,match_domain_data
) *data
= user
;
724 struct isl_hash_table_entry
*entry2
;
728 space
= FN(PW
,get_domain_space
)(pw
);
729 hash
= isl_space_get_hash(space
);
730 entry2
= isl_hash_table_find(data
->uset
->dim
->ctx
, &data
->uset
->table
,
731 hash
, &set_has_dim
, space
, 0);
732 isl_space_free(space
);
736 pw
= FN(PW
,copy
)(pw
);
737 pw
= data
->fn(pw
, isl_set_copy(entry2
->data
));
739 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, pw
);
746 /* Apply fn to each pair of PW in u and set in uset such that
747 * the set lives in the same space as the domain of PW
748 * and collect the results.
750 static __isl_give UNION
*match_domain_op(__isl_take UNION
*u
,
751 __isl_take isl_union_set
*uset
,
752 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*))
754 S(UNION
,match_domain_data
) data
= { NULL
, NULL
, fn
};
756 u
= FN(UNION
,align_params
)(u
, isl_union_set_get_space(uset
));
757 uset
= isl_union_set_align_params(uset
, FN(UNION
,get_space
)(u
));
764 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->type
,
767 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->table
.n
);
769 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
770 &match_domain_entry
, &data
) < 0)
774 isl_union_set_free(uset
);
778 isl_union_set_free(uset
);
779 FN(UNION
,free
)(data
.res
);
783 /* Intersect the domain of "u" with "uset".
784 * If "uset" is a parameters domain, then intersect the parameter
785 * domain of "u" with this set.
787 __isl_give UNION
*FN(UNION
,intersect_domain
)(__isl_take UNION
*u
,
788 __isl_take isl_union_set
*uset
)
790 if (isl_union_set_is_params(uset
))
791 return FN(UNION
,intersect_params
)(u
,
792 isl_set_from_union_set(uset
));
793 return match_domain_op(u
, uset
, &FN(PW
,intersect_domain
));
796 /* Internal data structure for isl_union_*_subtract_domain.
797 * uset is the set that needs to be removed from the domain.
798 * res collects the results.
800 S(UNION
,subtract_domain_data
) {
805 /* Take the set (which may be empty) in data->uset that lives
806 * in the same space as the domain of "pw", subtract it from the domain
807 * of "pw" and add the result to data->res.
809 static int FN(UNION
,subtract_domain_entry
)(__isl_take PW
*pw
, void *user
)
811 S(UNION
,subtract_domain_data
) *data
= user
;
815 space
= FN(PW
,get_domain_space
)(pw
);
816 set
= isl_union_set_extract_set(data
->uset
, space
);
817 pw
= FN(PW
,subtract_domain
)(pw
, set
);
818 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, pw
);
823 /* Subtract "uset' from the domain of "u".
825 __isl_give UNION
*FN(UNION
,subtract_domain
)(__isl_take UNION
*u
,
826 __isl_take isl_union_set
*uset
)
828 S(UNION
,subtract_domain_data
) data
;
835 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->type
,
838 data
.res
= FN(UNION
,alloc
)(isl_space_copy(u
->space
), u
->table
.n
);
840 if (FN(FN(UNION
,foreach
),PARTS
)(u
,
841 &FN(UNION
,subtract_domain_entry
), &data
) < 0)
842 data
.res
= FN(UNION
,free
)(data
.res
);
845 isl_union_set_free(uset
);
849 isl_union_set_free(uset
);
853 __isl_give UNION
*FN(UNION
,gist
)(__isl_take UNION
*u
,
854 __isl_take isl_union_set
*uset
)
856 if (isl_union_set_is_params(uset
))
857 return FN(UNION
,gist_params
)(u
, isl_set_from_union_set(uset
));
858 return match_domain_op(u
, uset
, &FN(PW
,gist
));
862 __isl_give isl_val
*FN(UNION
,eval
)(__isl_take UNION
*u
,
863 __isl_take isl_point
*pnt
)
866 struct isl_hash_table_entry
*entry
;
873 space
= isl_space_copy(pnt
->dim
);
876 hash
= isl_space_get_hash(space
);
877 entry
= isl_hash_table_find(u
->space
->ctx
, &u
->table
,
878 hash
, &has_domain_space
, space
, 0);
879 isl_space_free(space
);
881 v
= isl_val_zero(isl_point_get_ctx(pnt
));
884 v
= FN(PART
,eval
)(FN(PART
,copy
)(entry
->data
), pnt
);
895 static int coalesce_entry(void **entry
, void *user
)
897 PW
**pw
= (PW
**)entry
;
899 *pw
= FN(PW
,coalesce
)(*pw
);
906 __isl_give UNION
*FN(UNION
,coalesce
)(__isl_take UNION
*u
)
911 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
912 &coalesce_entry
, NULL
) < 0)
921 static int domain(__isl_take PART
*part
, void *user
)
923 isl_union_set
**uset
= (isl_union_set
**)user
;
925 *uset
= isl_union_set_add_set(*uset
, FN(PART
,domain
)(part
));
930 __isl_give isl_union_set
*FN(UNION
,domain
)(__isl_take UNION
*u
)
934 uset
= isl_union_set_empty(FN(UNION
,get_space
)(u
));
935 if (FN(FN(UNION
,foreach
),PARTS
)(u
, &domain
, &uset
) < 0)
942 isl_union_set_free(uset
);
947 static int mul_isl_int(void **entry
, void *user
)
949 PW
**pw
= (PW
**)entry
;
952 *pw
= FN(PW
,mul_isl_int
)(*pw
, *v
);
959 __isl_give UNION
*FN(UNION
,mul_isl_int
)(__isl_take UNION
*u
, isl_int v
)
961 if (isl_int_is_one(v
))
964 if (DEFAULT_IS_ZERO
&& u
&& isl_int_is_zero(v
)) {
966 isl_space
*dim
= FN(UNION
,get_space
)(u
);
968 zero
= FN(UNION
,ZERO
)(dim
, u
->type
);
970 zero
= FN(UNION
,ZERO
)(dim
);
976 u
= FN(UNION
,cow
)(u
);
981 if (isl_int_is_neg(v
))
982 u
->type
= isl_fold_type_negate(u
->type
);
984 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
985 &mul_isl_int
, &v
) < 0)
994 /* Multiply *entry by the isl_val "user".
996 * Return 0 on success and -1 on error.
998 static int scale_val(void **entry
, void *user
)
1000 PW
**pw
= (PW
**)entry
;
1003 *pw
= FN(PW
,scale_val
)(*pw
, isl_val_copy(v
));
1010 /* Multiply "u" by "v" and return the result.
1012 __isl_give UNION
*FN(UNION
,scale_val
)(__isl_take UNION
*u
,
1013 __isl_take isl_val
*v
)
1017 if (isl_val_is_one(v
)) {
1022 if (DEFAULT_IS_ZERO
&& u
&& isl_val_is_zero(v
)) {
1024 isl_space
*space
= FN(UNION
,get_space
)(u
);
1026 zero
= FN(UNION
,ZERO
)(space
, u
->type
);
1028 zero
= FN(UNION
,ZERO
)(space
);
1035 if (!isl_val_is_rat(v
))
1036 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1037 "expecting rational factor", goto error
);
1039 u
= FN(UNION
,cow
)(u
);
1044 if (isl_val_is_neg(v
))
1045 u
->type
= isl_fold_type_negate(u
->type
);
1047 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
, &scale_val
, v
) < 0)
1058 /* Divide *entry by the isl_val "user".
1060 * Return 0 on success and -1 on error.
1062 static int FN(UNION
,scale_down_val_entry
)(void **entry
, void *user
)
1064 PW
**pw
= (PW
**)entry
;
1067 *pw
= FN(PW
,scale_down_val
)(*pw
, isl_val_copy(v
));
1074 /* Divide "u" by "v" and return the result.
1076 __isl_give UNION
*FN(UNION
,scale_down_val
)(__isl_take UNION
*u
,
1077 __isl_take isl_val
*v
)
1081 if (isl_val_is_one(v
)) {
1086 if (!isl_val_is_rat(v
))
1087 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1088 "expecting rational factor", goto error
);
1089 if (isl_val_is_zero(v
))
1090 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1091 "cannot scale down by zero", goto error
);
1093 u
= FN(UNION
,cow
)(u
);
1098 if (isl_val_is_neg(v
))
1099 u
->type
= isl_fold_type_negate(u
->type
);
1101 if (isl_hash_table_foreach(FN(UNION
,get_ctx
)(u
), &u
->table
,
1102 &FN(UNION
,scale_down_val_entry
), v
) < 0)
1113 S(UNION
,plain_is_equal_data
)
1119 static int plain_is_equal_entry(void **entry
, void *user
)
1121 S(UNION
,plain_is_equal_data
) *data
= user
;
1123 struct isl_hash_table_entry
*entry2
;
1126 hash
= isl_space_get_hash(pw
->dim
);
1127 entry2
= isl_hash_table_find(data
->u2
->space
->ctx
, &data
->u2
->table
,
1128 hash
, &has_same_domain_space
, pw
->dim
, 0);
1134 data
->is_equal
= FN(PW
,plain_is_equal
)(pw
, entry2
->data
);
1135 if (data
->is_equal
< 0 || !data
->is_equal
)
1141 int FN(UNION
,plain_is_equal
)(__isl_keep UNION
*u1
, __isl_keep UNION
*u2
)
1143 S(UNION
,plain_is_equal_data
) data
= { NULL
, 1 };
1149 if (u1
->table
.n
!= u2
->table
.n
)
1152 u1
= FN(UNION
,copy
)(u1
);
1153 u2
= FN(UNION
,copy
)(u2
);
1154 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
1155 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
1160 if (isl_hash_table_foreach(u1
->space
->ctx
, &u1
->table
,
1161 &plain_is_equal_entry
, &data
) < 0 &&
1168 return data
.is_equal
;
1176 /* Replace *entry by its opposite.
1178 * Return 0 on success and -1 on error.
1180 static int FN(UNION
,neg_entry
)(void **entry
, void *user
)
1182 PW
**pw
= (PW
**) entry
;
1184 *pw
= FN(PW
,neg
)(*pw
);
1186 return *pw
? 0 : -1;
1189 /* Return the opposite of "u".
1191 __isl_give UNION
*FN(UNION
,neg
)(__isl_take UNION
*u
)
1193 u
= FN(UNION
,cow
)(u
);
1197 if (isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
1198 &FN(UNION
,neg_entry
), NULL
) < 0)
1199 return FN(UNION
,free
)(u
);
1205 /* Internal data structure for isl_union_*_drop_dims.
1206 * type, first and n are passed to isl_*_drop_dims.
1207 * res collects the results.
1209 S(UNION
,drop_dims_data
) {
1210 enum isl_dim_type type
;
1217 /* Drop the parameters specified by "data" from "part" and
1218 * add the results to data->res.
1220 static int FN(UNION
,drop_dims_entry
)(__isl_take PART
*part
, void *user
)
1222 S(UNION
,drop_dims_data
) *data
= user
;
1224 part
= FN(PART
,drop_dims
)(part
, data
->type
, data
->first
, data
->n
);
1225 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, part
);
1232 /* Drop the specified parameters from "u".
1233 * That is, type is required to be isl_dim_param.
1235 __isl_give UNION
*FN(UNION
,drop_dims
)( __isl_take UNION
*u
,
1236 enum isl_dim_type type
, unsigned first
, unsigned n
)
1239 S(UNION
,drop_dims_data
) data
= { type
, first
, n
};
1244 if (type
!= isl_dim_param
)
1245 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
1246 "can only project out parameters",
1247 return FN(UNION
,free
)(u
));
1249 space
= FN(UNION
,get_space
)(u
);
1250 space
= isl_space_drop_dims(space
, type
, first
, n
);
1252 data
.res
= FN(UNION
,alloc
)(space
, u
->type
, u
->table
.n
);
1254 data
.res
= FN(UNION
,alloc
)(space
, u
->table
.n
);
1256 if (FN(FN(UNION
,foreach
),PARTS
)(u
,
1257 &FN(UNION
,drop_dims_entry
), &data
) < 0)
1258 data
.res
= FN(UNION
,free
)(data
.res
);
1265 /* Internal data structure for isl_union_*_set_dim_name.
1266 * pos is the position of the parameter that needs to be renamed.
1267 * s is the new name.
1268 * res collects the results.
1270 S(UNION
,set_dim_name_data
) {
1277 /* Change the name of the parameter at position data->pos of "part" to data->s
1278 * and add the result to data->res.
1280 static int FN(UNION
,set_dim_name_entry
)(__isl_take PART
*part
, void *user
)
1282 S(UNION
,set_dim_name_data
) *data
= user
;
1284 part
= FN(PART
,set_dim_name
)(part
, isl_dim_param
, data
->pos
, data
->s
);
1285 data
->res
= FN(FN(UNION
,add
),PARTS
)(data
->res
, part
);
1292 /* Change the name of the parameter at position "pos" to "s".
1293 * That is, type is required to be isl_dim_param.
1295 __isl_give UNION
*FN(UNION
,set_dim_name
)(__isl_take UNION
*u
,
1296 enum isl_dim_type type
, unsigned pos
, const char *s
)
1298 S(UNION
,set_dim_name_data
) data
= { pos
, s
};
1304 if (type
!= isl_dim_param
)
1305 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
1306 "can only set parameter names",
1307 return FN(UNION
,free
)(u
));
1309 space
= FN(UNION
,get_space
)(u
);
1310 space
= isl_space_set_dim_name(space
, type
, pos
, s
);
1312 data
.res
= FN(UNION
,alloc
)(space
, u
->type
, u
->table
.n
);
1314 data
.res
= FN(UNION
,alloc
)(space
, u
->table
.n
);
1317 if (FN(FN(UNION
,foreach
),PARTS
)(u
,
1318 &FN(UNION
,set_dim_name_entry
), &data
) < 0)
1319 data
.res
= FN(UNION
,free
)(data
.res
);
1326 /* Reset the user pointer on all identifiers of parameters and tuples
1327 * of the space of "part" and add the result to *res.
1329 static int FN(UNION
,reset_user_entry
)(__isl_take PART
*part
, void *user
)
1333 part
= FN(PART
,reset_user
)(part
);
1334 *res
= FN(FN(UNION
,add
),PARTS
)(*res
, part
);
1341 /* Reset the user pointer on all identifiers of parameters and tuples
1342 * of the spaces of "u".
1344 __isl_give UNION
*FN(UNION
,reset_user
)(__isl_take UNION
*u
)
1352 space
= FN(UNION
,get_space
)(u
);
1353 space
= isl_space_reset_user(space
);
1355 res
= FN(UNION
,alloc
)(space
, u
->type
, u
->table
.n
);
1357 res
= FN(UNION
,alloc
)(space
, u
->table
.n
);
1359 if (FN(FN(UNION
,foreach
),PARTS
)(u
,
1360 &FN(UNION
,reset_user_entry
), &res
) < 0)
1361 res
= FN(UNION
,free
)(res
);