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
16 #include "has_single_reference_templ.c"
18 __isl_give UNION
*FN(UNION
,cow
)(__isl_take UNION
*u
);
20 isl_ctx
*FN(UNION
,get_ctx
)(__isl_keep UNION
*u
)
22 return u
? u
->space
->ctx
: NULL
;
25 /* Return the space of "u".
27 static __isl_keep isl_space
*FN(UNION
,peek_space
)(__isl_keep UNION
*u
)
34 /* Return a copy of the space of "u".
36 __isl_give isl_space
*FN(UNION
,get_space
)(__isl_keep UNION
*u
)
38 return isl_space_copy(FN(UNION
,peek_space
)(u
));
41 /* Return the number of parameters of "u", where "type"
42 * is required to be set to isl_dim_param.
44 isl_size
FN(UNION
,dim
)(__isl_keep UNION
*u
, enum isl_dim_type type
)
47 return isl_size_error
;
49 if (type
!= isl_dim_param
)
50 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
51 "can only reference parameters", return isl_size_error
);
53 return isl_space_dim(u
->space
, type
);
56 /* Return the position of the parameter with the given name
58 * Return -1 if no such dimension can be found.
60 int FN(UNION
,find_dim_by_name
)(__isl_keep UNION
*u
, enum isl_dim_type type
,
65 return isl_space_find_dim_by_name(u
->space
, type
, name
);
69 #define OPT_TYPE_PARAM , enum isl_fold type
70 #define OPT_TYPE_ARG(loc) , loc type
71 #define OPT_SET_TYPE(loc,val) loc type = (val);
73 #define OPT_TYPE_PARAM
74 #define OPT_TYPE_ARG(loc)
75 #define OPT_SET_TYPE(loc,val)
78 static __isl_give UNION
*FN(UNION
,alloc
)(__isl_take isl_space
*space
79 OPT_TYPE_PARAM
, int size
)
83 space
= isl_space_params(space
);
87 u
= isl_calloc_type(space
->ctx
, UNION
);
92 OPT_SET_TYPE(u
->, type
);
94 if (isl_hash_table_init(space
->ctx
, &u
->table
, size
) < 0)
95 return FN(UNION
,free
)(u
);
99 isl_space_free(space
);
103 /* Create an empty/zero union without specifying any parameters.
105 __isl_give UNION
*FN(FN(UNION
,ZERO
),ctx
)(isl_ctx
*ctx OPT_TYPE_PARAM
)
109 space
= isl_space_unit(ctx
);
110 return FN(FN(UNION
,ZERO
),space
)(space
OPT_TYPE_ARG());
113 __isl_give UNION
*FN(FN(UNION
,ZERO
),space
)(__isl_take isl_space
*space
116 return FN(UNION
,alloc
)(space
OPT_TYPE_ARG(), 16);
119 /* This is an alternative name for the function above.
121 __isl_give UNION
*FN(UNION
,ZERO
)(__isl_take isl_space
*space OPT_TYPE_PARAM
)
123 return FN(FN(UNION
,ZERO
),space
)(space
OPT_TYPE_ARG());
126 __isl_give UNION
*FN(UNION
,copy
)(__isl_keep UNION
*u
)
135 /* Extract the element of "u" living in "space" (ignoring parameters).
137 * Return the ZERO element if "u" does not contain any element
140 __isl_give PART
*FN(FN(UNION
,extract
),BASE
)(__isl_keep UNION
*u
,
141 __isl_take isl_space
*space
)
143 struct isl_hash_table_entry
*entry
;
145 space
= isl_space_replace_params(space
, FN(UNION
,peek_space
)(u
));
147 entry
= FN(UNION
,find_part_entry
)(u
, space
, 0);
150 if (entry
== isl_hash_table_entry_none
)
151 return FN(PART
,ZERO
)(space
OPT_TYPE_ARG(u
->));
152 isl_space_free(space
);
153 return FN(PART
,copy
)(entry
->data
);
155 isl_space_free(space
);
159 /* Add "part" to "u".
160 * If "disjoint" is set, then "u" is not allowed to already have
161 * a part that is defined over a domain that overlaps with the domain
163 * Otherwise, compute the union sum of "part" and the part in "u"
164 * defined on the same space.
166 static __isl_give UNION
*FN(UNION
,add_part_generic
)(__isl_take UNION
*u
,
167 __isl_take PART
*part
, int disjoint
)
170 struct isl_hash_table_entry
*entry
;
175 empty
= FN(PART
,IS_ZERO
)(part
);
183 u
= FN(UNION
,align_params
)(u
, FN(PART
,get_space
)(part
));
184 part
= FN(PART
,align_params
)(part
, FN(UNION
,get_space
)(u
));
186 u
= FN(UNION
,cow
)(u
);
191 if (FN(UNION
,check_disjoint_domain_other
)(u
, part
) < 0)
193 entry
= FN(UNION
,find_part_entry
)(u
, part
->dim
, 1);
201 FN(UNION
,check_disjoint_domain
)(entry
->data
, part
) < 0)
203 entry
->data
= FN(PART
,union_add_
)(entry
->data
,
204 FN(PART
,copy
)(part
));
207 empty
= FN(PART
,IS_ZERO
)(part
);
211 u
= FN(UNION
,remove_part_entry
)(u
, entry
);
222 /* Add "part" to "u", where "u" is assumed not to already have
223 * a part that is defined on the same space as "part".
225 __isl_give UNION
*FN(FN(UNION
,add
),BASE
)(__isl_take UNION
*u
,
226 __isl_take PART
*part
)
228 return FN(UNION
,add_part_generic
)(u
, part
, 1);
231 /* Allocate a UNION with the same type (if any) and the same size as "u" and
232 * with space "space".
234 static __isl_give UNION
*FN(UNION
,alloc_same_size_on_space
)(__isl_keep UNION
*u
,
235 __isl_take isl_space
*space
)
239 return FN(UNION
,alloc
)(space
OPT_TYPE_ARG(u
->), u
->table
.n
);
241 isl_space_free(space
);
245 /* Allocate a UNION with the same space, the same type (if any) and
246 * the same size as "u".
248 static __isl_give UNION
*FN(UNION
,alloc_same_size
)(__isl_keep UNION
*u
)
250 return FN(UNION
,alloc_same_size_on_space
)(u
, FN(UNION
,get_space
)(u
));
253 /* Data structure that specifies how isl_union_*_transform
254 * should modify the base expressions in the union expression.
256 * If "inplace" is set, then the base expression in the input union
257 * are modified in place. This means that "fn" should not
258 * change the meaning of the union or that the union only
259 * has a single reference.
260 * If "space" is not NULL, then a new union is created in this space.
261 * If "filter" is not NULL, then only the base expressions that satisfy "filter"
262 * are taken into account.
263 * "fn" is applied to each entry in the input.
264 * "fn_user" is passed as the second argument to "fn".
266 S(UNION
,transform_control
) {
269 isl_bool (*filter
)(__isl_keep PART
*part
);
270 __isl_give PART
*(*fn
)(__isl_take PART
*part
, void *user
);
274 /* Internal data structure for isl_union_*_transform_space.
275 * "control" specifies how the base expressions should be modified.
276 * "res" collects the results (if control->inplace is not set).
278 S(UNION
,transform_data
)
280 S(UNION
,transform_control
) *control
;
284 /* Apply control->fn to "part" and add the result to data->res or
285 * place it back into the input union if control->inplace is set.
287 static isl_stat
FN(UNION
,transform_entry
)(void **entry
, void *user
)
289 S(UNION
,transform_data
) *data
= (S(UNION
,transform_data
) *)user
;
292 if (data
->control
->filter
) {
295 handle
= data
->control
->filter(part
);
297 return isl_stat_error
;
302 if (!data
->control
->inplace
)
303 part
= FN(PART
,copy
)(part
);
304 part
= data
->control
->fn(part
, data
->control
->fn_user
);
305 if (data
->control
->inplace
)
308 data
->res
= FN(FN(UNION
,add
),BASE
)(data
->res
, part
);
309 if (!part
|| !data
->res
)
310 return isl_stat_error
;
315 /* Return a UNION that is obtained by modifying "u" according to "control".
317 static __isl_give UNION
*FN(UNION
,transform
)(__isl_take UNION
*u
,
318 S(UNION
,transform_control
) *control
)
320 S(UNION
,transform_data
) data
= { control
};
323 if (control
->inplace
) {
327 space
= isl_space_copy(control
->space
);
329 space
= FN(UNION
,get_space
)(u
);
330 data
.res
= FN(UNION
,alloc_same_size_on_space
)(u
, space
);
332 if (FN(UNION
,foreach_inplace
)(u
, &FN(UNION
,transform_entry
), &data
) < 0)
333 data
.res
= FN(UNION
,free
)(data
.res
);
334 if (!control
->inplace
)
339 /* Return a UNION living in "space" that is otherwise obtained by modifying "u"
340 * according to "control".
342 static __isl_give UNION
*FN(UNION
,transform_space
)(__isl_take UNION
*u
,
343 __isl_take isl_space
*space
, S(UNION
,transform_control
) *control
)
346 return FN(UNION
,free
)(u
);
347 control
->space
= space
;
348 u
= FN(UNION
,transform
)(u
, control
);
349 isl_space_free(space
);
353 /* Update "u" by applying "fn" to each entry.
354 * This operation is assumed not to change the number of entries nor
355 * the spaces of the entries.
357 * If there is only one reference to "u", then change "u" inplace.
358 * Otherwise, create a new UNION from "u" and discard the original.
360 static __isl_give UNION
*FN(UNION
,transform_inplace
)(__isl_take UNION
*u
,
361 __isl_give PART
*(*fn
)(__isl_take PART
*part
, void *user
), void *user
)
363 S(UNION
,transform_control
) control
= { .fn
= fn
, .fn_user
= user
};
366 single_ref
= FN(UNION
,has_single_reference
)(u
);
368 return FN(UNION
,free
)(u
);
371 return FN(UNION
,transform
)(u
, &control
);
374 /* An isl_union_*_transform callback for use in isl_union_*_dup
375 * that simply returns "part".
377 static __isl_give PART
*FN(UNION
,copy_part
)(__isl_take PART
*part
, void *user
)
382 __isl_give UNION
*FN(UNION
,dup
)(__isl_keep UNION
*u
)
384 S(UNION
,transform_control
) control
= { .fn
= &FN(UNION
,copy_part
) };
386 u
= FN(UNION
,copy
)(u
);
387 return FN(UNION
,transform
)(u
, &control
);
390 __isl_give UNION
*FN(UNION
,cow
)(__isl_take UNION
*u
)
398 return FN(UNION
,dup
)(u
);
401 __isl_null UNION
*FN(UNION
,free
)(__isl_take UNION
*u
)
409 isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
410 &FN(UNION
,free_u_entry
), NULL
);
411 isl_hash_table_clear(&u
->table
);
412 isl_space_free(u
->space
);
417 static __isl_give PART
*FN(UNION
,align_entry
)(__isl_take PART
*part
, void *user
)
419 isl_reordering
*exp
= user
;
421 exp
= isl_reordering_extend_space(isl_reordering_copy(exp
),
422 FN(PART
,get_domain_space
)(part
));
423 return FN(PART
,realign_domain
)(part
, exp
);
426 /* Reorder the parameters of "u" according to the given reordering.
428 static __isl_give UNION
*FN(UNION
,realign_domain
)(__isl_take UNION
*u
,
429 __isl_take isl_reordering
*r
)
431 S(UNION
,transform_control
) control
= {
432 .fn
= &FN(UNION
,align_entry
),
440 space
= isl_reordering_get_space(r
);
441 u
= FN(UNION
,transform_space
)(u
, space
, &control
);
442 isl_reordering_free(r
);
446 isl_reordering_free(r
);
450 /* Align the parameters of "u" to those of "model".
452 __isl_give UNION
*FN(UNION
,align_params
)(__isl_take UNION
*u
,
453 __isl_take isl_space
*model
)
455 isl_bool equal_params
;
461 equal_params
= isl_space_has_equal_params(u
->space
, model
);
462 if (equal_params
< 0)
465 isl_space_free(model
);
469 r
= isl_parameter_alignment_reordering(u
->space
, model
);
470 isl_space_free(model
);
472 return FN(UNION
,realign_domain
)(u
, r
);
474 isl_space_free(model
);
479 /* Add "part" to *u, taking the union sum if "u" already has
480 * a part defined on the same space as "part".
482 static isl_stat
FN(UNION
,union_add_part
)(__isl_take PART
*part
, void *user
)
484 UNION
**u
= (UNION
**)user
;
486 *u
= FN(UNION
,add_part_generic
)(*u
, part
, 0);
491 /* Compute the sum of "u1" and "u2" on the union of their domains,
492 * with the actual sum on the shared domain and
493 * the defined expression on the symmetric difference of the domains.
495 * This is an internal function that is exposed under different
496 * names depending on whether the base expressions have a zero default
498 * If they do, then this function is called "add".
499 * Otherwise, it is called "union_add".
501 static __isl_give UNION
*FN(UNION
,union_add_
)(__isl_take UNION
*u1
,
502 __isl_take UNION
*u2
)
504 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
505 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
507 u1
= FN(UNION
,cow
)(u1
);
512 if (FN(FN(UNION
,foreach
),BASE
)(u2
, &FN(UNION
,union_add_part
), &u1
) < 0)
524 __isl_give UNION
*FN(FN(UNION
,from
),BASE
)(__isl_take PART
*part
)
532 space
= FN(PART
,get_space
)(part
);
533 space
= isl_space_drop_dims(space
, isl_dim_in
, 0,
534 isl_space_dim(space
, isl_dim_in
));
535 space
= isl_space_drop_dims(space
, isl_dim_out
, 0,
536 isl_space_dim(space
, isl_dim_out
));
537 u
= FN(UNION
,ZERO
)(space
OPT_TYPE_ARG(part
->));
538 u
= FN(FN(UNION
,add
),BASE
)(u
, part
);
543 S(UNION
,match_bin_data
) {
546 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*);
549 /* Check if data->u2 has an element living in the same space as "part".
550 * If so, call data->fn on the two elements and add the result to
553 static isl_stat
FN(UNION
,match_bin_entry
)(__isl_take PART
*part
, void *user
)
555 S(UNION
,match_bin_data
) *data
= user
;
556 struct isl_hash_table_entry
*entry2
;
560 space
= FN(PART
,get_space
)(part
);
561 entry2
= FN(UNION
,find_part_entry
)(data
->u2
, space
, 0);
562 isl_space_free(space
);
565 if (entry2
== isl_hash_table_entry_none
) {
570 part2
= entry2
->data
;
571 if (!isl_space_tuple_is_equal(part
->dim
, isl_dim_out
,
572 part2
->dim
, isl_dim_out
))
573 isl_die(FN(UNION
,get_ctx
)(data
->u2
), isl_error_invalid
,
574 "entries should have the same range space",
577 part
= data
->fn(part
, FN(PART
, copy
)(entry2
->data
));
579 data
->res
= FN(FN(UNION
,add
),BASE
)(data
->res
, part
);
581 return isl_stat_error
;
586 return isl_stat_error
;
589 /* This function is currently only used from isl_polynomial.c
590 * and not from isl_fold.c.
592 static __isl_give UNION
*FN(UNION
,match_bin_op
)(__isl_take UNION
*u1
,
593 __isl_take UNION
*u2
,
594 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*))
595 __attribute__ ((unused
));
596 /* For each pair of elements in "u1" and "u2" living in the same space,
597 * call "fn" and collect the results.
599 static __isl_give UNION
*FN(UNION
,match_bin_op
)(__isl_take UNION
*u1
,
600 __isl_take UNION
*u2
,
601 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*))
603 S(UNION
,match_bin_data
) data
= { NULL
, NULL
, fn
};
605 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
606 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
612 data
.res
= FN(UNION
,alloc_same_size
)(u1
);
613 if (FN(FN(UNION
,foreach
),BASE
)(u1
,
614 &FN(UNION
,match_bin_entry
), &data
) < 0)
623 FN(UNION
,free
)(data
.res
);
627 /* Compute the sum of "u1" and "u2".
629 * If the base expressions have a default zero value, then the sum
630 * is computed on the union of the domains of "u1" and "u2".
631 * Otherwise, it is computed on their shared domains.
633 __isl_give UNION
*FN(UNION
,add
)(__isl_take UNION
*u1
, __isl_take UNION
*u2
)
636 return FN(UNION
,union_add_
)(u1
, u2
);
638 return FN(UNION
,match_bin_op
)(u1
, u2
, &FN(PART
,add
));
643 /* Subtract "u2" from "u1" and return the result.
645 __isl_give UNION
*FN(UNION
,sub
)(__isl_take UNION
*u1
, __isl_take UNION
*u2
)
647 return FN(UNION
,match_bin_op
)(u1
, u2
, &FN(PART
,sub
));
651 S(UNION
,any_set_data
) {
653 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*);
656 static __isl_give PART
*FN(UNION
,any_set_entry
)(__isl_take PART
*part
,
659 S(UNION
,any_set_data
) *data
= user
;
661 return data
->fn(part
, isl_set_copy(data
->set
));
664 /* Update each element of "u" by calling "fn" on the element and "set".
666 static __isl_give UNION
*FN(UNION
,any_set_op
)(__isl_take UNION
*u
,
667 __isl_take isl_set
*set
,
668 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*))
670 S(UNION
,any_set_data
) data
= { NULL
, fn
};
671 S(UNION
,transform_control
) control
= {
672 .fn
= &FN(UNION
,any_set_entry
),
676 u
= FN(UNION
,align_params
)(u
, isl_set_get_space(set
));
677 set
= isl_set_align_params(set
, FN(UNION
,get_space
)(u
));
683 u
= FN(UNION
,transform
)(u
, &control
);
692 /* Intersect the domain of "u" with the parameter domain "context".
694 __isl_give UNION
*FN(UNION
,intersect_params
)(__isl_take UNION
*u
,
695 __isl_take isl_set
*set
)
697 return FN(UNION
,any_set_op
)(u
, set
, &FN(PW
,intersect_params
));
700 /* Compute the gist of the domain of "u" with respect to
701 * the parameter domain "context".
703 __isl_give UNION
*FN(UNION
,gist_params
)(__isl_take UNION
*u
,
704 __isl_take isl_set
*set
)
706 return FN(UNION
,any_set_op
)(u
, set
, &FN(PW
,gist_params
));
709 S(UNION
,match_domain_data
) {
712 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*);
715 static isl_bool
FN(UNION
,set_has_space
)(const void *entry
, const void *val
)
717 isl_set
*set
= (isl_set
*)entry
;
718 isl_space
*space
= (isl_space
*)val
;
720 return isl_space_is_equal(set
->dim
, space
);
723 /* Find the set in data->uset that lives in the same space as the domain
724 * of "part", apply data->fn to *entry and this set (if any), and add
725 * the result to data->res.
727 static isl_stat
FN(UNION
,match_domain_entry
)(__isl_take PART
*part
, void *user
)
729 S(UNION
,match_domain_data
) *data
= user
;
731 struct isl_hash_table_entry
*entry2
;
734 space
= FN(PART
,get_domain_space
)(part
);
735 hash
= isl_space_get_hash(space
);
736 entry2
= isl_hash_table_find(data
->uset
->dim
->ctx
, &data
->uset
->table
,
737 hash
, &FN(UNION
,set_has_space
), space
, 0);
738 isl_space_free(space
);
739 if (!entry2
|| entry2
== isl_hash_table_entry_none
) {
741 return isl_stat_non_null(entry2
);
744 part
= data
->fn(part
, isl_set_copy(entry2
->data
));
746 data
->res
= FN(FN(UNION
,add
),BASE
)(data
->res
, part
);
748 return isl_stat_error
;
753 /* Apply fn to each pair of PW in u and set in uset such that
754 * the set lives in the same space as the domain of PW
755 * and collect the results.
757 static __isl_give UNION
*FN(UNION
,match_domain_op
)(__isl_take UNION
*u
,
758 __isl_take isl_union_set
*uset
,
759 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*))
761 S(UNION
,match_domain_data
) data
= { NULL
, NULL
, fn
};
763 u
= FN(UNION
,align_params
)(u
, isl_union_set_get_space(uset
));
764 uset
= isl_union_set_align_params(uset
, FN(UNION
,get_space
)(u
));
770 data
.res
= FN(UNION
,alloc_same_size
)(u
);
771 if (FN(FN(UNION
,foreach
),BASE
)(u
,
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 /* Take the set (which may be empty) in data->uset that lives
799 * in the same space as the domain of "pw", subtract it from the domain
800 * of "part" and return the result.
802 static __isl_give PART
*FN(UNION
,subtract_domain_entry
)(__isl_take PART
*part
,
805 isl_union_set
*uset
= user
;
809 space
= FN(PART
,get_domain_space
)(part
);
810 set
= isl_union_set_extract_set(uset
, space
);
811 return FN(PART
,subtract_domain
)(part
, set
);
814 /* Subtract "uset' from the domain of "u".
816 __isl_give UNION
*FN(UNION
,subtract_domain
)(__isl_take UNION
*u
,
817 __isl_take isl_union_set
*uset
)
819 S(UNION
,transform_control
) control
= {
820 .fn
= &FN(UNION
,subtract_domain_entry
),
824 u
= FN(UNION
,transform
)(u
, &control
);
825 isl_union_set_free(uset
);
829 __isl_give UNION
*FN(UNION
,gist
)(__isl_take UNION
*u
,
830 __isl_take isl_union_set
*uset
)
832 if (isl_union_set_is_params(uset
))
833 return FN(UNION
,gist_params
)(u
, isl_set_from_union_set(uset
));
834 return FN(UNION
,match_domain_op
)(u
, uset
, &FN(PW
,gist
));
837 /* Coalesce an entry in a UNION. Coalescing is performed in-place.
838 * Since the UNION may have several references, the entry is only
839 * replaced if the coalescing is successful.
841 static isl_stat
FN(UNION
,coalesce_entry
)(void **entry
, void *user
)
843 PART
**part_p
= (PART
**) entry
;
846 part
= FN(PART
,copy
)(*part_p
);
847 part
= FN(PW
,coalesce
)(part
);
849 return isl_stat_error
;
850 FN(PART
,free
)(*part_p
);
856 __isl_give UNION
*FN(UNION
,coalesce
)(__isl_take UNION
*u
)
858 if (FN(UNION
,foreach_inplace
)(u
, &FN(UNION
,coalesce_entry
), NULL
) < 0)
867 static isl_stat
FN(UNION
,domain_entry
)(__isl_take PART
*part
, void *user
)
869 isl_union_set
**uset
= (isl_union_set
**)user
;
871 *uset
= isl_union_set_add_set(*uset
, FN(PART
,domain
)(part
));
876 __isl_give isl_union_set
*FN(UNION
,domain
)(__isl_take UNION
*u
)
880 uset
= isl_union_set_empty(FN(UNION
,get_space
)(u
));
881 if (FN(FN(UNION
,foreach
),BASE
)(u
, &FN(UNION
,domain_entry
), &uset
) < 0)
888 isl_union_set_free(uset
);
894 /* Negate the type of "u".
896 static __isl_give UNION
*FN(UNION
,negate_type
)(__isl_take UNION
*u
)
898 u
= FN(UNION
,cow
)(u
);
901 u
->type
= isl_fold_type_negate(u
->type
);
905 /* Negate the type of "u".
906 * Since "u" does not have a type, do nothing.
908 static __isl_give UNION
*FN(UNION
,negate_type
)(__isl_take UNION
*u
)
914 /* Multiply "part" by the isl_val "user" and return the result.
916 static __isl_give PART
*FN(UNION
,scale_val_entry
)(__isl_take PART
*part
,
921 return FN(PART
,scale_val
)(part
, isl_val_copy(v
));
924 /* Multiply "u" by "v" and return the result.
926 __isl_give UNION
*FN(UNION
,scale_val
)(__isl_take UNION
*u
,
927 __isl_take isl_val
*v
)
931 if (isl_val_is_one(v
)) {
936 if (DEFAULT_IS_ZERO
&& u
&& isl_val_is_zero(v
)) {
938 isl_space
*space
= FN(UNION
,get_space
)(u
);
939 zero
= FN(UNION
,ZERO
)(space
OPT_TYPE_ARG(u
->));
945 if (!isl_val_is_rat(v
))
946 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
947 "expecting rational factor", goto error
);
949 u
= FN(UNION
,transform_inplace
)(u
, &FN(UNION
,scale_val_entry
), v
);
950 if (isl_val_is_neg(v
))
951 u
= FN(UNION
,negate_type
)(u
);
961 /* Divide "part" by the isl_val "user" and return the result.
963 static __isl_give PART
*FN(UNION
,scale_down_val_entry
)(__isl_take PART
*part
,
968 return FN(PART
,scale_down_val
)(part
, isl_val_copy(v
));
971 /* Divide "u" by "v" and return the result.
973 __isl_give UNION
*FN(UNION
,scale_down_val
)(__isl_take UNION
*u
,
974 __isl_take isl_val
*v
)
978 if (isl_val_is_one(v
)) {
983 if (!isl_val_is_rat(v
))
984 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
985 "expecting rational factor", goto error
);
986 if (isl_val_is_zero(v
))
987 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
988 "cannot scale down by zero", goto error
);
990 u
= FN(UNION
,transform_inplace
)(u
, &FN(UNION
,scale_down_val_entry
), v
);
991 if (isl_val_is_neg(v
))
992 u
= FN(UNION
,negate_type
)(u
);
1002 S(UNION
,plain_is_equal_data
)
1008 static isl_stat
FN(UNION
,plain_is_equal_entry
)(void **entry
, void *user
)
1010 S(UNION
,plain_is_equal_data
) *data
= user
;
1011 struct isl_hash_table_entry
*entry2
;
1014 entry2
= FN(UNION
,find_part_entry
)(data
->u2
, pw
->dim
, 0);
1015 if (!entry2
|| entry2
== isl_hash_table_entry_none
) {
1017 data
->is_equal
= isl_bool_error
;
1019 data
->is_equal
= isl_bool_false
;
1020 return isl_stat_error
;
1023 data
->is_equal
= FN(PW
,plain_is_equal
)(pw
, entry2
->data
);
1024 if (data
->is_equal
< 0 || !data
->is_equal
)
1025 return isl_stat_error
;
1030 isl_bool
FN(UNION
,plain_is_equal
)(__isl_keep UNION
*u1
, __isl_keep UNION
*u2
)
1032 S(UNION
,plain_is_equal_data
) data
= { NULL
, isl_bool_true
};
1036 return isl_bool_error
;
1038 return isl_bool_true
;
1039 if (u1
->table
.n
!= u2
->table
.n
)
1040 return isl_bool_false
;
1041 n1
= FN(FN(UNION
,n
),BASE
)(u1
);
1042 n2
= FN(FN(UNION
,n
),BASE
)(u2
);
1043 if (n1
< 0 || n2
< 0)
1044 return isl_bool_error
;
1046 return isl_bool_false
;
1048 u1
= FN(UNION
,copy
)(u1
);
1049 u2
= FN(UNION
,copy
)(u2
);
1050 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
1051 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
1056 if (FN(UNION
,foreach_inplace
)(u1
,
1057 &FN(UNION
,plain_is_equal_entry
), &data
) < 0 &&
1064 return data
.is_equal
;
1068 return isl_bool_error
;
1071 /* Check whether the element that "entry" points to involves any NaNs and
1072 * store the result in *nan.
1073 * Abort as soon as one such element has been found.
1075 static isl_stat
FN(UNION
,involves_nan_entry
)(void **entry
, void *user
)
1077 isl_bool
*nan
= user
;
1080 *nan
= FN(PW
,involves_nan
)(pw
);
1081 if (*nan
< 0 || !nan
)
1082 return isl_stat_error
;
1087 /* Does "u" involve any NaNs?
1089 isl_bool
FN(UNION
,involves_nan
)(__isl_keep UNION
*u
)
1091 isl_bool nan
= isl_bool_false
;
1094 return isl_bool_error
;
1096 if (FN(UNION
,foreach_inplace
)(u
,
1097 &FN(UNION
,involves_nan_entry
), &nan
) < 0 &&
1099 return isl_bool_error
;
1104 /* Internal data structure for isl_union_*_drop_dims.
1105 * type, first and n are passed to isl_*_drop_dims.
1107 S(UNION
,drop_dims_data
) {
1108 enum isl_dim_type type
;
1113 /* Drop the parameters specified by "data" from "part" and return the result.
1115 static __isl_give PART
*FN(UNION
,drop_dims_entry
)(__isl_take PART
*part
,
1118 S(UNION
,drop_dims_data
) *data
= user
;
1120 return FN(PART
,drop_dims
)(part
, data
->type
, data
->first
, data
->n
);
1123 /* Drop the specified parameters from "u".
1124 * That is, type is required to be isl_dim_param.
1126 __isl_give UNION
*FN(UNION
,drop_dims
)( __isl_take UNION
*u
,
1127 enum isl_dim_type type
, unsigned first
, unsigned n
)
1130 S(UNION
,drop_dims_data
) data
= { type
, first
, n
};
1131 S(UNION
,transform_control
) control
= {
1132 .fn
= &FN(UNION
,drop_dims_entry
),
1139 if (type
!= isl_dim_param
)
1140 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
1141 "can only project out parameters",
1142 return FN(UNION
,free
)(u
));
1144 space
= FN(UNION
,get_space
)(u
);
1145 space
= isl_space_drop_dims(space
, type
, first
, n
);
1146 return FN(UNION
,transform_space
)(u
, space
, &control
);
1149 /* Internal data structure for isl_union_*_set_dim_name.
1150 * pos is the position of the parameter that needs to be renamed.
1151 * s is the new name.
1153 S(UNION
,set_dim_name_data
) {
1158 /* Change the name of the parameter at position data->pos of "part" to data->s
1159 * and return the result.
1161 static __isl_give PART
*FN(UNION
,set_dim_name_entry
)(__isl_take PART
*part
,
1164 S(UNION
,set_dim_name_data
) *data
= user
;
1166 return FN(PART
,set_dim_name
)(part
, isl_dim_param
, data
->pos
, data
->s
);
1169 /* Change the name of the parameter at position "pos" to "s".
1170 * That is, type is required to be isl_dim_param.
1172 __isl_give UNION
*FN(UNION
,set_dim_name
)(__isl_take UNION
*u
,
1173 enum isl_dim_type type
, unsigned pos
, const char *s
)
1175 S(UNION
,set_dim_name_data
) data
= { pos
, s
};
1176 S(UNION
,transform_control
) control
= {
1177 .fn
= &FN(UNION
,set_dim_name_entry
),
1185 if (type
!= isl_dim_param
)
1186 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
1187 "can only set parameter names",
1188 return FN(UNION
,free
)(u
));
1190 space
= FN(UNION
,get_space
)(u
);
1191 space
= isl_space_set_dim_name(space
, type
, pos
, s
);
1192 return FN(UNION
,transform_space
)(u
, space
, &control
);
1195 /* Reset the user pointer on all identifiers of parameters and tuples
1196 * of the space of "part" and return the result.
1198 static __isl_give PART
*FN(UNION
,reset_user_entry
)(__isl_take PART
*part
,
1201 return FN(PART
,reset_user
)(part
);
1204 /* Reset the user pointer on all identifiers of parameters and tuples
1205 * of the spaces of "u".
1207 __isl_give UNION
*FN(UNION
,reset_user
)(__isl_take UNION
*u
)
1209 S(UNION
,transform_control
) control
= {
1210 .fn
= &FN(UNION
,reset_user_entry
),
1214 space
= FN(UNION
,get_space
)(u
);
1215 space
= isl_space_reset_user(space
);
1216 return FN(UNION
,transform_space
)(u
, space
, &control
);
1219 /* Add the base expression held by "entry" to "list".
1221 static isl_stat
FN(UNION
,add_to_list
)(void **entry
, void *user
)
1224 LIST(PART
) **list
= user
;
1226 *list
= FN(LIST(PART
),add
)(*list
, FN(PART
,copy
)(pw
));
1228 return isl_stat_error
;
1233 /* Return a list containing all the base expressions in "u".
1235 * First construct a list of the appropriate size and
1236 * then add all the elements.
1238 __isl_give
LIST(PART
) *FN(FN(UNION
,get
),LIST(BASE
))(__isl_keep UNION
*u
)
1245 n
= FN(FN(UNION
,n
),BASE
)(u
);
1248 list
= FN(LIST(PART
),alloc
)(FN(UNION
,get_ctx(u
)), n
);
1249 if (FN(UNION
,foreach_inplace
)(u
, &FN(UNION
,add_to_list
), &list
) < 0)
1250 return FN(LIST(PART
),free
)(list
);