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 /* Internal data structure for isl_union_*_transform_space.
254 * "fn' is applied to each entry in the input.
255 * "res" collects the results.
257 S(UNION
,transform_data
)
259 __isl_give PART
*(*fn
)(__isl_take PART
*part
, void *user
);
265 /* Apply data->fn to "part" and add the result to data->res.
267 static isl_stat
FN(UNION
,transform_entry
)(__isl_take PART
*part
, void *user
)
269 S(UNION
,transform_data
) *data
= (S(UNION
,transform_data
) *)user
;
271 part
= data
->fn(part
, data
->user
);
272 data
->res
= FN(FN(UNION
,add
),BASE
)(data
->res
, part
);
274 return isl_stat_error
;
279 /* Return a UNION living in "space" that is obtained by applying "fn"
280 * to each of the entries in "u".
282 static __isl_give UNION
*FN(UNION
,transform_space
)(__isl_take UNION
*u
,
284 __isl_give PART
*(*fn
)(__isl_take PART
*part
, void *user
), void *user
)
286 S(UNION
,transform_data
) data
= { fn
, user
};
288 data
.res
= FN(UNION
,alloc_same_size_on_space
)(u
, space
);
289 if (FN(FN(UNION
,foreach
),BASE
)(u
,
290 &FN(UNION
,transform_entry
), &data
) < 0)
291 data
.res
= FN(UNION
,free
)(data
.res
);
296 /* Return a UNION that lives in the same space as "u" and that is obtained
297 * by applying "fn" to each of the entries in "u".
299 static __isl_give UNION
*FN(UNION
,transform
)(__isl_take UNION
*u
,
300 __isl_give PART
*(*fn
)(__isl_take PART
*part
, void *user
), void *user
)
302 return FN(UNION
,transform_space
)(u
, FN(UNION
,get_space
)(u
), fn
, user
);
305 /* Apply data->fn to *part and store the result back into *part.
307 static isl_stat
FN(UNION
,transform_inplace_entry
)(void **part
, void *user
)
309 S(UNION
,transform_data
) *data
= (S(UNION
,transform_data
) *) user
;
311 *part
= data
->fn(*part
, data
->user
);
313 return isl_stat_error
;
317 /* Update "u" by applying "fn" to each entry.
318 * This operation is assumed not to change the number of entries nor
319 * the spaces of the entries.
321 * If there is only one reference to "u", then change "u" inplace.
322 * Otherwise, create a new UNION from "u" and discard the original.
324 static __isl_give UNION
*FN(UNION
,transform_inplace
)(__isl_take UNION
*u
,
325 __isl_give PART
*(*fn
)(__isl_take PART
*part
, void *user
), void *user
)
329 single_ref
= FN(UNION
,has_single_reference
)(u
);
331 return FN(UNION
,free
)(u
);
333 S(UNION
,transform_data
) data
= { fn
, user
};
334 if (FN(UNION
,foreach_inplace
)(u
,
335 &FN(UNION
,transform_inplace_entry
), &data
) < 0)
336 return FN(UNION
,free
)(u
);
339 return FN(UNION
,transform
)(u
, fn
, user
);
342 /* An isl_union_*_transform callback for use in isl_union_*_dup
343 * that simply returns "part".
345 static __isl_give PART
*FN(UNION
,copy_part
)(__isl_take PART
*part
, void *user
)
350 __isl_give UNION
*FN(UNION
,dup
)(__isl_keep UNION
*u
)
352 u
= FN(UNION
,copy
)(u
);
353 return FN(UNION
,transform
)(u
, &FN(UNION
,copy_part
), NULL
);
356 __isl_give UNION
*FN(UNION
,cow
)(__isl_take UNION
*u
)
364 return FN(UNION
,dup
)(u
);
367 __isl_null UNION
*FN(UNION
,free
)(__isl_take UNION
*u
)
375 isl_hash_table_foreach(u
->space
->ctx
, &u
->table
,
376 &FN(UNION
,free_u_entry
), NULL
);
377 isl_hash_table_clear(&u
->table
);
378 isl_space_free(u
->space
);
383 static __isl_give PART
*FN(UNION
,align_entry
)(__isl_take PART
*part
, void *user
)
385 isl_reordering
*exp
= user
;
387 exp
= isl_reordering_extend_space(isl_reordering_copy(exp
),
388 FN(PART
,get_domain_space
)(part
));
389 return FN(PART
,realign_domain
)(part
, exp
);
392 /* Reorder the parameters of "u" according to the given reordering.
394 static __isl_give UNION
*FN(UNION
,realign_domain
)(__isl_take UNION
*u
,
395 __isl_take isl_reordering
*r
)
402 space
= isl_reordering_get_space(r
);
403 u
= FN(UNION
,transform_space
)(u
, space
, &FN(UNION
,align_entry
), r
);
404 isl_reordering_free(r
);
408 isl_reordering_free(r
);
412 /* Align the parameters of "u" to those of "model".
414 __isl_give UNION
*FN(UNION
,align_params
)(__isl_take UNION
*u
,
415 __isl_take isl_space
*model
)
417 isl_bool equal_params
;
423 equal_params
= isl_space_has_equal_params(u
->space
, model
);
424 if (equal_params
< 0)
427 isl_space_free(model
);
431 r
= isl_parameter_alignment_reordering(u
->space
, model
);
432 isl_space_free(model
);
434 return FN(UNION
,realign_domain
)(u
, r
);
436 isl_space_free(model
);
441 /* Add "part" to *u, taking the union sum if "u" already has
442 * a part defined on the same space as "part".
444 static isl_stat
FN(UNION
,union_add_part
)(__isl_take PART
*part
, void *user
)
446 UNION
**u
= (UNION
**)user
;
448 *u
= FN(UNION
,add_part_generic
)(*u
, part
, 0);
453 /* Compute the sum of "u1" and "u2" on the union of their domains,
454 * with the actual sum on the shared domain and
455 * the defined expression on the symmetric difference of the domains.
457 * This is an internal function that is exposed under different
458 * names depending on whether the base expressions have a zero default
460 * If they do, then this function is called "add".
461 * Otherwise, it is called "union_add".
463 static __isl_give UNION
*FN(UNION
,union_add_
)(__isl_take UNION
*u1
,
464 __isl_take UNION
*u2
)
466 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
467 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
469 u1
= FN(UNION
,cow
)(u1
);
474 if (FN(FN(UNION
,foreach
),BASE
)(u2
, &FN(UNION
,union_add_part
), &u1
) < 0)
486 __isl_give UNION
*FN(FN(UNION
,from
),BASE
)(__isl_take PART
*part
)
494 space
= FN(PART
,get_space
)(part
);
495 space
= isl_space_drop_dims(space
, isl_dim_in
, 0,
496 isl_space_dim(space
, isl_dim_in
));
497 space
= isl_space_drop_dims(space
, isl_dim_out
, 0,
498 isl_space_dim(space
, isl_dim_out
));
499 u
= FN(UNION
,ZERO
)(space
OPT_TYPE_ARG(part
->));
500 u
= FN(FN(UNION
,add
),BASE
)(u
, part
);
505 S(UNION
,match_bin_data
) {
508 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*);
511 /* Check if data->u2 has an element living in the same space as "part".
512 * If so, call data->fn on the two elements and add the result to
515 static isl_stat
FN(UNION
,match_bin_entry
)(__isl_take PART
*part
, void *user
)
517 S(UNION
,match_bin_data
) *data
= user
;
518 struct isl_hash_table_entry
*entry2
;
522 space
= FN(PART
,get_space
)(part
);
523 entry2
= FN(UNION
,find_part_entry
)(data
->u2
, space
, 0);
524 isl_space_free(space
);
527 if (entry2
== isl_hash_table_entry_none
) {
532 part2
= entry2
->data
;
533 if (!isl_space_tuple_is_equal(part
->dim
, isl_dim_out
,
534 part2
->dim
, isl_dim_out
))
535 isl_die(FN(UNION
,get_ctx
)(data
->u2
), isl_error_invalid
,
536 "entries should have the same range space",
539 part
= data
->fn(part
, FN(PART
, copy
)(entry2
->data
));
541 data
->res
= FN(FN(UNION
,add
),BASE
)(data
->res
, part
);
543 return isl_stat_error
;
548 return isl_stat_error
;
551 /* This function is currently only used from isl_polynomial.c
552 * and not from isl_fold.c.
554 static __isl_give UNION
*FN(UNION
,match_bin_op
)(__isl_take UNION
*u1
,
555 __isl_take UNION
*u2
,
556 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*))
557 __attribute__ ((unused
));
558 /* For each pair of elements in "u1" and "u2" living in the same space,
559 * call "fn" and collect the results.
561 static __isl_give UNION
*FN(UNION
,match_bin_op
)(__isl_take UNION
*u1
,
562 __isl_take UNION
*u2
,
563 __isl_give PART
*(*fn
)(__isl_take PART
*, __isl_take PART
*))
565 S(UNION
,match_bin_data
) data
= { NULL
, NULL
, fn
};
567 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
568 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
574 data
.res
= FN(UNION
,alloc_same_size
)(u1
);
575 if (FN(FN(UNION
,foreach
),BASE
)(u1
,
576 &FN(UNION
,match_bin_entry
), &data
) < 0)
585 FN(UNION
,free
)(data
.res
);
589 /* Compute the sum of "u1" and "u2".
591 * If the base expressions have a default zero value, then the sum
592 * is computed on the union of the domains of "u1" and "u2".
593 * Otherwise, it is computed on their shared domains.
595 __isl_give UNION
*FN(UNION
,add
)(__isl_take UNION
*u1
, __isl_take UNION
*u2
)
598 return FN(UNION
,union_add_
)(u1
, u2
);
600 return FN(UNION
,match_bin_op
)(u1
, u2
, &FN(PART
,add
));
605 /* Subtract "u2" from "u1" and return the result.
607 __isl_give UNION
*FN(UNION
,sub
)(__isl_take UNION
*u1
, __isl_take UNION
*u2
)
609 return FN(UNION
,match_bin_op
)(u1
, u2
, &FN(PART
,sub
));
613 S(UNION
,any_set_data
) {
615 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*);
618 static __isl_give PART
*FN(UNION
,any_set_entry
)(__isl_take PART
*part
,
621 S(UNION
,any_set_data
) *data
= user
;
623 return data
->fn(part
, isl_set_copy(data
->set
));
626 /* Update each element of "u" by calling "fn" on the element and "set".
628 static __isl_give UNION
*FN(UNION
,any_set_op
)(__isl_take UNION
*u
,
629 __isl_take isl_set
*set
,
630 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*))
632 S(UNION
,any_set_data
) data
= { NULL
, fn
};
634 u
= FN(UNION
,align_params
)(u
, isl_set_get_space(set
));
635 set
= isl_set_align_params(set
, FN(UNION
,get_space
)(u
));
641 u
= FN(UNION
,transform
)(u
, &FN(UNION
,any_set_entry
), &data
);
650 /* Intersect the domain of "u" with the parameter domain "context".
652 __isl_give UNION
*FN(UNION
,intersect_params
)(__isl_take UNION
*u
,
653 __isl_take isl_set
*set
)
655 return FN(UNION
,any_set_op
)(u
, set
, &FN(PW
,intersect_params
));
658 /* Compute the gist of the domain of "u" with respect to
659 * the parameter domain "context".
661 __isl_give UNION
*FN(UNION
,gist_params
)(__isl_take UNION
*u
,
662 __isl_take isl_set
*set
)
664 return FN(UNION
,any_set_op
)(u
, set
, &FN(PW
,gist_params
));
667 S(UNION
,match_domain_data
) {
670 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*);
673 static int FN(UNION
,set_has_space
)(const void *entry
, const void *val
)
675 isl_set
*set
= (isl_set
*)entry
;
676 isl_space
*space
= (isl_space
*)val
;
678 return isl_space_is_equal(set
->dim
, space
);
681 /* Find the set in data->uset that lives in the same space as the domain
682 * of "part", apply data->fn to *entry and this set (if any), and add
683 * the result to data->res.
685 static isl_stat
FN(UNION
,match_domain_entry
)(__isl_take PART
*part
, void *user
)
687 S(UNION
,match_domain_data
) *data
= user
;
689 struct isl_hash_table_entry
*entry2
;
692 space
= FN(PART
,get_domain_space
)(part
);
693 hash
= isl_space_get_hash(space
);
694 entry2
= isl_hash_table_find(data
->uset
->dim
->ctx
, &data
->uset
->table
,
695 hash
, &FN(UNION
,set_has_space
), space
, 0);
696 isl_space_free(space
);
702 part
= data
->fn(part
, isl_set_copy(entry2
->data
));
704 data
->res
= FN(FN(UNION
,add
),BASE
)(data
->res
, part
);
706 return isl_stat_error
;
711 /* Apply fn to each pair of PW in u and set in uset such that
712 * the set lives in the same space as the domain of PW
713 * and collect the results.
715 static __isl_give UNION
*FN(UNION
,match_domain_op
)(__isl_take UNION
*u
,
716 __isl_take isl_union_set
*uset
,
717 __isl_give PW
*(*fn
)(__isl_take PW
*, __isl_take isl_set
*))
719 S(UNION
,match_domain_data
) data
= { NULL
, NULL
, fn
};
721 u
= FN(UNION
,align_params
)(u
, isl_union_set_get_space(uset
));
722 uset
= isl_union_set_align_params(uset
, FN(UNION
,get_space
)(u
));
728 data
.res
= FN(UNION
,alloc_same_size
)(u
);
729 if (FN(FN(UNION
,foreach
),BASE
)(u
,
730 &FN(UNION
,match_domain_entry
), &data
) < 0)
734 isl_union_set_free(uset
);
738 isl_union_set_free(uset
);
739 FN(UNION
,free
)(data
.res
);
743 /* Intersect the domain of "u" with "uset".
744 * If "uset" is a parameters domain, then intersect the parameter
745 * domain of "u" with this set.
747 __isl_give UNION
*FN(UNION
,intersect_domain
)(__isl_take UNION
*u
,
748 __isl_take isl_union_set
*uset
)
750 if (isl_union_set_is_params(uset
))
751 return FN(UNION
,intersect_params
)(u
,
752 isl_set_from_union_set(uset
));
753 return FN(UNION
,match_domain_op
)(u
, uset
, &FN(PW
,intersect_domain
));
756 /* Take the set (which may be empty) in data->uset that lives
757 * in the same space as the domain of "pw", subtract it from the domain
758 * of "part" and return the result.
760 static __isl_give PART
*FN(UNION
,subtract_domain_entry
)(__isl_take PART
*part
,
763 isl_union_set
*uset
= user
;
767 space
= FN(PART
,get_domain_space
)(part
);
768 set
= isl_union_set_extract_set(uset
, space
);
769 return FN(PART
,subtract_domain
)(part
, set
);
772 /* Subtract "uset' from the domain of "u".
774 __isl_give UNION
*FN(UNION
,subtract_domain
)(__isl_take UNION
*u
,
775 __isl_take isl_union_set
*uset
)
777 u
= FN(UNION
,transform
)(u
, &FN(UNION
,subtract_domain_entry
), uset
);
778 isl_union_set_free(uset
);
782 __isl_give UNION
*FN(UNION
,gist
)(__isl_take UNION
*u
,
783 __isl_take isl_union_set
*uset
)
785 if (isl_union_set_is_params(uset
))
786 return FN(UNION
,gist_params
)(u
, isl_set_from_union_set(uset
));
787 return FN(UNION
,match_domain_op
)(u
, uset
, &FN(PW
,gist
));
790 /* Coalesce an entry in a UNION. Coalescing is performed in-place.
791 * Since the UNION may have several references, the entry is only
792 * replaced if the coalescing is successful.
794 static isl_stat
FN(UNION
,coalesce_entry
)(void **entry
, void *user
)
796 PART
**part_p
= (PART
**) entry
;
799 part
= FN(PART
,copy
)(*part_p
);
800 part
= FN(PW
,coalesce
)(part
);
802 return isl_stat_error
;
803 FN(PART
,free
)(*part_p
);
809 __isl_give UNION
*FN(UNION
,coalesce
)(__isl_take UNION
*u
)
811 if (FN(UNION
,foreach_inplace
)(u
, &FN(UNION
,coalesce_entry
), NULL
) < 0)
820 static isl_stat
FN(UNION
,domain_entry
)(__isl_take PART
*part
, void *user
)
822 isl_union_set
**uset
= (isl_union_set
**)user
;
824 *uset
= isl_union_set_add_set(*uset
, FN(PART
,domain
)(part
));
829 __isl_give isl_union_set
*FN(UNION
,domain
)(__isl_take UNION
*u
)
833 uset
= isl_union_set_empty(FN(UNION
,get_space
)(u
));
834 if (FN(FN(UNION
,foreach
),BASE
)(u
, &FN(UNION
,domain_entry
), &uset
) < 0)
841 isl_union_set_free(uset
);
847 /* Negate the type of "u".
849 static __isl_give UNION
*FN(UNION
,negate_type
)(__isl_take UNION
*u
)
851 u
= FN(UNION
,cow
)(u
);
854 u
->type
= isl_fold_type_negate(u
->type
);
858 /* Negate the type of "u".
859 * Since "u" does not have a type, do nothing.
861 static __isl_give UNION
*FN(UNION
,negate_type
)(__isl_take UNION
*u
)
867 /* Multiply "part" by the isl_val "user" and return the result.
869 static __isl_give PART
*FN(UNION
,scale_val_entry
)(__isl_take PART
*part
,
874 return FN(PART
,scale_val
)(part
, isl_val_copy(v
));
877 /* Multiply "u" by "v" and return the result.
879 __isl_give UNION
*FN(UNION
,scale_val
)(__isl_take UNION
*u
,
880 __isl_take isl_val
*v
)
884 if (isl_val_is_one(v
)) {
889 if (DEFAULT_IS_ZERO
&& u
&& isl_val_is_zero(v
)) {
891 isl_space
*space
= FN(UNION
,get_space
)(u
);
892 zero
= FN(UNION
,ZERO
)(space
OPT_TYPE_ARG(u
->));
898 if (!isl_val_is_rat(v
))
899 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
900 "expecting rational factor", goto error
);
902 u
= FN(UNION
,transform_inplace
)(u
, &FN(UNION
,scale_val_entry
), v
);
903 if (isl_val_is_neg(v
))
904 u
= FN(UNION
,negate_type
)(u
);
914 /* Divide "part" by the isl_val "user" and return the result.
916 static __isl_give PART
*FN(UNION
,scale_down_val_entry
)(__isl_take PART
*part
,
921 return FN(PART
,scale_down_val
)(part
, isl_val_copy(v
));
924 /* Divide "u" by "v" and return the result.
926 __isl_give UNION
*FN(UNION
,scale_down_val
)(__isl_take UNION
*u
,
927 __isl_take isl_val
*v
)
931 if (isl_val_is_one(v
)) {
936 if (!isl_val_is_rat(v
))
937 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
938 "expecting rational factor", goto error
);
939 if (isl_val_is_zero(v
))
940 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
941 "cannot scale down by zero", goto error
);
943 u
= FN(UNION
,transform_inplace
)(u
, &FN(UNION
,scale_down_val_entry
), v
);
944 if (isl_val_is_neg(v
))
945 u
= FN(UNION
,negate_type
)(u
);
955 S(UNION
,plain_is_equal_data
)
961 static isl_stat
FN(UNION
,plain_is_equal_entry
)(void **entry
, void *user
)
963 S(UNION
,plain_is_equal_data
) *data
= user
;
964 struct isl_hash_table_entry
*entry2
;
967 entry2
= FN(UNION
,find_part_entry
)(data
->u2
, pw
->dim
, 0);
968 if (!entry2
|| entry2
== isl_hash_table_entry_none
) {
970 data
->is_equal
= isl_bool_error
;
972 data
->is_equal
= isl_bool_false
;
973 return isl_stat_error
;
976 data
->is_equal
= FN(PW
,plain_is_equal
)(pw
, entry2
->data
);
977 if (data
->is_equal
< 0 || !data
->is_equal
)
978 return isl_stat_error
;
983 isl_bool
FN(UNION
,plain_is_equal
)(__isl_keep UNION
*u1
, __isl_keep UNION
*u2
)
985 S(UNION
,plain_is_equal_data
) data
= { NULL
, isl_bool_true
};
989 return isl_bool_error
;
991 return isl_bool_true
;
992 if (u1
->table
.n
!= u2
->table
.n
)
993 return isl_bool_false
;
994 n1
= FN(FN(UNION
,n
),BASE
)(u1
);
995 n2
= FN(FN(UNION
,n
),BASE
)(u2
);
996 if (n1
< 0 || n2
< 0)
997 return isl_bool_error
;
999 return isl_bool_false
;
1001 u1
= FN(UNION
,copy
)(u1
);
1002 u2
= FN(UNION
,copy
)(u2
);
1003 u1
= FN(UNION
,align_params
)(u1
, FN(UNION
,get_space
)(u2
));
1004 u2
= FN(UNION
,align_params
)(u2
, FN(UNION
,get_space
)(u1
));
1009 if (FN(UNION
,foreach_inplace
)(u1
,
1010 &FN(UNION
,plain_is_equal_entry
), &data
) < 0 &&
1017 return data
.is_equal
;
1021 return isl_bool_error
;
1024 /* Check whether the element that "entry" points to involves any NaNs and
1025 * store the result in *nan.
1026 * Abort as soon as one such element has been found.
1028 static isl_stat
FN(UNION
,involves_nan_entry
)(void **entry
, void *user
)
1030 isl_bool
*nan
= user
;
1033 *nan
= FN(PW
,involves_nan
)(pw
);
1034 if (*nan
< 0 || !nan
)
1035 return isl_stat_error
;
1040 /* Does "u" involve any NaNs?
1042 isl_bool
FN(UNION
,involves_nan
)(__isl_keep UNION
*u
)
1044 isl_bool nan
= isl_bool_false
;
1047 return isl_bool_error
;
1049 if (FN(UNION
,foreach_inplace
)(u
,
1050 &FN(UNION
,involves_nan_entry
), &nan
) < 0 &&
1052 return isl_bool_error
;
1057 /* Internal data structure for isl_union_*_drop_dims.
1058 * type, first and n are passed to isl_*_drop_dims.
1060 S(UNION
,drop_dims_data
) {
1061 enum isl_dim_type type
;
1066 /* Drop the parameters specified by "data" from "part" and return the result.
1068 static __isl_give PART
*FN(UNION
,drop_dims_entry
)(__isl_take PART
*part
,
1071 S(UNION
,drop_dims_data
) *data
= user
;
1073 return FN(PART
,drop_dims
)(part
, data
->type
, data
->first
, data
->n
);
1076 /* Drop the specified parameters from "u".
1077 * That is, type is required to be isl_dim_param.
1079 __isl_give UNION
*FN(UNION
,drop_dims
)( __isl_take UNION
*u
,
1080 enum isl_dim_type type
, unsigned first
, unsigned n
)
1083 S(UNION
,drop_dims_data
) data
= { type
, first
, n
};
1088 if (type
!= isl_dim_param
)
1089 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
1090 "can only project out parameters",
1091 return FN(UNION
,free
)(u
));
1093 space
= FN(UNION
,get_space
)(u
);
1094 space
= isl_space_drop_dims(space
, type
, first
, n
);
1095 return FN(UNION
,transform_space
)(u
, space
, &FN(UNION
,drop_dims_entry
),
1099 /* Internal data structure for isl_union_*_set_dim_name.
1100 * pos is the position of the parameter that needs to be renamed.
1101 * s is the new name.
1103 S(UNION
,set_dim_name_data
) {
1108 /* Change the name of the parameter at position data->pos of "part" to data->s
1109 * and return the result.
1111 static __isl_give PART
*FN(UNION
,set_dim_name_entry
)(__isl_take PART
*part
,
1114 S(UNION
,set_dim_name_data
) *data
= user
;
1116 return FN(PART
,set_dim_name
)(part
, isl_dim_param
, data
->pos
, data
->s
);
1119 /* Change the name of the parameter at position "pos" to "s".
1120 * That is, type is required to be isl_dim_param.
1122 __isl_give UNION
*FN(UNION
,set_dim_name
)(__isl_take UNION
*u
,
1123 enum isl_dim_type type
, unsigned pos
, const char *s
)
1125 S(UNION
,set_dim_name_data
) data
= { pos
, s
};
1131 if (type
!= isl_dim_param
)
1132 isl_die(FN(UNION
,get_ctx
)(u
), isl_error_invalid
,
1133 "can only set parameter names",
1134 return FN(UNION
,free
)(u
));
1136 space
= FN(UNION
,get_space
)(u
);
1137 space
= isl_space_set_dim_name(space
, type
, pos
, s
);
1138 return FN(UNION
,transform_space
)(u
, space
,
1139 &FN(UNION
,set_dim_name_entry
), &data
);
1142 /* Reset the user pointer on all identifiers of parameters and tuples
1143 * of the space of "part" and return the result.
1145 static __isl_give PART
*FN(UNION
,reset_user_entry
)(__isl_take PART
*part
,
1148 return FN(PART
,reset_user
)(part
);
1151 /* Reset the user pointer on all identifiers of parameters and tuples
1152 * of the spaces of "u".
1154 __isl_give UNION
*FN(UNION
,reset_user
)(__isl_take UNION
*u
)
1158 space
= FN(UNION
,get_space
)(u
);
1159 space
= isl_space_reset_user(space
);
1160 return FN(UNION
,transform_space
)(u
, space
, &FN(UNION
,reset_user_entry
),
1164 /* Add the base expression held by "entry" to "list".
1166 static isl_stat
FN(UNION
,add_to_list
)(void **entry
, void *user
)
1169 LIST(PART
) **list
= user
;
1171 *list
= FN(LIST(PART
),add
)(*list
, FN(PART
,copy
)(pw
));
1173 return isl_stat_error
;
1178 /* Return a list containing all the base expressions in "u".
1180 * First construct a list of the appropriate size and
1181 * then add all the elements.
1183 __isl_give
LIST(PART
) *FN(FN(UNION
,get
),LIST(BASE
))(__isl_keep UNION
*u
)
1190 n
= FN(FN(UNION
,n
),BASE
)(u
);
1193 list
= FN(LIST(PART
),alloc
)(FN(UNION
,get_ctx(u
)), n
);
1194 if (FN(UNION
,foreach_inplace
)(u
, &FN(UNION
,add_to_list
), &list
) < 0)
1195 return FN(LIST(PART
),free
)(list
);