1 /*
2  * Copyright 2017      Sven Verdoolaege
3  *
4  * Use of this software is governed by the MIT license
5  *
6  * Written by Sven Verdoolaege.
7  */
8 
9 /* These versions of the explicit domain functions are used
10  * when the multi expression may have an explicit domain.
11  */
12 
13 #include <isl_multi_macro.h>
14 
15 __isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi);
16 
17 /* Does "multi" have an explicit domain?
18  *
19  * An explicit domain is only available if "multi" is zero-dimensional.
20  */
FN(MULTI (BASE),has_explicit_domain)21 static int FN(MULTI(BASE),has_explicit_domain)(__isl_keep MULTI(BASE) *multi)
22 {
23 	return multi && multi->n == 0;
24 }
25 
26 /* Check that "multi" has an explicit domain.
27  */
FN(MULTI (BASE),check_has_explicit_domain)28 static isl_stat FN(MULTI(BASE),check_has_explicit_domain)(
29 	__isl_keep MULTI(BASE) *multi)
30 {
31 	if (!multi)
32 		return isl_stat_error;
33 	if (!FN(MULTI(BASE),has_explicit_domain)(multi))
34 		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_internal,
35 			"expression does not have an explicit domain",
36 			return isl_stat_error);
37 	return isl_stat_ok;
38 }
39 
40 /* Return the explicit domain of "multi", assuming it has one.
41  */
FN(MULTI (BASE),peek_explicit_domain)42 static __isl_keep DOM *FN(MULTI(BASE),peek_explicit_domain)(
43 	__isl_keep MULTI(BASE) *multi)
44 {
45 	if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
46 		return NULL;
47 	return multi->u.dom;
48 }
49 
50 /* Return a copy of the explicit domain of "multi", assuming it has one.
51  */
FN(MULTI (BASE),get_explicit_domain)52 static __isl_give DOM *FN(MULTI(BASE),get_explicit_domain)(
53 	__isl_keep MULTI(BASE) *multi)
54 {
55 	return FN(DOM,copy)(FN(MULTI(BASE),peek_explicit_domain)(multi));
56 }
57 
58 /* Replace the explicit domain of "multi" by "dom", assuming it has one.
59  */
MULTI(BASE)60 static __isl_give MULTI(BASE) *FN(MULTI(BASE),set_explicit_domain)(
61 	__isl_take MULTI(BASE) *multi, __isl_take DOM *dom)
62 {
63 	if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
64 		goto error;
65 	multi = FN(MULTI(BASE),cow)(multi);
66 	if (!multi || !dom)
67 		goto error;
68 	FN(DOM,free)(multi->u.dom);
69 	multi->u.dom = dom;
70 	if (!multi->u.dom)
71 		return FN(MULTI(BASE),free)(multi);
72 	return multi;
73 error:
74 	FN(MULTI(BASE),free)(multi);
75 	FN(DOM,free)(dom);
76 	return NULL;
77 }
78 
79 /* Intersect the domain of "dst" with the explicit domain of "src".
80  *
81  * In the case of isl_multi_union_pw_aff objects, the explicit domain
82  * of "src" is allowed to have only constraints on the parameters, even
83  * if the domain of "dst" contains actual domain elements.  In this case,
84  * the domain of "dst" is intersected with those parameter constraints.
85  */
MULTI(BASE)86 static __isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_explicit_domain)(
87 	__isl_take MULTI(BASE) *dst, __isl_keep MULTI(BASE) *src)
88 {
89 	isl_bool is_params;
90 	DOM *dom;
91 
92 	dom = FN(MULTI(BASE),peek_explicit_domain)(src);
93 	is_params = FN(DOM,is_params)(dom);
94 	if (is_params < 0)
95 		return FN(MULTI(BASE),free)(dst);
96 
97 	dom = FN(DOM,copy)(dom);
98 	if (!is_params) {
99 		dst = FN(MULTI(BASE),intersect_domain)(dst, dom);
100 	} else {
101 		isl_set *params;
102 
103 		params = FN(DOM,params)(dom);
104 		dst = FN(MULTI(BASE),intersect_params)(dst, params);
105 	}
106 
107 	return dst;
108 }
109 
110 /* Set the explicit domain of "dst" to that of "src".
111  */
MULTI(BASE)112 static __isl_give MULTI(BASE) *FN(MULTI(BASE),copy_explicit_domain)(
113 	__isl_take MULTI(BASE) *dst, __isl_keep MULTI(BASE) *src)
114 {
115 	DOM *dom;
116 
117 	dom = FN(MULTI(BASE),get_explicit_domain)(src);
118 	dst = FN(MULTI(BASE),set_explicit_domain)(dst, dom);
119 
120 	return dst;
121 }
122 
123 /* Align the parameters of the explicit domain of "multi" to those of "space".
124  */
MULTI(BASE)125 static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_explicit_domain_params)(
126 	__isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
127 {
128 	DOM *dom;
129 
130 	dom = FN(MULTI(BASE),get_explicit_domain)(multi);
131 	dom = FN(DOM,align_params)(dom, space);
132 	multi = FN(MULTI(BASE),set_explicit_domain)(multi, dom);
133 
134 	return multi;
135 }
136 
137 /* Replace the space of the explicit domain of "multi" by "space",
138  * without modifying its dimension.
139  */
MULTI(BASE)140 static __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_explicit_domain_space)(
141 	__isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
142 {
143 	DOM *dom;
144 
145 	dom = FN(MULTI(BASE),get_explicit_domain)(multi);
146 	dom = FN(DOM,reset_equal_dim_space)(dom, space);
147 	multi = FN(MULTI(BASE),set_explicit_domain)(multi, dom);
148 
149 	return multi;
150 }
151 
152 /* Free the explicit domain of "multi".
153  */
FN(MULTI (BASE),free_explicit_domain)154 static void FN(MULTI(BASE),free_explicit_domain)(__isl_keep MULTI(BASE) *multi)
155 {
156 	if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
157 		return;
158 	FN(DOM,free)(multi->u.dom);
159 }
160 
161 /* Do "multi1" and "multi2" have the same explicit domain?
162  */
FN(MULTI (BASE),equal_explicit_domain)163 static isl_bool FN(MULTI(BASE),equal_explicit_domain)(
164 	__isl_keep MULTI(BASE) *multi1, __isl_keep MULTI(BASE) *multi2)
165 {
166 	DOM *dom1, *dom2;
167 	isl_bool equal;
168 
169 	if (FN(MULTI(BASE),check_has_explicit_domain)(multi1) < 0 ||
170 	    FN(MULTI(BASE),check_has_explicit_domain)(multi2) < 0)
171 		return isl_bool_error;
172 	dom1 = FN(MULTI(BASE),get_explicit_domain)(multi1);
173 	dom2 = FN(MULTI(BASE),get_explicit_domain)(multi2);
174 	equal = FN(DOM,is_equal)(dom1, dom2);
175 	FN(DOM,free)(dom1);
176 	FN(DOM,free)(dom2);
177 
178 	return equal;
179 }
180 
181 static isl_stat FN(MULTI(BASE),check_explicit_domain)(
182 	__isl_keep MULTI(BASE) *multi) __attribute__ ((unused));
183 
184 /* Debugging function to check that the explicit domain of "multi"
185  * has the correct space.
186  */
FN(MULTI (BASE),check_explicit_domain)187 isl_stat FN(MULTI(BASE),check_explicit_domain)(__isl_keep MULTI(BASE) *multi)
188 {
189 	isl_space *space1, *space2;
190 	isl_bool equal;
191 
192 	if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
193 		return isl_stat_error;
194 	space1 = isl_space_domain(isl_space_copy(multi->space));
195 	space2 = FN(DOM,get_space)(multi->u.dom);
196 	equal = isl_space_is_equal(space1, space2);
197 	isl_space_free(space1);
198 	isl_space_free(space2);
199 	if (equal < 0)
200 		return isl_stat_error;
201 	if (!equal)
202 		isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_internal,
203 			"check failed", return isl_stat_error);
204 	return isl_stat_ok;
205 }
206