2 * Copyright 2011 INRIA Saclay
3 * Copyright 2012 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 #include <isl_pw_macro.h>
15 /* Given a function "cmp" that returns the set of elements where
16 * "el1" is "better" than "el2", return this set.
18 static __isl_give isl_set
*FN(PW
,better
)(__isl_keep EL
*el1
, __isl_keep EL
*el2
,
19 __isl_give isl_set
*(*cmp
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
21 return cmp(FN(EL
,copy
)(el1
), FN(EL
,copy
)(el2
));
24 /* Return a list containing the domains of the pieces of "pw".
26 static __isl_give isl_set_list
*FN(PW
,extract_domains
)(__isl_keep PW
*pw
)
34 ctx
= FN(PW
,get_ctx
)(pw
);
35 list
= isl_set_list_alloc(ctx
, pw
->n
);
36 for (i
= 0; i
< pw
->n
; ++i
)
37 list
= isl_set_list_add(list
, isl_set_copy(pw
->p
[i
].set
));
42 /* Given sets B ("set"), C ("better") and A' ("out"), return
44 * (B \cap C) \cup ((B \setminus C) \setminus A')
46 static __isl_give isl_set
*FN(PW
,better_or_out
)(__isl_take isl_set
*set
,
47 __isl_take isl_set
*better
, __isl_take isl_set
*out
)
49 isl_set
*set_better
, *set_out
;
51 set_better
= isl_set_intersect(isl_set_copy(set
), isl_set_copy(better
));
52 set_out
= isl_set_subtract(isl_set_subtract(set
, better
), out
);
54 return isl_set_union(set_better
, set_out
);
57 /* Given sets A ("set"), C ("better") and B' ("out"), return
59 * (A \setminus C) \cup ((A \cap C) \setminus B')
61 static __isl_give isl_set
*FN(PW
,worse_or_out
)(__isl_take isl_set
*set
,
62 __isl_take isl_set
*better
, __isl_take isl_set
*out
)
64 isl_set
*set_worse
, *set_out
;
66 set_worse
= isl_set_subtract(isl_set_copy(set
), isl_set_copy(better
));
67 set_out
= isl_set_subtract(isl_set_intersect(set
, better
), out
);
69 return isl_set_union(set_worse
, set_out
);
72 /* Given two piecewise expressions "pw1" and "pw2", replace their domains
73 * by the sets in "list1" and "list2" and combine the results into
74 * a single piecewise expression.
75 * The pieces of "pw1" and "pw2" are assumed to have been sorted
76 * according to the function value expressions.
77 * The pieces of the result are also sorted in this way.
79 * Run through the pieces of "pw1" and "pw2" in order until they
80 * have both been exhausted, picking the piece from "pw1" or "pw2"
81 * depending on which should come first, together with the corresponding
82 * domain from "list1" or "list2". In cases where the next pieces
83 * in both "pw1" and "pw2" have the same function value expression,
84 * construct only a single piece in the result with as domain
85 * the union of the domains in "list1" and "list2".
87 static __isl_give PW
*FN(PW
,merge
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
,
88 __isl_take isl_set_list
*list1
, __isl_take isl_set_list
*list2
)
96 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->n
+ pw2
->n
);
99 while (i
< pw1
->n
|| j
< pw2
->n
) {
104 if (i
< pw1
->n
&& j
< pw2
->n
)
105 cmp
= FN(EL
,plain_cmp
)(pw1
->p
[i
].FIELD
,
108 cmp
= i
< pw1
->n
? -1 : 1;
111 set
= isl_set_list_get_set(list1
, i
);
112 el
= FN(EL
,copy
)(pw1
->p
[i
].FIELD
);
114 } else if (cmp
> 0) {
115 set
= isl_set_list_get_set(list2
, j
);
116 el
= FN(EL
,copy
)(pw2
->p
[j
].FIELD
);
119 set
= isl_set_union(isl_set_list_get_set(list1
, i
),
120 isl_set_list_get_set(list2
, j
));
121 el
= FN(EL
,copy
)(pw1
->p
[i
].FIELD
);
125 res
= FN(PW
,add_piece
)(res
, set
, el
);
128 isl_set_list_free(list1
);
129 isl_set_list_free(list2
);
134 isl_set_list_free(list1
);
135 isl_set_list_free(list2
);
141 /* Given a function "cmp" that returns the set of elements where
142 * "el1" is "better" than "el2", return a piecewise
143 * expression defined on the union of the definition domains
144 * of "pw1" and "pw2" that maps to the "best" of "pw1" and
145 * "pw2" on each cell. If only one of the two input functions
146 * is defined on a given cell, then it is considered the best.
148 * Run through all pairs of pieces in "pw1" and "pw2".
149 * If the domains of these pieces intersect, then the intersection
150 * needs to be distributed over the two pieces based on "cmp".
151 * Let C be the set where the piece from "pw2" is better (according to "cmp")
152 * than the piece from "pw1". Let A be the domain of the piece from "pw1" and
153 * B the domain of the piece from "pw2".
155 * The elements in C need to be removed from A, except for those parts
156 * that lie outside of B. That is,
158 * A <- (A \setminus C) \cup ((A \cap C) \setminus B')
160 * Conversely, the elements in B need to be restricted to C, except
161 * for those parts that lie outside of A. That is
163 * B <- (B \cap C) \cup ((B \setminus C) \setminus A')
165 * Since all pairs of pieces are considered, the domains are updated
166 * several times. A and B refer to these updated domains
167 * (kept track of in "list1" and "list2"), while A' and B' refer
168 * to the original domains of the pieces. It is safe to use these
169 * original domains because the difference between, say, A' and A is
170 * the domains of pw2-pieces that have been removed before and
171 * those domains are disjoint from B. A' is used instead of A
172 * because the continued updating of A may result in this domain
173 * getting broken up into more disjuncts.
175 * After the updated domains have been computed, the result is constructed
176 * from "pw1", "pw2", "list1" and "list2". If there are any pieces
177 * in "pw1" and "pw2" with the same function value expression, then
178 * they are combined into a single piece in the result.
179 * In order to be able to do this efficiently, the pieces of "pw1" and
180 * "pw2" are first sorted according to their function value expressions.
182 static __isl_give PW
*FN(PW
,union_opt_cmp
)(
183 __isl_take PW
*pw1
, __isl_take PW
*pw2
,
184 __isl_give isl_set
*(*cmp
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
190 isl_set_list
*list1
= NULL
, *list2
= NULL
;
195 ctx
= isl_space_get_ctx(pw1
->dim
);
196 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
197 isl_die(ctx
, isl_error_invalid
,
198 "arguments should live in the same space", goto error
);
200 if (FN(PW
,is_empty
)(pw1
)) {
205 if (FN(PW
,is_empty
)(pw2
)) {
210 pw1
= FN(PW
,sort
)(pw1
);
211 pw2
= FN(PW
,sort
)(pw2
);
215 list1
= FN(PW
,extract_domains
)(pw1
);
216 list2
= FN(PW
,extract_domains
)(pw2
);
218 for (i
= 0; i
< pw1
->n
; ++i
) {
219 for (j
= 0; j
< pw2
->n
; ++j
) {
221 isl_set
*better
, *set_i
, *set_j
;
223 disjoint
= isl_set_is_disjoint(pw1
->p
[i
].set
,
229 better
= FN(PW
,better
)(pw2
->p
[j
].FIELD
,
230 pw1
->p
[i
].FIELD
, cmp
);
231 set_i
= isl_set_list_get_set(list1
, i
);
232 set_j
= isl_set_copy(pw2
->p
[j
].set
);
233 set_i
= FN(PW
,worse_or_out
)(set_i
,
234 isl_set_copy(better
), set_j
);
235 list1
= isl_set_list_set_set(list1
, i
, set_i
);
236 set_i
= isl_set_copy(pw1
->p
[i
].set
);
237 set_j
= isl_set_list_get_set(list2
, j
);
238 set_j
= FN(PW
,better_or_out
)(set_j
, better
, set_i
);
239 list2
= isl_set_list_set_set(list2
, j
, set_j
);
243 res
= FN(PW
,merge
)(pw1
, pw2
, list1
, list2
);
247 isl_set_list_free(list1
);
248 isl_set_list_free(list2
);
252 return FN(PW
,free
)(res
);