2 * Copyright 2011 INRIA Saclay
3 * Copyright 2011 Sven Verdoolaege
4 * Copyright 2012-2014 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
6 * Copyright 2016 Sven Verdoolaege
7 * Copyright 2018,2020 Cerebras Systems
8 * Copyright 2021 Sven Verdoolaege
9 * Copyright 2022 Cerebras Systems
11 * Use of this software is governed by the MIT license
13 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
14 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
16 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
17 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
18 * B.P. 105 - 78153 Le Chesnay, France
19 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
20 * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA
23 #include <isl_ctx_private.h>
24 #include <isl_map_private.h>
25 #include <isl_union_map_private.h>
26 #include <isl_aff_private.h>
27 #include <isl_space_private.h>
28 #include <isl_local_space_private.h>
29 #include <isl_vec_private.h>
30 #include <isl_mat_private.h>
31 #include <isl_id_private.h>
32 #include <isl/constraint.h>
35 #include <isl_val_private.h>
36 #include <isl_point_private.h>
37 #include <isl_maybe_aff.h>
38 #include <isl_config.h>
43 #include <isl_list_templ.c>
44 #include <isl_list_read_templ.c>
47 #define EL_BASE pw_aff
49 #include <isl_list_templ.c>
50 #include <isl_list_read_templ.c>
53 #define EL_BASE pw_multi_aff
55 #include <isl_list_templ.c>
56 #include <isl_list_read_templ.c>
59 #define EL_BASE union_pw_aff
61 #include <isl_list_templ.c>
62 #include <isl_list_read_templ.c>
65 #define EL_BASE union_pw_multi_aff
67 #include <isl_list_templ.c>
69 /* Construct an isl_aff from the given domain local space "ls" and
70 * coefficients "v", where the local space is known to be valid
71 * for an affine expression.
73 static __isl_give isl_aff
*isl_aff_alloc_vec_validated(
74 __isl_take isl_local_space
*ls
, __isl_take isl_vec
*v
)
81 aff
= isl_calloc_type(v
->ctx
, struct isl_aff
);
91 isl_local_space_free(ls
);
96 /* Construct an isl_aff from the given domain local space "ls" and
99 * First check that "ls" is a valid domain local space
100 * for an affine expression.
102 __isl_give isl_aff
*isl_aff_alloc_vec(__isl_take isl_local_space
*ls
,
103 __isl_take isl_vec
*v
)
110 ctx
= isl_local_space_get_ctx(ls
);
111 if (!isl_local_space_divs_known(ls
))
112 isl_die(ctx
, isl_error_invalid
, "local space has unknown divs",
114 if (!isl_local_space_is_set(ls
))
115 isl_die(ctx
, isl_error_invalid
,
116 "domain of affine expression should be a set",
118 return isl_aff_alloc_vec_validated(ls
, v
);
120 isl_local_space_free(ls
);
125 __isl_give isl_aff
*isl_aff_alloc(__isl_take isl_local_space
*ls
)
134 ctx
= isl_local_space_get_ctx(ls
);
136 total
= isl_local_space_dim(ls
, isl_dim_all
);
139 v
= isl_vec_alloc(ctx
, 1 + 1 + total
);
140 return isl_aff_alloc_vec(ls
, v
);
142 isl_local_space_free(ls
);
146 __isl_give isl_aff
*isl_aff_copy(__isl_keep isl_aff
*aff
)
155 __isl_give isl_aff
*isl_aff_dup(__isl_keep isl_aff
*aff
)
160 return isl_aff_alloc_vec_validated(isl_local_space_copy(aff
->ls
),
161 isl_vec_copy(aff
->v
));
164 __isl_give isl_aff
*isl_aff_cow(__isl_take isl_aff
*aff
)
172 return isl_aff_dup(aff
);
175 /* Return a copy of the rational affine expression of "aff".
177 static __isl_give isl_vec
*isl_aff_get_rat_aff(__isl_keep isl_aff
*aff
)
181 return isl_vec_copy(aff
->v
);
184 /* Return the rational affine expression of "aff".
185 * This may be either a copy or the expression itself
186 * if there is only one reference to "aff".
187 * This allows the expression to be modified inplace
188 * if both the "aff" and its expression have only a single reference.
189 * The caller is not allowed to modify "aff" between this call and
190 * a subsequent call to isl_aff_restore_rat_aff.
191 * The only exception is that isl_aff_free can be called instead.
193 static __isl_give isl_vec
*isl_aff_take_rat_aff(__isl_keep isl_aff
*aff
)
200 return isl_aff_get_rat_aff(aff
);
206 /* Set the rational affine expression of "aff" to "v",
207 * where the rational affine expression of "aff" may be missing
208 * due to a preceding call to isl_aff_take_rat_aff.
209 * However, in this case, "aff" only has a single reference and
210 * then the call to isl_aff_cow has no effect.
212 static __isl_give isl_aff
*isl_aff_restore_rat_aff(__isl_keep isl_aff
*aff
,
213 __isl_take isl_vec
*v
)
223 aff
= isl_aff_cow(aff
);
226 isl_vec_free(aff
->v
);
236 __isl_give isl_aff
*isl_aff_zero_on_domain(__isl_take isl_local_space
*ls
)
240 aff
= isl_aff_alloc(ls
);
244 isl_int_set_si(aff
->v
->el
[0], 1);
245 isl_seq_clr(aff
->v
->el
+ 1, aff
->v
->size
- 1);
250 /* Return an affine expression that is equal to zero on domain space "space".
252 __isl_give isl_aff
*isl_aff_zero_on_domain_space(__isl_take isl_space
*space
)
254 return isl_aff_zero_on_domain(isl_local_space_from_space(space
));
257 /* This function performs the same operation as isl_aff_zero_on_domain_space,
258 * but is considered as a function on an isl_space when exported.
260 __isl_give isl_aff
*isl_space_zero_aff_on_domain(__isl_take isl_space
*space
)
262 return isl_aff_zero_on_domain_space(space
);
265 /* Return a piecewise affine expression defined on the specified domain
266 * that is equal to zero.
268 __isl_give isl_pw_aff
*isl_pw_aff_zero_on_domain(__isl_take isl_local_space
*ls
)
270 return isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls
));
273 /* Change "aff" into a NaN.
275 * Note that this function gets called from isl_aff_nan_on_domain,
276 * so "aff" may not have been initialized yet.
278 static __isl_give isl_aff
*isl_aff_set_nan(__isl_take isl_aff
*aff
)
282 v
= isl_aff_take_rat_aff(aff
);
284 aff
= isl_aff_restore_rat_aff(aff
, v
);
289 /* Return an affine expression defined on the specified domain
290 * that represents NaN.
292 __isl_give isl_aff
*isl_aff_nan_on_domain(__isl_take isl_local_space
*ls
)
296 aff
= isl_aff_alloc(ls
);
297 return isl_aff_set_nan(aff
);
300 /* Return an affine expression defined on the specified domain space
301 * that represents NaN.
303 __isl_give isl_aff
*isl_aff_nan_on_domain_space(__isl_take isl_space
*space
)
305 return isl_aff_nan_on_domain(isl_local_space_from_space(space
));
308 /* Return a piecewise affine expression defined on the specified domain space
309 * that represents NaN.
311 __isl_give isl_pw_aff
*isl_pw_aff_nan_on_domain_space(
312 __isl_take isl_space
*space
)
314 return isl_pw_aff_from_aff(isl_aff_nan_on_domain_space(space
));
317 /* Return a piecewise affine expression defined on the specified domain
318 * that represents NaN.
320 __isl_give isl_pw_aff
*isl_pw_aff_nan_on_domain(__isl_take isl_local_space
*ls
)
322 return isl_pw_aff_from_aff(isl_aff_nan_on_domain(ls
));
325 /* Return an affine expression that is equal to "val" on
326 * domain local space "ls".
328 * Note that the encoding for the special value NaN
329 * is the same in isl_val and isl_aff, so this does not need
330 * to be treated in any special way.
332 __isl_give isl_aff
*isl_aff_val_on_domain(__isl_take isl_local_space
*ls
,
333 __isl_take isl_val
*val
)
339 if (!isl_val_is_rat(val
) && !isl_val_is_nan(val
))
340 isl_die(isl_val_get_ctx(val
), isl_error_invalid
,
341 "expecting rational value or NaN", goto error
);
343 aff
= isl_aff_alloc(isl_local_space_copy(ls
));
347 isl_seq_clr(aff
->v
->el
+ 2, aff
->v
->size
- 2);
348 isl_int_set(aff
->v
->el
[1], val
->n
);
349 isl_int_set(aff
->v
->el
[0], val
->d
);
351 isl_local_space_free(ls
);
355 isl_local_space_free(ls
);
360 /* Return an affine expression that is equal to "val" on domain space "space".
362 __isl_give isl_aff
*isl_aff_val_on_domain_space(__isl_take isl_space
*space
,
363 __isl_take isl_val
*val
)
365 return isl_aff_val_on_domain(isl_local_space_from_space(space
), val
);
368 /* Return an affine expression that is equal to the specified dimension
371 __isl_give isl_aff
*isl_aff_var_on_domain(__isl_take isl_local_space
*ls
,
372 enum isl_dim_type type
, unsigned pos
)
380 space
= isl_local_space_get_space(ls
);
383 if (isl_space_is_map(space
))
384 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
385 "expecting (parameter) set space", goto error
);
386 if (isl_local_space_check_range(ls
, type
, pos
, 1) < 0)
389 isl_space_free(space
);
390 aff
= isl_aff_alloc(ls
);
394 pos
+= isl_local_space_offset(aff
->ls
, type
);
396 isl_int_set_si(aff
->v
->el
[0], 1);
397 isl_seq_clr(aff
->v
->el
+ 1, aff
->v
->size
- 1);
398 isl_int_set_si(aff
->v
->el
[1 + pos
], 1);
402 isl_local_space_free(ls
);
403 isl_space_free(space
);
407 /* Return a piecewise affine expression that is equal to
408 * the specified dimension in "ls".
410 __isl_give isl_pw_aff
*isl_pw_aff_var_on_domain(__isl_take isl_local_space
*ls
,
411 enum isl_dim_type type
, unsigned pos
)
413 return isl_pw_aff_from_aff(isl_aff_var_on_domain(ls
, type
, pos
));
416 /* Return an affine expression that is equal to the parameter
417 * in the domain space "space" with identifier "id".
419 __isl_give isl_aff
*isl_aff_param_on_domain_space_id(
420 __isl_take isl_space
*space
, __isl_take isl_id
*id
)
427 pos
= isl_space_find_dim_by_id(space
, isl_dim_param
, id
);
429 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
430 "parameter not found in space", goto error
);
432 ls
= isl_local_space_from_space(space
);
433 return isl_aff_var_on_domain(ls
, isl_dim_param
, pos
);
435 isl_space_free(space
);
440 /* This function performs the same operation as
441 * isl_aff_param_on_domain_space_id,
442 * but is considered as a function on an isl_space when exported.
444 __isl_give isl_aff
*isl_space_param_aff_on_domain_id(
445 __isl_take isl_space
*space
, __isl_take isl_id
*id
)
447 return isl_aff_param_on_domain_space_id(space
, id
);
450 __isl_null isl_aff
*isl_aff_free(__isl_take isl_aff
*aff
)
458 isl_local_space_free(aff
->ls
);
459 isl_vec_free(aff
->v
);
466 isl_ctx
*isl_aff_get_ctx(__isl_keep isl_aff
*aff
)
468 return aff
? isl_local_space_get_ctx(aff
->ls
) : NULL
;
471 /* Return a hash value that digests "aff".
473 uint32_t isl_aff_get_hash(__isl_keep isl_aff
*aff
)
475 uint32_t hash
, ls_hash
, v_hash
;
480 hash
= isl_hash_init();
481 ls_hash
= isl_local_space_get_hash(aff
->ls
);
482 isl_hash_hash(hash
, ls_hash
);
483 v_hash
= isl_vec_get_hash(aff
->v
);
484 isl_hash_hash(hash
, v_hash
);
489 /* Return the domain local space of "aff".
491 static __isl_keep isl_local_space
*isl_aff_peek_domain_local_space(
492 __isl_keep isl_aff
*aff
)
494 return aff
? aff
->ls
: NULL
;
497 /* Return the number of variables of the given type in the domain of "aff".
499 isl_size
isl_aff_domain_dim(__isl_keep isl_aff
*aff
, enum isl_dim_type type
)
503 ls
= isl_aff_peek_domain_local_space(aff
);
504 return isl_local_space_dim(ls
, type
);
507 /* Externally, an isl_aff has a map space, but internally, the
508 * ls field corresponds to the domain of that space.
510 isl_size
isl_aff_dim(__isl_keep isl_aff
*aff
, enum isl_dim_type type
)
513 return isl_size_error
;
514 if (type
== isl_dim_out
)
516 if (type
== isl_dim_in
)
518 return isl_aff_domain_dim(aff
, type
);
521 /* Return the offset of the first variable of type "type" within
522 * the variables of the domain of "aff".
524 static isl_size
isl_aff_domain_var_offset(__isl_keep isl_aff
*aff
,
525 enum isl_dim_type type
)
529 ls
= isl_aff_peek_domain_local_space(aff
);
530 return isl_local_space_var_offset(ls
, type
);
533 /* Return the offset of the first coefficient of type "type" in
534 * the domain of "aff".
536 isl_size
isl_aff_domain_offset(__isl_keep isl_aff
*aff
, enum isl_dim_type type
)
540 offset
= isl_aff_domain_var_offset(aff
, type
);
542 return isl_size_error
;
546 /* Return the position of the dimension of the given type and name
548 * Return -1 if no such dimension can be found.
550 int isl_aff_find_dim_by_name(__isl_keep isl_aff
*aff
, enum isl_dim_type type
,
555 if (type
== isl_dim_out
)
557 if (type
== isl_dim_in
)
559 return isl_local_space_find_dim_by_name(aff
->ls
, type
, name
);
562 /* Return the domain space of "aff".
564 static __isl_keep isl_space
*isl_aff_peek_domain_space(__isl_keep isl_aff
*aff
)
566 return aff
? isl_local_space_peek_space(aff
->ls
) : NULL
;
569 __isl_give isl_space
*isl_aff_get_domain_space(__isl_keep isl_aff
*aff
)
571 return isl_space_copy(isl_aff_peek_domain_space(aff
));
574 __isl_give isl_space
*isl_aff_get_space(__isl_keep isl_aff
*aff
)
579 space
= isl_local_space_get_space(aff
->ls
);
580 space
= isl_space_from_domain(space
);
581 space
= isl_space_add_dims(space
, isl_dim_out
, 1);
585 /* Return a copy of the domain space of "aff".
587 __isl_give isl_local_space
*isl_aff_get_domain_local_space(
588 __isl_keep isl_aff
*aff
)
590 return isl_local_space_copy(isl_aff_peek_domain_local_space(aff
));
593 __isl_give isl_local_space
*isl_aff_get_local_space(__isl_keep isl_aff
*aff
)
598 ls
= isl_local_space_copy(aff
->ls
);
599 ls
= isl_local_space_from_domain(ls
);
600 ls
= isl_local_space_add_dims(ls
, isl_dim_out
, 1);
604 /* Return the local space of the domain of "aff".
605 * This may be either a copy or the local space itself
606 * if there is only one reference to "aff".
607 * This allows the local space to be modified inplace
608 * if both the expression and its local space have only a single reference.
609 * The caller is not allowed to modify "aff" between this call and
610 * a subsequent call to isl_aff_restore_domain_local_space.
611 * The only exception is that isl_aff_free can be called instead.
613 __isl_give isl_local_space
*isl_aff_take_domain_local_space(
614 __isl_keep isl_aff
*aff
)
621 return isl_aff_get_domain_local_space(aff
);
627 /* Set the local space of the domain of "aff" to "ls",
628 * where the local space of "aff" may be missing
629 * due to a preceding call to isl_aff_take_domain_local_space.
630 * However, in this case, "aff" only has a single reference and
631 * then the call to isl_aff_cow has no effect.
633 __isl_give isl_aff
*isl_aff_restore_domain_local_space(
634 __isl_keep isl_aff
*aff
, __isl_take isl_local_space
*ls
)
640 isl_local_space_free(ls
);
644 aff
= isl_aff_cow(aff
);
647 isl_local_space_free(aff
->ls
);
653 isl_local_space_free(ls
);
657 /* Externally, an isl_aff has a map space, but internally, the
658 * ls field corresponds to the domain of that space.
660 const char *isl_aff_get_dim_name(__isl_keep isl_aff
*aff
,
661 enum isl_dim_type type
, unsigned pos
)
665 if (type
== isl_dim_out
)
667 if (type
== isl_dim_in
)
669 return isl_local_space_get_dim_name(aff
->ls
, type
, pos
);
672 __isl_give isl_aff
*isl_aff_reset_domain_space(__isl_take isl_aff
*aff
,
673 __isl_take isl_space
*space
)
675 aff
= isl_aff_cow(aff
);
679 aff
->ls
= isl_local_space_reset_space(aff
->ls
, space
);
681 return isl_aff_free(aff
);
686 isl_space_free(space
);
690 /* Reset the space of "aff". This function is called from isl_pw_templ.c
691 * and doesn't know if the space of an element object is represented
692 * directly or through its domain. It therefore passes along both.
694 __isl_give isl_aff
*isl_aff_reset_space_and_domain(__isl_take isl_aff
*aff
,
695 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
697 isl_space_free(space
);
698 return isl_aff_reset_domain_space(aff
, domain
);
701 /* Reorder the dimensions of the domain of "aff" according
702 * to the given reordering.
704 __isl_give isl_aff
*isl_aff_realign_domain(__isl_take isl_aff
*aff
,
705 __isl_take isl_reordering
*r
)
707 aff
= isl_aff_cow(aff
);
711 r
= isl_reordering_extend(r
, aff
->ls
->div
->n_row
);
712 aff
->v
= isl_vec_reorder(aff
->v
, 2, isl_reordering_copy(r
));
713 aff
->ls
= isl_local_space_realign(aff
->ls
, r
);
715 if (!aff
->v
|| !aff
->ls
)
716 return isl_aff_free(aff
);
721 isl_reordering_free(r
);
725 __isl_give isl_aff
*isl_aff_align_params(__isl_take isl_aff
*aff
,
726 __isl_take isl_space
*model
)
728 isl_space
*domain_space
;
729 isl_bool equal_params
;
731 domain_space
= isl_aff_peek_domain_space(aff
);
732 equal_params
= isl_space_has_equal_params(domain_space
, model
);
733 if (equal_params
< 0)
738 exp
= isl_parameter_alignment_reordering(domain_space
, model
);
739 aff
= isl_aff_realign_domain(aff
, exp
);
742 isl_space_free(model
);
745 isl_space_free(model
);
752 #include "isl_unbind_params_templ.c"
754 /* Is "aff" obviously equal to zero?
756 * If the denominator is zero, then "aff" is not equal to zero.
758 isl_bool
isl_aff_plain_is_zero(__isl_keep isl_aff
*aff
)
763 return isl_bool_error
;
765 if (isl_int_is_zero(aff
->v
->el
[0]))
766 return isl_bool_false
;
767 pos
= isl_seq_first_non_zero(aff
->v
->el
+ 1, aff
->v
->size
- 1);
768 return isl_bool_ok(pos
< 0);
771 /* Does "aff" represent NaN?
773 isl_bool
isl_aff_is_nan(__isl_keep isl_aff
*aff
)
776 return isl_bool_error
;
778 return isl_bool_ok(isl_seq_first_non_zero(aff
->v
->el
, 2) < 0);
781 /* Are "aff1" and "aff2" obviously equal?
783 * NaN is not equal to anything, not even to another NaN.
785 isl_bool
isl_aff_plain_is_equal(__isl_keep isl_aff
*aff1
,
786 __isl_keep isl_aff
*aff2
)
791 return isl_bool_error
;
793 if (isl_aff_is_nan(aff1
) || isl_aff_is_nan(aff2
))
794 return isl_bool_false
;
796 equal
= isl_local_space_is_equal(aff1
->ls
, aff2
->ls
);
797 if (equal
< 0 || !equal
)
800 return isl_vec_is_equal(aff1
->v
, aff2
->v
);
803 /* Return the common denominator of "aff" in "v".
805 * We cannot return anything meaningful in case of a NaN.
807 isl_stat
isl_aff_get_denominator(__isl_keep isl_aff
*aff
, isl_int
*v
)
810 return isl_stat_error
;
811 if (isl_aff_is_nan(aff
))
812 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
813 "cannot get denominator of NaN", return isl_stat_error
);
814 isl_int_set(*v
, aff
->v
->el
[0]);
818 /* Return the common denominator of "aff".
820 __isl_give isl_val
*isl_aff_get_denominator_val(__isl_keep isl_aff
*aff
)
827 ctx
= isl_aff_get_ctx(aff
);
828 if (isl_aff_is_nan(aff
))
829 return isl_val_nan(ctx
);
830 return isl_val_int_from_isl_int(ctx
, aff
->v
->el
[0]);
833 /* Return the constant term of "aff".
835 __isl_give isl_val
*isl_aff_get_constant_val(__isl_keep isl_aff
*aff
)
843 ctx
= isl_aff_get_ctx(aff
);
844 if (isl_aff_is_nan(aff
))
845 return isl_val_nan(ctx
);
846 v
= isl_val_rat_from_isl_int(ctx
, aff
->v
->el
[1], aff
->v
->el
[0]);
847 return isl_val_normalize(v
);
850 /* Return the coefficient of the variable of type "type" at position "pos"
853 __isl_give isl_val
*isl_aff_get_coefficient_val(__isl_keep isl_aff
*aff
,
854 enum isl_dim_type type
, int pos
)
862 ctx
= isl_aff_get_ctx(aff
);
863 if (type
== isl_dim_out
)
864 isl_die(ctx
, isl_error_invalid
,
865 "output/set dimension does not have a coefficient",
867 if (type
== isl_dim_in
)
870 if (isl_local_space_check_range(aff
->ls
, type
, pos
, 1) < 0)
873 if (isl_aff_is_nan(aff
))
874 return isl_val_nan(ctx
);
875 pos
+= isl_local_space_offset(aff
->ls
, type
);
876 v
= isl_val_rat_from_isl_int(ctx
, aff
->v
->el
[1 + pos
], aff
->v
->el
[0]);
877 return isl_val_normalize(v
);
880 /* Return the sign of the coefficient of the variable of type "type"
881 * at position "pos" of "aff".
883 int isl_aff_coefficient_sgn(__isl_keep isl_aff
*aff
, enum isl_dim_type type
,
891 ctx
= isl_aff_get_ctx(aff
);
892 if (type
== isl_dim_out
)
893 isl_die(ctx
, isl_error_invalid
,
894 "output/set dimension does not have a coefficient",
896 if (type
== isl_dim_in
)
899 if (isl_local_space_check_range(aff
->ls
, type
, pos
, 1) < 0)
902 pos
+= isl_local_space_offset(aff
->ls
, type
);
903 return isl_int_sgn(aff
->v
->el
[1 + pos
]);
906 /* Replace the numerator of the constant term of "aff" by "v".
908 * A NaN is unaffected by this operation.
910 __isl_give isl_aff
*isl_aff_set_constant(__isl_take isl_aff
*aff
, isl_int v
)
914 if (isl_aff_is_nan(aff
))
916 aff
= isl_aff_cow(aff
);
920 aff
->v
= isl_vec_cow(aff
->v
);
922 return isl_aff_free(aff
);
924 isl_int_set(aff
->v
->el
[1], v
);
929 /* Replace the constant term of "aff" by "v".
931 * A NaN is unaffected by this operation.
933 __isl_give isl_aff
*isl_aff_set_constant_val(__isl_take isl_aff
*aff
,
934 __isl_take isl_val
*v
)
939 if (isl_aff_is_nan(aff
)) {
944 if (!isl_val_is_rat(v
))
945 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
946 "expecting rational value", goto error
);
948 if (isl_int_eq(aff
->v
->el
[1], v
->n
) &&
949 isl_int_eq(aff
->v
->el
[0], v
->d
)) {
954 aff
= isl_aff_cow(aff
);
957 aff
->v
= isl_vec_cow(aff
->v
);
961 if (isl_int_eq(aff
->v
->el
[0], v
->d
)) {
962 isl_int_set(aff
->v
->el
[1], v
->n
);
963 } else if (isl_int_is_one(v
->d
)) {
964 isl_int_mul(aff
->v
->el
[1], aff
->v
->el
[0], v
->n
);
966 isl_seq_scale(aff
->v
->el
+ 1,
967 aff
->v
->el
+ 1, v
->d
, aff
->v
->size
- 1);
968 isl_int_mul(aff
->v
->el
[1], aff
->v
->el
[0], v
->n
);
969 isl_int_mul(aff
->v
->el
[0], aff
->v
->el
[0], v
->d
);
970 aff
->v
= isl_vec_normalize(aff
->v
);
983 /* Add "v" to the constant term of "aff".
985 * A NaN is unaffected by this operation.
987 __isl_give isl_aff
*isl_aff_add_constant(__isl_take isl_aff
*aff
, isl_int v
)
989 if (isl_int_is_zero(v
))
994 if (isl_aff_is_nan(aff
))
996 aff
= isl_aff_cow(aff
);
1000 aff
->v
= isl_vec_cow(aff
->v
);
1002 return isl_aff_free(aff
);
1004 isl_int_addmul(aff
->v
->el
[1], aff
->v
->el
[0], v
);
1009 /* Add "v" to the constant term of "aff",
1010 * in case "aff" is a rational expression.
1012 static __isl_give isl_aff
*isl_aff_add_rat_constant_val(__isl_take isl_aff
*aff
,
1013 __isl_take isl_val
*v
)
1015 aff
= isl_aff_cow(aff
);
1019 aff
->v
= isl_vec_cow(aff
->v
);
1023 if (isl_int_is_one(v
->d
)) {
1024 isl_int_addmul(aff
->v
->el
[1], aff
->v
->el
[0], v
->n
);
1025 } else if (isl_int_eq(aff
->v
->el
[0], v
->d
)) {
1026 isl_int_add(aff
->v
->el
[1], aff
->v
->el
[1], v
->n
);
1027 aff
->v
= isl_vec_normalize(aff
->v
);
1031 isl_seq_scale(aff
->v
->el
+ 1,
1032 aff
->v
->el
+ 1, v
->d
, aff
->v
->size
- 1);
1033 isl_int_addmul(aff
->v
->el
[1], aff
->v
->el
[0], v
->n
);
1034 isl_int_mul(aff
->v
->el
[0], aff
->v
->el
[0], v
->d
);
1035 aff
->v
= isl_vec_normalize(aff
->v
);
1048 /* Return the first argument and free the second.
1050 static __isl_give isl_aff
*pick_free(__isl_take isl_aff
*aff
,
1051 __isl_take isl_val
*v
)
1057 /* Replace the first argument by NaN and free the second argument.
1059 static __isl_give isl_aff
*set_nan_free_val(__isl_take isl_aff
*aff
,
1060 __isl_take isl_val
*v
)
1063 return isl_aff_set_nan(aff
);
1066 /* Add "v" to the constant term of "aff".
1068 * A NaN is unaffected by this operation.
1069 * Conversely, adding a NaN turns "aff" into a NaN.
1071 __isl_give isl_aff
*isl_aff_add_constant_val(__isl_take isl_aff
*aff
,
1072 __isl_take isl_val
*v
)
1074 isl_bool is_nan
, is_zero
, is_rat
;
1076 is_nan
= isl_aff_is_nan(aff
);
1077 is_zero
= isl_val_is_zero(v
);
1078 if (is_nan
< 0 || is_zero
< 0)
1080 if (is_nan
|| is_zero
)
1081 return pick_free(aff
, v
);
1083 is_nan
= isl_val_is_nan(v
);
1084 is_rat
= isl_val_is_rat(v
);
1085 if (is_nan
< 0 || is_rat
< 0)
1088 return set_nan_free_val(aff
, v
);
1090 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
1091 "expecting rational value or NaN", goto error
);
1093 return isl_aff_add_rat_constant_val(aff
, v
);
1100 __isl_give isl_aff
*isl_aff_add_constant_si(__isl_take isl_aff
*aff
, int v
)
1105 isl_int_set_si(t
, v
);
1106 aff
= isl_aff_add_constant(aff
, t
);
1112 /* Add "v" to the numerator of the constant term of "aff".
1114 * A NaN is unaffected by this operation.
1116 __isl_give isl_aff
*isl_aff_add_constant_num(__isl_take isl_aff
*aff
, isl_int v
)
1118 if (isl_int_is_zero(v
))
1123 if (isl_aff_is_nan(aff
))
1125 aff
= isl_aff_cow(aff
);
1129 aff
->v
= isl_vec_cow(aff
->v
);
1131 return isl_aff_free(aff
);
1133 isl_int_add(aff
->v
->el
[1], aff
->v
->el
[1], v
);
1138 /* Add "v" to the numerator of the constant term of "aff".
1140 * A NaN is unaffected by this operation.
1142 __isl_give isl_aff
*isl_aff_add_constant_num_si(__isl_take isl_aff
*aff
, int v
)
1150 isl_int_set_si(t
, v
);
1151 aff
= isl_aff_add_constant_num(aff
, t
);
1157 /* Replace the numerator of the constant term of "aff" by "v".
1159 * A NaN is unaffected by this operation.
1161 __isl_give isl_aff
*isl_aff_set_constant_si(__isl_take isl_aff
*aff
, int v
)
1165 if (isl_aff_is_nan(aff
))
1167 aff
= isl_aff_cow(aff
);
1171 aff
->v
= isl_vec_cow(aff
->v
);
1173 return isl_aff_free(aff
);
1175 isl_int_set_si(aff
->v
->el
[1], v
);
1180 /* Replace the numerator of the coefficient of the variable of type "type"
1181 * at position "pos" of "aff" by "v".
1183 * A NaN is unaffected by this operation.
1185 __isl_give isl_aff
*isl_aff_set_coefficient(__isl_take isl_aff
*aff
,
1186 enum isl_dim_type type
, int pos
, isl_int v
)
1191 if (type
== isl_dim_out
)
1192 isl_die(aff
->v
->ctx
, isl_error_invalid
,
1193 "output/set dimension does not have a coefficient",
1194 return isl_aff_free(aff
));
1195 if (type
== isl_dim_in
)
1198 if (isl_local_space_check_range(aff
->ls
, type
, pos
, 1) < 0)
1199 return isl_aff_free(aff
);
1201 if (isl_aff_is_nan(aff
))
1203 aff
= isl_aff_cow(aff
);
1207 aff
->v
= isl_vec_cow(aff
->v
);
1209 return isl_aff_free(aff
);
1211 pos
+= isl_local_space_offset(aff
->ls
, type
);
1212 isl_int_set(aff
->v
->el
[1 + pos
], v
);
1217 /* Replace the numerator of the coefficient of the variable of type "type"
1218 * at position "pos" of "aff" by "v".
1220 * A NaN is unaffected by this operation.
1222 __isl_give isl_aff
*isl_aff_set_coefficient_si(__isl_take isl_aff
*aff
,
1223 enum isl_dim_type type
, int pos
, int v
)
1228 if (type
== isl_dim_out
)
1229 isl_die(aff
->v
->ctx
, isl_error_invalid
,
1230 "output/set dimension does not have a coefficient",
1231 return isl_aff_free(aff
));
1232 if (type
== isl_dim_in
)
1235 if (isl_local_space_check_range(aff
->ls
, type
, pos
, 1) < 0)
1236 return isl_aff_free(aff
);
1238 if (isl_aff_is_nan(aff
))
1240 pos
+= isl_local_space_offset(aff
->ls
, type
);
1241 if (isl_int_cmp_si(aff
->v
->el
[1 + pos
], v
) == 0)
1244 aff
= isl_aff_cow(aff
);
1248 aff
->v
= isl_vec_cow(aff
->v
);
1250 return isl_aff_free(aff
);
1252 isl_int_set_si(aff
->v
->el
[1 + pos
], v
);
1257 /* Replace the coefficient of the variable of type "type" at position "pos"
1260 * A NaN is unaffected by this operation.
1262 __isl_give isl_aff
*isl_aff_set_coefficient_val(__isl_take isl_aff
*aff
,
1263 enum isl_dim_type type
, int pos
, __isl_take isl_val
*v
)
1268 if (type
== isl_dim_out
)
1269 isl_die(aff
->v
->ctx
, isl_error_invalid
,
1270 "output/set dimension does not have a coefficient",
1272 if (type
== isl_dim_in
)
1275 if (isl_local_space_check_range(aff
->ls
, type
, pos
, 1) < 0)
1276 return isl_aff_free(aff
);
1278 if (isl_aff_is_nan(aff
)) {
1282 if (!isl_val_is_rat(v
))
1283 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
1284 "expecting rational value", goto error
);
1286 pos
+= isl_local_space_offset(aff
->ls
, type
);
1287 if (isl_int_eq(aff
->v
->el
[1 + pos
], v
->n
) &&
1288 isl_int_eq(aff
->v
->el
[0], v
->d
)) {
1293 aff
= isl_aff_cow(aff
);
1296 aff
->v
= isl_vec_cow(aff
->v
);
1300 if (isl_int_eq(aff
->v
->el
[0], v
->d
)) {
1301 isl_int_set(aff
->v
->el
[1 + pos
], v
->n
);
1302 } else if (isl_int_is_one(v
->d
)) {
1303 isl_int_mul(aff
->v
->el
[1 + pos
], aff
->v
->el
[0], v
->n
);
1305 isl_seq_scale(aff
->v
->el
+ 1,
1306 aff
->v
->el
+ 1, v
->d
, aff
->v
->size
- 1);
1307 isl_int_mul(aff
->v
->el
[1 + pos
], aff
->v
->el
[0], v
->n
);
1308 isl_int_mul(aff
->v
->el
[0], aff
->v
->el
[0], v
->d
);
1309 aff
->v
= isl_vec_normalize(aff
->v
);
1322 /* Add "v" to the coefficient of the variable of type "type"
1323 * at position "pos" of "aff".
1325 * A NaN is unaffected by this operation.
1327 __isl_give isl_aff
*isl_aff_add_coefficient(__isl_take isl_aff
*aff
,
1328 enum isl_dim_type type
, int pos
, isl_int v
)
1333 if (type
== isl_dim_out
)
1334 isl_die(aff
->v
->ctx
, isl_error_invalid
,
1335 "output/set dimension does not have a coefficient",
1336 return isl_aff_free(aff
));
1337 if (type
== isl_dim_in
)
1340 if (isl_local_space_check_range(aff
->ls
, type
, pos
, 1) < 0)
1341 return isl_aff_free(aff
);
1343 if (isl_aff_is_nan(aff
))
1345 aff
= isl_aff_cow(aff
);
1349 aff
->v
= isl_vec_cow(aff
->v
);
1351 return isl_aff_free(aff
);
1353 pos
+= isl_local_space_offset(aff
->ls
, type
);
1354 isl_int_addmul(aff
->v
->el
[1 + pos
], aff
->v
->el
[0], v
);
1359 /* Add "v" to the coefficient of the variable of type "type"
1360 * at position "pos" of "aff".
1362 * A NaN is unaffected by this operation.
1364 __isl_give isl_aff
*isl_aff_add_coefficient_val(__isl_take isl_aff
*aff
,
1365 enum isl_dim_type type
, int pos
, __isl_take isl_val
*v
)
1370 if (isl_val_is_zero(v
)) {
1375 if (type
== isl_dim_out
)
1376 isl_die(aff
->v
->ctx
, isl_error_invalid
,
1377 "output/set dimension does not have a coefficient",
1379 if (type
== isl_dim_in
)
1382 if (isl_local_space_check_range(aff
->ls
, type
, pos
, 1) < 0)
1385 if (isl_aff_is_nan(aff
)) {
1389 if (!isl_val_is_rat(v
))
1390 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
1391 "expecting rational value", goto error
);
1393 aff
= isl_aff_cow(aff
);
1397 aff
->v
= isl_vec_cow(aff
->v
);
1401 pos
+= isl_local_space_offset(aff
->ls
, type
);
1402 if (isl_int_is_one(v
->d
)) {
1403 isl_int_addmul(aff
->v
->el
[1 + pos
], aff
->v
->el
[0], v
->n
);
1404 } else if (isl_int_eq(aff
->v
->el
[0], v
->d
)) {
1405 isl_int_add(aff
->v
->el
[1 + pos
], aff
->v
->el
[1 + pos
], v
->n
);
1406 aff
->v
= isl_vec_normalize(aff
->v
);
1410 isl_seq_scale(aff
->v
->el
+ 1,
1411 aff
->v
->el
+ 1, v
->d
, aff
->v
->size
- 1);
1412 isl_int_addmul(aff
->v
->el
[1 + pos
], aff
->v
->el
[0], v
->n
);
1413 isl_int_mul(aff
->v
->el
[0], aff
->v
->el
[0], v
->d
);
1414 aff
->v
= isl_vec_normalize(aff
->v
);
1427 __isl_give isl_aff
*isl_aff_add_coefficient_si(__isl_take isl_aff
*aff
,
1428 enum isl_dim_type type
, int pos
, int v
)
1433 isl_int_set_si(t
, v
);
1434 aff
= isl_aff_add_coefficient(aff
, type
, pos
, t
);
1440 __isl_give isl_aff
*isl_aff_get_div(__isl_keep isl_aff
*aff
, int pos
)
1445 return isl_local_space_get_div(aff
->ls
, pos
);
1448 /* Return the negation of "aff".
1450 * As a special case, -NaN = NaN.
1452 __isl_give isl_aff
*isl_aff_neg(__isl_take isl_aff
*aff
)
1456 if (isl_aff_is_nan(aff
))
1458 aff
= isl_aff_cow(aff
);
1461 aff
->v
= isl_vec_cow(aff
->v
);
1463 return isl_aff_free(aff
);
1465 isl_seq_neg(aff
->v
->el
+ 1, aff
->v
->el
+ 1, aff
->v
->size
- 1);
1470 /* Remove divs from the local space that do not appear in the affine
1473 * First remove any unused local variables at the end.
1474 * Then look for other unused local variables. These need some extra care
1475 * because a local variable that does not appear in the affine expression
1476 * may still appear in the definition of some later local variable.
1478 __isl_give isl_aff
*isl_aff_remove_unused_divs(__isl_take isl_aff
*aff
)
1484 isl_local_space
*ls
;
1486 n
= isl_aff_domain_dim(aff
, isl_dim_div
);
1487 v_div
= isl_aff_domain_var_offset(aff
, isl_dim_div
);
1488 if (n
< 0 || v_div
< 0)
1489 return isl_aff_free(aff
);
1491 pos
= isl_seq_last_non_zero(aff
->v
->el
+ 1 + 1 + v_div
, n
) + 1;
1493 aff
= isl_aff_drop_dims(aff
, isl_dim_div
, pos
, n
- pos
);
1494 if (pos
<= 1 || !aff
)
1497 ls
= isl_aff_peek_domain_local_space(aff
);
1498 active
= isl_local_space_get_active(ls
, aff
->v
->el
+ 2);
1500 return isl_aff_free(aff
);
1501 for (pos
= pos
- 2; pos
>= 0; pos
--) {
1502 if (active
[v_div
+ pos
])
1504 aff
= isl_aff_drop_dims(aff
, isl_dim_div
, pos
, 1);
1511 /* Look for any divs in the aff->ls with a denominator equal to one
1512 * and plug them into the affine expression and any subsequent divs
1513 * that may reference the div.
1515 static __isl_give isl_aff
*plug_in_integral_divs(__isl_take isl_aff
*aff
)
1522 isl_local_space
*ls
;
1525 n
= isl_aff_domain_dim(aff
, isl_dim_div
);
1526 off
= isl_aff_domain_offset(aff
, isl_dim_div
);
1527 if (n
< 0 || off
< 0)
1528 return isl_aff_free(aff
);
1530 for (i
= 0; i
< n
; ++i
) {
1531 if (!isl_int_is_one(aff
->ls
->div
->row
[i
][0]))
1533 ls
= isl_local_space_copy(aff
->ls
);
1534 ls
= isl_local_space_substitute_seq(ls
, isl_dim_div
, i
,
1535 aff
->ls
->div
->row
[i
], len
, i
+ 1, n
- (i
+ 1));
1536 vec
= isl_vec_copy(aff
->v
);
1537 vec
= isl_vec_cow(vec
);
1543 isl_seq_substitute(vec
->el
, off
+ i
, aff
->ls
->div
->row
[i
],
1548 isl_vec_free(aff
->v
);
1550 isl_local_space_free(aff
->ls
);
1557 isl_local_space_free(ls
);
1558 return isl_aff_free(aff
);
1561 /* Look for any divs j that appear with a unit coefficient inside
1562 * the definitions of other divs i and plug them into the definitions
1565 * In particular, an expression of the form
1567 * floor((f(..) + floor(g(..)/n))/m)
1571 * floor((n * f(..) + g(..))/(n * m))
1573 * This simplification is correct because we can move the expression
1574 * f(..) into the inner floor in the original expression to obtain
1576 * floor(floor((n * f(..) + g(..))/n)/m)
1578 * from which we can derive the simplified expression.
1580 static __isl_give isl_aff
*plug_in_unit_divs(__isl_take isl_aff
*aff
)
1586 n
= isl_aff_domain_dim(aff
, isl_dim_div
);
1587 off
= isl_aff_domain_offset(aff
, isl_dim_div
);
1588 if (n
< 0 || off
< 0)
1589 return isl_aff_free(aff
);
1590 for (i
= 1; i
< n
; ++i
) {
1591 for (j
= 0; j
< i
; ++j
) {
1592 if (!isl_int_is_one(aff
->ls
->div
->row
[i
][1 + off
+ j
]))
1594 aff
->ls
= isl_local_space_substitute_seq(aff
->ls
,
1595 isl_dim_div
, j
, aff
->ls
->div
->row
[j
],
1596 aff
->v
->size
, i
, 1);
1598 return isl_aff_free(aff
);
1605 /* Swap divs "a" and "b" in "aff", which is assumed to be non-NULL.
1607 * Even though this function is only called on isl_affs with a single
1608 * reference, we are careful to only change aff->v and aff->ls together.
1610 static __isl_give isl_aff
*swap_div(__isl_take isl_aff
*aff
, int a
, int b
)
1612 isl_size off
= isl_aff_domain_offset(aff
, isl_dim_div
);
1613 isl_local_space
*ls
;
1617 return isl_aff_free(aff
);
1619 ls
= isl_local_space_copy(aff
->ls
);
1620 ls
= isl_local_space_swap_div(ls
, a
, b
);
1621 v
= isl_vec_copy(aff
->v
);
1626 isl_int_swap(v
->el
[1 + off
+ a
], v
->el
[1 + off
+ b
]);
1627 isl_vec_free(aff
->v
);
1629 isl_local_space_free(aff
->ls
);
1635 isl_local_space_free(ls
);
1636 return isl_aff_free(aff
);
1639 /* Merge divs "a" and "b" in "aff", which is assumed to be non-NULL.
1641 * We currently do not actually remove div "b", but simply add its
1642 * coefficient to that of "a" and then zero it out.
1644 static __isl_give isl_aff
*merge_divs(__isl_take isl_aff
*aff
, int a
, int b
)
1646 isl_size off
= isl_aff_domain_offset(aff
, isl_dim_div
);
1649 return isl_aff_free(aff
);
1651 if (isl_int_is_zero(aff
->v
->el
[1 + off
+ b
]))
1654 aff
->v
= isl_vec_cow(aff
->v
);
1656 return isl_aff_free(aff
);
1658 isl_int_add(aff
->v
->el
[1 + off
+ a
],
1659 aff
->v
->el
[1 + off
+ a
], aff
->v
->el
[1 + off
+ b
]);
1660 isl_int_set_si(aff
->v
->el
[1 + off
+ b
], 0);
1665 /* Sort the divs in the local space of "aff" according to
1666 * the comparison function "cmp_row" in isl_local_space.c,
1667 * combining the coefficients of identical divs.
1669 * Reordering divs does not change the semantics of "aff",
1670 * so there is no need to call isl_aff_cow.
1671 * Moreover, this function is currently only called on isl_affs
1672 * with a single reference.
1674 static __isl_give isl_aff
*sort_divs(__isl_take isl_aff
*aff
)
1679 n
= isl_aff_dim(aff
, isl_dim_div
);
1681 return isl_aff_free(aff
);
1682 for (i
= 1; i
< n
; ++i
) {
1683 for (j
= i
- 1; j
>= 0; --j
) {
1684 int cmp
= isl_mat_cmp_div(aff
->ls
->div
, j
, j
+ 1);
1688 aff
= merge_divs(aff
, j
, j
+ 1);
1690 aff
= swap_div(aff
, j
, j
+ 1);
1699 /* Normalize the representation of "aff".
1701 * This function should only be called on "new" isl_affs, i.e.,
1702 * with only a single reference. We therefore do not need to
1703 * worry about affecting other instances.
1705 __isl_give isl_aff
*isl_aff_normalize(__isl_take isl_aff
*aff
)
1709 aff
->v
= isl_vec_normalize(aff
->v
);
1711 return isl_aff_free(aff
);
1712 aff
= plug_in_integral_divs(aff
);
1713 aff
= plug_in_unit_divs(aff
);
1714 aff
= sort_divs(aff
);
1715 aff
= isl_aff_remove_unused_divs(aff
);
1719 /* Given f, return floor(f).
1720 * If f is an integer expression, then just return f.
1721 * If f is a constant, then return the constant floor(f).
1722 * Otherwise, if f = g/m, write g = q m + r,
1723 * create a new div d = [r/m] and return the expression q + d.
1724 * The coefficients in r are taken to lie between -m/2 and m/2.
1726 * reduce_div_coefficients performs the same normalization.
1728 * As a special case, floor(NaN) = NaN.
1730 __isl_give isl_aff
*isl_aff_floor(__isl_take isl_aff
*aff
)
1740 if (isl_aff_is_nan(aff
))
1742 if (isl_int_is_one(aff
->v
->el
[0]))
1745 aff
= isl_aff_cow(aff
);
1749 aff
->v
= isl_vec_cow(aff
->v
);
1751 return isl_aff_free(aff
);
1753 if (isl_aff_is_cst(aff
)) {
1754 isl_int_fdiv_q(aff
->v
->el
[1], aff
->v
->el
[1], aff
->v
->el
[0]);
1755 isl_int_set_si(aff
->v
->el
[0], 1);
1759 div
= isl_vec_copy(aff
->v
);
1760 div
= isl_vec_cow(div
);
1762 return isl_aff_free(aff
);
1764 ctx
= isl_aff_get_ctx(aff
);
1765 isl_int_fdiv_q(aff
->v
->el
[0], aff
->v
->el
[0], ctx
->two
);
1766 for (i
= 1; i
< aff
->v
->size
; ++i
) {
1767 isl_int_fdiv_r(div
->el
[i
], div
->el
[i
], div
->el
[0]);
1768 isl_int_fdiv_q(aff
->v
->el
[i
], aff
->v
->el
[i
], div
->el
[0]);
1769 if (isl_int_gt(div
->el
[i
], aff
->v
->el
[0])) {
1770 isl_int_sub(div
->el
[i
], div
->el
[i
], div
->el
[0]);
1771 isl_int_add_ui(aff
->v
->el
[i
], aff
->v
->el
[i
], 1);
1775 aff
->ls
= isl_local_space_add_div(aff
->ls
, div
);
1777 return isl_aff_free(aff
);
1779 size
= aff
->v
->size
;
1780 aff
->v
= isl_vec_extend(aff
->v
, size
+ 1);
1782 return isl_aff_free(aff
);
1783 isl_int_set_si(aff
->v
->el
[0], 1);
1784 isl_int_set_si(aff
->v
->el
[size
], 1);
1786 aff
= isl_aff_normalize(aff
);
1793 * aff mod m = aff - m * floor(aff/m)
1795 * with m an integer value.
1797 __isl_give isl_aff
*isl_aff_mod_val(__isl_take isl_aff
*aff
,
1798 __isl_take isl_val
*m
)
1805 if (!isl_val_is_int(m
))
1806 isl_die(isl_val_get_ctx(m
), isl_error_invalid
,
1807 "expecting integer modulo", goto error
);
1809 res
= isl_aff_copy(aff
);
1810 aff
= isl_aff_scale_down_val(aff
, isl_val_copy(m
));
1811 aff
= isl_aff_floor(aff
);
1812 aff
= isl_aff_scale_val(aff
, m
);
1813 res
= isl_aff_sub(res
, aff
);
1824 * pwaff mod m = pwaff - m * floor(pwaff/m)
1826 __isl_give isl_pw_aff
*isl_pw_aff_mod(__isl_take isl_pw_aff
*pwaff
, isl_int m
)
1830 res
= isl_pw_aff_copy(pwaff
);
1831 pwaff
= isl_pw_aff_scale_down(pwaff
, m
);
1832 pwaff
= isl_pw_aff_floor(pwaff
);
1833 pwaff
= isl_pw_aff_scale(pwaff
, m
);
1834 res
= isl_pw_aff_sub(res
, pwaff
);
1841 * pa mod m = pa - m * floor(pa/m)
1843 * with m an integer value.
1845 __isl_give isl_pw_aff
*isl_pw_aff_mod_val(__isl_take isl_pw_aff
*pa
,
1846 __isl_take isl_val
*m
)
1850 if (!isl_val_is_int(m
))
1851 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
1852 "expecting integer modulo", goto error
);
1853 pa
= isl_pw_aff_mod(pa
, m
->n
);
1857 isl_pw_aff_free(pa
);
1862 /* Given f, return ceil(f).
1863 * If f is an integer expression, then just return f.
1864 * Otherwise, let f be the expression
1870 * floor((e + m - 1)/m)
1872 * As a special case, ceil(NaN) = NaN.
1874 __isl_give isl_aff
*isl_aff_ceil(__isl_take isl_aff
*aff
)
1879 if (isl_aff_is_nan(aff
))
1881 if (isl_int_is_one(aff
->v
->el
[0]))
1884 aff
= isl_aff_cow(aff
);
1887 aff
->v
= isl_vec_cow(aff
->v
);
1889 return isl_aff_free(aff
);
1891 isl_int_add(aff
->v
->el
[1], aff
->v
->el
[1], aff
->v
->el
[0]);
1892 isl_int_sub_ui(aff
->v
->el
[1], aff
->v
->el
[1], 1);
1893 aff
= isl_aff_floor(aff
);
1898 /* Apply the expansion computed by isl_merge_divs.
1899 * The expansion itself is given by "exp" while the resulting
1900 * list of divs is given by "div".
1902 __isl_give isl_aff
*isl_aff_expand_divs(__isl_take isl_aff
*aff
,
1903 __isl_take isl_mat
*div
, int *exp
)
1909 aff
= isl_aff_cow(aff
);
1911 offset
= isl_aff_domain_offset(aff
, isl_dim_div
);
1912 old_n_div
= isl_aff_domain_dim(aff
, isl_dim_div
);
1913 new_n_div
= isl_mat_rows(div
);
1914 if (offset
< 0 || old_n_div
< 0 || new_n_div
< 0)
1917 aff
->v
= isl_vec_expand(aff
->v
, 1 + offset
, old_n_div
, exp
, new_n_div
);
1918 aff
->ls
= isl_local_space_replace_divs(aff
->ls
, div
);
1919 if (!aff
->v
|| !aff
->ls
)
1920 return isl_aff_free(aff
);
1928 /* Add two affine expressions that live in the same local space.
1930 static __isl_give isl_aff
*add_expanded(__isl_take isl_aff
*aff1
,
1931 __isl_take isl_aff
*aff2
)
1935 aff1
= isl_aff_cow(aff1
);
1939 aff1
->v
= isl_vec_cow(aff1
->v
);
1945 isl_int_gcd(gcd
, aff1
->v
->el
[0], aff2
->v
->el
[0]);
1946 isl_int_divexact(f
, aff2
->v
->el
[0], gcd
);
1947 isl_seq_scale(aff1
->v
->el
+ 1, aff1
->v
->el
+ 1, f
, aff1
->v
->size
- 1);
1948 isl_int_divexact(f
, aff1
->v
->el
[0], gcd
);
1949 isl_seq_addmul(aff1
->v
->el
+ 1, f
, aff2
->v
->el
+ 1, aff1
->v
->size
- 1);
1950 isl_int_divexact(f
, aff2
->v
->el
[0], gcd
);
1951 isl_int_mul(aff1
->v
->el
[0], aff1
->v
->el
[0], f
);
1956 aff1
= isl_aff_normalize(aff1
);
1964 /* Replace one of the arguments by a NaN and free the other one.
1966 static __isl_give isl_aff
*set_nan_free(__isl_take isl_aff
*aff1
,
1967 __isl_take isl_aff
*aff2
)
1970 return isl_aff_set_nan(aff1
);
1973 /* Return the sum of "aff1" and "aff2".
1975 * If either of the two is NaN, then the result is NaN.
1977 __isl_give isl_aff
*isl_aff_add(__isl_take isl_aff
*aff1
,
1978 __isl_take isl_aff
*aff2
)
1984 isl_size n_div1
, n_div2
;
1989 ctx
= isl_aff_get_ctx(aff1
);
1990 if (!isl_space_is_equal(aff1
->ls
->dim
, aff2
->ls
->dim
))
1991 isl_die(ctx
, isl_error_invalid
,
1992 "spaces don't match", goto error
);
1994 if (isl_aff_is_nan(aff1
)) {
1998 if (isl_aff_is_nan(aff2
)) {
2003 n_div1
= isl_aff_dim(aff1
, isl_dim_div
);
2004 n_div2
= isl_aff_dim(aff2
, isl_dim_div
);
2005 if (n_div1
< 0 || n_div2
< 0)
2007 if (n_div1
== 0 && n_div2
== 0)
2008 return add_expanded(aff1
, aff2
);
2010 exp1
= isl_alloc_array(ctx
, int, n_div1
);
2011 exp2
= isl_alloc_array(ctx
, int, n_div2
);
2012 if ((n_div1
&& !exp1
) || (n_div2
&& !exp2
))
2015 div
= isl_merge_divs(aff1
->ls
->div
, aff2
->ls
->div
, exp1
, exp2
);
2016 aff1
= isl_aff_expand_divs(aff1
, isl_mat_copy(div
), exp1
);
2017 aff2
= isl_aff_expand_divs(aff2
, div
, exp2
);
2021 return add_expanded(aff1
, aff2
);
2030 __isl_give isl_aff
*isl_aff_sub(__isl_take isl_aff
*aff1
,
2031 __isl_take isl_aff
*aff2
)
2033 return isl_aff_add(aff1
, isl_aff_neg(aff2
));
2036 /* Return the result of scaling "aff" by a factor of "f".
2038 * As a special case, f * NaN = NaN.
2040 __isl_give isl_aff
*isl_aff_scale(__isl_take isl_aff
*aff
, isl_int f
)
2046 if (isl_aff_is_nan(aff
))
2049 if (isl_int_is_one(f
))
2052 aff
= isl_aff_cow(aff
);
2055 aff
->v
= isl_vec_cow(aff
->v
);
2057 return isl_aff_free(aff
);
2059 if (isl_int_is_pos(f
) && isl_int_is_divisible_by(aff
->v
->el
[0], f
)) {
2060 isl_int_divexact(aff
->v
->el
[0], aff
->v
->el
[0], f
);
2065 isl_int_gcd(gcd
, aff
->v
->el
[0], f
);
2066 isl_int_divexact(aff
->v
->el
[0], aff
->v
->el
[0], gcd
);
2067 isl_int_divexact(gcd
, f
, gcd
);
2068 isl_seq_scale(aff
->v
->el
+ 1, aff
->v
->el
+ 1, gcd
, aff
->v
->size
- 1);
2074 /* Multiple "aff" by "v".
2076 __isl_give isl_aff
*isl_aff_scale_val(__isl_take isl_aff
*aff
,
2077 __isl_take isl_val
*v
)
2082 if (isl_val_is_one(v
)) {
2087 if (!isl_val_is_rat(v
))
2088 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
2089 "expecting rational factor", goto error
);
2091 aff
= isl_aff_scale(aff
, v
->n
);
2092 aff
= isl_aff_scale_down(aff
, v
->d
);
2102 /* Return the result of scaling "aff" down by a factor of "f".
2104 * As a special case, NaN/f = NaN.
2106 __isl_give isl_aff
*isl_aff_scale_down(__isl_take isl_aff
*aff
, isl_int f
)
2112 if (isl_aff_is_nan(aff
))
2115 if (isl_int_is_one(f
))
2118 aff
= isl_aff_cow(aff
);
2122 if (isl_int_is_zero(f
))
2123 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
2124 "cannot scale down by zero", return isl_aff_free(aff
));
2126 aff
->v
= isl_vec_cow(aff
->v
);
2128 return isl_aff_free(aff
);
2131 isl_seq_gcd(aff
->v
->el
+ 1, aff
->v
->size
- 1, &gcd
);
2132 isl_int_gcd(gcd
, gcd
, f
);
2133 isl_seq_scale_down(aff
->v
->el
+ 1, aff
->v
->el
+ 1, gcd
, aff
->v
->size
- 1);
2134 isl_int_divexact(gcd
, f
, gcd
);
2135 isl_int_mul(aff
->v
->el
[0], aff
->v
->el
[0], gcd
);
2141 /* Divide "aff" by "v".
2143 __isl_give isl_aff
*isl_aff_scale_down_val(__isl_take isl_aff
*aff
,
2144 __isl_take isl_val
*v
)
2149 if (isl_val_is_one(v
)) {
2154 if (!isl_val_is_rat(v
))
2155 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
2156 "expecting rational factor", goto error
);
2157 if (!isl_val_is_pos(v
))
2158 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
2159 "factor needs to be positive", goto error
);
2161 aff
= isl_aff_scale(aff
, v
->d
);
2162 aff
= isl_aff_scale_down(aff
, v
->n
);
2172 __isl_give isl_aff
*isl_aff_scale_down_ui(__isl_take isl_aff
*aff
, unsigned f
)
2180 isl_int_set_ui(v
, f
);
2181 aff
= isl_aff_scale_down(aff
, v
);
2187 __isl_give isl_aff
*isl_aff_set_dim_name(__isl_take isl_aff
*aff
,
2188 enum isl_dim_type type
, unsigned pos
, const char *s
)
2190 aff
= isl_aff_cow(aff
);
2193 if (type
== isl_dim_out
)
2194 isl_die(aff
->v
->ctx
, isl_error_invalid
,
2195 "cannot set name of output/set dimension",
2196 return isl_aff_free(aff
));
2197 if (type
== isl_dim_in
)
2199 aff
->ls
= isl_local_space_set_dim_name(aff
->ls
, type
, pos
, s
);
2201 return isl_aff_free(aff
);
2206 __isl_give isl_aff
*isl_aff_set_dim_id(__isl_take isl_aff
*aff
,
2207 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
2209 aff
= isl_aff_cow(aff
);
2212 if (type
== isl_dim_out
)
2213 isl_die(aff
->v
->ctx
, isl_error_invalid
,
2214 "cannot set name of output/set dimension",
2216 if (type
== isl_dim_in
)
2218 aff
->ls
= isl_local_space_set_dim_id(aff
->ls
, type
, pos
, id
);
2220 return isl_aff_free(aff
);
2229 /* Replace the identifier of the input tuple of "aff" by "id".
2230 * type is currently required to be equal to isl_dim_in
2232 __isl_give isl_aff
*isl_aff_set_tuple_id(__isl_take isl_aff
*aff
,
2233 enum isl_dim_type type
, __isl_take isl_id
*id
)
2235 aff
= isl_aff_cow(aff
);
2238 if (type
!= isl_dim_in
)
2239 isl_die(aff
->v
->ctx
, isl_error_invalid
,
2240 "cannot only set id of input tuple", goto error
);
2241 aff
->ls
= isl_local_space_set_tuple_id(aff
->ls
, isl_dim_set
, id
);
2243 return isl_aff_free(aff
);
2252 /* Exploit the equalities in "eq" to simplify the affine expression
2253 * and the expressions of the integer divisions in the local space.
2254 * The integer divisions in this local space are assumed to appear
2255 * as regular dimensions in "eq".
2257 static __isl_give isl_aff
*isl_aff_substitute_equalities_lifted(
2258 __isl_take isl_aff
*aff
, __isl_take isl_basic_set
*eq
)
2266 if (eq
->n_eq
== 0) {
2267 isl_basic_set_free(eq
);
2271 aff
= isl_aff_cow(aff
);
2275 aff
->ls
= isl_local_space_substitute_equalities(aff
->ls
,
2276 isl_basic_set_copy(eq
));
2277 aff
->v
= isl_vec_cow(aff
->v
);
2278 if (!aff
->ls
|| !aff
->v
)
2281 o_div
= isl_basic_set_offset(eq
, isl_dim_div
);
2283 for (i
= 0; i
< eq
->n_eq
; ++i
) {
2284 j
= isl_seq_last_non_zero(eq
->eq
[i
], o_div
+ n_div
);
2285 if (j
< 0 || j
== 0 || j
>= o_div
)
2288 isl_seq_elim(aff
->v
->el
+ 1, eq
->eq
[i
], j
, o_div
,
2292 isl_basic_set_free(eq
);
2293 aff
= isl_aff_normalize(aff
);
2296 isl_basic_set_free(eq
);
2301 /* Exploit the equalities in "eq" to simplify the affine expression
2302 * and the expressions of the integer divisions in the local space.
2304 __isl_give isl_aff
*isl_aff_substitute_equalities(__isl_take isl_aff
*aff
,
2305 __isl_take isl_basic_set
*eq
)
2309 n_div
= isl_aff_domain_dim(aff
, isl_dim_div
);
2313 eq
= isl_basic_set_add_dims(eq
, isl_dim_set
, n_div
);
2314 return isl_aff_substitute_equalities_lifted(aff
, eq
);
2316 isl_basic_set_free(eq
);
2321 /* Look for equalities among the variables shared by context and aff
2322 * and the integer divisions of aff, if any.
2323 * The equalities are then used to eliminate coefficients and/or integer
2324 * divisions from aff.
2326 __isl_give isl_aff
*isl_aff_gist(__isl_take isl_aff
*aff
,
2327 __isl_take isl_set
*context
)
2329 isl_local_space
*ls
;
2330 isl_basic_set
*hull
;
2332 ls
= isl_aff_get_domain_local_space(aff
);
2333 context
= isl_local_space_lift_set(ls
, context
);
2335 hull
= isl_set_affine_hull(context
);
2336 return isl_aff_substitute_equalities_lifted(aff
, hull
);
2339 __isl_give isl_aff
*isl_aff_gist_params(__isl_take isl_aff
*aff
,
2340 __isl_take isl_set
*context
)
2342 isl_set
*dom_context
= isl_set_universe(isl_aff_get_domain_space(aff
));
2343 dom_context
= isl_set_intersect_params(dom_context
, context
);
2344 return isl_aff_gist(aff
, dom_context
);
2347 /* Return a basic set containing those elements in the space
2348 * of aff where it is positive. "rational" should not be set.
2350 * If "aff" is NaN, then it is not positive.
2352 static __isl_give isl_basic_set
*aff_pos_basic_set(__isl_take isl_aff
*aff
,
2353 int rational
, void *user
)
2355 isl_constraint
*ineq
;
2356 isl_basic_set
*bset
;
2361 if (isl_aff_is_nan(aff
)) {
2362 isl_space
*space
= isl_aff_get_domain_space(aff
);
2364 return isl_basic_set_empty(space
);
2367 isl_die(isl_aff_get_ctx(aff
), isl_error_unsupported
,
2368 "rational sets not supported", goto error
);
2370 ineq
= isl_inequality_from_aff(aff
);
2371 c
= isl_constraint_get_constant_val(ineq
);
2372 c
= isl_val_sub_ui(c
, 1);
2373 ineq
= isl_constraint_set_constant_val(ineq
, c
);
2375 bset
= isl_basic_set_from_constraint(ineq
);
2376 bset
= isl_basic_set_simplify(bset
);
2383 /* Return a basic set containing those elements in the space
2384 * of aff where it is non-negative.
2385 * If "rational" is set, then return a rational basic set.
2387 * If "aff" is NaN, then it is not non-negative (it's not negative either).
2389 static __isl_give isl_basic_set
*aff_nonneg_basic_set(
2390 __isl_take isl_aff
*aff
, int rational
, void *user
)
2392 isl_constraint
*ineq
;
2393 isl_basic_set
*bset
;
2397 if (isl_aff_is_nan(aff
)) {
2398 isl_space
*space
= isl_aff_get_domain_space(aff
);
2400 return isl_basic_set_empty(space
);
2403 ineq
= isl_inequality_from_aff(aff
);
2405 bset
= isl_basic_set_from_constraint(ineq
);
2407 bset
= isl_basic_set_set_rational(bset
);
2408 bset
= isl_basic_set_simplify(bset
);
2412 /* Return a basic set containing those elements in the space
2413 * of aff where it is non-negative.
2415 __isl_give isl_basic_set
*isl_aff_nonneg_basic_set(__isl_take isl_aff
*aff
)
2417 return aff_nonneg_basic_set(aff
, 0, NULL
);
2420 /* Return a basic set containing those elements in the domain space
2421 * of "aff" where it is positive.
2423 __isl_give isl_basic_set
*isl_aff_pos_basic_set(__isl_take isl_aff
*aff
)
2425 aff
= isl_aff_add_constant_num_si(aff
, -1);
2426 return isl_aff_nonneg_basic_set(aff
);
2429 /* Return a basic set containing those elements in the domain space
2430 * of aff where it is negative.
2432 __isl_give isl_basic_set
*isl_aff_neg_basic_set(__isl_take isl_aff
*aff
)
2434 aff
= isl_aff_neg(aff
);
2435 return isl_aff_pos_basic_set(aff
);
2438 /* Return a basic set containing those elements in the space
2439 * of aff where it is zero.
2440 * If "rational" is set, then return a rational basic set.
2442 * If "aff" is NaN, then it is not zero.
2444 static __isl_give isl_basic_set
*aff_zero_basic_set(__isl_take isl_aff
*aff
,
2445 int rational
, void *user
)
2447 isl_constraint
*ineq
;
2448 isl_basic_set
*bset
;
2452 if (isl_aff_is_nan(aff
)) {
2453 isl_space
*space
= isl_aff_get_domain_space(aff
);
2455 return isl_basic_set_empty(space
);
2458 ineq
= isl_equality_from_aff(aff
);
2460 bset
= isl_basic_set_from_constraint(ineq
);
2462 bset
= isl_basic_set_set_rational(bset
);
2463 bset
= isl_basic_set_simplify(bset
);
2467 /* Return a basic set containing those elements in the space
2468 * of aff where it is zero.
2470 __isl_give isl_basic_set
*isl_aff_zero_basic_set(__isl_take isl_aff
*aff
)
2472 return aff_zero_basic_set(aff
, 0, NULL
);
2475 /* Return a basic set containing those elements in the shared space
2476 * of aff1 and aff2 where aff1 is greater than or equal to aff2.
2478 __isl_give isl_basic_set
*isl_aff_ge_basic_set(__isl_take isl_aff
*aff1
,
2479 __isl_take isl_aff
*aff2
)
2481 aff1
= isl_aff_sub(aff1
, aff2
);
2483 return isl_aff_nonneg_basic_set(aff1
);
2486 /* Return a basic set containing those elements in the shared domain space
2487 * of "aff1" and "aff2" where "aff1" is greater than "aff2".
2489 __isl_give isl_basic_set
*isl_aff_gt_basic_set(__isl_take isl_aff
*aff1
,
2490 __isl_take isl_aff
*aff2
)
2492 aff1
= isl_aff_sub(aff1
, aff2
);
2494 return isl_aff_pos_basic_set(aff1
);
2497 /* Return a set containing those elements in the shared space
2498 * of aff1 and aff2 where aff1 is greater than or equal to aff2.
2500 __isl_give isl_set
*isl_aff_ge_set(__isl_take isl_aff
*aff1
,
2501 __isl_take isl_aff
*aff2
)
2503 return isl_set_from_basic_set(isl_aff_ge_basic_set(aff1
, aff2
));
2506 /* Return a set containing those elements in the shared domain space
2507 * of aff1 and aff2 where aff1 is greater than aff2.
2509 * If either of the two inputs is NaN, then the result is empty,
2510 * as comparisons with NaN always return false.
2512 __isl_give isl_set
*isl_aff_gt_set(__isl_take isl_aff
*aff1
,
2513 __isl_take isl_aff
*aff2
)
2515 return isl_set_from_basic_set(isl_aff_gt_basic_set(aff1
, aff2
));
2518 /* Return a basic set containing those elements in the shared space
2519 * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
2521 __isl_give isl_basic_set
*isl_aff_le_basic_set(__isl_take isl_aff
*aff1
,
2522 __isl_take isl_aff
*aff2
)
2524 return isl_aff_ge_basic_set(aff2
, aff1
);
2527 /* Return a basic set containing those elements in the shared domain space
2528 * of "aff1" and "aff2" where "aff1" is smaller than "aff2".
2530 __isl_give isl_basic_set
*isl_aff_lt_basic_set(__isl_take isl_aff
*aff1
,
2531 __isl_take isl_aff
*aff2
)
2533 return isl_aff_gt_basic_set(aff2
, aff1
);
2536 /* Return a set containing those elements in the shared space
2537 * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
2539 __isl_give isl_set
*isl_aff_le_set(__isl_take isl_aff
*aff1
,
2540 __isl_take isl_aff
*aff2
)
2542 return isl_aff_ge_set(aff2
, aff1
);
2545 /* Return a set containing those elements in the shared domain space
2546 * of "aff1" and "aff2" where "aff1" is smaller than "aff2".
2548 __isl_give isl_set
*isl_aff_lt_set(__isl_take isl_aff
*aff1
,
2549 __isl_take isl_aff
*aff2
)
2551 return isl_set_from_basic_set(isl_aff_lt_basic_set(aff1
, aff2
));
2554 /* Return a basic set containing those elements in the shared space
2555 * of aff1 and aff2 where aff1 and aff2 are equal.
2557 __isl_give isl_basic_set
*isl_aff_eq_basic_set(__isl_take isl_aff
*aff1
,
2558 __isl_take isl_aff
*aff2
)
2560 aff1
= isl_aff_sub(aff1
, aff2
);
2562 return isl_aff_zero_basic_set(aff1
);
2565 /* Return a set containing those elements in the shared space
2566 * of aff1 and aff2 where aff1 and aff2 are equal.
2568 __isl_give isl_set
*isl_aff_eq_set(__isl_take isl_aff
*aff1
,
2569 __isl_take isl_aff
*aff2
)
2571 return isl_set_from_basic_set(isl_aff_eq_basic_set(aff1
, aff2
));
2574 /* Return a set containing those elements in the shared domain space
2575 * of aff1 and aff2 where aff1 and aff2 are not equal.
2577 * If either of the two inputs is NaN, then the result is empty,
2578 * as comparisons with NaN always return false.
2580 __isl_give isl_set
*isl_aff_ne_set(__isl_take isl_aff
*aff1
,
2581 __isl_take isl_aff
*aff2
)
2583 isl_set
*set_lt
, *set_gt
;
2585 set_lt
= isl_aff_lt_set(isl_aff_copy(aff1
),
2586 isl_aff_copy(aff2
));
2587 set_gt
= isl_aff_gt_set(aff1
, aff2
);
2588 return isl_set_union_disjoint(set_lt
, set_gt
);
2591 __isl_give isl_aff
*isl_aff_add_on_domain(__isl_keep isl_set
*dom
,
2592 __isl_take isl_aff
*aff1
, __isl_take isl_aff
*aff2
)
2594 aff1
= isl_aff_add(aff1
, aff2
);
2595 aff1
= isl_aff_gist(aff1
, isl_set_copy(dom
));
2599 isl_bool
isl_aff_is_empty(__isl_keep isl_aff
*aff
)
2602 return isl_bool_error
;
2604 return isl_bool_false
;
2608 #define TYPE isl_aff
2610 #include "check_type_range_templ.c"
2612 /* Check whether the given affine expression has non-zero coefficient
2613 * for any dimension in the given range or if any of these dimensions
2614 * appear with non-zero coefficients in any of the integer divisions
2615 * involved in the affine expression.
2617 isl_bool
isl_aff_involves_dims(__isl_keep isl_aff
*aff
,
2618 enum isl_dim_type type
, unsigned first
, unsigned n
)
2622 isl_bool involves
= isl_bool_false
;
2625 return isl_bool_error
;
2627 return isl_bool_false
;
2628 if (isl_aff_check_range(aff
, type
, first
, n
) < 0)
2629 return isl_bool_error
;
2631 active
= isl_local_space_get_active(aff
->ls
, aff
->v
->el
+ 2);
2635 first
+= isl_local_space_offset(aff
->ls
, type
) - 1;
2636 for (i
= 0; i
< n
; ++i
)
2637 if (active
[first
+ i
]) {
2638 involves
= isl_bool_true
;
2647 return isl_bool_error
;
2650 /* Does "aff" involve any local variables, i.e., integer divisions?
2652 isl_bool
isl_aff_involves_locals(__isl_keep isl_aff
*aff
)
2656 n
= isl_aff_dim(aff
, isl_dim_div
);
2658 return isl_bool_error
;
2659 return isl_bool_ok(n
> 0);
2662 __isl_give isl_aff
*isl_aff_drop_dims(__isl_take isl_aff
*aff
,
2663 enum isl_dim_type type
, unsigned first
, unsigned n
)
2667 if (type
== isl_dim_out
)
2668 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
2669 "cannot drop output/set dimension",
2670 return isl_aff_free(aff
));
2671 if (type
== isl_dim_in
)
2673 if (n
== 0 && !isl_local_space_is_named_or_nested(aff
->ls
, type
))
2676 if (isl_local_space_check_range(aff
->ls
, type
, first
, n
) < 0)
2677 return isl_aff_free(aff
);
2679 aff
= isl_aff_cow(aff
);
2683 aff
->ls
= isl_local_space_drop_dims(aff
->ls
, type
, first
, n
);
2685 return isl_aff_free(aff
);
2687 first
+= 1 + isl_local_space_offset(aff
->ls
, type
);
2688 aff
->v
= isl_vec_drop_els(aff
->v
, first
, n
);
2690 return isl_aff_free(aff
);
2695 /* Is the domain of "aff" a product?
2697 static isl_bool
isl_aff_domain_is_product(__isl_keep isl_aff
*aff
)
2699 return isl_space_is_product(isl_aff_peek_domain_space(aff
));
2703 #define TYPE isl_aff
2704 #include <isl_domain_factor_templ.c>
2706 /* Project the domain of the affine expression onto its parameter space.
2707 * The affine expression may not involve any of the domain dimensions.
2709 __isl_give isl_aff
*isl_aff_project_domain_on_params(__isl_take isl_aff
*aff
)
2714 n
= isl_aff_dim(aff
, isl_dim_in
);
2716 return isl_aff_free(aff
);
2717 aff
= isl_aff_drop_domain(aff
, 0, n
);
2718 space
= isl_aff_get_domain_space(aff
);
2719 space
= isl_space_params(space
);
2720 aff
= isl_aff_reset_domain_space(aff
, space
);
2724 /* Convert an affine expression defined over a parameter domain
2725 * into one that is defined over a zero-dimensional set.
2727 __isl_give isl_aff
*isl_aff_from_range(__isl_take isl_aff
*aff
)
2729 isl_local_space
*ls
;
2731 ls
= isl_aff_take_domain_local_space(aff
);
2732 ls
= isl_local_space_set_from_params(ls
);
2733 aff
= isl_aff_restore_domain_local_space(aff
, ls
);
2738 __isl_give isl_aff
*isl_aff_insert_dims(__isl_take isl_aff
*aff
,
2739 enum isl_dim_type type
, unsigned first
, unsigned n
)
2743 if (type
== isl_dim_out
)
2744 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
2745 "cannot insert output/set dimensions",
2746 return isl_aff_free(aff
));
2747 if (type
== isl_dim_in
)
2749 if (n
== 0 && !isl_local_space_is_named_or_nested(aff
->ls
, type
))
2752 if (isl_local_space_check_range(aff
->ls
, type
, first
, 0) < 0)
2753 return isl_aff_free(aff
);
2755 aff
= isl_aff_cow(aff
);
2759 aff
->ls
= isl_local_space_insert_dims(aff
->ls
, type
, first
, n
);
2761 return isl_aff_free(aff
);
2763 first
+= 1 + isl_local_space_offset(aff
->ls
, type
);
2764 aff
->v
= isl_vec_insert_zero_els(aff
->v
, first
, n
);
2766 return isl_aff_free(aff
);
2771 __isl_give isl_aff
*isl_aff_add_dims(__isl_take isl_aff
*aff
,
2772 enum isl_dim_type type
, unsigned n
)
2776 pos
= isl_aff_dim(aff
, type
);
2778 return isl_aff_free(aff
);
2780 return isl_aff_insert_dims(aff
, type
, pos
, n
);
2783 /* Move the "n" dimensions of "src_type" starting at "src_pos" of "aff"
2784 * to dimensions of "dst_type" at "dst_pos".
2786 * We only support moving input dimensions to parameters and vice versa.
2788 __isl_give isl_aff
*isl_aff_move_dims(__isl_take isl_aff
*aff
,
2789 enum isl_dim_type dst_type
, unsigned dst_pos
,
2790 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
2794 isl_size src_off
, dst_off
;
2799 !isl_local_space_is_named_or_nested(aff
->ls
, src_type
) &&
2800 !isl_local_space_is_named_or_nested(aff
->ls
, dst_type
))
2803 if (dst_type
== isl_dim_out
|| src_type
== isl_dim_out
)
2804 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
2805 "cannot move output/set dimension",
2806 return isl_aff_free(aff
));
2807 if (dst_type
== isl_dim_div
|| src_type
== isl_dim_div
)
2808 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
2809 "cannot move divs", return isl_aff_free(aff
));
2810 if (dst_type
== isl_dim_in
)
2811 dst_type
= isl_dim_set
;
2812 if (src_type
== isl_dim_in
)
2813 src_type
= isl_dim_set
;
2815 if (isl_local_space_check_range(aff
->ls
, src_type
, src_pos
, n
) < 0)
2816 return isl_aff_free(aff
);
2817 if (dst_type
== src_type
)
2818 isl_die(isl_aff_get_ctx(aff
), isl_error_unsupported
,
2819 "moving dims within the same type not supported",
2820 return isl_aff_free(aff
));
2822 aff
= isl_aff_cow(aff
);
2823 src_off
= isl_aff_domain_offset(aff
, src_type
);
2824 dst_off
= isl_aff_domain_offset(aff
, dst_type
);
2825 if (src_off
< 0 || dst_off
< 0)
2826 return isl_aff_free(aff
);
2828 g_src_pos
= 1 + src_off
+ src_pos
;
2829 g_dst_pos
= 1 + dst_off
+ dst_pos
;
2830 if (dst_type
> src_type
)
2833 aff
->v
= isl_vec_move_els(aff
->v
, g_dst_pos
, g_src_pos
, n
);
2834 aff
->ls
= isl_local_space_move_dims(aff
->ls
, dst_type
, dst_pos
,
2835 src_type
, src_pos
, n
);
2836 if (!aff
->v
|| !aff
->ls
)
2837 return isl_aff_free(aff
);
2839 aff
= sort_divs(aff
);
2844 /* Given an affine function on a domain (A -> B),
2845 * interchange A and B in the wrapped domain
2846 * to obtain a function on the domain (B -> A).
2848 * Since this may change the position of some variables,
2849 * it may also change the normalized order of the local variables.
2850 * Restore this order. Since sort_divs assumes the input
2851 * has a single reference, an explicit isl_aff_cow is required.
2853 __isl_give isl_aff
*isl_aff_domain_reverse(__isl_take isl_aff
*aff
)
2856 isl_local_space
*ls
;
2858 isl_size n_in
, n_out
;
2861 space
= isl_aff_peek_domain_space(aff
);
2862 offset
= isl_space_offset(space
, isl_dim_set
);
2863 n_in
= isl_space_wrapped_dim(space
, isl_dim_set
, isl_dim_in
);
2864 n_out
= isl_space_wrapped_dim(space
, isl_dim_set
, isl_dim_out
);
2865 if (offset
< 0 || n_in
< 0 || n_out
< 0)
2866 return isl_aff_free(aff
);
2868 v
= isl_aff_take_rat_aff(aff
);
2869 v
= isl_vec_move_els(v
, 1 + 1 + offset
, 1 + 1 + offset
+ n_in
, n_out
);
2870 aff
= isl_aff_restore_rat_aff(aff
, v
);
2872 ls
= isl_aff_take_domain_local_space(aff
);
2873 ls
= isl_local_space_wrapped_reverse(ls
);
2874 aff
= isl_aff_restore_domain_local_space(aff
, ls
);
2876 aff
= isl_aff_cow(aff
);
2877 aff
= sort_divs(aff
);
2882 /* Return a zero isl_aff in the given space.
2884 * This is a helper function for isl_pw_*_as_* that ensures a uniform
2885 * interface over all piecewise types.
2887 static __isl_give isl_aff
*isl_aff_zero_in_space(__isl_take isl_space
*space
)
2889 isl_local_space
*ls
;
2891 ls
= isl_local_space_from_space(isl_space_domain(space
));
2892 return isl_aff_zero_on_domain(ls
);
2895 #define isl_aff_involves_nan isl_aff_is_nan
2898 #define PW isl_pw_aff
2902 #define EL_IS_ZERO is_empty
2906 #define IS_ZERO is_empty
2909 #undef DEFAULT_IS_ZERO
2910 #define DEFAULT_IS_ZERO 0
2912 #include <isl_pw_templ.c>
2913 #include <isl_pw_un_op_templ.c>
2914 #include <isl_pw_add_constant_val_templ.c>
2915 #include <isl_pw_add_disjoint_templ.c>
2916 #include <isl_pw_bind_domain_templ.c>
2917 #include <isl_pw_domain_reverse_templ.c>
2918 #include <isl_pw_eval.c>
2919 #include <isl_pw_hash.c>
2920 #include <isl_pw_fix_templ.c>
2921 #include <isl_pw_from_range_templ.c>
2922 #include <isl_pw_insert_dims_templ.c>
2923 #include <isl_pw_insert_domain_templ.c>
2924 #include <isl_pw_move_dims_templ.c>
2925 #include <isl_pw_neg_templ.c>
2926 #include <isl_pw_pullback_templ.c>
2927 #include <isl_pw_scale_templ.c>
2928 #include <isl_pw_sub_templ.c>
2929 #include <isl_pw_union_opt.c>
2934 #include <isl_union_single.c>
2935 #include <isl_union_neg.c>
2936 #include <isl_union_sub_templ.c>
2941 #include <isl_union_pw_templ.c>
2943 /* Compute a piecewise quasi-affine expression with a domain that
2944 * is the union of those of pwaff1 and pwaff2 and such that on each
2945 * cell, the quasi-affine expression is the maximum of those of pwaff1
2946 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
2947 * cell, then the associated expression is the defined one.
2949 __isl_give isl_pw_aff
*isl_pw_aff_union_max(__isl_take isl_pw_aff
*pwaff1
,
2950 __isl_take isl_pw_aff
*pwaff2
)
2952 isl_pw_aff_align_params_bin(&pwaff1
, &pwaff2
);
2953 return isl_pw_aff_union_opt_cmp(pwaff1
, pwaff2
, &isl_aff_ge_set
);
2956 /* Compute a piecewise quasi-affine expression with a domain that
2957 * is the union of those of pwaff1 and pwaff2 and such that on each
2958 * cell, the quasi-affine expression is the minimum of those of pwaff1
2959 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
2960 * cell, then the associated expression is the defined one.
2962 __isl_give isl_pw_aff
*isl_pw_aff_union_min(__isl_take isl_pw_aff
*pwaff1
,
2963 __isl_take isl_pw_aff
*pwaff2
)
2965 isl_pw_aff_align_params_bin(&pwaff1
, &pwaff2
);
2966 return isl_pw_aff_union_opt_cmp(pwaff1
, pwaff2
, &isl_aff_le_set
);
2969 __isl_give isl_pw_aff
*isl_pw_aff_union_opt(__isl_take isl_pw_aff
*pwaff1
,
2970 __isl_take isl_pw_aff
*pwaff2
, int max
)
2973 return isl_pw_aff_union_max(pwaff1
, pwaff2
);
2975 return isl_pw_aff_union_min(pwaff1
, pwaff2
);
2978 /* Is the domain of "pa" a product?
2980 static isl_bool
isl_pw_aff_domain_is_product(__isl_keep isl_pw_aff
*pa
)
2982 return isl_space_domain_is_wrapping(isl_pw_aff_peek_space(pa
));
2986 #define TYPE isl_pw_aff
2987 #include <isl_domain_factor_templ.c>
2989 /* Return a set containing those elements in the domain
2990 * of "pwaff" where it satisfies "fn" (if complement is 0) or
2991 * does not satisfy "fn" (if complement is 1).
2993 * The pieces with a NaN never belong to the result since
2994 * NaN does not satisfy any property.
2996 static __isl_give isl_set
*pw_aff_locus(__isl_take isl_pw_aff
*pwaff
,
2997 __isl_give isl_basic_set
*(*fn
)(__isl_take isl_aff
*aff
, int rational
,
2999 int complement
, void *user
)
3007 set
= isl_set_empty(isl_pw_aff_get_domain_space(pwaff
));
3009 for (i
= 0; i
< pwaff
->n
; ++i
) {
3010 isl_basic_set
*bset
;
3011 isl_set
*set_i
, *locus
;
3014 if (isl_aff_is_nan(pwaff
->p
[i
].aff
))
3017 rational
= isl_set_has_rational(pwaff
->p
[i
].set
);
3018 bset
= fn(isl_aff_copy(pwaff
->p
[i
].aff
), rational
, user
);
3019 locus
= isl_set_from_basic_set(bset
);
3020 set_i
= isl_set_copy(pwaff
->p
[i
].set
);
3022 set_i
= isl_set_subtract(set_i
, locus
);
3024 set_i
= isl_set_intersect(set_i
, locus
);
3025 set
= isl_set_union_disjoint(set
, set_i
);
3028 isl_pw_aff_free(pwaff
);
3033 /* Return a set containing those elements in the domain
3034 * of "pa" where it is positive.
3036 __isl_give isl_set
*isl_pw_aff_pos_set(__isl_take isl_pw_aff
*pa
)
3038 return pw_aff_locus(pa
, &aff_pos_basic_set
, 0, NULL
);
3041 /* Return a set containing those elements in the domain
3042 * of pwaff where it is non-negative.
3044 __isl_give isl_set
*isl_pw_aff_nonneg_set(__isl_take isl_pw_aff
*pwaff
)
3046 return pw_aff_locus(pwaff
, &aff_nonneg_basic_set
, 0, NULL
);
3049 /* Return a set containing those elements in the domain
3050 * of pwaff where it is zero.
3052 __isl_give isl_set
*isl_pw_aff_zero_set(__isl_take isl_pw_aff
*pwaff
)
3054 return pw_aff_locus(pwaff
, &aff_zero_basic_set
, 0, NULL
);
3057 /* Return a set containing those elements in the domain
3058 * of pwaff where it is not zero.
3060 __isl_give isl_set
*isl_pw_aff_non_zero_set(__isl_take isl_pw_aff
*pwaff
)
3062 return pw_aff_locus(pwaff
, &aff_zero_basic_set
, 1, NULL
);
3065 /* Bind the affine function "aff" to the parameter "id",
3066 * returning the elements in the domain where the affine expression
3067 * is equal to the parameter.
3069 __isl_give isl_basic_set
*isl_aff_bind_id(__isl_take isl_aff
*aff
,
3070 __isl_take isl_id
*id
)
3075 space
= isl_aff_get_domain_space(aff
);
3076 space
= isl_space_add_param_id(space
, isl_id_copy(id
));
3078 aff
= isl_aff_align_params(aff
, isl_space_copy(space
));
3079 aff_id
= isl_aff_param_on_domain_space_id(space
, id
);
3081 return isl_aff_eq_basic_set(aff
, aff_id
);
3084 /* Wrapper around isl_aff_bind_id for use as pw_aff_locus callback.
3085 * "rational" should not be set.
3087 static __isl_give isl_basic_set
*aff_bind_id(__isl_take isl_aff
*aff
,
3088 int rational
, void *user
)
3095 isl_die(isl_aff_get_ctx(aff
), isl_error_unsupported
,
3096 "rational binding not supported", goto error
);
3097 return isl_aff_bind_id(aff
, isl_id_copy(id
));
3103 /* Bind the piecewise affine function "pa" to the parameter "id",
3104 * returning the elements in the domain where the expression
3105 * is equal to the parameter.
3107 __isl_give isl_set
*isl_pw_aff_bind_id(__isl_take isl_pw_aff
*pa
,
3108 __isl_take isl_id
*id
)
3112 bound
= pw_aff_locus(pa
, &aff_bind_id
, 0, id
);
3118 /* Return a set containing those elements in the shared domain
3119 * of pwaff1 and pwaff2 where pwaff1 is greater than (or equal) to pwaff2.
3121 * We compute the difference on the shared domain and then construct
3122 * the set of values where this difference is non-negative.
3123 * If strict is set, we first subtract 1 from the difference.
3124 * If equal is set, we only return the elements where pwaff1 and pwaff2
3127 static __isl_give isl_set
*pw_aff_gte_set(__isl_take isl_pw_aff
*pwaff1
,
3128 __isl_take isl_pw_aff
*pwaff2
, int strict
, int equal
)
3130 isl_set
*set1
, *set2
;
3132 set1
= isl_pw_aff_domain(isl_pw_aff_copy(pwaff1
));
3133 set2
= isl_pw_aff_domain(isl_pw_aff_copy(pwaff2
));
3134 set1
= isl_set_intersect(set1
, set2
);
3135 pwaff1
= isl_pw_aff_intersect_domain(pwaff1
, isl_set_copy(set1
));
3136 pwaff2
= isl_pw_aff_intersect_domain(pwaff2
, isl_set_copy(set1
));
3137 pwaff1
= isl_pw_aff_add(pwaff1
, isl_pw_aff_neg(pwaff2
));
3140 isl_space
*space
= isl_set_get_space(set1
);
3142 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
3143 aff
= isl_aff_add_constant_si(aff
, -1);
3144 pwaff1
= isl_pw_aff_add(pwaff1
, isl_pw_aff_alloc(set1
, aff
));
3149 return isl_pw_aff_zero_set(pwaff1
);
3150 return isl_pw_aff_nonneg_set(pwaff1
);
3153 /* Return a set containing those elements in the shared domain
3154 * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2.
3156 __isl_give isl_set
*isl_pw_aff_eq_set(__isl_take isl_pw_aff
*pwaff1
,
3157 __isl_take isl_pw_aff
*pwaff2
)
3159 isl_pw_aff_align_params_bin(&pwaff1
, &pwaff2
);
3160 return pw_aff_gte_set(pwaff1
, pwaff2
, 0, 1);
3163 /* Return a set containing those elements in the shared domain
3164 * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2.
3166 __isl_give isl_set
*isl_pw_aff_ge_set(__isl_take isl_pw_aff
*pwaff1
,
3167 __isl_take isl_pw_aff
*pwaff2
)
3169 isl_pw_aff_align_params_bin(&pwaff1
, &pwaff2
);
3170 return pw_aff_gte_set(pwaff1
, pwaff2
, 0, 0);
3173 /* Return a set containing those elements in the shared domain
3174 * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2.
3176 __isl_give isl_set
*isl_pw_aff_gt_set(__isl_take isl_pw_aff
*pwaff1
,
3177 __isl_take isl_pw_aff
*pwaff2
)
3179 isl_pw_aff_align_params_bin(&pwaff1
, &pwaff2
);
3180 return pw_aff_gte_set(pwaff1
, pwaff2
, 1, 0);
3183 __isl_give isl_set
*isl_pw_aff_le_set(__isl_take isl_pw_aff
*pwaff1
,
3184 __isl_take isl_pw_aff
*pwaff2
)
3186 return isl_pw_aff_ge_set(pwaff2
, pwaff1
);
3189 __isl_give isl_set
*isl_pw_aff_lt_set(__isl_take isl_pw_aff
*pwaff1
,
3190 __isl_take isl_pw_aff
*pwaff2
)
3192 return isl_pw_aff_gt_set(pwaff2
, pwaff1
);
3195 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3196 * where the function values are ordered in the same way as "order",
3197 * which returns a set in the shared domain of its two arguments.
3199 * Let "pa1" and "pa2" be defined on domains A and B respectively.
3200 * We first pull back the two functions such that they are defined on
3201 * the domain [A -> B]. Then we apply "order", resulting in a set
3202 * in the space [A -> B]. Finally, we unwrap this set to obtain
3203 * a map in the space A -> B.
3205 static __isl_give isl_map
*isl_pw_aff_order_map(
3206 __isl_take isl_pw_aff
*pa1
, __isl_take isl_pw_aff
*pa2
,
3207 __isl_give isl_set
*(*order
)(__isl_take isl_pw_aff
*pa1
,
3208 __isl_take isl_pw_aff
*pa2
))
3210 isl_space
*space1
, *space2
;
3214 isl_pw_aff_align_params_bin(&pa1
, &pa2
);
3215 space1
= isl_space_domain(isl_pw_aff_get_space(pa1
));
3216 space2
= isl_space_domain(isl_pw_aff_get_space(pa2
));
3217 space1
= isl_space_map_from_domain_and_range(space1
, space2
);
3218 ma
= isl_multi_aff_domain_map(isl_space_copy(space1
));
3219 pa1
= isl_pw_aff_pullback_multi_aff(pa1
, ma
);
3220 ma
= isl_multi_aff_range_map(space1
);
3221 pa2
= isl_pw_aff_pullback_multi_aff(pa2
, ma
);
3222 set
= order(pa1
, pa2
);
3224 return isl_set_unwrap(set
);
3227 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3228 * where the function values are equal.
3230 __isl_give isl_map
*isl_pw_aff_eq_map(__isl_take isl_pw_aff
*pa1
,
3231 __isl_take isl_pw_aff
*pa2
)
3233 return isl_pw_aff_order_map(pa1
, pa2
, &isl_pw_aff_eq_set
);
3236 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3237 * where the function value of "pa1" is less than or equal to
3238 * the function value of "pa2".
3240 __isl_give isl_map
*isl_pw_aff_le_map(__isl_take isl_pw_aff
*pa1
,
3241 __isl_take isl_pw_aff
*pa2
)
3243 return isl_pw_aff_order_map(pa1
, pa2
, &isl_pw_aff_le_set
);
3246 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3247 * where the function value of "pa1" is less than the function value of "pa2".
3249 __isl_give isl_map
*isl_pw_aff_lt_map(__isl_take isl_pw_aff
*pa1
,
3250 __isl_take isl_pw_aff
*pa2
)
3252 return isl_pw_aff_order_map(pa1
, pa2
, &isl_pw_aff_lt_set
);
3255 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3256 * where the function value of "pa1" is greater than or equal to
3257 * the function value of "pa2".
3259 __isl_give isl_map
*isl_pw_aff_ge_map(__isl_take isl_pw_aff
*pa1
,
3260 __isl_take isl_pw_aff
*pa2
)
3262 return isl_pw_aff_order_map(pa1
, pa2
, &isl_pw_aff_ge_set
);
3265 /* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
3266 * where the function value of "pa1" is greater than the function value
3269 __isl_give isl_map
*isl_pw_aff_gt_map(__isl_take isl_pw_aff
*pa1
,
3270 __isl_take isl_pw_aff
*pa2
)
3272 return isl_pw_aff_order_map(pa1
, pa2
, &isl_pw_aff_gt_set
);
3275 /* Return a set containing those elements in the shared domain
3276 * of the elements of list1 and list2 where each element in list1
3277 * has the relation specified by "fn" with each element in list2.
3279 static __isl_give isl_set
*pw_aff_list_set(__isl_take isl_pw_aff_list
*list1
,
3280 __isl_take isl_pw_aff_list
*list2
,
3281 __isl_give isl_set
*(*fn
)(__isl_take isl_pw_aff
*pwaff1
,
3282 __isl_take isl_pw_aff
*pwaff2
))
3288 if (!list1
|| !list2
)
3291 ctx
= isl_pw_aff_list_get_ctx(list1
);
3292 if (list1
->n
< 1 || list2
->n
< 1)
3293 isl_die(ctx
, isl_error_invalid
,
3294 "list should contain at least one element", goto error
);
3296 set
= isl_set_universe(isl_pw_aff_get_domain_space(list1
->p
[0]));
3297 for (i
= 0; i
< list1
->n
; ++i
)
3298 for (j
= 0; j
< list2
->n
; ++j
) {
3301 set_ij
= fn(isl_pw_aff_copy(list1
->p
[i
]),
3302 isl_pw_aff_copy(list2
->p
[j
]));
3303 set
= isl_set_intersect(set
, set_ij
);
3306 isl_pw_aff_list_free(list1
);
3307 isl_pw_aff_list_free(list2
);
3310 isl_pw_aff_list_free(list1
);
3311 isl_pw_aff_list_free(list2
);
3315 /* Return a set containing those elements in the shared domain
3316 * of the elements of list1 and list2 where each element in list1
3317 * is equal to each element in list2.
3319 __isl_give isl_set
*isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list
*list1
,
3320 __isl_take isl_pw_aff_list
*list2
)
3322 return pw_aff_list_set(list1
, list2
, &isl_pw_aff_eq_set
);
3325 __isl_give isl_set
*isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list
*list1
,
3326 __isl_take isl_pw_aff_list
*list2
)
3328 return pw_aff_list_set(list1
, list2
, &isl_pw_aff_ne_set
);
3331 /* Return a set containing those elements in the shared domain
3332 * of the elements of list1 and list2 where each element in list1
3333 * is less than or equal to each element in list2.
3335 __isl_give isl_set
*isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list
*list1
,
3336 __isl_take isl_pw_aff_list
*list2
)
3338 return pw_aff_list_set(list1
, list2
, &isl_pw_aff_le_set
);
3341 __isl_give isl_set
*isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list
*list1
,
3342 __isl_take isl_pw_aff_list
*list2
)
3344 return pw_aff_list_set(list1
, list2
, &isl_pw_aff_lt_set
);
3347 __isl_give isl_set
*isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list
*list1
,
3348 __isl_take isl_pw_aff_list
*list2
)
3350 return pw_aff_list_set(list1
, list2
, &isl_pw_aff_ge_set
);
3353 __isl_give isl_set
*isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list
*list1
,
3354 __isl_take isl_pw_aff_list
*list2
)
3356 return pw_aff_list_set(list1
, list2
, &isl_pw_aff_gt_set
);
3360 /* Return a set containing those elements in the shared domain
3361 * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2.
3363 __isl_give isl_set
*isl_pw_aff_ne_set(__isl_take isl_pw_aff
*pwaff1
,
3364 __isl_take isl_pw_aff
*pwaff2
)
3366 isl_set
*set_lt
, *set_gt
;
3368 isl_pw_aff_align_params_bin(&pwaff1
, &pwaff2
);
3369 set_lt
= isl_pw_aff_lt_set(isl_pw_aff_copy(pwaff1
),
3370 isl_pw_aff_copy(pwaff2
));
3371 set_gt
= isl_pw_aff_gt_set(pwaff1
, pwaff2
);
3372 return isl_set_union_disjoint(set_lt
, set_gt
);
3375 __isl_give isl_pw_aff
*isl_pw_aff_scale_down(__isl_take isl_pw_aff
*pwaff
,
3380 if (isl_int_is_one(v
))
3382 if (!isl_int_is_pos(v
))
3383 isl_die(isl_pw_aff_get_ctx(pwaff
), isl_error_invalid
,
3384 "factor needs to be positive",
3385 return isl_pw_aff_free(pwaff
));
3386 pwaff
= isl_pw_aff_cow(pwaff
);
3392 for (i
= 0; i
< pwaff
->n
; ++i
) {
3393 pwaff
->p
[i
].aff
= isl_aff_scale_down(pwaff
->p
[i
].aff
, v
);
3394 if (!pwaff
->p
[i
].aff
)
3395 return isl_pw_aff_free(pwaff
);
3401 __isl_give isl_pw_aff
*isl_pw_aff_floor(__isl_take isl_pw_aff
*pwaff
)
3403 struct isl_pw_aff_un_op_control control
= { .fn_base
= &isl_aff_floor
};
3404 return isl_pw_aff_un_op(pwaff
, &control
);
3407 __isl_give isl_pw_aff
*isl_pw_aff_ceil(__isl_take isl_pw_aff
*pwaff
)
3409 struct isl_pw_aff_un_op_control control
= { .fn_base
= &isl_aff_ceil
};
3410 return isl_pw_aff_un_op(pwaff
, &control
);
3413 /* Assuming that "cond1" and "cond2" are disjoint,
3414 * return an affine expression that is equal to pwaff1 on cond1
3415 * and to pwaff2 on cond2.
3417 static __isl_give isl_pw_aff
*isl_pw_aff_select(
3418 __isl_take isl_set
*cond1
, __isl_take isl_pw_aff
*pwaff1
,
3419 __isl_take isl_set
*cond2
, __isl_take isl_pw_aff
*pwaff2
)
3421 pwaff1
= isl_pw_aff_intersect_domain(pwaff1
, cond1
);
3422 pwaff2
= isl_pw_aff_intersect_domain(pwaff2
, cond2
);
3424 return isl_pw_aff_add_disjoint(pwaff1
, pwaff2
);
3427 /* Return an affine expression that is equal to pwaff_true for elements
3428 * where "cond" is non-zero and to pwaff_false for elements where "cond"
3430 * That is, return cond ? pwaff_true : pwaff_false;
3432 * If "cond" involves and NaN, then we conservatively return a NaN
3433 * on its entire domain. In principle, we could consider the pieces
3434 * where it is NaN separately from those where it is not.
3436 * If "pwaff_true" and "pwaff_false" are obviously equal to each other,
3437 * then only use the domain of "cond" to restrict the domain.
3439 __isl_give isl_pw_aff
*isl_pw_aff_cond(__isl_take isl_pw_aff
*cond
,
3440 __isl_take isl_pw_aff
*pwaff_true
, __isl_take isl_pw_aff
*pwaff_false
)
3442 isl_set
*cond_true
, *cond_false
;
3447 if (isl_pw_aff_involves_nan(cond
)) {
3448 isl_space
*space
= isl_pw_aff_get_domain_space(cond
);
3449 isl_local_space
*ls
= isl_local_space_from_space(space
);
3450 isl_pw_aff_free(cond
);
3451 isl_pw_aff_free(pwaff_true
);
3452 isl_pw_aff_free(pwaff_false
);
3453 return isl_pw_aff_nan_on_domain(ls
);
3456 pwaff_true
= isl_pw_aff_align_params(pwaff_true
,
3457 isl_pw_aff_get_space(pwaff_false
));
3458 pwaff_false
= isl_pw_aff_align_params(pwaff_false
,
3459 isl_pw_aff_get_space(pwaff_true
));
3460 equal
= isl_pw_aff_plain_is_equal(pwaff_true
, pwaff_false
);
3466 dom
= isl_set_coalesce(isl_pw_aff_domain(cond
));
3467 isl_pw_aff_free(pwaff_false
);
3468 return isl_pw_aff_intersect_domain(pwaff_true
, dom
);
3471 cond_true
= isl_pw_aff_non_zero_set(isl_pw_aff_copy(cond
));
3472 cond_false
= isl_pw_aff_zero_set(cond
);
3473 return isl_pw_aff_select(cond_true
, pwaff_true
,
3474 cond_false
, pwaff_false
);
3476 isl_pw_aff_free(cond
);
3477 isl_pw_aff_free(pwaff_true
);
3478 isl_pw_aff_free(pwaff_false
);
3482 isl_bool
isl_aff_is_cst(__isl_keep isl_aff
*aff
)
3487 return isl_bool_error
;
3489 pos
= isl_seq_first_non_zero(aff
->v
->el
+ 2, aff
->v
->size
- 2);
3490 return isl_bool_ok(pos
== -1);
3493 /* Check whether pwaff is a piecewise constant.
3495 isl_bool
isl_pw_aff_is_cst(__isl_keep isl_pw_aff
*pwaff
)
3500 return isl_bool_error
;
3502 for (i
= 0; i
< pwaff
->n
; ++i
) {
3503 isl_bool is_cst
= isl_aff_is_cst(pwaff
->p
[i
].aff
);
3504 if (is_cst
< 0 || !is_cst
)
3508 return isl_bool_true
;
3511 /* Return the product of "aff1" and "aff2".
3513 * If either of the two is NaN, then the result is NaN.
3515 * Otherwise, at least one of "aff1" or "aff2" needs to be a constant.
3517 __isl_give isl_aff
*isl_aff_mul(__isl_take isl_aff
*aff1
,
3518 __isl_take isl_aff
*aff2
)
3523 if (isl_aff_is_nan(aff1
)) {
3527 if (isl_aff_is_nan(aff2
)) {
3532 if (!isl_aff_is_cst(aff2
) && isl_aff_is_cst(aff1
))
3533 return isl_aff_mul(aff2
, aff1
);
3535 if (!isl_aff_is_cst(aff2
))
3536 isl_die(isl_aff_get_ctx(aff1
), isl_error_invalid
,
3537 "at least one affine expression should be constant",
3540 aff1
= isl_aff_cow(aff1
);
3544 aff1
= isl_aff_scale(aff1
, aff2
->v
->el
[1]);
3545 aff1
= isl_aff_scale_down(aff1
, aff2
->v
->el
[0]);
3555 /* Divide "aff1" by "aff2", assuming "aff2" is a constant.
3557 * If either of the two is NaN, then the result is NaN.
3558 * A division by zero also results in NaN.
3560 __isl_give isl_aff
*isl_aff_div(__isl_take isl_aff
*aff1
,
3561 __isl_take isl_aff
*aff2
)
3563 isl_bool is_cst
, is_zero
;
3569 if (isl_aff_is_nan(aff1
)) {
3573 if (isl_aff_is_nan(aff2
)) {
3578 is_cst
= isl_aff_is_cst(aff2
);
3582 isl_die(isl_aff_get_ctx(aff2
), isl_error_invalid
,
3583 "second argument should be a constant", goto error
);
3584 is_zero
= isl_aff_plain_is_zero(aff2
);
3588 return set_nan_free(aff1
, aff2
);
3590 neg
= isl_int_is_neg(aff2
->v
->el
[1]);
3592 isl_int_neg(aff2
->v
->el
[0], aff2
->v
->el
[0]);
3593 isl_int_neg(aff2
->v
->el
[1], aff2
->v
->el
[1]);
3596 aff1
= isl_aff_scale(aff1
, aff2
->v
->el
[0]);
3597 aff1
= isl_aff_scale_down(aff1
, aff2
->v
->el
[1]);
3600 isl_int_neg(aff2
->v
->el
[0], aff2
->v
->el
[0]);
3601 isl_int_neg(aff2
->v
->el
[1], aff2
->v
->el
[1]);
3612 __isl_give isl_pw_aff
*isl_pw_aff_add(__isl_take isl_pw_aff
*pwaff1
,
3613 __isl_take isl_pw_aff
*pwaff2
)
3615 isl_pw_aff_align_params_bin(&pwaff1
, &pwaff2
);
3616 return isl_pw_aff_on_shared_domain(pwaff1
, pwaff2
, &isl_aff_add
);
3619 __isl_give isl_pw_aff
*isl_pw_aff_mul(__isl_take isl_pw_aff
*pwaff1
,
3620 __isl_take isl_pw_aff
*pwaff2
)
3622 isl_pw_aff_align_params_bin(&pwaff1
, &pwaff2
);
3623 return isl_pw_aff_on_shared_domain(pwaff1
, pwaff2
, &isl_aff_mul
);
3626 /* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant.
3628 __isl_give isl_pw_aff
*isl_pw_aff_div(__isl_take isl_pw_aff
*pa1
,
3629 __isl_take isl_pw_aff
*pa2
)
3633 is_cst
= isl_pw_aff_is_cst(pa2
);
3637 isl_die(isl_pw_aff_get_ctx(pa2
), isl_error_invalid
,
3638 "second argument should be a piecewise constant",
3640 isl_pw_aff_align_params_bin(&pa1
, &pa2
);
3641 return isl_pw_aff_on_shared_domain(pa1
, pa2
, &isl_aff_div
);
3643 isl_pw_aff_free(pa1
);
3644 isl_pw_aff_free(pa2
);
3648 /* Compute the quotient of the integer division of "pa1" by "pa2"
3649 * with rounding towards zero.
3650 * "pa2" is assumed to be a piecewise constant.
3652 * In particular, return
3654 * pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)
3657 __isl_give isl_pw_aff
*isl_pw_aff_tdiv_q(__isl_take isl_pw_aff
*pa1
,
3658 __isl_take isl_pw_aff
*pa2
)
3664 is_cst
= isl_pw_aff_is_cst(pa2
);
3668 isl_die(isl_pw_aff_get_ctx(pa2
), isl_error_invalid
,
3669 "second argument should be a piecewise constant",
3672 pa1
= isl_pw_aff_div(pa1
, pa2
);
3674 cond
= isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1
));
3675 f
= isl_pw_aff_floor(isl_pw_aff_copy(pa1
));
3676 c
= isl_pw_aff_ceil(pa1
);
3677 return isl_pw_aff_cond(isl_set_indicator_function(cond
), f
, c
);
3679 isl_pw_aff_free(pa1
);
3680 isl_pw_aff_free(pa2
);
3684 /* Compute the remainder of the integer division of "pa1" by "pa2"
3685 * with rounding towards zero.
3686 * "pa2" is assumed to be a piecewise constant.
3688 * In particular, return
3690 * pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2))
3693 __isl_give isl_pw_aff
*isl_pw_aff_tdiv_r(__isl_take isl_pw_aff
*pa1
,
3694 __isl_take isl_pw_aff
*pa2
)
3699 is_cst
= isl_pw_aff_is_cst(pa2
);
3703 isl_die(isl_pw_aff_get_ctx(pa2
), isl_error_invalid
,
3704 "second argument should be a piecewise constant",
3706 res
= isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1
), isl_pw_aff_copy(pa2
));
3707 res
= isl_pw_aff_mul(pa2
, res
);
3708 res
= isl_pw_aff_sub(pa1
, res
);
3711 isl_pw_aff_free(pa1
);
3712 isl_pw_aff_free(pa2
);
3716 /* Does either of "pa1" or "pa2" involve any NaN?
3718 static isl_bool
either_involves_nan(__isl_keep isl_pw_aff
*pa1
,
3719 __isl_keep isl_pw_aff
*pa2
)
3723 has_nan
= isl_pw_aff_involves_nan(pa1
);
3724 if (has_nan
< 0 || has_nan
)
3726 return isl_pw_aff_involves_nan(pa2
);
3729 /* Return a piecewise affine expression defined on the specified domain
3730 * that represents NaN.
3732 static __isl_give isl_pw_aff
*nan_on_domain_set(__isl_take isl_set
*dom
)
3734 isl_local_space
*ls
;
3737 ls
= isl_local_space_from_space(isl_set_get_space(dom
));
3738 pa
= isl_pw_aff_nan_on_domain(ls
);
3739 pa
= isl_pw_aff_intersect_domain(pa
, dom
);
3744 /* Replace "pa1" and "pa2" (at least one of which involves a NaN)
3745 * by a NaN on their shared domain.
3747 * In principle, the result could be refined to only being NaN
3748 * on the parts of this domain where at least one of "pa1" or "pa2" is NaN.
3750 static __isl_give isl_pw_aff
*replace_by_nan(__isl_take isl_pw_aff
*pa1
,
3751 __isl_take isl_pw_aff
*pa2
)
3755 dom
= isl_set_intersect(isl_pw_aff_domain(pa1
), isl_pw_aff_domain(pa2
));
3756 return nan_on_domain_set(dom
);
3759 static __isl_give isl_pw_aff
*pw_aff_min(__isl_take isl_pw_aff
*pwaff1
,
3760 __isl_take isl_pw_aff
*pwaff2
)
3765 dom
= isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1
)),
3766 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2
)));
3767 le
= isl_pw_aff_le_set(isl_pw_aff_copy(pwaff1
),
3768 isl_pw_aff_copy(pwaff2
));
3769 dom
= isl_set_subtract(dom
, isl_set_copy(le
));
3770 return isl_pw_aff_select(le
, pwaff1
, dom
, pwaff2
);
3773 static __isl_give isl_pw_aff
*pw_aff_max(__isl_take isl_pw_aff
*pwaff1
,
3774 __isl_take isl_pw_aff
*pwaff2
)
3779 dom
= isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1
)),
3780 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2
)));
3781 ge
= isl_pw_aff_ge_set(isl_pw_aff_copy(pwaff1
),
3782 isl_pw_aff_copy(pwaff2
));
3783 dom
= isl_set_subtract(dom
, isl_set_copy(ge
));
3784 return isl_pw_aff_select(ge
, pwaff1
, dom
, pwaff2
);
3787 /* Return an expression for the minimum (if "max" is not set) or
3788 * the maximum (if "max" is set) of "pa1" and "pa2".
3789 * If either expression involves any NaN, then return a NaN
3790 * on the shared domain as result.
3792 static __isl_give isl_pw_aff
*pw_aff_min_max(__isl_take isl_pw_aff
*pa1
,
3793 __isl_take isl_pw_aff
*pa2
, int max
)
3797 has_nan
= either_involves_nan(pa1
, pa2
);
3799 pa1
= isl_pw_aff_free(pa1
);
3801 return replace_by_nan(pa1
, pa2
);
3803 isl_pw_aff_align_params_bin(&pa1
, &pa2
);
3805 return pw_aff_max(pa1
, pa2
);
3807 return pw_aff_min(pa1
, pa2
);
3810 /* Return an expression for the minimum of "pwaff1" and "pwaff2".
3812 __isl_give isl_pw_aff
*isl_pw_aff_min(__isl_take isl_pw_aff
*pwaff1
,
3813 __isl_take isl_pw_aff
*pwaff2
)
3815 return pw_aff_min_max(pwaff1
, pwaff2
, 0);
3818 /* Return an expression for the maximum of "pwaff1" and "pwaff2".
3820 __isl_give isl_pw_aff
*isl_pw_aff_max(__isl_take isl_pw_aff
*pwaff1
,
3821 __isl_take isl_pw_aff
*pwaff2
)
3823 return pw_aff_min_max(pwaff1
, pwaff2
, 1);
3826 /* Does "pa" not involve any NaN?
3828 static isl_bool
pw_aff_no_nan(__isl_keep isl_pw_aff
*pa
, void *user
)
3830 return isl_bool_not(isl_pw_aff_involves_nan(pa
));
3833 /* Does any element of "list" involve any NaN?
3835 * That is, is it not the case that every element does not involve any NaN?
3837 static isl_bool
isl_pw_aff_list_involves_nan(__isl_keep isl_pw_aff_list
*list
)
3839 return isl_bool_not(isl_pw_aff_list_every(list
, &pw_aff_no_nan
, NULL
));
3842 /* Replace "list" (consisting of "n" elements, of which
3843 * at least one element involves a NaN)
3844 * by a NaN on the shared domain of the elements.
3846 * In principle, the result could be refined to only being NaN
3847 * on the parts of this domain where at least one of the elements is NaN.
3849 static __isl_give isl_pw_aff
*replace_list_by_nan(
3850 __isl_take isl_pw_aff_list
*list
, int n
)
3855 dom
= isl_pw_aff_domain(isl_pw_aff_list_get_at(list
, 0));
3856 for (i
= 1; i
< n
; ++i
) {
3859 dom_i
= isl_pw_aff_domain(isl_pw_aff_list_get_at(list
, i
));
3860 dom
= isl_set_intersect(dom
, dom_i
);
3863 isl_pw_aff_list_free(list
);
3864 return nan_on_domain_set(dom
);
3867 /* Return the set where the element at "pos1" of "list" is less than or
3868 * equal to the element at "pos2".
3869 * Equality is only allowed if "pos1" is smaller than "pos2".
3871 static __isl_give isl_set
*less(__isl_keep isl_pw_aff_list
*list
,
3874 isl_pw_aff
*pa1
, *pa2
;
3876 pa1
= isl_pw_aff_list_get_at(list
, pos1
);
3877 pa2
= isl_pw_aff_list_get_at(list
, pos2
);
3880 return isl_pw_aff_le_set(pa1
, pa2
);
3882 return isl_pw_aff_lt_set(pa1
, pa2
);
3885 /* Return an isl_pw_aff that maps each element in the intersection of the
3886 * domains of the piecewise affine expressions in "list"
3887 * to the maximal (if "max" is set) or minimal (if "max" is not set)
3888 * expression in "list" at that element.
3889 * If any expression involves any NaN, then return a NaN
3890 * on the shared domain as result.
3892 * If "list" has n elements, then the result consists of n pieces,
3893 * where, in the case of a minimum, each piece has as value expression
3894 * the value expression of one of the elements and as domain
3895 * the set of elements where that value expression
3896 * is less than (or equal) to the other value expressions.
3897 * In the case of a maximum, the condition is
3898 * that all the other value expressions are less than (or equal)
3899 * to the given value expression.
3901 * In order to produce disjoint pieces, a pair of elements
3902 * in the original domain is only allowed to be equal to each other
3903 * on exactly one of the two pieces corresponding to the two elements.
3904 * The position in the list is used to break ties.
3905 * In particular, in the case of a minimum,
3906 * in the piece corresponding to a given element,
3907 * this element is allowed to be equal to any later element in the list,
3908 * but not to any earlier element in the list.
3910 static __isl_give isl_pw_aff
*isl_pw_aff_list_opt(
3911 __isl_take isl_pw_aff_list
*list
, int max
)
3917 isl_pw_aff
*pa
, *res
;
3919 n
= isl_pw_aff_list_size(list
);
3923 isl_die(isl_pw_aff_list_get_ctx(list
), isl_error_invalid
,
3924 "list should contain at least one element", goto error
);
3926 has_nan
= isl_pw_aff_list_involves_nan(list
);
3930 return replace_list_by_nan(list
, n
);
3932 pa
= isl_pw_aff_list_get_at(list
, 0);
3933 space
= isl_pw_aff_get_space(pa
);
3934 isl_pw_aff_free(pa
);
3935 res
= isl_pw_aff_empty(space
);
3937 for (i
= 0; i
< n
; ++i
) {
3938 pa
= isl_pw_aff_list_get_at(list
, i
);
3939 for (j
= 0; j
< n
; ++j
) {
3945 dom
= less(list
, j
, i
);
3947 dom
= less(list
, i
, j
);
3949 pa
= isl_pw_aff_intersect_domain(pa
, dom
);
3951 res
= isl_pw_aff_add_disjoint(res
, pa
);
3954 isl_pw_aff_list_free(list
);
3957 isl_pw_aff_list_free(list
);
3961 /* Return an isl_pw_aff that maps each element in the intersection of the
3962 * domains of the elements of list to the minimal corresponding affine
3965 __isl_give isl_pw_aff
*isl_pw_aff_list_min(__isl_take isl_pw_aff_list
*list
)
3967 return isl_pw_aff_list_opt(list
, 0);
3970 /* Return an isl_pw_aff that maps each element in the intersection of the
3971 * domains of the elements of list to the maximal corresponding affine
3974 __isl_give isl_pw_aff
*isl_pw_aff_list_max(__isl_take isl_pw_aff_list
*list
)
3976 return isl_pw_aff_list_opt(list
, 1);
3979 /* Mark the domains of "pwaff" as rational.
3981 __isl_give isl_pw_aff
*isl_pw_aff_set_rational(__isl_take isl_pw_aff
*pwaff
)
3985 pwaff
= isl_pw_aff_cow(pwaff
);
3991 for (i
= 0; i
< pwaff
->n
; ++i
) {
3992 pwaff
->p
[i
].set
= isl_set_set_rational(pwaff
->p
[i
].set
);
3993 if (!pwaff
->p
[i
].set
)
3994 return isl_pw_aff_free(pwaff
);
4000 /* Mark the domains of the elements of "list" as rational.
4002 __isl_give isl_pw_aff_list
*isl_pw_aff_list_set_rational(
4003 __isl_take isl_pw_aff_list
*list
)
4013 for (i
= 0; i
< n
; ++i
) {
4016 pa
= isl_pw_aff_list_get_pw_aff(list
, i
);
4017 pa
= isl_pw_aff_set_rational(pa
);
4018 list
= isl_pw_aff_list_set_pw_aff(list
, i
, pa
);
4024 /* Do the parameters of "aff" match those of "space"?
4026 isl_bool
isl_aff_matching_params(__isl_keep isl_aff
*aff
,
4027 __isl_keep isl_space
*space
)
4029 isl_space
*aff_space
;
4033 return isl_bool_error
;
4035 aff_space
= isl_aff_get_domain_space(aff
);
4037 match
= isl_space_has_equal_params(space
, aff_space
);
4039 isl_space_free(aff_space
);
4043 /* Check that the domain space of "aff" matches "space".
4045 isl_stat
isl_aff_check_match_domain_space(__isl_keep isl_aff
*aff
,
4046 __isl_keep isl_space
*space
)
4048 isl_space
*aff_space
;
4052 return isl_stat_error
;
4054 aff_space
= isl_aff_get_domain_space(aff
);
4056 match
= isl_space_has_equal_params(space
, aff_space
);
4060 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
4061 "parameters don't match", goto error
);
4062 match
= isl_space_tuple_is_equal(space
, isl_dim_in
,
4063 aff_space
, isl_dim_set
);
4067 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
4068 "domains don't match", goto error
);
4069 isl_space_free(aff_space
);
4072 isl_space_free(aff_space
);
4073 return isl_stat_error
;
4076 /* Return the shared (universe) domain of the elements of "ma".
4078 * Since an isl_multi_aff (and an isl_aff) is always total,
4079 * the domain is always the universe set in its domain space.
4080 * This is a helper function for use in the generic isl_multi_*_bind.
4082 static __isl_give isl_basic_set
*isl_multi_aff_domain(
4083 __isl_take isl_multi_aff
*ma
)
4087 space
= isl_multi_aff_get_space(ma
);
4088 isl_multi_aff_free(ma
);
4090 return isl_basic_set_universe(isl_space_domain(space
));
4096 #include <isl_multi_no_explicit_domain.c>
4097 #include <isl_multi_templ.c>
4098 #include <isl_multi_un_op_templ.c>
4099 #include <isl_multi_bin_val_templ.c>
4100 #include <isl_multi_add_constant_templ.c>
4101 #include <isl_multi_align_set.c>
4102 #include <isl_multi_arith_templ.c>
4103 #include <isl_multi_bind_domain_templ.c>
4104 #include <isl_multi_cmp.c>
4105 #include <isl_multi_dim_id_templ.c>
4106 #include <isl_multi_dims.c>
4107 #include <isl_multi_domain_reverse_templ.c>
4108 #include <isl_multi_floor.c>
4109 #include <isl_multi_from_base_templ.c>
4110 #include <isl_multi_identity_templ.c>
4111 #include <isl_multi_insert_domain_templ.c>
4112 #include <isl_multi_locals_templ.c>
4113 #include <isl_multi_move_dims_templ.c>
4114 #include <isl_multi_nan_templ.c>
4115 #include <isl_multi_product_templ.c>
4116 #include <isl_multi_splice_templ.c>
4117 #include <isl_multi_tuple_id_templ.c>
4118 #include <isl_multi_unbind_params_templ.c>
4119 #include <isl_multi_zero_templ.c>
4123 #include <isl_multi_check_domain_templ.c>
4124 #include <isl_multi_apply_set_no_explicit_domain_templ.c>
4125 #include <isl_multi_gist.c>
4128 #define DOMBASE basic_set
4129 #include <isl_multi_bind_templ.c>
4131 /* Construct an isl_multi_aff living in "space" that corresponds
4132 * to the affine transformation matrix "mat".
4134 __isl_give isl_multi_aff
*isl_multi_aff_from_aff_mat(
4135 __isl_take isl_space
*space
, __isl_take isl_mat
*mat
)
4138 isl_local_space
*ls
= NULL
;
4139 isl_multi_aff
*ma
= NULL
;
4140 isl_size n_row
, n_col
, n_out
, total
;
4146 ctx
= isl_mat_get_ctx(mat
);
4148 n_row
= isl_mat_rows(mat
);
4149 n_col
= isl_mat_cols(mat
);
4150 n_out
= isl_space_dim(space
, isl_dim_out
);
4151 total
= isl_space_dim(space
, isl_dim_all
);
4152 if (n_row
< 0 || n_col
< 0 || n_out
< 0 || total
< 0)
4155 isl_die(ctx
, isl_error_invalid
,
4156 "insufficient number of rows", goto error
);
4158 isl_die(ctx
, isl_error_invalid
,
4159 "insufficient number of columns", goto error
);
4160 if (1 + n_out
!= n_row
|| 2 + total
!= n_row
+ n_col
)
4161 isl_die(ctx
, isl_error_invalid
,
4162 "dimension mismatch", goto error
);
4164 ma
= isl_multi_aff_zero(isl_space_copy(space
));
4165 space
= isl_space_domain(space
);
4166 ls
= isl_local_space_from_space(isl_space_copy(space
));
4168 for (i
= 0; i
< n_row
- 1; ++i
) {
4172 v
= isl_vec_alloc(ctx
, 1 + n_col
);
4175 isl_int_set(v
->el
[0], mat
->row
[0][0]);
4176 isl_seq_cpy(v
->el
+ 1, mat
->row
[1 + i
], n_col
);
4177 v
= isl_vec_normalize(v
);
4178 aff
= isl_aff_alloc_vec_validated(isl_local_space_copy(ls
), v
);
4179 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
4182 isl_space_free(space
);
4183 isl_local_space_free(ls
);
4187 isl_space_free(space
);
4188 isl_local_space_free(ls
);
4190 isl_multi_aff_free(ma
);
4194 /* Return the constant terms of the affine expressions of "ma".
4196 __isl_give isl_multi_val
*isl_multi_aff_get_constant_multi_val(
4197 __isl_keep isl_multi_aff
*ma
)
4204 n
= isl_multi_aff_size(ma
);
4207 space
= isl_space_range(isl_multi_aff_get_space(ma
));
4208 space
= isl_space_drop_all_params(space
);
4209 mv
= isl_multi_val_zero(space
);
4211 for (i
= 0; i
< n
; ++i
) {
4215 aff
= isl_multi_aff_get_at(ma
, i
);
4216 val
= isl_aff_get_constant_val(aff
);
4218 mv
= isl_multi_val_set_at(mv
, i
, val
);
4224 /* Remove any internal structure of the domain of "ma".
4225 * If there is any such internal structure in the input,
4226 * then the name of the corresponding space is also removed.
4228 __isl_give isl_multi_aff
*isl_multi_aff_flatten_domain(
4229 __isl_take isl_multi_aff
*ma
)
4236 if (!ma
->space
->nested
[0])
4239 space
= isl_multi_aff_get_space(ma
);
4240 space
= isl_space_flatten_domain(space
);
4241 ma
= isl_multi_aff_reset_space(ma
, space
);
4246 /* Given a map space, return an isl_multi_aff that maps a wrapped copy
4247 * of the space to its domain.
4249 __isl_give isl_multi_aff
*isl_multi_aff_domain_map(__isl_take isl_space
*space
)
4253 isl_local_space
*ls
;
4258 if (!isl_space_is_map(space
))
4259 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
4260 "not a map space", goto error
);
4262 n_in
= isl_space_dim(space
, isl_dim_in
);
4265 space
= isl_space_domain_map(space
);
4267 ma
= isl_multi_aff_alloc(isl_space_copy(space
));
4269 isl_space_free(space
);
4273 space
= isl_space_domain(space
);
4274 ls
= isl_local_space_from_space(space
);
4275 for (i
= 0; i
< n_in
; ++i
) {
4278 aff
= isl_aff_var_on_domain(isl_local_space_copy(ls
),
4280 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
4282 isl_local_space_free(ls
);
4285 isl_space_free(space
);
4289 /* This function performs the same operation as isl_multi_aff_domain_map,
4290 * but is considered as a function on an isl_space when exported.
4292 __isl_give isl_multi_aff
*isl_space_domain_map_multi_aff(
4293 __isl_take isl_space
*space
)
4295 return isl_multi_aff_domain_map(space
);
4298 /* Given a map space, return an isl_multi_aff that maps a wrapped copy
4299 * of the space to its range.
4301 __isl_give isl_multi_aff
*isl_multi_aff_range_map(__isl_take isl_space
*space
)
4304 isl_size n_in
, n_out
;
4305 isl_local_space
*ls
;
4310 if (!isl_space_is_map(space
))
4311 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
4312 "not a map space", goto error
);
4314 n_in
= isl_space_dim(space
, isl_dim_in
);
4315 n_out
= isl_space_dim(space
, isl_dim_out
);
4316 if (n_in
< 0 || n_out
< 0)
4318 space
= isl_space_range_map(space
);
4320 ma
= isl_multi_aff_alloc(isl_space_copy(space
));
4322 isl_space_free(space
);
4326 space
= isl_space_domain(space
);
4327 ls
= isl_local_space_from_space(space
);
4328 for (i
= 0; i
< n_out
; ++i
) {
4331 aff
= isl_aff_var_on_domain(isl_local_space_copy(ls
),
4332 isl_dim_set
, n_in
+ i
);
4333 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
4335 isl_local_space_free(ls
);
4338 isl_space_free(space
);
4342 /* This function performs the same operation as isl_multi_aff_range_map,
4343 * but is considered as a function on an isl_space when exported.
4345 __isl_give isl_multi_aff
*isl_space_range_map_multi_aff(
4346 __isl_take isl_space
*space
)
4348 return isl_multi_aff_range_map(space
);
4351 /* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy
4352 * of the space to its domain.
4354 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_domain_map(
4355 __isl_take isl_space
*space
)
4357 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_domain_map(space
));
4360 /* This function performs the same operation as isl_pw_multi_aff_domain_map,
4361 * but is considered as a function on an isl_space when exported.
4363 __isl_give isl_pw_multi_aff
*isl_space_domain_map_pw_multi_aff(
4364 __isl_take isl_space
*space
)
4366 return isl_pw_multi_aff_domain_map(space
);
4369 /* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy
4370 * of the space to its range.
4372 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_range_map(
4373 __isl_take isl_space
*space
)
4375 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_range_map(space
));
4378 /* This function performs the same operation as isl_pw_multi_aff_range_map,
4379 * but is considered as a function on an isl_space when exported.
4381 __isl_give isl_pw_multi_aff
*isl_space_range_map_pw_multi_aff(
4382 __isl_take isl_space
*space
)
4384 return isl_pw_multi_aff_range_map(space
);
4387 /* Given the space of a set and a range of set dimensions,
4388 * construct an isl_multi_aff that projects out those dimensions.
4390 __isl_give isl_multi_aff
*isl_multi_aff_project_out_map(
4391 __isl_take isl_space
*space
, enum isl_dim_type type
,
4392 unsigned first
, unsigned n
)
4396 isl_local_space
*ls
;
4401 if (!isl_space_is_set(space
))
4402 isl_die(isl_space_get_ctx(space
), isl_error_unsupported
,
4403 "expecting set space", goto error
);
4404 if (type
!= isl_dim_set
)
4405 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
4406 "only set dimensions can be projected out", goto error
);
4407 if (isl_space_check_range(space
, type
, first
, n
) < 0)
4410 dim
= isl_space_dim(space
, isl_dim_set
);
4414 space
= isl_space_from_domain(space
);
4415 space
= isl_space_add_dims(space
, isl_dim_out
, dim
- n
);
4418 return isl_multi_aff_alloc(space
);
4420 ma
= isl_multi_aff_alloc(isl_space_copy(space
));
4421 space
= isl_space_domain(space
);
4422 ls
= isl_local_space_from_space(space
);
4424 for (i
= 0; i
< first
; ++i
) {
4427 aff
= isl_aff_var_on_domain(isl_local_space_copy(ls
),
4429 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
4432 for (i
= 0; i
< dim
- (first
+ n
); ++i
) {
4435 aff
= isl_aff_var_on_domain(isl_local_space_copy(ls
),
4436 isl_dim_set
, first
+ n
+ i
);
4437 ma
= isl_multi_aff_set_aff(ma
, first
+ i
, aff
);
4440 isl_local_space_free(ls
);
4443 isl_space_free(space
);
4447 /* Given the space of a set and a range of set dimensions,
4448 * construct an isl_pw_multi_aff that projects out those dimensions.
4450 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_project_out_map(
4451 __isl_take isl_space
*space
, enum isl_dim_type type
,
4452 unsigned first
, unsigned n
)
4456 ma
= isl_multi_aff_project_out_map(space
, type
, first
, n
);
4457 return isl_pw_multi_aff_from_multi_aff(ma
);
4460 /* This function performs the same operation as isl_pw_multi_aff_from_multi_aff,
4461 * but is considered as a function on an isl_multi_aff when exported.
4463 __isl_give isl_pw_multi_aff
*isl_multi_aff_to_pw_multi_aff(
4464 __isl_take isl_multi_aff
*ma
)
4466 return isl_pw_multi_aff_from_multi_aff(ma
);
4469 /* Create a piecewise multi-affine expression in the given space that maps each
4470 * input dimension to the corresponding output dimension.
4472 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_identity(
4473 __isl_take isl_space
*space
)
4475 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_identity(space
));
4478 /* Create a piecewise multi expression that maps elements in the given space
4481 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_identity_on_domain_space(
4482 __isl_take isl_space
*space
)
4486 ma
= isl_multi_aff_identity_on_domain_space(space
);
4487 return isl_pw_multi_aff_from_multi_aff(ma
);
4490 /* This function performs the same operation as
4491 * isl_pw_multi_aff_identity_on_domain_space,
4492 * but is considered as a function on an isl_space when exported.
4494 __isl_give isl_pw_multi_aff
*isl_space_identity_pw_multi_aff_on_domain(
4495 __isl_take isl_space
*space
)
4497 return isl_pw_multi_aff_identity_on_domain_space(space
);
4500 /* Exploit the equalities in "eq" to simplify the affine expressions.
4502 static __isl_give isl_multi_aff
*isl_multi_aff_substitute_equalities(
4503 __isl_take isl_multi_aff
*maff
, __isl_take isl_basic_set
*eq
)
4508 n
= isl_multi_aff_size(maff
);
4512 for (i
= 0; i
< n
; ++i
) {
4515 aff
= isl_multi_aff_take_at(maff
, i
);
4516 aff
= isl_aff_substitute_equalities(aff
,
4517 isl_basic_set_copy(eq
));
4518 maff
= isl_multi_aff_restore_at(maff
, i
, aff
);
4521 isl_basic_set_free(eq
);
4524 isl_basic_set_free(eq
);
4525 isl_multi_aff_free(maff
);
4529 __isl_give isl_multi_aff
*isl_multi_aff_scale(__isl_take isl_multi_aff
*maff
,
4535 n
= isl_multi_aff_size(maff
);
4537 return isl_multi_aff_free(maff
);
4539 for (i
= 0; i
< n
; ++i
) {
4542 aff
= isl_multi_aff_take_at(maff
, i
);
4543 aff
= isl_aff_scale(aff
, f
);
4544 maff
= isl_multi_aff_restore_at(maff
, i
, aff
);
4550 __isl_give isl_multi_aff
*isl_multi_aff_add_on_domain(__isl_keep isl_set
*dom
,
4551 __isl_take isl_multi_aff
*maff1
, __isl_take isl_multi_aff
*maff2
)
4553 maff1
= isl_multi_aff_add(maff1
, maff2
);
4554 maff1
= isl_multi_aff_gist(maff1
, isl_set_copy(dom
));
4558 isl_bool
isl_multi_aff_is_empty(__isl_keep isl_multi_aff
*maff
)
4561 return isl_bool_error
;
4563 return isl_bool_false
;
4566 /* Return the set of domain elements where "ma1" is lexicographically
4567 * smaller than or equal to "ma2".
4569 __isl_give isl_set
*isl_multi_aff_lex_le_set(__isl_take isl_multi_aff
*ma1
,
4570 __isl_take isl_multi_aff
*ma2
)
4572 return isl_multi_aff_lex_ge_set(ma2
, ma1
);
4575 /* Return the set of domain elements where "ma1" is lexicographically
4576 * smaller than "ma2".
4578 __isl_give isl_set
*isl_multi_aff_lex_lt_set(__isl_take isl_multi_aff
*ma1
,
4579 __isl_take isl_multi_aff
*ma2
)
4581 return isl_multi_aff_lex_gt_set(ma2
, ma1
);
4584 /* Return the set of domain elements where "ma1" is lexicographically
4585 * greater than to "ma2". If "equal" is set, then include the domain
4586 * elements where they are equal.
4587 * Do this for the case where there are no entries.
4588 * In this case, "ma1" cannot be greater than "ma2",
4589 * but it is (greater than or) equal to "ma2".
4591 static __isl_give isl_set
*isl_multi_aff_lex_gte_set_0d(
4592 __isl_take isl_multi_aff
*ma1
, __isl_take isl_multi_aff
*ma2
, int equal
)
4596 space
= isl_multi_aff_get_domain_space(ma1
);
4598 isl_multi_aff_free(ma1
);
4599 isl_multi_aff_free(ma2
);
4602 return isl_set_universe(space
);
4604 return isl_set_empty(space
);
4607 /* Return the set where entry "i" of "ma1" and "ma2"
4608 * satisfy the relation prescribed by "cmp".
4610 static __isl_give isl_set
*isl_multi_aff_order_at(__isl_keep isl_multi_aff
*ma1
,
4611 __isl_keep isl_multi_aff
*ma2
, int i
,
4612 __isl_give isl_set
*(*cmp
)(__isl_take isl_aff
*aff1
,
4613 __isl_take isl_aff
*aff2
))
4615 isl_aff
*aff1
, *aff2
;
4617 aff1
= isl_multi_aff_get_at(ma1
, i
);
4618 aff2
= isl_multi_aff_get_at(ma2
, i
);
4619 return cmp(aff1
, aff2
);
4622 /* Return the set of domain elements where "ma1" is lexicographically
4623 * greater than to "ma2". If "equal" is set, then include the domain
4624 * elements where they are equal.
4626 * In particular, for all but the final entry,
4627 * include the set of elements where this entry is strictly greater in "ma1"
4628 * and all previous entries are equal.
4629 * The final entry is also allowed to be equal in the two functions
4630 * if "equal" is set.
4632 * The case where there are no entries is handled separately.
4634 static __isl_give isl_set
*isl_multi_aff_lex_gte_set(
4635 __isl_take isl_multi_aff
*ma1
, __isl_take isl_multi_aff
*ma2
, int equal
)
4644 if (isl_multi_aff_check_equal_space(ma1
, ma2
) < 0)
4646 n
= isl_multi_aff_size(ma1
);
4650 return isl_multi_aff_lex_gte_set_0d(ma1
, ma2
, equal
);
4652 space
= isl_multi_aff_get_domain_space(ma1
);
4653 res
= isl_set_empty(isl_space_copy(space
));
4654 equal_set
= isl_set_universe(space
);
4656 for (i
= 0; i
+ 1 < n
; ++i
) {
4660 gt
= isl_multi_aff_order_at(ma1
, ma2
, i
, &isl_aff_gt_set
);
4661 gt
= isl_set_intersect(gt
, isl_set_copy(equal_set
));
4662 res
= isl_set_union(res
, gt
);
4663 eq
= isl_multi_aff_order_at(ma1
, ma2
, i
, &isl_aff_eq_set
);
4664 equal_set
= isl_set_intersect(equal_set
, eq
);
4666 empty
= isl_set_is_empty(equal_set
);
4667 if (empty
>= 0 && empty
)
4672 gte
= isl_multi_aff_order_at(ma1
, ma2
, n
- 1, &isl_aff_ge_set
);
4674 gte
= isl_multi_aff_order_at(ma1
, ma2
, n
- 1, &isl_aff_gt_set
);
4675 isl_multi_aff_free(ma1
);
4676 isl_multi_aff_free(ma2
);
4678 gte
= isl_set_intersect(gte
, equal_set
);
4679 return isl_set_union(res
, gte
);
4681 isl_multi_aff_free(ma1
);
4682 isl_multi_aff_free(ma2
);
4686 /* Return the set of domain elements where "ma1" is lexicographically
4687 * greater than or equal to "ma2".
4689 __isl_give isl_set
*isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff
*ma1
,
4690 __isl_take isl_multi_aff
*ma2
)
4692 return isl_multi_aff_lex_gte_set(ma1
, ma2
, 1);
4695 /* Return the set of domain elements where "ma1" is lexicographically
4696 * greater than "ma2".
4698 __isl_give isl_set
*isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff
*ma1
,
4699 __isl_take isl_multi_aff
*ma2
)
4701 return isl_multi_aff_lex_gte_set(ma1
, ma2
, 0);
4704 #define isl_multi_aff_zero_in_space isl_multi_aff_zero
4707 #define PW isl_pw_multi_aff
4709 #define BASE multi_aff
4711 #define EL_IS_ZERO is_empty
4715 #define IS_ZERO is_empty
4718 #undef DEFAULT_IS_ZERO
4719 #define DEFAULT_IS_ZERO 0
4721 #include <isl_pw_templ.c>
4722 #include <isl_pw_un_op_templ.c>
4723 #include <isl_pw_add_constant_multi_val_templ.c>
4724 #include <isl_pw_add_constant_val_templ.c>
4725 #include <isl_pw_add_disjoint_templ.c>
4726 #include <isl_pw_bind_domain_templ.c>
4727 #include <isl_pw_domain_reverse_templ.c>
4728 #include <isl_pw_fix_templ.c>
4729 #include <isl_pw_from_range_templ.c>
4730 #include <isl_pw_insert_dims_templ.c>
4731 #include <isl_pw_insert_domain_templ.c>
4732 #include <isl_pw_locals_templ.c>
4733 #include <isl_pw_move_dims_templ.c>
4734 #include <isl_pw_neg_templ.c>
4735 #include <isl_pw_pullback_templ.c>
4736 #include <isl_pw_range_tuple_id_templ.c>
4737 #include <isl_pw_union_opt.c>
4740 #define BASE pw_multi_aff
4742 #include <isl_union_multi.c>
4743 #include "isl_union_locals_templ.c"
4744 #include <isl_union_neg.c>
4745 #include <isl_union_sub_templ.c>
4748 #define BASE multi_aff
4750 #include <isl_union_pw_templ.c>
4752 /* Generic function for extracting a factor from a product "pma".
4753 * "check_space" checks that the space is that of the right kind of product.
4754 * "space_factor" extracts the factor from the space.
4755 * "multi_aff_factor" extracts the factor from the constituent functions.
4757 static __isl_give isl_pw_multi_aff
*pw_multi_aff_factor(
4758 __isl_take isl_pw_multi_aff
*pma
,
4759 isl_stat (*check_space
)(__isl_keep isl_pw_multi_aff
*pma
),
4760 __isl_give isl_space
*(*space_factor
)(__isl_take isl_space
*space
),
4761 __isl_give isl_multi_aff
*(*multi_aff_factor
)(
4762 __isl_take isl_multi_aff
*ma
))
4767 if (check_space(pma
) < 0)
4768 return isl_pw_multi_aff_free(pma
);
4770 space
= isl_pw_multi_aff_take_space(pma
);
4771 space
= space_factor(space
);
4773 for (i
= 0; pma
&& i
< pma
->n
; ++i
) {
4776 ma
= isl_pw_multi_aff_take_base_at(pma
, i
);
4777 ma
= multi_aff_factor(ma
);
4778 pma
= isl_pw_multi_aff_restore_base_at(pma
, i
, ma
);
4781 pma
= isl_pw_multi_aff_restore_space(pma
, space
);
4786 /* Is the range of "pma" a wrapped relation?
4788 static isl_bool
isl_pw_multi_aff_range_is_wrapping(
4789 __isl_keep isl_pw_multi_aff
*pma
)
4791 return isl_space_range_is_wrapping(isl_pw_multi_aff_peek_space(pma
));
4794 /* Check that the range of "pma" is a product.
4796 static isl_stat
pw_multi_aff_check_range_product(
4797 __isl_keep isl_pw_multi_aff
*pma
)
4801 wraps
= isl_pw_multi_aff_range_is_wrapping(pma
);
4803 return isl_stat_error
;
4805 isl_die(isl_pw_multi_aff_get_ctx(pma
), isl_error_invalid
,
4806 "range is not a product", return isl_stat_error
);
4810 /* Given a function A -> [B -> C], extract the function A -> B.
4812 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_range_factor_domain(
4813 __isl_take isl_pw_multi_aff
*pma
)
4815 return pw_multi_aff_factor(pma
, &pw_multi_aff_check_range_product
,
4816 &isl_space_range_factor_domain
,
4817 &isl_multi_aff_range_factor_domain
);
4820 /* Given a function A -> [B -> C], extract the function A -> C.
4822 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_range_factor_range(
4823 __isl_take isl_pw_multi_aff
*pma
)
4825 return pw_multi_aff_factor(pma
, &pw_multi_aff_check_range_product
,
4826 &isl_space_range_factor_range
,
4827 &isl_multi_aff_range_factor_range
);
4830 /* Given two piecewise multi affine expressions, return a piecewise
4831 * multi-affine expression defined on the union of the definition domains
4832 * of the inputs that is equal to the lexicographic maximum of the two
4833 * inputs on each cell. If only one of the two inputs is defined on
4834 * a given cell, then it is considered to be the maximum.
4836 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_union_lexmax(
4837 __isl_take isl_pw_multi_aff
*pma1
,
4838 __isl_take isl_pw_multi_aff
*pma2
)
4840 isl_pw_multi_aff_align_params_bin(&pma1
, &pma2
);
4841 return isl_pw_multi_aff_union_opt_cmp(pma1
, pma2
,
4842 &isl_multi_aff_lex_ge_set
);
4845 /* Given two piecewise multi affine expressions, return a piecewise
4846 * multi-affine expression defined on the union of the definition domains
4847 * of the inputs that is equal to the lexicographic minimum of the two
4848 * inputs on each cell. If only one of the two inputs is defined on
4849 * a given cell, then it is considered to be the minimum.
4851 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_union_lexmin(
4852 __isl_take isl_pw_multi_aff
*pma1
,
4853 __isl_take isl_pw_multi_aff
*pma2
)
4855 isl_pw_multi_aff_align_params_bin(&pma1
, &pma2
);
4856 return isl_pw_multi_aff_union_opt_cmp(pma1
, pma2
,
4857 &isl_multi_aff_lex_le_set
);
4860 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_add(
4861 __isl_take isl_pw_multi_aff
*pma1
, __isl_take isl_pw_multi_aff
*pma2
)
4863 isl_pw_multi_aff_align_params_bin(&pma1
, &pma2
);
4864 return isl_pw_multi_aff_on_shared_domain(pma1
, pma2
,
4865 &isl_multi_aff_add
);
4868 /* Subtract "pma2" from "pma1" and return the result.
4870 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_sub(
4871 __isl_take isl_pw_multi_aff
*pma1
, __isl_take isl_pw_multi_aff
*pma2
)
4873 isl_pw_multi_aff_align_params_bin(&pma1
, &pma2
);
4874 return isl_pw_multi_aff_on_shared_domain(pma1
, pma2
,
4875 &isl_multi_aff_sub
);
4878 /* Given two piecewise multi-affine expressions A -> B and C -> D,
4879 * construct a piecewise multi-affine expression [A -> C] -> [B -> D].
4881 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_product(
4882 __isl_take isl_pw_multi_aff
*pma1
, __isl_take isl_pw_multi_aff
*pma2
)
4886 isl_pw_multi_aff
*res
;
4888 if (isl_pw_multi_aff_align_params_bin(&pma1
, &pma2
) < 0)
4891 n
= pma1
->n
* pma2
->n
;
4892 space
= isl_space_product(isl_space_copy(pma1
->dim
),
4893 isl_space_copy(pma2
->dim
));
4894 res
= isl_pw_multi_aff_alloc_size(space
, n
);
4896 for (i
= 0; i
< pma1
->n
; ++i
) {
4897 for (j
= 0; j
< pma2
->n
; ++j
) {
4901 domain
= isl_set_product(isl_set_copy(pma1
->p
[i
].set
),
4902 isl_set_copy(pma2
->p
[j
].set
));
4903 ma
= isl_multi_aff_product(
4904 isl_multi_aff_copy(pma1
->p
[i
].maff
),
4905 isl_multi_aff_copy(pma2
->p
[j
].maff
));
4906 res
= isl_pw_multi_aff_add_piece(res
, domain
, ma
);
4910 isl_pw_multi_aff_free(pma1
);
4911 isl_pw_multi_aff_free(pma2
);
4914 isl_pw_multi_aff_free(pma1
);
4915 isl_pw_multi_aff_free(pma2
);
4919 /* Subtract the initial "n" elements in "ma" with coefficients in "c" and
4920 * denominator "denom".
4921 * "denom" is allowed to be negative, in which case the actual denominator
4922 * is -denom and the expressions are added instead.
4924 static __isl_give isl_aff
*subtract_initial(__isl_take isl_aff
*aff
,
4925 __isl_keep isl_multi_aff
*ma
, int n
, isl_int
*c
, isl_int denom
)
4931 first
= isl_seq_first_non_zero(c
, n
);
4935 sign
= isl_int_sgn(denom
);
4937 isl_int_abs(d
, denom
);
4938 for (i
= first
; i
< n
; ++i
) {
4941 if (isl_int_is_zero(c
[i
]))
4943 aff_i
= isl_multi_aff_get_aff(ma
, i
);
4944 aff_i
= isl_aff_scale(aff_i
, c
[i
]);
4945 aff_i
= isl_aff_scale_down(aff_i
, d
);
4947 aff
= isl_aff_sub(aff
, aff_i
);
4949 aff
= isl_aff_add(aff
, aff_i
);
4956 /* Extract an affine expression that expresses the output dimension "pos"
4957 * of "bmap" in terms of the parameters and input dimensions from
4959 * Note that this expression may involve integer divisions defined
4960 * in terms of parameters and input dimensions.
4961 * The equality may also involve references to earlier (but not later)
4962 * output dimensions. These are replaced by the corresponding elements
4965 * If the equality is of the form
4967 * f(i) + h(j) + a x + g(i) = 0,
4969 * with f(i) a linear combinations of the parameters and input dimensions,
4970 * g(i) a linear combination of integer divisions defined in terms of the same
4971 * and h(j) a linear combinations of earlier output dimensions,
4972 * then the affine expression is
4974 * (-f(i) - g(i))/a - h(j)/a
4976 * If the equality is of the form
4978 * f(i) + h(j) - a x + g(i) = 0,
4980 * then the affine expression is
4982 * (f(i) + g(i))/a - h(j)/(-a)
4985 * If "div" refers to an integer division (i.e., it is smaller than
4986 * the number of integer divisions), then the equality constraint
4987 * does involve an integer division (the one at position "div") that
4988 * is defined in terms of output dimensions. However, this integer
4989 * division can be eliminated by exploiting a pair of constraints
4990 * x >= l and x <= l + n, with n smaller than the coefficient of "div"
4991 * in the equality constraint. "ineq" refers to inequality x >= l, i.e.,
4993 * In particular, let
4995 * x = e(i) + m floor(...)
4997 * with e(i) the expression derived above and floor(...) the integer
4998 * division involving output dimensions.
5009 * e(i) + m floor(...) - l = (e(i) + m floor(...) - l) mod m
5010 * = (e(i) - l) mod m
5014 * x - l = (e(i) - l) mod m
5018 * x = ((e(i) - l) mod m) + l
5020 * The variable "shift" below contains the expression -l, which may
5021 * also involve a linear combination of earlier output dimensions.
5023 static __isl_give isl_aff
*extract_aff_from_equality(
5024 __isl_keep isl_basic_map
*bmap
, int pos
, int eq
, int div
, int ineq
,
5025 __isl_keep isl_multi_aff
*ma
)
5028 isl_size n_div
, n_out
;
5030 isl_local_space
*ls
;
5031 isl_aff
*aff
, *shift
;
5034 ctx
= isl_basic_map_get_ctx(bmap
);
5035 ls
= isl_basic_map_get_local_space(bmap
);
5036 ls
= isl_local_space_domain(ls
);
5037 aff
= isl_aff_alloc(isl_local_space_copy(ls
));
5040 o_out
= isl_basic_map_offset(bmap
, isl_dim_out
);
5041 n_out
= isl_basic_map_dim(bmap
, isl_dim_out
);
5042 n_div
= isl_basic_map_dim(bmap
, isl_dim_div
);
5043 if (n_out
< 0 || n_div
< 0)
5045 if (isl_int_is_neg(bmap
->eq
[eq
][o_out
+ pos
])) {
5046 isl_seq_cpy(aff
->v
->el
+ 1, bmap
->eq
[eq
], o_out
);
5047 isl_seq_cpy(aff
->v
->el
+ 1 + o_out
,
5048 bmap
->eq
[eq
] + o_out
+ n_out
, n_div
);
5050 isl_seq_neg(aff
->v
->el
+ 1, bmap
->eq
[eq
], o_out
);
5051 isl_seq_neg(aff
->v
->el
+ 1 + o_out
,
5052 bmap
->eq
[eq
] + o_out
+ n_out
, n_div
);
5055 isl_int_set_si(aff
->v
->el
[1 + o_out
+ div
], 0);
5056 isl_int_abs(aff
->v
->el
[0], bmap
->eq
[eq
][o_out
+ pos
]);
5057 aff
= subtract_initial(aff
, ma
, pos
, bmap
->eq
[eq
] + o_out
,
5058 bmap
->eq
[eq
][o_out
+ pos
]);
5060 shift
= isl_aff_alloc(isl_local_space_copy(ls
));
5063 isl_seq_cpy(shift
->v
->el
+ 1, bmap
->ineq
[ineq
], o_out
);
5064 isl_seq_cpy(shift
->v
->el
+ 1 + o_out
,
5065 bmap
->ineq
[ineq
] + o_out
+ n_out
, n_div
);
5066 isl_int_set_si(shift
->v
->el
[0], 1);
5067 shift
= subtract_initial(shift
, ma
, pos
,
5068 bmap
->ineq
[ineq
] + o_out
, ctx
->negone
);
5069 aff
= isl_aff_add(aff
, isl_aff_copy(shift
));
5070 mod
= isl_val_int_from_isl_int(ctx
,
5071 bmap
->eq
[eq
][o_out
+ n_out
+ div
]);
5072 mod
= isl_val_abs(mod
);
5073 aff
= isl_aff_mod_val(aff
, mod
);
5074 aff
= isl_aff_sub(aff
, shift
);
5077 isl_local_space_free(ls
);
5080 isl_local_space_free(ls
);
5085 /* Given a basic map with output dimensions defined
5086 * in terms of the parameters input dimensions and earlier
5087 * output dimensions using an equality (and possibly a pair on inequalities),
5088 * extract an isl_aff that expresses output dimension "pos" in terms
5089 * of the parameters and input dimensions.
5090 * Note that this expression may involve integer divisions defined
5091 * in terms of parameters and input dimensions.
5092 * "ma" contains the expressions corresponding to earlier output dimensions.
5094 * This function shares some similarities with
5095 * isl_basic_map_has_defining_equality and isl_constraint_get_bound.
5097 static __isl_give isl_aff
*extract_isl_aff_from_basic_map(
5098 __isl_keep isl_basic_map
*bmap
, int pos
, __isl_keep isl_multi_aff
*ma
)
5105 eq
= isl_basic_map_output_defining_equality(bmap
, pos
, &div
, &ineq
);
5106 if (eq
>= bmap
->n_eq
)
5107 isl_die(isl_basic_map_get_ctx(bmap
), isl_error_invalid
,
5108 "unable to find suitable equality", return NULL
);
5109 aff
= extract_aff_from_equality(bmap
, pos
, eq
, div
, ineq
, ma
);
5111 aff
= isl_aff_remove_unused_divs(aff
);
5115 /* Given a basic map where each output dimension is defined
5116 * in terms of the parameters and input dimensions using an equality,
5117 * extract an isl_multi_aff that expresses the output dimensions in terms
5118 * of the parameters and input dimensions.
5120 static __isl_give isl_multi_aff
*extract_isl_multi_aff_from_basic_map(
5121 __isl_take isl_basic_map
*bmap
)
5130 ma
= isl_multi_aff_alloc(isl_basic_map_get_space(bmap
));
5131 n_out
= isl_basic_map_dim(bmap
, isl_dim_out
);
5133 ma
= isl_multi_aff_free(ma
);
5135 for (i
= 0; i
< n_out
; ++i
) {
5138 aff
= extract_isl_aff_from_basic_map(bmap
, i
, ma
);
5139 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
5142 isl_basic_map_free(bmap
);
5147 /* Given a basic set where each set dimension is defined
5148 * in terms of the parameters using an equality,
5149 * extract an isl_multi_aff that expresses the set dimensions in terms
5150 * of the parameters.
5152 __isl_give isl_multi_aff
*isl_multi_aff_from_basic_set_equalities(
5153 __isl_take isl_basic_set
*bset
)
5155 return extract_isl_multi_aff_from_basic_map(bset
);
5158 /* Create an isl_pw_multi_aff that is equivalent to
5159 * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain).
5160 * The given basic map is such that each output dimension is defined
5161 * in terms of the parameters and input dimensions using an equality.
5163 * Since some applications expect the result of isl_pw_multi_aff_from_map
5164 * to only contain integer affine expressions, we compute the floor
5165 * of the expression before returning.
5167 * Remove all constraints involving local variables without
5168 * an explicit representation (resulting in the removal of those
5169 * local variables) prior to the actual extraction to ensure
5170 * that the local spaces in which the resulting affine expressions
5171 * are created do not contain any unknown local variables.
5172 * Removing such constraints is safe because constraints involving
5173 * unknown local variables are not used to determine whether
5174 * a basic map is obviously single-valued.
5176 static __isl_give isl_pw_multi_aff
*plain_pw_multi_aff_from_map(
5177 __isl_take isl_set
*domain
, __isl_take isl_basic_map
*bmap
)
5181 bmap
= isl_basic_map_drop_constraints_involving_unknown_divs(bmap
);
5182 ma
= extract_isl_multi_aff_from_basic_map(bmap
);
5183 ma
= isl_multi_aff_floor(ma
);
5184 return isl_pw_multi_aff_alloc(domain
, ma
);
5187 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5188 * This obviously only works if the input "map" is single-valued.
5189 * If so, we compute the lexicographic minimum of the image in the form
5190 * of an isl_pw_multi_aff. Since the image is unique, it is equal
5191 * to its lexicographic minimum.
5192 * If the input is not single-valued, we produce an error.
5194 static __isl_give isl_pw_multi_aff
*pw_multi_aff_from_map_base(
5195 __isl_take isl_map
*map
)
5199 isl_pw_multi_aff
*pma
;
5201 sv
= isl_map_is_single_valued(map
);
5205 isl_die(isl_map_get_ctx(map
), isl_error_invalid
,
5206 "map is not single-valued", goto error
);
5207 map
= isl_map_make_disjoint(map
);
5211 pma
= isl_pw_multi_aff_empty(isl_map_get_space(map
));
5213 for (i
= 0; i
< map
->n
; ++i
) {
5214 isl_pw_multi_aff
*pma_i
;
5215 isl_basic_map
*bmap
;
5216 bmap
= isl_basic_map_copy(map
->p
[i
]);
5217 pma_i
= isl_basic_map_lexmin_pw_multi_aff(bmap
);
5218 pma
= isl_pw_multi_aff_add_disjoint(pma
, pma_i
);
5228 /* Construct an isl_aff from the given domain local space "ls" and
5229 * coefficients "v", where the local space may involve
5230 * local variables without a known expression, as long as these
5231 * do not have a non-zero coefficient in "v".
5232 * These need to be pruned away first since an isl_aff cannot
5233 * reference any local variables without a known expression.
5234 * For simplicity, remove all local variables that have a zero coefficient and
5235 * that are not used in other local variables with a non-zero coefficient.
5237 static __isl_give isl_aff
*isl_aff_alloc_vec_prune(
5238 __isl_take isl_local_space
*ls
, __isl_take isl_vec
*v
)
5241 isl_size n_div
, v_div
;
5243 n_div
= isl_local_space_dim(ls
, isl_dim_div
);
5244 v_div
= isl_local_space_var_offset(ls
, isl_dim_div
);
5245 if (n_div
< 0 || v_div
< 0 || !v
)
5247 for (i
= n_div
- 1; i
>= 0; --i
) {
5250 if (!isl_int_is_zero(v
->el
[1 + 1 + v_div
+ i
]))
5252 involves
= isl_local_space_involves_dims(ls
, isl_dim_div
, i
, 1);
5257 ls
= isl_local_space_drop_dims(ls
, isl_dim_div
, i
, 1);
5258 v
= isl_vec_drop_els(v
, 1 + 1 + v_div
+ i
, 1);
5263 return isl_aff_alloc_vec(ls
, v
);
5265 isl_local_space_free(ls
);
5270 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
5271 * taking into account that the output dimension at position "d"
5272 * is equal to some expression f in the parameters and input dimensions
5273 * represented by "aff".
5275 * Let "map" be of the form
5279 * Construct a mapping
5283 * apply that to the map, obtaining
5287 * and equate dimension "d" to x.
5288 * An isl_pw_multi_aff representation of this map is then computed and
5289 * the above expression is plugged in in the result.
5291 static __isl_give isl_pw_multi_aff
*pw_multi_aff_from_map_plug_in(
5292 __isl_take isl_map
*map
, int d
, __isl_take isl_aff
*aff
)
5297 isl_pw_multi_aff
*pma
;
5300 is_set
= isl_map_is_set(map
);
5304 n_in
= is_set
? 0 : isl_map_dim(map
, isl_dim_in
);
5309 ma
= isl_multi_aff_from_aff(aff
);
5313 space
= isl_space_domain(isl_map_get_space(map
));
5314 ma
= isl_multi_aff_identity(isl_space_map_from_set(space
));
5315 ma
= isl_multi_aff_range_product(ma
,
5316 isl_multi_aff_from_aff(aff
));
5319 insert
= isl_map_from_multi_aff_internal(isl_multi_aff_copy(ma
));
5320 map
= isl_map_apply_domain(map
, insert
);
5321 map
= isl_map_equate(map
, isl_dim_in
, n_in
, isl_dim_out
, d
);
5322 pma
= isl_pw_multi_aff_from_map(map
);
5323 pma
= isl_pw_multi_aff_pullback_multi_aff(pma
, ma
);
5332 /* Look for a pair of constraints in "hull" that ensure
5333 * that output dimension "d" is equal to some integer division expression
5334 * in the parameters and input dimensions and
5335 * return this expression if found.
5337 * In particular, looks for a pair of constraints
5339 * e(...) + c1 - m x >= 0 i.e., m x <= e(...) + c1
5343 * -e(...) + c2 + m x >= 0 i.e., m x >= e(...) - c2
5345 * where m > 1 and e only depends on parameters and input dimensions,
5348 * c1 + c2 < m i.e., -c2 >= c1 - (m - 1)
5350 * If such a pair of constraints can be found
5353 * x = floor((e(...) + c1) / m)
5355 * with e(...) an expression that does not involve any other output dimensions.
5357 * Note that we know that
5361 * If c1 + c2 were 0, then we would have detected an equality during
5362 * simplification. If c1 + c2 were negative, then we would have detected
5365 * The constraint defining the integer division is guaranteed not to involve
5366 * any local variables without a known expression, but such local variables
5367 * may appear in other constraints. They therefore need to be removed
5368 * during the construction of the affine expression.
5370 static __isl_give isl_maybe_isl_aff
isl_basic_map_try_find_output_div(
5371 __isl_keep isl_basic_map
*hull
, int d
)
5375 isl_maybe_isl_aff res
= { isl_bool_false
, NULL
};
5376 isl_local_space
*ls
;
5381 n_ineq
= isl_basic_map_n_inequality(hull
);
5385 i
= isl_basic_map_find_output_upper_div_constraint(hull
, d
);
5391 is_set
= isl_basic_map_is_set(hull
);
5393 hull
= isl_basic_map_free(hull
);
5395 ls
= isl_basic_map_get_local_space(hull
);
5397 ls
= isl_local_space_wrap(ls
);
5398 v
= isl_basic_map_inequality_extract_output_upper_bound(hull
, i
, d
);
5400 aff
= isl_aff_alloc_vec_prune(ls
, v
);
5401 aff
= isl_aff_floor(aff
);
5404 aff
= isl_aff_project_domain_on_params(aff
);
5406 aff
= isl_aff_domain_factor_domain(aff
);
5408 res
.valid
= isl_bool_true
;
5412 res
.valid
= isl_bool_error
;
5416 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5418 * As a special case, we first check if there is any pair of constraints,
5419 * shared by all the basic maps in "map" that force a given dimension
5420 * to be equal to the floor or modulo of some affine combination
5421 * of the input dimensions.
5423 * Sort the constraints first to make it easier to find such pairs
5426 static __isl_give isl_pw_multi_aff
*pw_multi_aff_from_map_check_div_mod(
5427 __isl_take isl_map
*map
)
5431 isl_basic_map
*hull
;
5433 hull
= isl_map_unshifted_simple_hull(isl_map_copy(map
));
5434 hull
= isl_basic_map_sort_constraints(hull
);
5435 dim
= isl_map_dim(map
, isl_dim_out
);
5439 dim
= isl_map_dim(map
, isl_dim_out
);
5440 for (d
= 0; d
< dim
; ++d
) {
5441 isl_maybe_isl_aff sub
;
5443 sub
= isl_basic_map_try_find_output_div(hull
, d
);
5444 if (sub
.valid
>= 0 && !sub
.valid
)
5445 sub
= isl_basic_map_try_find_output_mod(hull
, d
);
5450 isl_basic_map_free(hull
);
5451 return pw_multi_aff_from_map_plug_in(map
, d
, sub
.value
);
5453 isl_basic_map_free(hull
);
5454 return pw_multi_aff_from_map_base(map
);
5457 isl_basic_map_free(hull
);
5461 /* Given an affine expression
5463 * [A -> B] -> f(A,B)
5465 * construct an isl_multi_aff
5469 * such that dimension "d" in B' is set to "aff" and the remaining
5470 * dimensions are set equal to the corresponding dimensions in B.
5471 * "n_in" is the dimension of the space A.
5472 * "n_out" is the dimension of the space B.
5474 * If "is_set" is set, then the affine expression is of the form
5478 * and we construct an isl_multi_aff
5482 static __isl_give isl_multi_aff
*range_map(__isl_take isl_aff
*aff
, int d
,
5483 unsigned n_in
, unsigned n_out
, int is_set
)
5487 isl_space
*space
, *space2
;
5488 isl_local_space
*ls
;
5490 space
= isl_aff_get_domain_space(aff
);
5491 ls
= isl_local_space_from_space(isl_space_copy(space
));
5492 space2
= isl_space_copy(space
);
5494 space2
= isl_space_range(isl_space_unwrap(space2
));
5495 space
= isl_space_map_from_domain_and_range(space
, space2
);
5496 ma
= isl_multi_aff_alloc(space
);
5497 ma
= isl_multi_aff_set_aff(ma
, d
, aff
);
5499 for (i
= 0; i
< n_out
; ++i
) {
5502 aff
= isl_aff_var_on_domain(isl_local_space_copy(ls
),
5503 isl_dim_set
, n_in
+ i
);
5504 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
5507 isl_local_space_free(ls
);
5512 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
5513 * taking into account that the dimension at position "d" can be written as
5515 * x = m a + f(..) (1)
5517 * where m is equal to "gcd".
5518 * "i" is the index of the equality in "hull" that defines f(..).
5519 * In particular, the equality is of the form
5521 * f(..) - x + m g(existentials) = 0
5525 * -f(..) + x + m g(existentials) = 0
5527 * We basically plug (1) into "map", resulting in a map with "a"
5528 * in the range instead of "x". The corresponding isl_pw_multi_aff
5529 * defining "a" is then plugged back into (1) to obtain a definition for "x".
5531 * Specifically, given the input map
5535 * We first wrap it into a set
5539 * and define (1) on top of the corresponding space, resulting in "aff".
5540 * We use this to create an isl_multi_aff that maps the output position "d"
5541 * from "a" to "x", leaving all other (intput and output) dimensions unchanged.
5542 * We plug this into the wrapped map, unwrap the result and compute the
5543 * corresponding isl_pw_multi_aff.
5544 * The result is an expression
5552 * so that we can plug that into "aff", after extending the latter to
5558 * If "map" is actually a set, then there is no "A" space, meaning
5559 * that we do not need to perform any wrapping, and that the result
5560 * of the recursive call is of the form
5564 * which is plugged into a mapping of the form
5568 static __isl_give isl_pw_multi_aff
*pw_multi_aff_from_map_stride(
5569 __isl_take isl_map
*map
, __isl_take isl_basic_map
*hull
, int d
, int i
,
5574 isl_local_space
*ls
;
5577 isl_pw_multi_aff
*pma
, *id
;
5583 is_set
= isl_map_is_set(map
);
5587 n_in
= isl_basic_map_dim(hull
, isl_dim_in
);
5588 n_out
= isl_basic_map_dim(hull
, isl_dim_out
);
5589 if (n_in
< 0 || n_out
< 0)
5591 o_out
= isl_basic_map_offset(hull
, isl_dim_out
);
5596 set
= isl_map_wrap(map
);
5597 space
= isl_space_map_from_set(isl_set_get_space(set
));
5598 ma
= isl_multi_aff_identity(space
);
5599 ls
= isl_local_space_from_space(isl_set_get_space(set
));
5600 aff
= isl_aff_alloc(ls
);
5602 isl_int_set_si(aff
->v
->el
[0], 1);
5603 if (isl_int_is_one(hull
->eq
[i
][o_out
+ d
]))
5604 isl_seq_neg(aff
->v
->el
+ 1, hull
->eq
[i
],
5607 isl_seq_cpy(aff
->v
->el
+ 1, hull
->eq
[i
],
5609 isl_int_set(aff
->v
->el
[1 + o_out
+ d
], gcd
);
5611 ma
= isl_multi_aff_set_aff(ma
, n_in
+ d
, isl_aff_copy(aff
));
5612 set
= isl_set_preimage_multi_aff(set
, ma
);
5614 ma
= range_map(aff
, d
, n_in
, n_out
, is_set
);
5619 map
= isl_set_unwrap(set
);
5620 pma
= isl_pw_multi_aff_from_map(map
);
5623 space
= isl_pw_multi_aff_get_domain_space(pma
);
5624 space
= isl_space_map_from_set(space
);
5625 id
= isl_pw_multi_aff_identity(space
);
5626 pma
= isl_pw_multi_aff_range_product(id
, pma
);
5628 id
= isl_pw_multi_aff_from_multi_aff(ma
);
5629 pma
= isl_pw_multi_aff_pullback_pw_multi_aff(id
, pma
);
5631 isl_basic_map_free(hull
);
5635 isl_basic_map_free(hull
);
5639 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5640 * "hull" contains the equalities valid for "map".
5642 * Check if any of the output dimensions is "strided".
5643 * That is, we check if it can be written as
5647 * with m greater than 1, a some combination of existentially quantified
5648 * variables and f an expression in the parameters and input dimensions.
5649 * If so, we remove the stride in pw_multi_aff_from_map_stride.
5651 * Otherwise, we continue with pw_multi_aff_from_map_check_div_mod for a further
5654 static __isl_give isl_pw_multi_aff
*pw_multi_aff_from_map_check_strides(
5655 __isl_take isl_map
*map
, __isl_take isl_basic_map
*hull
)
5664 n_div
= isl_basic_map_dim(hull
, isl_dim_div
);
5665 n_out
= isl_basic_map_dim(hull
, isl_dim_out
);
5666 if (n_div
< 0 || n_out
< 0)
5670 isl_basic_map_free(hull
);
5671 return pw_multi_aff_from_map_check_div_mod(map
);
5676 o_div
= isl_basic_map_offset(hull
, isl_dim_div
);
5677 o_out
= isl_basic_map_offset(hull
, isl_dim_out
);
5679 for (i
= 0; i
< n_out
; ++i
) {
5680 for (j
= 0; j
< hull
->n_eq
; ++j
) {
5681 isl_int
*eq
= hull
->eq
[j
];
5682 isl_pw_multi_aff
*res
;
5684 if (!isl_int_is_one(eq
[o_out
+ i
]) &&
5685 !isl_int_is_negone(eq
[o_out
+ i
]))
5687 if (isl_seq_first_non_zero(eq
+ o_out
, i
) != -1)
5689 if (isl_seq_first_non_zero(eq
+ o_out
+ i
+ 1,
5690 n_out
- (i
+ 1)) != -1)
5692 isl_seq_gcd(eq
+ o_div
, n_div
, &gcd
);
5693 if (isl_int_is_zero(gcd
))
5695 if (isl_int_is_one(gcd
))
5698 res
= pw_multi_aff_from_map_stride(map
, hull
,
5706 isl_basic_map_free(hull
);
5707 return pw_multi_aff_from_map_check_div_mod(map
);
5710 isl_basic_map_free(hull
);
5714 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
5716 * As a special case, we first check if all output dimensions are uniquely
5717 * defined in terms of the parameters and input dimensions over the entire
5718 * domain. If so, we extract the desired isl_pw_multi_aff directly
5719 * from the affine hull of "map" and its domain.
5721 * Otherwise, continue with pw_multi_aff_from_map_check_strides for more
5724 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_from_map(__isl_take isl_map
*map
)
5728 isl_basic_map
*hull
;
5730 n
= isl_map_n_basic_map(map
);
5735 hull
= isl_map_unshifted_simple_hull(isl_map_copy(map
));
5736 hull
= isl_basic_map_plain_affine_hull(hull
);
5737 sv
= isl_basic_map_plain_is_single_valued(hull
);
5739 return plain_pw_multi_aff_from_map(isl_map_domain(map
),
5741 isl_basic_map_free(hull
);
5743 map
= isl_map_detect_equalities(map
);
5744 hull
= isl_map_unshifted_simple_hull(isl_map_copy(map
));
5745 sv
= isl_basic_map_plain_is_single_valued(hull
);
5747 return plain_pw_multi_aff_from_map(isl_map_domain(map
), hull
);
5749 return pw_multi_aff_from_map_check_strides(map
, hull
);
5750 isl_basic_map_free(hull
);
5756 /* This function performs the same operation as isl_pw_multi_aff_from_map,
5757 * but is considered as a function on an isl_map when exported.
5759 __isl_give isl_pw_multi_aff
*isl_map_as_pw_multi_aff(__isl_take isl_map
*map
)
5761 return isl_pw_multi_aff_from_map(map
);
5764 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_from_set(__isl_take isl_set
*set
)
5766 return isl_pw_multi_aff_from_map(set
);
5769 /* This function performs the same operation as isl_pw_multi_aff_from_set,
5770 * but is considered as a function on an isl_set when exported.
5772 __isl_give isl_pw_multi_aff
*isl_set_as_pw_multi_aff(__isl_take isl_set
*set
)
5774 return isl_pw_multi_aff_from_set(set
);
5777 /* Convert "map" into an isl_pw_multi_aff (if possible) and
5780 static isl_stat
pw_multi_aff_from_map(__isl_take isl_map
*map
, void *user
)
5782 isl_union_pw_multi_aff
**upma
= user
;
5783 isl_pw_multi_aff
*pma
;
5785 pma
= isl_pw_multi_aff_from_map(map
);
5786 *upma
= isl_union_pw_multi_aff_add_pw_multi_aff(*upma
, pma
);
5788 return *upma
? isl_stat_ok
: isl_stat_error
;
5791 /* Create an isl_union_pw_multi_aff with the given isl_aff on a universe
5794 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_from_aff(
5795 __isl_take isl_aff
*aff
)
5798 isl_pw_multi_aff
*pma
;
5800 ma
= isl_multi_aff_from_aff(aff
);
5801 pma
= isl_pw_multi_aff_from_multi_aff(ma
);
5802 return isl_union_pw_multi_aff_from_pw_multi_aff(pma
);
5805 /* Try and create an isl_union_pw_multi_aff that is equivalent
5806 * to the given isl_union_map.
5807 * The isl_union_map is required to be single-valued in each space.
5808 * Otherwise, an error is produced.
5810 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_from_union_map(
5811 __isl_take isl_union_map
*umap
)
5814 isl_union_pw_multi_aff
*upma
;
5816 space
= isl_union_map_get_space(umap
);
5817 upma
= isl_union_pw_multi_aff_empty(space
);
5818 if (isl_union_map_foreach_map(umap
, &pw_multi_aff_from_map
, &upma
) < 0)
5819 upma
= isl_union_pw_multi_aff_free(upma
);
5820 isl_union_map_free(umap
);
5825 /* This function performs the same operation as
5826 * isl_union_pw_multi_aff_from_union_map,
5827 * but is considered as a function on an isl_union_map when exported.
5829 __isl_give isl_union_pw_multi_aff
*isl_union_map_as_union_pw_multi_aff(
5830 __isl_take isl_union_map
*umap
)
5832 return isl_union_pw_multi_aff_from_union_map(umap
);
5835 /* Try and create an isl_union_pw_multi_aff that is equivalent
5836 * to the given isl_union_set.
5837 * The isl_union_set is required to be a singleton in each space.
5838 * Otherwise, an error is produced.
5840 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_from_union_set(
5841 __isl_take isl_union_set
*uset
)
5843 return isl_union_pw_multi_aff_from_union_map(uset
);
5846 /* Return the piecewise affine expression "set ? 1 : 0".
5848 __isl_give isl_pw_aff
*isl_set_indicator_function(__isl_take isl_set
*set
)
5851 isl_space
*space
= isl_set_get_space(set
);
5852 isl_local_space
*ls
= isl_local_space_from_space(space
);
5853 isl_aff
*zero
= isl_aff_zero_on_domain(isl_local_space_copy(ls
));
5854 isl_aff
*one
= isl_aff_zero_on_domain(ls
);
5856 one
= isl_aff_add_constant_si(one
, 1);
5857 pa
= isl_pw_aff_alloc(isl_set_copy(set
), one
);
5858 set
= isl_set_complement(set
);
5859 pa
= isl_pw_aff_add_disjoint(pa
, isl_pw_aff_alloc(set
, zero
));
5864 /* Plug in "subs" for dimension "type", "pos" of "aff".
5866 * Let i be the dimension to replace and let "subs" be of the form
5870 * and "aff" of the form
5876 * (a f + d g')/(m d)
5878 * where g' is the result of plugging in "subs" in each of the integer
5881 __isl_give isl_aff
*isl_aff_substitute(__isl_take isl_aff
*aff
,
5882 enum isl_dim_type type
, unsigned pos
, __isl_keep isl_aff
*subs
)
5888 aff
= isl_aff_cow(aff
);
5890 return isl_aff_free(aff
);
5892 ctx
= isl_aff_get_ctx(aff
);
5893 if (!isl_space_is_equal(aff
->ls
->dim
, subs
->ls
->dim
))
5894 isl_die(ctx
, isl_error_invalid
,
5895 "spaces don't match", return isl_aff_free(aff
));
5896 n_div
= isl_aff_domain_dim(subs
, isl_dim_div
);
5898 return isl_aff_free(aff
);
5900 isl_die(ctx
, isl_error_unsupported
,
5901 "cannot handle divs yet", return isl_aff_free(aff
));
5903 aff
->ls
= isl_local_space_substitute(aff
->ls
, type
, pos
, subs
);
5905 return isl_aff_free(aff
);
5907 aff
->v
= isl_vec_cow(aff
->v
);
5909 return isl_aff_free(aff
);
5911 pos
+= isl_local_space_offset(aff
->ls
, type
);
5914 isl_seq_substitute(aff
->v
->el
, pos
, subs
->v
->el
,
5915 aff
->v
->size
, subs
->v
->size
, v
);
5921 /* Plug in "subs" for dimension "type", "pos" in each of the affine
5922 * expressions in "maff".
5924 __isl_give isl_multi_aff
*isl_multi_aff_substitute(
5925 __isl_take isl_multi_aff
*maff
, enum isl_dim_type type
, unsigned pos
,
5926 __isl_keep isl_aff
*subs
)
5931 n
= isl_multi_aff_size(maff
);
5933 return isl_multi_aff_free(maff
);
5935 if (type
== isl_dim_in
)
5938 for (i
= 0; i
< n
; ++i
) {
5941 aff
= isl_multi_aff_take_at(maff
, i
);
5942 aff
= isl_aff_substitute(aff
, type
, pos
, subs
);
5943 maff
= isl_multi_aff_restore_at(maff
, i
, aff
);
5949 /* Plug in "subs" for input dimension "pos" of "pma".
5951 * pma is of the form
5955 * while subs is of the form
5957 * v' = B_j(v) -> S_j
5959 * Each pair i,j such that C_ij = A_i \cap B_i is non-empty
5960 * has a contribution in the result, in particular
5962 * C_ij(S_j) -> M_i(S_j)
5964 * Note that plugging in S_j in C_ij may also result in an empty set
5965 * and this contribution should simply be discarded.
5967 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_substitute(
5968 __isl_take isl_pw_multi_aff
*pma
, unsigned pos
,
5969 __isl_keep isl_pw_aff
*subs
)
5972 isl_pw_multi_aff
*res
;
5975 return isl_pw_multi_aff_free(pma
);
5977 n
= pma
->n
* subs
->n
;
5978 res
= isl_pw_multi_aff_alloc_size(isl_space_copy(pma
->dim
), n
);
5980 for (i
= 0; i
< pma
->n
; ++i
) {
5981 for (j
= 0; j
< subs
->n
; ++j
) {
5983 isl_multi_aff
*res_ij
;
5986 common
= isl_set_intersect(
5987 isl_set_copy(pma
->p
[i
].set
),
5988 isl_set_copy(subs
->p
[j
].set
));
5989 common
= isl_set_substitute(common
,
5990 pos
, subs
->p
[j
].aff
);
5991 empty
= isl_set_plain_is_empty(common
);
5992 if (empty
< 0 || empty
) {
5993 isl_set_free(common
);
5999 res_ij
= isl_multi_aff_substitute(
6000 isl_multi_aff_copy(pma
->p
[i
].maff
),
6001 isl_dim_in
, pos
, subs
->p
[j
].aff
);
6003 res
= isl_pw_multi_aff_add_piece(res
, common
, res_ij
);
6007 isl_pw_multi_aff_free(pma
);
6010 isl_pw_multi_aff_free(pma
);
6011 isl_pw_multi_aff_free(res
);
6015 /* Compute the preimage of a range of dimensions in the affine expression "src"
6016 * under "ma" and put the result in "dst". The number of dimensions in "src"
6017 * that precede the range is given by "n_before". The number of dimensions
6018 * in the range is given by the number of output dimensions of "ma".
6019 * The number of dimensions that follow the range is given by "n_after".
6020 * If "has_denom" is set (to one),
6021 * then "src" and "dst" have an extra initial denominator.
6022 * "n_div_ma" is the number of existentials in "ma"
6023 * "n_div_bset" is the number of existentials in "src"
6024 * The resulting "dst" (which is assumed to have been allocated by
6025 * the caller) contains coefficients for both sets of existentials,
6026 * first those in "ma" and then those in "src".
6027 * f, c1, c2 and g are temporary objects that have been initialized
6030 * Let src represent the expression
6032 * (a(p) + f_u u + b v + f_w w + c(divs))/d
6034 * and let ma represent the expressions
6036 * v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i
6038 * We start out with the following expression for dst:
6040 * (a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d
6042 * with the multiplication factor f initially equal to 1
6043 * and f \sum_i b_i v_i kept separately.
6044 * For each x_i that we substitute, we multiply the numerator
6045 * (and denominator) of dst by c_1 = m_i and add the numerator
6046 * of the x_i expression multiplied by c_2 = f b_i,
6047 * after removing the common factors of c_1 and c_2.
6048 * The multiplication factor f also needs to be multiplied by c_1
6049 * for the next x_j, j > i.
6051 isl_stat
isl_seq_preimage(isl_int
*dst
, isl_int
*src
,
6052 __isl_keep isl_multi_aff
*ma
, int n_before
, int n_after
,
6053 int n_div_ma
, int n_div_bmap
,
6054 isl_int f
, isl_int c1
, isl_int c2
, isl_int g
, int has_denom
)
6057 isl_size n_param
, n_in
, n_out
;
6060 n_param
= isl_multi_aff_dim(ma
, isl_dim_param
);
6061 n_in
= isl_multi_aff_dim(ma
, isl_dim_in
);
6062 n_out
= isl_multi_aff_dim(ma
, isl_dim_out
);
6063 if (n_param
< 0 || n_in
< 0 || n_out
< 0)
6064 return isl_stat_error
;
6066 isl_seq_cpy(dst
, src
, has_denom
+ 1 + n_param
+ n_before
);
6067 o_dst
= o_src
= has_denom
+ 1 + n_param
+ n_before
;
6068 isl_seq_clr(dst
+ o_dst
, n_in
);
6071 isl_seq_cpy(dst
+ o_dst
, src
+ o_src
, n_after
);
6074 isl_seq_clr(dst
+ o_dst
, n_div_ma
);
6076 isl_seq_cpy(dst
+ o_dst
, src
+ o_src
, n_div_bmap
);
6078 isl_int_set_si(f
, 1);
6080 for (i
= 0; i
< n_out
; ++i
) {
6081 int offset
= has_denom
+ 1 + n_param
+ n_before
+ i
;
6083 if (isl_int_is_zero(src
[offset
]))
6085 isl_int_set(c1
, ma
->u
.p
[i
]->v
->el
[0]);
6086 isl_int_mul(c2
, f
, src
[offset
]);
6087 isl_int_gcd(g
, c1
, c2
);
6088 isl_int_divexact(c1
, c1
, g
);
6089 isl_int_divexact(c2
, c2
, g
);
6091 isl_int_mul(f
, f
, c1
);
6094 isl_seq_combine(dst
+ o_dst
, c1
, dst
+ o_dst
,
6095 c2
, ma
->u
.p
[i
]->v
->el
+ o_src
, 1 + n_param
);
6096 o_dst
+= 1 + n_param
;
6097 o_src
+= 1 + n_param
;
6098 isl_seq_scale(dst
+ o_dst
, dst
+ o_dst
, c1
, n_before
);
6100 isl_seq_combine(dst
+ o_dst
, c1
, dst
+ o_dst
,
6101 c2
, ma
->u
.p
[i
]->v
->el
+ o_src
, n_in
);
6104 isl_seq_scale(dst
+ o_dst
, dst
+ o_dst
, c1
, n_after
);
6106 isl_seq_combine(dst
+ o_dst
, c1
, dst
+ o_dst
,
6107 c2
, ma
->u
.p
[i
]->v
->el
+ o_src
, n_div_ma
);
6110 isl_seq_scale(dst
+ o_dst
, dst
+ o_dst
, c1
, n_div_bmap
);
6112 isl_int_mul(dst
[0], dst
[0], c1
);
6118 /* Compute the pullback of "aff" by the function represented by "ma".
6119 * In other words, plug in "ma" in "aff". The result is an affine expression
6120 * defined over the domain space of "ma".
6122 * If "aff" is represented by
6124 * (a(p) + b x + c(divs))/d
6126 * and ma is represented by
6128 * x = D(p) + F(y) + G(divs')
6130 * then the result is
6132 * (a(p) + b D(p) + b F(y) + b G(divs') + c(divs))/d
6134 * The divs in the local space of the input are similarly adjusted
6135 * through a call to isl_local_space_preimage_multi_aff.
6137 __isl_give isl_aff
*isl_aff_pullback_multi_aff(__isl_take isl_aff
*aff
,
6138 __isl_take isl_multi_aff
*ma
)
6140 isl_aff
*res
= NULL
;
6141 isl_local_space
*ls
;
6142 isl_size n_div_aff
, n_div_ma
;
6143 isl_int f
, c1
, c2
, g
;
6145 ma
= isl_multi_aff_align_divs(ma
);
6149 n_div_aff
= isl_aff_dim(aff
, isl_dim_div
);
6150 n_div_ma
= ma
->n
? isl_aff_dim(ma
->u
.p
[0], isl_dim_div
) : 0;
6151 if (n_div_aff
< 0 || n_div_ma
< 0)
6154 ls
= isl_aff_get_domain_local_space(aff
);
6155 ls
= isl_local_space_preimage_multi_aff(ls
, isl_multi_aff_copy(ma
));
6156 res
= isl_aff_alloc(ls
);
6165 if (isl_seq_preimage(res
->v
->el
, aff
->v
->el
, ma
, 0, 0,
6166 n_div_ma
, n_div_aff
, f
, c1
, c2
, g
, 1) < 0)
6167 res
= isl_aff_free(res
);
6175 isl_multi_aff_free(ma
);
6176 res
= isl_aff_normalize(res
);
6180 isl_multi_aff_free(ma
);
6185 /* Compute the pullback of "aff1" by the function represented by "aff2".
6186 * In other words, plug in "aff2" in "aff1". The result is an affine expression
6187 * defined over the domain space of "aff1".
6189 * The domain of "aff1" should match the range of "aff2", which means
6190 * that it should be single-dimensional.
6192 __isl_give isl_aff
*isl_aff_pullback_aff(__isl_take isl_aff
*aff1
,
6193 __isl_take isl_aff
*aff2
)
6197 ma
= isl_multi_aff_from_aff(aff2
);
6198 return isl_aff_pullback_multi_aff(aff1
, ma
);
6201 /* Compute the pullback of "ma1" by the function represented by "ma2".
6202 * In other words, plug in "ma2" in "ma1".
6204 __isl_give isl_multi_aff
*isl_multi_aff_pullback_multi_aff(
6205 __isl_take isl_multi_aff
*ma1
, __isl_take isl_multi_aff
*ma2
)
6209 isl_space
*space
= NULL
;
6211 isl_multi_aff_align_params_bin(&ma1
, &ma2
);
6212 ma2
= isl_multi_aff_align_divs(ma2
);
6213 n
= isl_multi_aff_size(ma1
);
6217 space
= isl_space_join(isl_multi_aff_get_space(ma2
),
6218 isl_multi_aff_get_space(ma1
));
6220 for (i
= 0; i
< n
; ++i
) {
6223 aff
= isl_multi_aff_take_at(ma1
, i
);
6224 aff
= isl_aff_pullback_multi_aff(aff
, isl_multi_aff_copy(ma2
));
6225 ma1
= isl_multi_aff_restore_at(ma1
, i
, aff
);
6228 ma1
= isl_multi_aff_reset_space(ma1
, space
);
6229 isl_multi_aff_free(ma2
);
6232 isl_space_free(space
);
6233 isl_multi_aff_free(ma2
);
6234 isl_multi_aff_free(ma1
);
6238 /* Extend the local space of "dst" to include the divs
6239 * in the local space of "src".
6241 * If "src" does not have any divs or if the local spaces of "dst" and
6242 * "src" are the same, then no extension is required.
6244 __isl_give isl_aff
*isl_aff_align_divs(__isl_take isl_aff
*dst
,
6245 __isl_keep isl_aff
*src
)
6248 isl_size src_n_div
, dst_n_div
;
6255 return isl_aff_free(dst
);
6257 ctx
= isl_aff_get_ctx(src
);
6258 equal
= isl_local_space_has_equal_space(src
->ls
, dst
->ls
);
6260 return isl_aff_free(dst
);
6262 isl_die(ctx
, isl_error_invalid
,
6263 "spaces don't match", goto error
);
6265 src_n_div
= isl_aff_domain_dim(src
, isl_dim_div
);
6266 dst_n_div
= isl_aff_domain_dim(dst
, isl_dim_div
);
6269 equal
= isl_local_space_is_equal(src
->ls
, dst
->ls
);
6270 if (equal
< 0 || src_n_div
< 0 || dst_n_div
< 0)
6271 return isl_aff_free(dst
);
6275 exp1
= isl_alloc_array(ctx
, int, src_n_div
);
6276 exp2
= isl_alloc_array(ctx
, int, dst_n_div
);
6277 if (!exp1
|| (dst_n_div
&& !exp2
))
6280 div
= isl_merge_divs(src
->ls
->div
, dst
->ls
->div
, exp1
, exp2
);
6281 dst
= isl_aff_expand_divs(dst
, div
, exp2
);
6289 return isl_aff_free(dst
);
6292 /* Adjust the local spaces of the affine expressions in "maff"
6293 * such that they all have the save divs.
6295 __isl_give isl_multi_aff
*isl_multi_aff_align_divs(
6296 __isl_take isl_multi_aff
*maff
)
6302 n
= isl_multi_aff_size(maff
);
6304 return isl_multi_aff_free(maff
);
6308 aff_0
= isl_multi_aff_take_at(maff
, 0);
6309 for (i
= 1; i
< n
; ++i
) {
6312 aff_i
= isl_multi_aff_peek_at(maff
, i
);
6313 aff_0
= isl_aff_align_divs(aff_0
, aff_i
);
6315 maff
= isl_multi_aff_restore_at(maff
, 0, aff_0
);
6317 aff_0
= isl_multi_aff_peek_at(maff
, 0);
6318 for (i
= 1; i
< n
; ++i
) {
6321 aff_i
= isl_multi_aff_take_at(maff
, i
);
6322 aff_i
= isl_aff_align_divs(aff_i
, aff_0
);
6323 maff
= isl_multi_aff_restore_at(maff
, i
, aff_i
);
6329 __isl_give isl_aff
*isl_aff_lift(__isl_take isl_aff
*aff
)
6331 aff
= isl_aff_cow(aff
);
6335 aff
->ls
= isl_local_space_lift(aff
->ls
);
6337 return isl_aff_free(aff
);
6342 /* Lift "maff" to a space with extra dimensions such that the result
6343 * has no more existentially quantified variables.
6344 * If "ls" is not NULL, then *ls is assigned the local space that lies
6345 * at the basis of the lifting applied to "maff".
6347 __isl_give isl_multi_aff
*isl_multi_aff_lift(__isl_take isl_multi_aff
*maff
,
6348 __isl_give isl_local_space
**ls
)
6358 n
= isl_multi_aff_size(maff
);
6360 return isl_multi_aff_free(maff
);
6364 isl_space
*space
= isl_multi_aff_get_domain_space(maff
);
6365 *ls
= isl_local_space_from_space(space
);
6367 return isl_multi_aff_free(maff
);
6372 maff
= isl_multi_aff_align_divs(maff
);
6374 aff
= isl_multi_aff_peek_at(maff
, 0);
6375 n_div
= isl_aff_dim(aff
, isl_dim_div
);
6377 return isl_multi_aff_free(maff
);
6378 space
= isl_multi_aff_get_space(maff
);
6379 space
= isl_space_lift(isl_space_domain(space
), n_div
);
6380 space
= isl_space_extend_domain_with_range(space
,
6381 isl_multi_aff_get_space(maff
));
6382 maff
= isl_multi_aff_restore_space(maff
, space
);
6385 aff
= isl_multi_aff_peek_at(maff
, 0);
6386 *ls
= isl_aff_get_domain_local_space(aff
);
6388 return isl_multi_aff_free(maff
);
6391 for (i
= 0; i
< n
; ++i
) {
6392 aff
= isl_multi_aff_take_at(maff
, i
);
6393 aff
= isl_aff_lift(aff
);
6394 maff
= isl_multi_aff_restore_at(maff
, i
, aff
);
6401 #define TYPE isl_pw_multi_aff
6403 #include "check_type_range_templ.c"
6405 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma".
6407 __isl_give isl_pw_aff
*isl_pw_multi_aff_get_at(
6408 __isl_keep isl_pw_multi_aff
*pma
, int pos
)
6415 if (isl_pw_multi_aff_check_range(pma
, isl_dim_out
, pos
, 1) < 0)
6418 n_out
= isl_pw_multi_aff_dim(pma
, isl_dim_out
);
6422 space
= isl_pw_multi_aff_get_space(pma
);
6423 space
= isl_space_drop_dims(space
, isl_dim_out
,
6424 pos
+ 1, n_out
- pos
- 1);
6425 space
= isl_space_drop_dims(space
, isl_dim_out
, 0, pos
);
6427 pa
= isl_pw_aff_alloc_size(space
, pma
->n
);
6428 for (i
= 0; i
< pma
->n
; ++i
) {
6430 aff
= isl_multi_aff_get_aff(pma
->p
[i
].maff
, pos
);
6431 pa
= isl_pw_aff_add_piece(pa
, isl_set_copy(pma
->p
[i
].set
), aff
);
6437 /* This is an alternative name for the function above.
6439 __isl_give isl_pw_aff
*isl_pw_multi_aff_get_pw_aff(
6440 __isl_keep isl_pw_multi_aff
*pma
, int pos
)
6442 return isl_pw_multi_aff_get_at(pma
, pos
);
6445 /* Return an isl_pw_multi_aff with the given "set" as domain and
6446 * an unnamed zero-dimensional range.
6448 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_from_domain(
6449 __isl_take isl_set
*set
)
6454 space
= isl_set_get_space(set
);
6455 space
= isl_space_from_domain(space
);
6456 ma
= isl_multi_aff_zero(space
);
6457 return isl_pw_multi_aff_alloc(set
, ma
);
6460 /* Add an isl_pw_multi_aff with the given "set" as domain and
6461 * an unnamed zero-dimensional range to *user.
6463 static isl_stat
add_pw_multi_aff_from_domain(__isl_take isl_set
*set
,
6466 isl_union_pw_multi_aff
**upma
= user
;
6467 isl_pw_multi_aff
*pma
;
6469 pma
= isl_pw_multi_aff_from_domain(set
);
6470 *upma
= isl_union_pw_multi_aff_add_pw_multi_aff(*upma
, pma
);
6475 /* Return an isl_union_pw_multi_aff with the given "uset" as domain and
6476 * an unnamed zero-dimensional range.
6478 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_from_domain(
6479 __isl_take isl_union_set
*uset
)
6482 isl_union_pw_multi_aff
*upma
;
6487 space
= isl_union_set_get_space(uset
);
6488 upma
= isl_union_pw_multi_aff_empty(space
);
6490 if (isl_union_set_foreach_set(uset
,
6491 &add_pw_multi_aff_from_domain
, &upma
) < 0)
6494 isl_union_set_free(uset
);
6497 isl_union_set_free(uset
);
6498 isl_union_pw_multi_aff_free(upma
);
6502 /* Local data for bin_entry and the callback "fn".
6504 struct isl_union_pw_multi_aff_bin_data
{
6505 isl_union_pw_multi_aff
*upma2
;
6506 isl_union_pw_multi_aff
*res
;
6507 isl_pw_multi_aff
*pma
;
6508 isl_stat (*fn
)(__isl_take isl_pw_multi_aff
*pma
, void *user
);
6511 /* Given an isl_pw_multi_aff from upma1, store it in data->pma
6512 * and call data->fn for each isl_pw_multi_aff in data->upma2.
6514 static isl_stat
bin_entry(__isl_take isl_pw_multi_aff
*pma
, void *user
)
6516 struct isl_union_pw_multi_aff_bin_data
*data
= user
;
6520 r
= isl_union_pw_multi_aff_foreach_pw_multi_aff(data
->upma2
,
6522 isl_pw_multi_aff_free(pma
);
6527 /* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
6528 * The isl_pw_multi_aff from upma1 is stored in data->pma (where data is
6529 * passed as user field) and the isl_pw_multi_aff from upma2 is available
6530 * as *entry. The callback should adjust data->res if desired.
6532 static __isl_give isl_union_pw_multi_aff
*bin_op(
6533 __isl_take isl_union_pw_multi_aff
*upma1
,
6534 __isl_take isl_union_pw_multi_aff
*upma2
,
6535 isl_stat (*fn
)(__isl_take isl_pw_multi_aff
*pma
, void *user
))
6538 struct isl_union_pw_multi_aff_bin_data data
= { NULL
, NULL
, NULL
, fn
};
6540 space
= isl_union_pw_multi_aff_get_space(upma2
);
6541 upma1
= isl_union_pw_multi_aff_align_params(upma1
, space
);
6542 space
= isl_union_pw_multi_aff_get_space(upma1
);
6543 upma2
= isl_union_pw_multi_aff_align_params(upma2
, space
);
6545 if (!upma1
|| !upma2
)
6549 data
.res
= isl_union_pw_multi_aff_alloc_same_size(upma1
);
6550 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1
,
6551 &bin_entry
, &data
) < 0)
6554 isl_union_pw_multi_aff_free(upma1
);
6555 isl_union_pw_multi_aff_free(upma2
);
6558 isl_union_pw_multi_aff_free(upma1
);
6559 isl_union_pw_multi_aff_free(upma2
);
6560 isl_union_pw_multi_aff_free(data
.res
);
6564 /* Given two isl_pw_multi_affs A -> B and C -> D,
6565 * construct an isl_pw_multi_aff (A * C) -> [B -> D].
6567 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_range_product(
6568 __isl_take isl_pw_multi_aff
*pma1
, __isl_take isl_pw_multi_aff
*pma2
)
6572 isl_pw_multi_aff_align_params_bin(&pma1
, &pma2
);
6573 space
= isl_space_range_product(isl_pw_multi_aff_get_space(pma1
),
6574 isl_pw_multi_aff_get_space(pma2
));
6575 return isl_pw_multi_aff_on_shared_domain_in(pma1
, pma2
, space
,
6576 &isl_multi_aff_range_product
);
6579 /* Given two isl_pw_multi_affs A -> B and C -> D,
6580 * construct an isl_pw_multi_aff (A * C) -> (B, D).
6582 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_flat_range_product(
6583 __isl_take isl_pw_multi_aff
*pma1
, __isl_take isl_pw_multi_aff
*pma2
)
6587 isl_pw_multi_aff_align_params_bin(&pma1
, &pma2
);
6588 space
= isl_space_range_product(isl_pw_multi_aff_get_space(pma1
),
6589 isl_pw_multi_aff_get_space(pma2
));
6590 space
= isl_space_flatten_range(space
);
6591 return isl_pw_multi_aff_on_shared_domain_in(pma1
, pma2
, space
,
6592 &isl_multi_aff_flat_range_product
);
6595 /* If data->pma and "pma2" have the same domain space, then use "range_product"
6596 * to compute some form of range product and add the result to data->res.
6598 static isl_stat
gen_range_product_entry(__isl_take isl_pw_multi_aff
*pma2
,
6599 __isl_give isl_pw_multi_aff
*(*range_product
)(
6600 __isl_take isl_pw_multi_aff
*pma1
,
6601 __isl_take isl_pw_multi_aff
*pma2
),
6604 struct isl_union_pw_multi_aff_bin_data
*data
= user
;
6606 isl_space
*space1
, *space2
;
6608 space1
= isl_pw_multi_aff_peek_space(data
->pma
);
6609 space2
= isl_pw_multi_aff_peek_space(pma2
);
6610 match
= isl_space_tuple_is_equal(space1
, isl_dim_in
,
6611 space2
, isl_dim_in
);
6612 if (match
< 0 || !match
) {
6613 isl_pw_multi_aff_free(pma2
);
6614 return match
< 0 ? isl_stat_error
: isl_stat_ok
;
6617 pma2
= range_product(isl_pw_multi_aff_copy(data
->pma
), pma2
);
6619 data
->res
= isl_union_pw_multi_aff_add_pw_multi_aff(data
->res
, pma2
);
6624 /* If data->pma and "pma2" have the same domain space, then compute
6625 * their flat range product and add the result to data->res.
6627 static isl_stat
flat_range_product_entry(__isl_take isl_pw_multi_aff
*pma2
,
6630 return gen_range_product_entry(pma2
,
6631 &isl_pw_multi_aff_flat_range_product
, user
);
6634 /* Given two isl_union_pw_multi_affs A -> B and C -> D,
6635 * construct an isl_union_pw_multi_aff (A * C) -> (B, D).
6637 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_flat_range_product(
6638 __isl_take isl_union_pw_multi_aff
*upma1
,
6639 __isl_take isl_union_pw_multi_aff
*upma2
)
6641 return bin_op(upma1
, upma2
, &flat_range_product_entry
);
6644 /* If data->pma and "pma2" have the same domain space, then compute
6645 * their range product and add the result to data->res.
6647 static isl_stat
range_product_entry(__isl_take isl_pw_multi_aff
*pma2
,
6650 return gen_range_product_entry(pma2
,
6651 &isl_pw_multi_aff_range_product
, user
);
6654 /* Given two isl_union_pw_multi_affs A -> B and C -> D,
6655 * construct an isl_union_pw_multi_aff (A * C) -> [B -> D].
6657 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_range_product(
6658 __isl_take isl_union_pw_multi_aff
*upma1
,
6659 __isl_take isl_union_pw_multi_aff
*upma2
)
6661 return bin_op(upma1
, upma2
, &range_product_entry
);
6664 /* Replace the affine expressions at position "pos" in "pma" by "pa".
6665 * The parameters are assumed to have been aligned.
6667 * The implementation essentially performs an isl_pw_*_on_shared_domain,
6668 * except that it works on two different isl_pw_* types.
6670 static __isl_give isl_pw_multi_aff
*pw_multi_aff_set_pw_aff(
6671 __isl_take isl_pw_multi_aff
*pma
, unsigned pos
,
6672 __isl_take isl_pw_aff
*pa
)
6675 isl_pw_multi_aff
*res
= NULL
;
6680 if (!isl_space_tuple_is_equal(pma
->dim
, isl_dim_in
,
6681 pa
->dim
, isl_dim_in
))
6682 isl_die(isl_pw_multi_aff_get_ctx(pma
), isl_error_invalid
,
6683 "domains don't match", goto error
);
6684 if (isl_pw_multi_aff_check_range(pma
, isl_dim_out
, pos
, 1) < 0)
6688 res
= isl_pw_multi_aff_alloc_size(isl_pw_multi_aff_get_space(pma
), n
);
6690 for (i
= 0; i
< pma
->n
; ++i
) {
6691 for (j
= 0; j
< pa
->n
; ++j
) {
6693 isl_multi_aff
*res_ij
;
6696 common
= isl_set_intersect(isl_set_copy(pma
->p
[i
].set
),
6697 isl_set_copy(pa
->p
[j
].set
));
6698 empty
= isl_set_plain_is_empty(common
);
6699 if (empty
< 0 || empty
) {
6700 isl_set_free(common
);
6706 res_ij
= isl_multi_aff_set_aff(
6707 isl_multi_aff_copy(pma
->p
[i
].maff
), pos
,
6708 isl_aff_copy(pa
->p
[j
].aff
));
6709 res_ij
= isl_multi_aff_gist(res_ij
,
6710 isl_set_copy(common
));
6712 res
= isl_pw_multi_aff_add_piece(res
, common
, res_ij
);
6716 isl_pw_multi_aff_free(pma
);
6717 isl_pw_aff_free(pa
);
6720 isl_pw_multi_aff_free(pma
);
6721 isl_pw_aff_free(pa
);
6722 return isl_pw_multi_aff_free(res
);
6725 /* Replace the affine expressions at position "pos" in "pma" by "pa".
6727 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_set_pw_aff(
6728 __isl_take isl_pw_multi_aff
*pma
, unsigned pos
,
6729 __isl_take isl_pw_aff
*pa
)
6731 isl_bool equal_params
;
6735 equal_params
= isl_space_has_equal_params(pma
->dim
, pa
->dim
);
6736 if (equal_params
< 0)
6739 return pw_multi_aff_set_pw_aff(pma
, pos
, pa
);
6740 if (isl_pw_multi_aff_check_named_params(pma
) < 0 ||
6741 isl_pw_aff_check_named_params(pa
) < 0)
6743 pma
= isl_pw_multi_aff_align_params(pma
, isl_pw_aff_get_space(pa
));
6744 pa
= isl_pw_aff_align_params(pa
, isl_pw_multi_aff_get_space(pma
));
6745 return pw_multi_aff_set_pw_aff(pma
, pos
, pa
);
6747 isl_pw_multi_aff_free(pma
);
6748 isl_pw_aff_free(pa
);
6752 /* Do the parameters of "pa" match those of "space"?
6754 isl_bool
isl_pw_aff_matching_params(__isl_keep isl_pw_aff
*pa
,
6755 __isl_keep isl_space
*space
)
6757 isl_space
*pa_space
;
6761 return isl_bool_error
;
6763 pa_space
= isl_pw_aff_get_space(pa
);
6765 match
= isl_space_has_equal_params(space
, pa_space
);
6767 isl_space_free(pa_space
);
6771 /* Check that the domain space of "pa" matches "space".
6773 isl_stat
isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff
*pa
,
6774 __isl_keep isl_space
*space
)
6776 isl_space
*pa_space
;
6780 return isl_stat_error
;
6782 pa_space
= isl_pw_aff_get_space(pa
);
6784 match
= isl_space_has_equal_params(space
, pa_space
);
6788 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
6789 "parameters don't match", goto error
);
6790 match
= isl_space_tuple_is_equal(space
, isl_dim_in
,
6791 pa_space
, isl_dim_in
);
6795 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
6796 "domains don't match", goto error
);
6797 isl_space_free(pa_space
);
6800 isl_space_free(pa_space
);
6801 return isl_stat_error
;
6809 #include <isl_multi_explicit_domain.c>
6810 #include <isl_multi_pw_aff_explicit_domain.c>
6811 #include <isl_multi_templ.c>
6812 #include <isl_multi_un_op_templ.c>
6813 #include <isl_multi_bin_val_templ.c>
6814 #include <isl_multi_add_constant_templ.c>
6815 #include <isl_multi_align_set.c>
6816 #include <isl_multi_apply_set_explicit_domain_templ.c>
6817 #include <isl_multi_arith_templ.c>
6818 #include <isl_multi_bind_templ.c>
6819 #include <isl_multi_bind_domain_templ.c>
6820 #include <isl_multi_coalesce.c>
6821 #include <isl_multi_domain_templ.c>
6822 #include <isl_multi_domain_reverse_templ.c>
6823 #include <isl_multi_dim_id_templ.c>
6824 #include <isl_multi_dims.c>
6825 #include <isl_multi_from_base_templ.c>
6826 #include <isl_multi_check_domain_templ.c>
6827 #include <isl_multi_gist.c>
6828 #include <isl_multi_hash.c>
6829 #include <isl_multi_identity_templ.c>
6830 #include <isl_multi_insert_domain_templ.c>
6831 #include <isl_multi_intersect.c>
6832 #include <isl_multi_min_max_templ.c>
6833 #include <isl_multi_move_dims_templ.c>
6834 #include <isl_multi_nan_templ.c>
6835 #include <isl_multi_param_templ.c>
6836 #include <isl_multi_product_templ.c>
6837 #include <isl_multi_splice_templ.c>
6838 #include <isl_multi_tuple_id_templ.c>
6839 #include <isl_multi_union_add_templ.c>
6840 #include <isl_multi_zero_templ.c>
6841 #include <isl_multi_unbind_params_templ.c>
6843 /* Is every element of "mpa" defined over a single universe domain?
6845 isl_bool
isl_multi_pw_aff_isa_multi_aff(__isl_keep isl_multi_pw_aff
*mpa
)
6847 return isl_multi_pw_aff_every(mpa
, &isl_pw_aff_isa_aff
);
6850 /* Given that every element of "mpa" is defined over a single universe domain,
6851 * return the corresponding base expressions.
6853 __isl_give isl_multi_aff
*isl_multi_pw_aff_as_multi_aff(
6854 __isl_take isl_multi_pw_aff
*mpa
)
6860 n
= isl_multi_pw_aff_size(mpa
);
6862 mpa
= isl_multi_pw_aff_free(mpa
);
6863 ma
= isl_multi_aff_alloc(isl_multi_pw_aff_get_space(mpa
));
6864 for (i
= 0; i
< n
; ++i
) {
6867 aff
= isl_pw_aff_as_aff(isl_multi_pw_aff_get_at(mpa
, i
));
6868 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
6870 isl_multi_pw_aff_free(mpa
);
6874 /* If "mpa" has an explicit domain, then intersect the domain of "map"
6875 * with this explicit domain.
6877 __isl_give isl_map
*isl_map_intersect_multi_pw_aff_explicit_domain(
6878 __isl_take isl_map
*map
, __isl_keep isl_multi_pw_aff
*mpa
)
6882 if (!isl_multi_pw_aff_has_explicit_domain(mpa
))
6885 dom
= isl_multi_pw_aff_domain(isl_multi_pw_aff_copy(mpa
));
6886 map
= isl_map_intersect_domain(map
, dom
);
6891 /* Are all elements of "mpa" piecewise constants?
6893 isl_bool
isl_multi_pw_aff_is_cst(__isl_keep isl_multi_pw_aff
*mpa
)
6895 return isl_multi_pw_aff_every(mpa
, &isl_pw_aff_is_cst
);
6898 /* Does "mpa" have a non-trivial explicit domain?
6900 * The explicit domain, if present, is trivial if it represents
6901 * an (obviously) universe set.
6903 isl_bool
isl_multi_pw_aff_has_non_trivial_domain(
6904 __isl_keep isl_multi_pw_aff
*mpa
)
6907 return isl_bool_error
;
6908 if (!isl_multi_pw_aff_has_explicit_domain(mpa
))
6909 return isl_bool_false
;
6910 return isl_bool_not(isl_set_plain_is_universe(mpa
->u
.dom
));
6916 #include "isl_opt_mpa_templ.c"
6918 /* Compute the minima of the set dimensions as a function of the
6919 * parameters, but independently of the other set dimensions.
6921 __isl_give isl_multi_pw_aff
*isl_set_min_multi_pw_aff(__isl_take isl_set
*set
)
6923 return set_opt_mpa(set
, &isl_set_dim_min
);
6926 /* Compute the maxima of the set dimensions as a function of the
6927 * parameters, but independently of the other set dimensions.
6929 __isl_give isl_multi_pw_aff
*isl_set_max_multi_pw_aff(__isl_take isl_set
*set
)
6931 return set_opt_mpa(set
, &isl_set_dim_max
);
6937 #include "isl_opt_mpa_templ.c"
6939 /* Compute the minima of the output dimensions as a function of the
6940 * parameters and input dimensions, but independently of
6941 * the other output dimensions.
6943 __isl_give isl_multi_pw_aff
*isl_map_min_multi_pw_aff(__isl_take isl_map
*map
)
6945 return map_opt_mpa(map
, &isl_map_dim_min
);
6948 /* Compute the maxima of the output dimensions as a function of the
6949 * parameters and input dimensions, but independently of
6950 * the other output dimensions.
6952 __isl_give isl_multi_pw_aff
*isl_map_max_multi_pw_aff(__isl_take isl_map
*map
)
6954 return map_opt_mpa(map
, &isl_map_dim_max
);
6958 #define TYPE isl_pw_multi_aff
6959 #include "isl_type_check_match_range_multi_val.c"
6961 /* Apply "fn" to the base expressions of "pma" and "mv".
6963 static __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_op_multi_val(
6964 __isl_take isl_pw_multi_aff
*pma
, __isl_take isl_multi_val
*mv
,
6965 __isl_give isl_multi_aff
*(*fn
)(__isl_take isl_multi_aff
*ma
,
6966 __isl_take isl_multi_val
*mv
))
6971 if (isl_pw_multi_aff_check_match_range_multi_val(pma
, mv
) < 0)
6974 n
= isl_pw_multi_aff_n_piece(pma
);
6978 for (i
= 0; i
< n
; ++i
) {
6981 ma
= isl_pw_multi_aff_take_base_at(pma
, i
);
6982 ma
= fn(ma
, isl_multi_val_copy(mv
));
6983 pma
= isl_pw_multi_aff_restore_base_at(pma
, i
, ma
);
6986 isl_multi_val_free(mv
);
6989 isl_multi_val_free(mv
);
6990 isl_pw_multi_aff_free(pma
);
6994 /* Scale the elements of "pma" by the corresponding elements of "mv".
6996 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_scale_multi_val(
6997 __isl_take isl_pw_multi_aff
*pma
, __isl_take isl_multi_val
*mv
)
6999 return isl_pw_multi_aff_op_multi_val(pma
, mv
,
7000 &isl_multi_aff_scale_multi_val
);
7003 /* Scale the elements of "pma" down by the corresponding elements of "mv".
7005 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_scale_down_multi_val(
7006 __isl_take isl_pw_multi_aff
*pma
, __isl_take isl_multi_val
*mv
)
7008 return isl_pw_multi_aff_op_multi_val(pma
, mv
,
7009 &isl_multi_aff_scale_down_multi_val
);
7012 /* This function is called for each entry of an isl_union_pw_multi_aff.
7013 * If the space of the entry matches that of data->mv,
7014 * then apply isl_pw_multi_aff_scale_multi_val and return the result.
7015 * Otherwise, return an empty isl_pw_multi_aff.
7017 static __isl_give isl_pw_multi_aff
*union_pw_multi_aff_scale_multi_val_entry(
7018 __isl_take isl_pw_multi_aff
*pma
, void *user
)
7021 isl_multi_val
*mv
= user
;
7023 equal
= isl_pw_multi_aff_match_range_multi_val(pma
, mv
);
7025 return isl_pw_multi_aff_free(pma
);
7027 isl_space
*space
= isl_pw_multi_aff_get_space(pma
);
7028 isl_pw_multi_aff_free(pma
);
7029 return isl_pw_multi_aff_empty(space
);
7032 return isl_pw_multi_aff_scale_multi_val(pma
, isl_multi_val_copy(mv
));
7035 /* Scale the elements of "upma" by the corresponding elements of "mv",
7036 * for those entries that match the space of "mv".
7038 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_scale_multi_val(
7039 __isl_take isl_union_pw_multi_aff
*upma
, __isl_take isl_multi_val
*mv
)
7041 struct isl_union_pw_multi_aff_transform_control control
= {
7042 .fn
= &union_pw_multi_aff_scale_multi_val_entry
,
7046 upma
= isl_union_pw_multi_aff_align_params(upma
,
7047 isl_multi_val_get_space(mv
));
7048 mv
= isl_multi_val_align_params(mv
,
7049 isl_union_pw_multi_aff_get_space(upma
));
7053 return isl_union_pw_multi_aff_transform(upma
, &control
);
7055 isl_multi_val_free(mv
);
7058 isl_multi_val_free(mv
);
7059 isl_union_pw_multi_aff_free(upma
);
7063 /* Construct and return a piecewise multi affine expression
7064 * in the given space with value zero in each of the output dimensions and
7065 * a universe domain.
7067 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_zero(__isl_take isl_space
*space
)
7069 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_zero(space
));
7072 /* Construct and return a piecewise multi affine expression
7073 * that is equal to the given piecewise affine expression.
7075 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_from_pw_aff(
7076 __isl_take isl_pw_aff
*pa
)
7080 isl_pw_multi_aff
*pma
;
7085 space
= isl_pw_aff_get_space(pa
);
7086 pma
= isl_pw_multi_aff_alloc_size(space
, pa
->n
);
7088 for (i
= 0; i
< pa
->n
; ++i
) {
7092 set
= isl_set_copy(pa
->p
[i
].set
);
7093 ma
= isl_multi_aff_from_aff(isl_aff_copy(pa
->p
[i
].aff
));
7094 pma
= isl_pw_multi_aff_add_piece(pma
, set
, ma
);
7097 isl_pw_aff_free(pa
);
7101 /* Construct and return a piecewise multi affine expression
7102 * that is equal to the given multi piecewise affine expression
7103 * on the shared domain of the piecewise affine expressions,
7104 * in the special case of a 0D multi piecewise affine expression.
7106 * Create a piecewise multi affine expression with the explicit domain of
7107 * the 0D multi piecewise affine expression as domain.
7109 static __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_from_multi_pw_aff_0D(
7110 __isl_take isl_multi_pw_aff
*mpa
)
7116 space
= isl_multi_pw_aff_get_space(mpa
);
7117 dom
= isl_multi_pw_aff_get_explicit_domain(mpa
);
7118 isl_multi_pw_aff_free(mpa
);
7120 ma
= isl_multi_aff_zero(space
);
7121 return isl_pw_multi_aff_alloc(dom
, ma
);
7124 /* Construct and return a piecewise multi affine expression
7125 * that is equal to the given multi piecewise affine expression
7126 * on the shared domain of the piecewise affine expressions.
7128 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_from_multi_pw_aff(
7129 __isl_take isl_multi_pw_aff
*mpa
)
7134 isl_pw_multi_aff
*pma
;
7140 return isl_pw_multi_aff_from_multi_pw_aff_0D(mpa
);
7142 space
= isl_multi_pw_aff_get_space(mpa
);
7143 pa
= isl_multi_pw_aff_get_pw_aff(mpa
, 0);
7144 pma
= isl_pw_multi_aff_from_pw_aff(pa
);
7146 for (i
= 1; i
< mpa
->n
; ++i
) {
7147 isl_pw_multi_aff
*pma_i
;
7149 pa
= isl_multi_pw_aff_get_pw_aff(mpa
, i
);
7150 pma_i
= isl_pw_multi_aff_from_pw_aff(pa
);
7151 pma
= isl_pw_multi_aff_range_product(pma
, pma_i
);
7154 pma
= isl_pw_multi_aff_reset_space(pma
, space
);
7156 isl_multi_pw_aff_free(mpa
);
7160 /* Convenience function that constructs an isl_multi_pw_aff
7161 * directly from an isl_aff.
7163 __isl_give isl_multi_pw_aff
*isl_multi_pw_aff_from_aff(__isl_take isl_aff
*aff
)
7165 return isl_multi_pw_aff_from_pw_aff(isl_pw_aff_from_aff(aff
));
7168 /* Construct and return a multi piecewise affine expression
7169 * that is equal to the given multi affine expression.
7171 __isl_give isl_multi_pw_aff
*isl_multi_pw_aff_from_multi_aff(
7172 __isl_take isl_multi_aff
*ma
)
7176 isl_multi_pw_aff
*mpa
;
7178 n
= isl_multi_aff_dim(ma
, isl_dim_out
);
7180 ma
= isl_multi_aff_free(ma
);
7184 mpa
= isl_multi_pw_aff_alloc(isl_multi_aff_get_space(ma
));
7186 for (i
= 0; i
< n
; ++i
) {
7189 pa
= isl_pw_aff_from_aff(isl_multi_aff_get_aff(ma
, i
));
7190 mpa
= isl_multi_pw_aff_set_pw_aff(mpa
, i
, pa
);
7193 isl_multi_aff_free(ma
);
7197 /* This function performs the same operation as isl_multi_pw_aff_from_multi_aff,
7198 * but is considered as a function on an isl_multi_aff when exported.
7200 __isl_give isl_multi_pw_aff
*isl_multi_aff_to_multi_pw_aff(
7201 __isl_take isl_multi_aff
*ma
)
7203 return isl_multi_pw_aff_from_multi_aff(ma
);
7206 /* Construct and return a multi piecewise affine expression
7207 * that is equal to the given piecewise multi affine expression.
7209 * If the resulting multi piecewise affine expression has
7210 * an explicit domain, then assign it the domain of the input.
7211 * In other cases, the domain is stored in the individual elements.
7213 __isl_give isl_multi_pw_aff
*isl_multi_pw_aff_from_pw_multi_aff(
7214 __isl_take isl_pw_multi_aff
*pma
)
7219 isl_multi_pw_aff
*mpa
;
7221 n
= isl_pw_multi_aff_dim(pma
, isl_dim_out
);
7223 pma
= isl_pw_multi_aff_free(pma
);
7224 space
= isl_pw_multi_aff_get_space(pma
);
7225 mpa
= isl_multi_pw_aff_alloc(space
);
7227 for (i
= 0; i
< n
; ++i
) {
7230 pa
= isl_pw_multi_aff_get_pw_aff(pma
, i
);
7231 mpa
= isl_multi_pw_aff_set_pw_aff(mpa
, i
, pa
);
7233 if (isl_multi_pw_aff_has_explicit_domain(mpa
)) {
7236 dom
= isl_pw_multi_aff_domain(isl_pw_multi_aff_copy(pma
));
7237 mpa
= isl_multi_pw_aff_intersect_domain(mpa
, dom
);
7240 isl_pw_multi_aff_free(pma
);
7244 /* This function performs the same operation as
7245 * isl_multi_pw_aff_from_pw_multi_aff,
7246 * but is considered as a function on an isl_pw_multi_aff when exported.
7248 __isl_give isl_multi_pw_aff
*isl_pw_multi_aff_to_multi_pw_aff(
7249 __isl_take isl_pw_multi_aff
*pma
)
7251 return isl_multi_pw_aff_from_pw_multi_aff(pma
);
7254 /* Do "pa1" and "pa2" represent the same function?
7256 * We first check if they are obviously equal.
7257 * If not, we convert them to maps and check if those are equal.
7259 * If "pa1" or "pa2" contain any NaNs, then they are considered
7260 * not to be the same. A NaN is not equal to anything, not even
7263 isl_bool
isl_pw_aff_is_equal(__isl_keep isl_pw_aff
*pa1
,
7264 __isl_keep isl_pw_aff
*pa2
)
7268 isl_map
*map1
, *map2
;
7271 return isl_bool_error
;
7273 equal
= isl_pw_aff_plain_is_equal(pa1
, pa2
);
7274 if (equal
< 0 || equal
)
7276 has_nan
= either_involves_nan(pa1
, pa2
);
7278 return isl_bool_error
;
7280 return isl_bool_false
;
7282 map1
= isl_map_from_pw_aff_internal(isl_pw_aff_copy(pa1
));
7283 map2
= isl_map_from_pw_aff_internal(isl_pw_aff_copy(pa2
));
7284 equal
= isl_map_is_equal(map1
, map2
);
7291 /* Do "mpa1" and "mpa2" represent the same function?
7293 * Note that we cannot convert the entire isl_multi_pw_aff
7294 * to a map because the domains of the piecewise affine expressions
7295 * may not be the same.
7297 isl_bool
isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff
*mpa1
,
7298 __isl_keep isl_multi_pw_aff
*mpa2
)
7301 isl_bool equal
, equal_params
;
7304 return isl_bool_error
;
7306 equal_params
= isl_space_has_equal_params(mpa1
->space
, mpa2
->space
);
7307 if (equal_params
< 0)
7308 return isl_bool_error
;
7309 if (!equal_params
) {
7310 if (!isl_space_has_named_params(mpa1
->space
))
7311 return isl_bool_false
;
7312 if (!isl_space_has_named_params(mpa2
->space
))
7313 return isl_bool_false
;
7314 mpa1
= isl_multi_pw_aff_copy(mpa1
);
7315 mpa2
= isl_multi_pw_aff_copy(mpa2
);
7316 mpa1
= isl_multi_pw_aff_align_params(mpa1
,
7317 isl_multi_pw_aff_get_space(mpa2
));
7318 mpa2
= isl_multi_pw_aff_align_params(mpa2
,
7319 isl_multi_pw_aff_get_space(mpa1
));
7320 equal
= isl_multi_pw_aff_is_equal(mpa1
, mpa2
);
7321 isl_multi_pw_aff_free(mpa1
);
7322 isl_multi_pw_aff_free(mpa2
);
7326 equal
= isl_space_is_equal(mpa1
->space
, mpa2
->space
);
7327 if (equal
< 0 || !equal
)
7330 for (i
= 0; i
< mpa1
->n
; ++i
) {
7331 equal
= isl_pw_aff_is_equal(mpa1
->u
.p
[i
], mpa2
->u
.p
[i
]);
7332 if (equal
< 0 || !equal
)
7336 return isl_bool_true
;
7339 /* Do "pma1" and "pma2" represent the same function?
7341 * First check if they are obviously equal.
7342 * If not, then convert them to maps and check if those are equal.
7344 * If "pa1" or "pa2" contain any NaNs, then they are considered
7345 * not to be the same. A NaN is not equal to anything, not even
7348 isl_bool
isl_pw_multi_aff_is_equal(__isl_keep isl_pw_multi_aff
*pma1
,
7349 __isl_keep isl_pw_multi_aff
*pma2
)
7353 isl_map
*map1
, *map2
;
7356 return isl_bool_error
;
7358 equal
= isl_pw_multi_aff_plain_is_equal(pma1
, pma2
);
7359 if (equal
< 0 || equal
)
7361 has_nan
= isl_pw_multi_aff_involves_nan(pma1
);
7362 if (has_nan
>= 0 && !has_nan
)
7363 has_nan
= isl_pw_multi_aff_involves_nan(pma2
);
7364 if (has_nan
< 0 || has_nan
)
7365 return isl_bool_not(has_nan
);
7367 map1
= isl_map_from_pw_multi_aff_internal(isl_pw_multi_aff_copy(pma1
));
7368 map2
= isl_map_from_pw_multi_aff_internal(isl_pw_multi_aff_copy(pma2
));
7369 equal
= isl_map_is_equal(map1
, map2
);
7377 #define BASE multi_aff
7379 #include "isl_multi_pw_aff_pullback_templ.c"
7382 #define BASE pw_multi_aff
7384 #include "isl_multi_pw_aff_pullback_templ.c"
7386 /* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
7387 * with the domain of "aff". The domain of the result is the same
7389 * "mpa" and "aff" are assumed to have been aligned.
7391 * We first extract the parametric constant from "aff", defined
7392 * over the correct domain.
7393 * Then we add the appropriate combinations of the members of "mpa".
7394 * Finally, we add the integer divisions through recursive calls.
7396 static __isl_give isl_pw_aff
*isl_multi_pw_aff_apply_aff_aligned(
7397 __isl_take isl_multi_pw_aff
*mpa
, __isl_take isl_aff
*aff
)
7400 isl_size n_in
, n_div
, n_mpa_in
;
7406 n_in
= isl_aff_dim(aff
, isl_dim_in
);
7407 n_div
= isl_aff_dim(aff
, isl_dim_div
);
7408 n_mpa_in
= isl_multi_pw_aff_dim(mpa
, isl_dim_in
);
7409 if (n_in
< 0 || n_div
< 0 || n_mpa_in
< 0)
7412 space
= isl_space_domain(isl_multi_pw_aff_get_space(mpa
));
7413 tmp
= isl_aff_copy(aff
);
7414 tmp
= isl_aff_drop_dims(tmp
, isl_dim_div
, 0, n_div
);
7415 tmp
= isl_aff_drop_dims(tmp
, isl_dim_in
, 0, n_in
);
7416 tmp
= isl_aff_add_dims(tmp
, isl_dim_in
, n_mpa_in
);
7417 tmp
= isl_aff_reset_domain_space(tmp
, space
);
7418 pa
= isl_pw_aff_from_aff(tmp
);
7420 for (i
= 0; i
< n_in
; ++i
) {
7423 if (!isl_aff_involves_dims(aff
, isl_dim_in
, i
, 1))
7425 v
= isl_aff_get_coefficient_val(aff
, isl_dim_in
, i
);
7426 pa_i
= isl_multi_pw_aff_get_pw_aff(mpa
, i
);
7427 pa_i
= isl_pw_aff_scale_val(pa_i
, v
);
7428 pa
= isl_pw_aff_add(pa
, pa_i
);
7431 for (i
= 0; i
< n_div
; ++i
) {
7435 if (!isl_aff_involves_dims(aff
, isl_dim_div
, i
, 1))
7437 div
= isl_aff_get_div(aff
, i
);
7438 pa_i
= isl_multi_pw_aff_apply_aff_aligned(
7439 isl_multi_pw_aff_copy(mpa
), div
);
7440 pa_i
= isl_pw_aff_floor(pa_i
);
7441 v
= isl_aff_get_coefficient_val(aff
, isl_dim_div
, i
);
7442 pa_i
= isl_pw_aff_scale_val(pa_i
, v
);
7443 pa
= isl_pw_aff_add(pa
, pa_i
);
7446 isl_multi_pw_aff_free(mpa
);
7451 isl_multi_pw_aff_free(mpa
);
7456 /* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
7457 * with the domain of "aff". The domain of the result is the same
7460 __isl_give isl_pw_aff
*isl_multi_pw_aff_apply_aff(
7461 __isl_take isl_multi_pw_aff
*mpa
, __isl_take isl_aff
*aff
)
7463 isl_bool equal_params
;
7467 equal_params
= isl_space_has_equal_params(aff
->ls
->dim
, mpa
->space
);
7468 if (equal_params
< 0)
7471 return isl_multi_pw_aff_apply_aff_aligned(mpa
, aff
);
7473 aff
= isl_aff_align_params(aff
, isl_multi_pw_aff_get_space(mpa
));
7474 mpa
= isl_multi_pw_aff_align_params(mpa
, isl_aff_get_space(aff
));
7476 return isl_multi_pw_aff_apply_aff_aligned(mpa
, aff
);
7479 isl_multi_pw_aff_free(mpa
);
7483 /* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
7484 * with the domain of "pa". The domain of the result is the same
7486 * "mpa" and "pa" are assumed to have been aligned.
7488 * We consider each piece in turn. Note that the domains of the
7489 * pieces are assumed to be disjoint and they remain disjoint
7490 * after taking the preimage (over the same function).
7492 static __isl_give isl_pw_aff
*isl_multi_pw_aff_apply_pw_aff_aligned(
7493 __isl_take isl_multi_pw_aff
*mpa
, __isl_take isl_pw_aff
*pa
)
7502 space
= isl_space_join(isl_multi_pw_aff_get_space(mpa
),
7503 isl_pw_aff_get_space(pa
));
7504 res
= isl_pw_aff_empty(space
);
7506 for (i
= 0; i
< pa
->n
; ++i
) {
7510 pa_i
= isl_multi_pw_aff_apply_aff_aligned(
7511 isl_multi_pw_aff_copy(mpa
),
7512 isl_aff_copy(pa
->p
[i
].aff
));
7513 domain
= isl_set_copy(pa
->p
[i
].set
);
7514 domain
= isl_set_preimage_multi_pw_aff(domain
,
7515 isl_multi_pw_aff_copy(mpa
));
7516 pa_i
= isl_pw_aff_intersect_domain(pa_i
, domain
);
7517 res
= isl_pw_aff_add_disjoint(res
, pa_i
);
7520 isl_pw_aff_free(pa
);
7521 isl_multi_pw_aff_free(mpa
);
7524 isl_pw_aff_free(pa
);
7525 isl_multi_pw_aff_free(mpa
);
7529 /* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
7530 * with the domain of "pa". The domain of the result is the same
7533 __isl_give isl_pw_aff
*isl_multi_pw_aff_apply_pw_aff(
7534 __isl_take isl_multi_pw_aff
*mpa
, __isl_take isl_pw_aff
*pa
)
7536 isl_bool equal_params
;
7540 equal_params
= isl_space_has_equal_params(pa
->dim
, mpa
->space
);
7541 if (equal_params
< 0)
7544 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa
, pa
);
7546 pa
= isl_pw_aff_align_params(pa
, isl_multi_pw_aff_get_space(mpa
));
7547 mpa
= isl_multi_pw_aff_align_params(mpa
, isl_pw_aff_get_space(pa
));
7549 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa
, pa
);
7551 isl_pw_aff_free(pa
);
7552 isl_multi_pw_aff_free(mpa
);
7556 /* Compute the pullback of "pa" by the function represented by "mpa".
7557 * In other words, plug in "mpa" in "pa".
7559 * The pullback is computed by applying "pa" to "mpa".
7561 __isl_give isl_pw_aff
*isl_pw_aff_pullback_multi_pw_aff(
7562 __isl_take isl_pw_aff
*pa
, __isl_take isl_multi_pw_aff
*mpa
)
7564 return isl_multi_pw_aff_apply_pw_aff(mpa
, pa
);
7568 #define BASE multi_pw_aff
7570 #include "isl_multi_pw_aff_pullback_templ.c"
7572 /* Align the parameters of "mpa1" and "mpa2", check that the ranges
7573 * of "mpa1" and "mpa2" live in the same space, construct map space
7574 * between the domain spaces of "mpa1" and "mpa2" and call "order"
7575 * with this map space as extract argument.
7577 static __isl_give isl_map
*isl_multi_pw_aff_order_map(
7578 __isl_take isl_multi_pw_aff
*mpa1
, __isl_take isl_multi_pw_aff
*mpa2
,
7579 __isl_give isl_map
*(*order
)(__isl_keep isl_multi_pw_aff
*mpa1
,
7580 __isl_keep isl_multi_pw_aff
*mpa2
, __isl_take isl_space
*space
))
7583 isl_space
*space1
, *space2
;
7586 mpa1
= isl_multi_pw_aff_align_params(mpa1
,
7587 isl_multi_pw_aff_get_space(mpa2
));
7588 mpa2
= isl_multi_pw_aff_align_params(mpa2
,
7589 isl_multi_pw_aff_get_space(mpa1
));
7592 match
= isl_space_tuple_is_equal(mpa1
->space
, isl_dim_out
,
7593 mpa2
->space
, isl_dim_out
);
7597 isl_die(isl_multi_pw_aff_get_ctx(mpa1
), isl_error_invalid
,
7598 "range spaces don't match", goto error
);
7599 space1
= isl_space_domain(isl_multi_pw_aff_get_space(mpa1
));
7600 space2
= isl_space_domain(isl_multi_pw_aff_get_space(mpa2
));
7601 space1
= isl_space_map_from_domain_and_range(space1
, space2
);
7603 res
= order(mpa1
, mpa2
, space1
);
7604 isl_multi_pw_aff_free(mpa1
);
7605 isl_multi_pw_aff_free(mpa2
);
7608 isl_multi_pw_aff_free(mpa1
);
7609 isl_multi_pw_aff_free(mpa2
);
7613 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7614 * where the function values are equal. "space" is the space of the result.
7615 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7617 * "mpa1" and "mpa2" are equal when each of the pairs of elements
7618 * in the sequences are equal.
7620 static __isl_give isl_map
*isl_multi_pw_aff_eq_map_on_space(
7621 __isl_keep isl_multi_pw_aff
*mpa1
, __isl_keep isl_multi_pw_aff
*mpa2
,
7622 __isl_take isl_space
*space
)
7628 n
= isl_multi_pw_aff_dim(mpa1
, isl_dim_out
);
7630 space
= isl_space_free(space
);
7631 res
= isl_map_universe(space
);
7633 for (i
= 0; i
< n
; ++i
) {
7634 isl_pw_aff
*pa1
, *pa2
;
7637 pa1
= isl_multi_pw_aff_get_pw_aff(mpa1
, i
);
7638 pa2
= isl_multi_pw_aff_get_pw_aff(mpa2
, i
);
7639 map
= isl_pw_aff_eq_map(pa1
, pa2
);
7640 res
= isl_map_intersect(res
, map
);
7646 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7647 * where the function values are equal.
7649 __isl_give isl_map
*isl_multi_pw_aff_eq_map(__isl_take isl_multi_pw_aff
*mpa1
,
7650 __isl_take isl_multi_pw_aff
*mpa2
)
7652 return isl_multi_pw_aff_order_map(mpa1
, mpa2
,
7653 &isl_multi_pw_aff_eq_map_on_space
);
7656 /* Intersect "map" with the result of applying "order"
7657 * on two copies of "mpa".
7659 static __isl_give isl_map
*isl_map_order_at_multi_pw_aff(
7660 __isl_take isl_map
*map
, __isl_take isl_multi_pw_aff
*mpa
,
7661 __isl_give isl_map
*(*order
)(__isl_take isl_multi_pw_aff
*mpa1
,
7662 __isl_take isl_multi_pw_aff
*mpa2
))
7664 return isl_map_intersect(map
, order(mpa
, isl_multi_pw_aff_copy(mpa
)));
7667 /* Return the subset of "map" where the domain and the range
7668 * have equal "mpa" values.
7670 __isl_give isl_map
*isl_map_eq_at_multi_pw_aff(__isl_take isl_map
*map
,
7671 __isl_take isl_multi_pw_aff
*mpa
)
7673 return isl_map_order_at_multi_pw_aff(map
, mpa
,
7674 &isl_multi_pw_aff_eq_map
);
7677 /* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
7678 * where the function values of "mpa1" lexicographically satisfies
7679 * "strict_base"/"base" compared to that of "mpa2".
7680 * "space" is the space of the result.
7681 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
7683 * "mpa1" lexicographically satisfies "strict_base"/"base" compared to "mpa2"
7684 * if, for some i, the i-th element of "mpa1" satisfies "strict_base"/"base"
7685 * when compared to the i-th element of "mpa2" while all previous elements are
7687 * In particular, if i corresponds to the final elements
7688 * then they need to satisfy "base", while "strict_base" needs to be satisfied
7689 * for other values of i.
7690 * If "base" is a strict order, then "base" and "strict_base" are the same.
7692 static __isl_give isl_map
*isl_multi_pw_aff_lex_map_on_space(
7693 __isl_keep isl_multi_pw_aff
*mpa1
, __isl_keep isl_multi_pw_aff
*mpa2
,
7694 __isl_give isl_map
*(*strict_base
)(__isl_take isl_pw_aff
*pa1
,
7695 __isl_take isl_pw_aff
*pa2
),
7696 __isl_give isl_map
*(*base
)(__isl_take isl_pw_aff
*pa1
,
7697 __isl_take isl_pw_aff
*pa2
),
7698 __isl_take isl_space
*space
)
7702 isl_map
*res
, *rest
;
7704 n
= isl_multi_pw_aff_dim(mpa1
, isl_dim_out
);
7706 space
= isl_space_free(space
);
7707 res
= isl_map_empty(isl_space_copy(space
));
7708 rest
= isl_map_universe(space
);
7710 for (i
= 0; i
< n
; ++i
) {
7712 isl_pw_aff
*pa1
, *pa2
;
7717 pa1
= isl_multi_pw_aff_get_pw_aff(mpa1
, i
);
7718 pa2
= isl_multi_pw_aff_get_pw_aff(mpa2
, i
);
7719 map
= last
? base(pa1
, pa2
) : strict_base(pa1
, pa2
);
7720 map
= isl_map_intersect(map
, isl_map_copy(rest
));
7721 res
= isl_map_union(res
, map
);
7726 pa1
= isl_multi_pw_aff_get_pw_aff(mpa1
, i
);
7727 pa2
= isl_multi_pw_aff_get_pw_aff(mpa2
, i
);
7728 map
= isl_pw_aff_eq_map(pa1
, pa2
);
7729 rest
= isl_map_intersect(rest
, map
);
7739 #define STRICT_ORDER lt
7740 #include "isl_aff_lex_templ.c"
7745 #define STRICT_ORDER lt
7746 #include "isl_aff_lex_templ.c"
7751 #define STRICT_ORDER gt
7752 #include "isl_aff_lex_templ.c"
7757 #define STRICT_ORDER gt
7758 #include "isl_aff_lex_templ.c"
7760 /* Compare two isl_affs.
7762 * Return -1 if "aff1" is "smaller" than "aff2", 1 if "aff1" is "greater"
7763 * than "aff2" and 0 if they are equal.
7765 * The order is fairly arbitrary. We do consider expressions that only involve
7766 * earlier dimensions as "smaller".
7768 int isl_aff_plain_cmp(__isl_keep isl_aff
*aff1
, __isl_keep isl_aff
*aff2
)
7781 cmp
= isl_local_space_cmp(aff1
->ls
, aff2
->ls
);
7785 last1
= isl_seq_last_non_zero(aff1
->v
->el
+ 1, aff1
->v
->size
- 1);
7786 last2
= isl_seq_last_non_zero(aff2
->v
->el
+ 1, aff1
->v
->size
- 1);
7788 return last1
- last2
;
7790 return isl_seq_cmp(aff1
->v
->el
, aff2
->v
->el
, aff1
->v
->size
);
7793 /* Compare two isl_pw_affs.
7795 * Return -1 if "pa1" is "smaller" than "pa2", 1 if "pa1" is "greater"
7796 * than "pa2" and 0 if they are equal.
7798 * The order is fairly arbitrary. We do consider expressions that only involve
7799 * earlier dimensions as "smaller".
7801 int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff
*pa1
,
7802 __isl_keep isl_pw_aff
*pa2
)
7815 cmp
= isl_space_cmp(pa1
->dim
, pa2
->dim
);
7819 if (pa1
->n
!= pa2
->n
)
7820 return pa1
->n
- pa2
->n
;
7822 for (i
= 0; i
< pa1
->n
; ++i
) {
7823 cmp
= isl_set_plain_cmp(pa1
->p
[i
].set
, pa2
->p
[i
].set
);
7826 cmp
= isl_aff_plain_cmp(pa1
->p
[i
].aff
, pa2
->p
[i
].aff
);
7834 /* Return a piecewise affine expression that is equal to "v" on "domain".
7836 __isl_give isl_pw_aff
*isl_pw_aff_val_on_domain(__isl_take isl_set
*domain
,
7837 __isl_take isl_val
*v
)
7840 isl_local_space
*ls
;
7843 space
= isl_set_get_space(domain
);
7844 ls
= isl_local_space_from_space(space
);
7845 aff
= isl_aff_val_on_domain(ls
, v
);
7847 return isl_pw_aff_alloc(domain
, aff
);
7850 /* This function performs the same operation as isl_pw_aff_val_on_domain,
7851 * but is considered as a function on an isl_set when exported.
7853 __isl_give isl_pw_aff
*isl_set_pw_aff_on_domain_val(__isl_take isl_set
*domain
,
7854 __isl_take isl_val
*v
)
7856 return isl_pw_aff_val_on_domain(domain
, v
);
7859 /* Return a piecewise affine expression that is equal to the parameter
7860 * with identifier "id" on "domain".
7862 __isl_give isl_pw_aff
*isl_pw_aff_param_on_domain_id(
7863 __isl_take isl_set
*domain
, __isl_take isl_id
*id
)
7868 space
= isl_set_get_space(domain
);
7869 space
= isl_space_add_param_id(space
, isl_id_copy(id
));
7870 domain
= isl_set_align_params(domain
, isl_space_copy(space
));
7871 aff
= isl_aff_param_on_domain_space_id(space
, id
);
7873 return isl_pw_aff_alloc(domain
, aff
);
7876 /* This function performs the same operation as
7877 * isl_pw_aff_param_on_domain_id,
7878 * but is considered as a function on an isl_set when exported.
7880 __isl_give isl_pw_aff
*isl_set_param_pw_aff_on_domain_id(
7881 __isl_take isl_set
*domain
, __isl_take isl_id
*id
)
7883 return isl_pw_aff_param_on_domain_id(domain
, id
);
7886 /* Return a multi affine expression that is equal to "mv" on domain
7889 __isl_give isl_multi_aff
*isl_multi_aff_multi_val_on_domain_space(
7890 __isl_take isl_space
*space
, __isl_take isl_multi_val
*mv
)
7895 isl_local_space
*ls
;
7898 n
= isl_multi_val_dim(mv
, isl_dim_set
);
7899 if (!space
|| n
< 0)
7902 space2
= isl_multi_val_get_space(mv
);
7903 space2
= isl_space_align_params(space2
, isl_space_copy(space
));
7904 space
= isl_space_align_params(space
, isl_space_copy(space2
));
7905 space
= isl_space_map_from_domain_and_range(space
, space2
);
7906 ma
= isl_multi_aff_alloc(isl_space_copy(space
));
7907 ls
= isl_local_space_from_space(isl_space_domain(space
));
7908 for (i
= 0; i
< n
; ++i
) {
7912 v
= isl_multi_val_get_val(mv
, i
);
7913 aff
= isl_aff_val_on_domain(isl_local_space_copy(ls
), v
);
7914 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
7916 isl_local_space_free(ls
);
7918 isl_multi_val_free(mv
);
7921 isl_space_free(space
);
7922 isl_multi_val_free(mv
);
7926 /* This is an alternative name for the function above.
7928 __isl_give isl_multi_aff
*isl_multi_aff_multi_val_on_space(
7929 __isl_take isl_space
*space
, __isl_take isl_multi_val
*mv
)
7931 return isl_multi_aff_multi_val_on_domain_space(space
, mv
);
7934 /* This function performs the same operation as
7935 * isl_multi_aff_multi_val_on_domain_space,
7936 * but is considered as a function on an isl_space when exported.
7938 __isl_give isl_multi_aff
*isl_space_multi_aff_on_domain_multi_val(
7939 __isl_take isl_space
*space
, __isl_take isl_multi_val
*mv
)
7941 return isl_multi_aff_multi_val_on_domain_space(space
, mv
);
7944 /* Return a piecewise multi-affine expression
7945 * that is equal to "mv" on "domain".
7947 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_multi_val_on_domain(
7948 __isl_take isl_set
*domain
, __isl_take isl_multi_val
*mv
)
7953 space
= isl_set_get_space(domain
);
7954 ma
= isl_multi_aff_multi_val_on_space(space
, mv
);
7956 return isl_pw_multi_aff_alloc(domain
, ma
);
7959 /* This function performs the same operation as
7960 * isl_pw_multi_aff_multi_val_on_domain,
7961 * but is considered as a function on an isl_set when exported.
7963 __isl_give isl_pw_multi_aff
*isl_set_pw_multi_aff_on_domain_multi_val(
7964 __isl_take isl_set
*domain
, __isl_take isl_multi_val
*mv
)
7966 return isl_pw_multi_aff_multi_val_on_domain(domain
, mv
);
7969 /* Internal data structure for isl_union_pw_multi_aff_multi_val_on_domain.
7970 * mv is the value that should be attained on each domain set
7971 * res collects the results
7973 struct isl_union_pw_multi_aff_multi_val_on_domain_data
{
7975 isl_union_pw_multi_aff
*res
;
7978 /* Create an isl_pw_multi_aff equal to data->mv on "domain"
7979 * and add it to data->res.
7981 static isl_stat
pw_multi_aff_multi_val_on_domain(__isl_take isl_set
*domain
,
7984 struct isl_union_pw_multi_aff_multi_val_on_domain_data
*data
= user
;
7985 isl_pw_multi_aff
*pma
;
7988 mv
= isl_multi_val_copy(data
->mv
);
7989 pma
= isl_pw_multi_aff_multi_val_on_domain(domain
, mv
);
7990 data
->res
= isl_union_pw_multi_aff_add_pw_multi_aff(data
->res
, pma
);
7992 return data
->res
? isl_stat_ok
: isl_stat_error
;
7995 /* Return a union piecewise multi-affine expression
7996 * that is equal to "mv" on "domain".
7998 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_multi_val_on_domain(
7999 __isl_take isl_union_set
*domain
, __isl_take isl_multi_val
*mv
)
8001 struct isl_union_pw_multi_aff_multi_val_on_domain_data data
;
8004 space
= isl_union_set_get_space(domain
);
8005 data
.res
= isl_union_pw_multi_aff_empty(space
);
8007 if (isl_union_set_foreach_set(domain
,
8008 &pw_multi_aff_multi_val_on_domain
, &data
) < 0)
8009 data
.res
= isl_union_pw_multi_aff_free(data
.res
);
8010 isl_union_set_free(domain
);
8011 isl_multi_val_free(mv
);
8015 /* Compute the pullback of data->pma by the function represented by "pma2",
8016 * provided the spaces match, and add the results to data->res.
8018 static isl_stat
pullback_entry(__isl_take isl_pw_multi_aff
*pma2
, void *user
)
8020 struct isl_union_pw_multi_aff_bin_data
*data
= user
;
8022 if (!isl_space_tuple_is_equal(data
->pma
->dim
, isl_dim_in
,
8023 pma2
->dim
, isl_dim_out
)) {
8024 isl_pw_multi_aff_free(pma2
);
8028 pma2
= isl_pw_multi_aff_pullback_pw_multi_aff(
8029 isl_pw_multi_aff_copy(data
->pma
), pma2
);
8031 data
->res
= isl_union_pw_multi_aff_add_pw_multi_aff(data
->res
, pma2
);
8033 return isl_stat_error
;
8038 /* Compute the pullback of "upma1" by the function represented by "upma2".
8040 __isl_give isl_union_pw_multi_aff
*
8041 isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
8042 __isl_take isl_union_pw_multi_aff
*upma1
,
8043 __isl_take isl_union_pw_multi_aff
*upma2
)
8045 return bin_op(upma1
, upma2
, &pullback_entry
);
8048 /* Apply "upma2" to "upma1".
8050 * That is, compute the pullback of "upma2" by "upma1".
8052 __isl_give isl_union_pw_multi_aff
*
8053 isl_union_pw_multi_aff_apply_union_pw_multi_aff(
8054 __isl_take isl_union_pw_multi_aff
*upma1
,
8055 __isl_take isl_union_pw_multi_aff
*upma2
)
8057 return isl_union_pw_multi_aff_pullback_union_pw_multi_aff(upma2
, upma1
);
8061 #define BASE pw_multi_aff
8063 #include "isl_copy_tuple_id_templ.c"
8065 /* Given a function "pma1" of the form A[B -> C] -> D and
8066 * a function "pma2" of the form E -> B,
8067 * replace the domain of the wrapped relation inside the domain of "pma1"
8068 * by the preimage with respect to "pma2".
8069 * In other words, plug in "pma2" in this nested domain.
8070 * The result is of the form A[E -> C] -> D.
8072 * In particular, extend E -> B to A[E -> C] -> A[B -> C] and
8073 * plug that into "pma1".
8075 __isl_give isl_pw_multi_aff
*
8076 isl_pw_multi_aff_preimage_domain_wrapped_domain_pw_multi_aff(
8077 __isl_take isl_pw_multi_aff
*pma1
, __isl_take isl_pw_multi_aff
*pma2
)
8079 isl_space
*pma1_space
, *pma2_space
;
8081 isl_pw_multi_aff
*id
;
8083 pma1_space
= isl_pw_multi_aff_peek_space(pma1
);
8084 pma2_space
= isl_pw_multi_aff_peek_space(pma2
);
8086 if (isl_space_check_domain_is_wrapping(pma1_space
) < 0)
8088 if (isl_space_check_wrapped_tuple_is_equal(pma1_space
,
8089 isl_dim_in
, isl_dim_in
, pma2_space
, isl_dim_out
) < 0)
8092 space
= isl_space_domain(isl_space_copy(pma1_space
));
8093 space
= isl_space_range(isl_space_unwrap(space
));
8094 id
= isl_pw_multi_aff_identity_on_domain_space(space
);
8095 pma2
= isl_pw_multi_aff_product(pma2
, id
);
8097 pma2
= isl_pw_multi_aff_copy_tuple_id(pma2
, isl_dim_in
,
8098 pma1_space
, isl_dim_in
);
8099 pma2
= isl_pw_multi_aff_copy_tuple_id(pma2
, isl_dim_out
,
8100 pma1_space
, isl_dim_in
);
8102 return isl_pw_multi_aff_pullback_pw_multi_aff(pma1
, pma2
);
8104 isl_pw_multi_aff_free(pma1
);
8105 isl_pw_multi_aff_free(pma2
);
8109 /* If data->pma and "pma2" are such that
8110 * data->pma is of the form A[B -> C] -> D and
8111 * "pma2" is of the form E -> B,
8112 * then replace the domain of the wrapped relation
8113 * inside the domain of data->pma by the preimage with respect to "pma2" and
8114 * add the result to data->res.
8116 static isl_stat
preimage_domain_wrapped_domain_entry(
8117 __isl_take isl_pw_multi_aff
*pma2
, void *user
)
8119 struct isl_union_pw_multi_aff_bin_data
*data
= user
;
8120 isl_space
*pma1_space
, *pma2_space
;
8123 pma1_space
= isl_pw_multi_aff_peek_space(data
->pma
);
8124 pma2_space
= isl_pw_multi_aff_peek_space(pma2
);
8126 match
= isl_space_domain_is_wrapping(pma1_space
);
8127 if (match
>= 0 && match
)
8128 match
= isl_space_wrapped_tuple_is_equal(pma1_space
, isl_dim_in
,
8129 isl_dim_in
, pma2_space
, isl_dim_out
);
8130 if (match
< 0 || !match
) {
8131 isl_pw_multi_aff_free(pma2
);
8132 return match
< 0 ? isl_stat_error
: isl_stat_ok
;
8135 pma2
= isl_pw_multi_aff_preimage_domain_wrapped_domain_pw_multi_aff(
8136 isl_pw_multi_aff_copy(data
->pma
), pma2
);
8138 data
->res
= isl_union_pw_multi_aff_add_pw_multi_aff(data
->res
, pma2
);
8140 return isl_stat_non_null(data
->res
);
8143 /* For each pair of functions A[B -> C] -> D in "upma1" and
8144 * E -> B in "upma2",
8145 * replace the domain of the wrapped relation inside the domain of the first
8146 * by the preimage with respect to the second and collect the results.
8147 * In other words, plug in the second function in this nested domain.
8148 * The results are of the form A[E -> C] -> D.
8150 __isl_give isl_union_pw_multi_aff
*
8151 isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff(
8152 __isl_take isl_union_pw_multi_aff
*upma1
,
8153 __isl_take isl_union_pw_multi_aff
*upma2
)
8155 return bin_op(upma1
, upma2
, &preimage_domain_wrapped_domain_entry
);
8158 /* Check that the domain space of "upa" matches "space".
8160 * This function is called from isl_multi_union_pw_aff_set_union_pw_aff and
8161 * can in principle never fail since the space "space" is that
8162 * of the isl_multi_union_pw_aff and is a set space such that
8163 * there is no domain space to match.
8165 * We check the parameters and double-check that "space" is
8166 * indeed that of a set.
8168 static isl_stat
isl_union_pw_aff_check_match_domain_space(
8169 __isl_keep isl_union_pw_aff
*upa
, __isl_keep isl_space
*space
)
8171 isl_space
*upa_space
;
8175 return isl_stat_error
;
8177 match
= isl_space_is_set(space
);
8179 return isl_stat_error
;
8181 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
8182 "expecting set space", return isl_stat_error
);
8184 upa_space
= isl_union_pw_aff_get_space(upa
);
8185 match
= isl_space_has_equal_params(space
, upa_space
);
8189 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
8190 "parameters don't match", goto error
);
8192 isl_space_free(upa_space
);
8195 isl_space_free(upa_space
);
8196 return isl_stat_error
;
8199 /* Do the parameters of "upa" match those of "space"?
8201 static isl_bool
isl_union_pw_aff_matching_params(
8202 __isl_keep isl_union_pw_aff
*upa
, __isl_keep isl_space
*space
)
8204 isl_space
*upa_space
;
8208 return isl_bool_error
;
8210 upa_space
= isl_union_pw_aff_get_space(upa
);
8212 match
= isl_space_has_equal_params(space
, upa_space
);
8214 isl_space_free(upa_space
);
8218 /* Internal data structure for isl_union_pw_aff_reset_domain_space.
8219 * space represents the new parameters.
8220 * res collects the results.
8222 struct isl_union_pw_aff_reset_params_data
{
8224 isl_union_pw_aff
*res
;
8227 /* Replace the parameters of "pa" by data->space and
8228 * add the result to data->res.
8230 static isl_stat
reset_params(__isl_take isl_pw_aff
*pa
, void *user
)
8232 struct isl_union_pw_aff_reset_params_data
*data
= user
;
8235 space
= isl_pw_aff_get_space(pa
);
8236 space
= isl_space_replace_params(space
, data
->space
);
8237 pa
= isl_pw_aff_reset_space(pa
, space
);
8238 data
->res
= isl_union_pw_aff_add_pw_aff(data
->res
, pa
);
8240 return data
->res
? isl_stat_ok
: isl_stat_error
;
8243 /* Replace the domain space of "upa" by "space".
8244 * Since a union expression does not have a (single) domain space,
8245 * "space" is necessarily a parameter space.
8247 * Since the order and the names of the parameters determine
8248 * the hash value, we need to create a new hash table.
8250 static __isl_give isl_union_pw_aff
*isl_union_pw_aff_reset_domain_space(
8251 __isl_take isl_union_pw_aff
*upa
, __isl_take isl_space
*space
)
8253 struct isl_union_pw_aff_reset_params_data data
= { space
};
8256 match
= isl_union_pw_aff_matching_params(upa
, space
);
8258 upa
= isl_union_pw_aff_free(upa
);
8260 isl_space_free(space
);
8264 data
.res
= isl_union_pw_aff_empty(isl_space_copy(space
));
8265 if (isl_union_pw_aff_foreach_pw_aff(upa
, &reset_params
, &data
) < 0)
8266 data
.res
= isl_union_pw_aff_free(data
.res
);
8268 isl_union_pw_aff_free(upa
);
8269 isl_space_free(space
);
8273 /* Return the floor of "pa".
8275 static __isl_give isl_pw_aff
*floor_entry(__isl_take isl_pw_aff
*pa
, void *user
)
8277 return isl_pw_aff_floor(pa
);
8280 /* Given f, return floor(f).
8282 __isl_give isl_union_pw_aff
*isl_union_pw_aff_floor(
8283 __isl_take isl_union_pw_aff
*upa
)
8285 return isl_union_pw_aff_transform_inplace(upa
, &floor_entry
, NULL
);
8290 * upa mod m = upa - m * floor(upa/m)
8292 * with m an integer value.
8294 __isl_give isl_union_pw_aff
*isl_union_pw_aff_mod_val(
8295 __isl_take isl_union_pw_aff
*upa
, __isl_take isl_val
*m
)
8297 isl_union_pw_aff
*res
;
8302 if (!isl_val_is_int(m
))
8303 isl_die(isl_val_get_ctx(m
), isl_error_invalid
,
8304 "expecting integer modulo", goto error
);
8305 if (!isl_val_is_pos(m
))
8306 isl_die(isl_val_get_ctx(m
), isl_error_invalid
,
8307 "expecting positive modulo", goto error
);
8309 res
= isl_union_pw_aff_copy(upa
);
8310 upa
= isl_union_pw_aff_scale_down_val(upa
, isl_val_copy(m
));
8311 upa
= isl_union_pw_aff_floor(upa
);
8312 upa
= isl_union_pw_aff_scale_val(upa
, m
);
8313 res
= isl_union_pw_aff_sub(res
, upa
);
8318 isl_union_pw_aff_free(upa
);
8322 /* Internal data structure for isl_union_pw_multi_aff_get_union_pw_aff.
8323 * pos is the output position that needs to be extracted.
8324 * res collects the results.
8326 struct isl_union_pw_multi_aff_get_union_pw_aff_data
{
8328 isl_union_pw_aff
*res
;
8331 /* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma"
8332 * (assuming it has such a dimension) and add it to data->res.
8334 static isl_stat
get_union_pw_aff(__isl_take isl_pw_multi_aff
*pma
, void *user
)
8336 struct isl_union_pw_multi_aff_get_union_pw_aff_data
*data
= user
;
8340 n_out
= isl_pw_multi_aff_dim(pma
, isl_dim_out
);
8342 return isl_stat_error
;
8343 if (data
->pos
>= n_out
) {
8344 isl_pw_multi_aff_free(pma
);
8348 pa
= isl_pw_multi_aff_get_pw_aff(pma
, data
->pos
);
8349 isl_pw_multi_aff_free(pma
);
8351 data
->res
= isl_union_pw_aff_add_pw_aff(data
->res
, pa
);
8353 return data
->res
? isl_stat_ok
: isl_stat_error
;
8356 /* Extract an isl_union_pw_aff corresponding to
8357 * output dimension "pos" of "upma".
8359 __isl_give isl_union_pw_aff
*isl_union_pw_multi_aff_get_union_pw_aff(
8360 __isl_keep isl_union_pw_multi_aff
*upma
, int pos
)
8362 struct isl_union_pw_multi_aff_get_union_pw_aff_data data
;
8369 isl_die(isl_union_pw_multi_aff_get_ctx(upma
), isl_error_invalid
,
8370 "cannot extract at negative position", return NULL
);
8372 space
= isl_union_pw_multi_aff_get_space(upma
);
8373 data
.res
= isl_union_pw_aff_empty(space
);
8375 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma
,
8376 &get_union_pw_aff
, &data
) < 0)
8377 data
.res
= isl_union_pw_aff_free(data
.res
);
8382 /* Return a union piecewise affine expression
8383 * that is equal to "aff" on "domain".
8385 __isl_give isl_union_pw_aff
*isl_union_pw_aff_aff_on_domain(
8386 __isl_take isl_union_set
*domain
, __isl_take isl_aff
*aff
)
8390 pa
= isl_pw_aff_from_aff(aff
);
8391 return isl_union_pw_aff_pw_aff_on_domain(domain
, pa
);
8394 /* Return a union piecewise affine expression
8395 * that is equal to the parameter identified by "id" on "domain".
8397 * Make sure the parameter appears in the space passed to
8398 * isl_aff_param_on_domain_space_id.
8400 __isl_give isl_union_pw_aff
*isl_union_pw_aff_param_on_domain_id(
8401 __isl_take isl_union_set
*domain
, __isl_take isl_id
*id
)
8406 space
= isl_union_set_get_space(domain
);
8407 space
= isl_space_add_param_id(space
, isl_id_copy(id
));
8408 aff
= isl_aff_param_on_domain_space_id(space
, id
);
8409 return isl_union_pw_aff_aff_on_domain(domain
, aff
);
8412 /* Internal data structure for isl_union_pw_aff_pw_aff_on_domain.
8413 * "pa" is the piecewise symbolic value that the resulting isl_union_pw_aff
8415 * "res" collects the results.
8417 struct isl_union_pw_aff_pw_aff_on_domain_data
{
8419 isl_union_pw_aff
*res
;
8422 /* Construct a piecewise affine expression that is equal to data->pa
8423 * on "domain" and add the result to data->res.
8425 static isl_stat
pw_aff_on_domain(__isl_take isl_set
*domain
, void *user
)
8427 struct isl_union_pw_aff_pw_aff_on_domain_data
*data
= user
;
8431 pa
= isl_pw_aff_copy(data
->pa
);
8432 dim
= isl_set_dim(domain
, isl_dim_set
);
8434 pa
= isl_pw_aff_free(pa
);
8435 pa
= isl_pw_aff_from_range(pa
);
8436 pa
= isl_pw_aff_add_dims(pa
, isl_dim_in
, dim
);
8437 pa
= isl_pw_aff_reset_domain_space(pa
, isl_set_get_space(domain
));
8438 pa
= isl_pw_aff_intersect_domain(pa
, domain
);
8439 data
->res
= isl_union_pw_aff_add_pw_aff(data
->res
, pa
);
8441 return data
->res
? isl_stat_ok
: isl_stat_error
;
8444 /* Return a union piecewise affine expression
8445 * that is equal to "pa" on "domain", assuming "domain" and "pa"
8446 * have been aligned.
8448 * Construct an isl_pw_aff on each of the sets in "domain" and
8449 * collect the results.
8451 static __isl_give isl_union_pw_aff
*isl_union_pw_aff_pw_aff_on_domain_aligned(
8452 __isl_take isl_union_set
*domain
, __isl_take isl_pw_aff
*pa
)
8454 struct isl_union_pw_aff_pw_aff_on_domain_data data
;
8457 space
= isl_union_set_get_space(domain
);
8458 data
.res
= isl_union_pw_aff_empty(space
);
8460 if (isl_union_set_foreach_set(domain
, &pw_aff_on_domain
, &data
) < 0)
8461 data
.res
= isl_union_pw_aff_free(data
.res
);
8462 isl_union_set_free(domain
);
8463 isl_pw_aff_free(pa
);
8467 /* Return a union piecewise affine expression
8468 * that is equal to "pa" on "domain".
8470 * Check that "pa" is a parametric expression,
8471 * align the parameters if needed and call
8472 * isl_union_pw_aff_pw_aff_on_domain_aligned.
8474 __isl_give isl_union_pw_aff
*isl_union_pw_aff_pw_aff_on_domain(
8475 __isl_take isl_union_set
*domain
, __isl_take isl_pw_aff
*pa
)
8478 isl_bool equal_params
;
8479 isl_space
*domain_space
, *pa_space
;
8481 pa_space
= isl_pw_aff_peek_space(pa
);
8482 is_set
= isl_space_is_set(pa_space
);
8486 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
8487 "expecting parametric expression", goto error
);
8489 domain_space
= isl_union_set_get_space(domain
);
8490 pa_space
= isl_pw_aff_get_space(pa
);
8491 equal_params
= isl_space_has_equal_params(domain_space
, pa_space
);
8492 if (equal_params
>= 0 && !equal_params
) {
8495 space
= isl_space_align_params(domain_space
, pa_space
);
8496 pa
= isl_pw_aff_align_params(pa
, isl_space_copy(space
));
8497 domain
= isl_union_set_align_params(domain
, space
);
8499 isl_space_free(domain_space
);
8500 isl_space_free(pa_space
);
8503 if (equal_params
< 0)
8505 return isl_union_pw_aff_pw_aff_on_domain_aligned(domain
, pa
);
8507 isl_union_set_free(domain
);
8508 isl_pw_aff_free(pa
);
8512 /* Internal data structure for isl_union_pw_aff_val_on_domain.
8513 * "v" is the value that the resulting isl_union_pw_aff needs to attain.
8514 * "res" collects the results.
8516 struct isl_union_pw_aff_val_on_domain_data
{
8518 isl_union_pw_aff
*res
;
8521 /* Construct a piecewise affine expression that is equal to data->v
8522 * on "domain" and add the result to data->res.
8524 static isl_stat
pw_aff_val_on_domain(__isl_take isl_set
*domain
, void *user
)
8526 struct isl_union_pw_aff_val_on_domain_data
*data
= user
;
8530 v
= isl_val_copy(data
->v
);
8531 pa
= isl_pw_aff_val_on_domain(domain
, v
);
8532 data
->res
= isl_union_pw_aff_add_pw_aff(data
->res
, pa
);
8534 return data
->res
? isl_stat_ok
: isl_stat_error
;
8537 /* Return a union piecewise affine expression
8538 * that is equal to "v" on "domain".
8540 * Construct an isl_pw_aff on each of the sets in "domain" and
8541 * collect the results.
8543 __isl_give isl_union_pw_aff
*isl_union_pw_aff_val_on_domain(
8544 __isl_take isl_union_set
*domain
, __isl_take isl_val
*v
)
8546 struct isl_union_pw_aff_val_on_domain_data data
;
8549 space
= isl_union_set_get_space(domain
);
8550 data
.res
= isl_union_pw_aff_empty(space
);
8552 if (isl_union_set_foreach_set(domain
, &pw_aff_val_on_domain
, &data
) < 0)
8553 data
.res
= isl_union_pw_aff_free(data
.res
);
8554 isl_union_set_free(domain
);
8559 /* Construct a piecewise multi affine expression
8560 * that is equal to "pa" and add it to upma.
8562 static isl_stat
pw_multi_aff_from_pw_aff_entry(__isl_take isl_pw_aff
*pa
,
8565 isl_union_pw_multi_aff
**upma
= user
;
8566 isl_pw_multi_aff
*pma
;
8568 pma
= isl_pw_multi_aff_from_pw_aff(pa
);
8569 *upma
= isl_union_pw_multi_aff_add_pw_multi_aff(*upma
, pma
);
8571 return *upma
? isl_stat_ok
: isl_stat_error
;
8574 /* Construct and return a union piecewise multi affine expression
8575 * that is equal to the given union piecewise affine expression.
8577 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_from_union_pw_aff(
8578 __isl_take isl_union_pw_aff
*upa
)
8581 isl_union_pw_multi_aff
*upma
;
8586 space
= isl_union_pw_aff_get_space(upa
);
8587 upma
= isl_union_pw_multi_aff_empty(space
);
8589 if (isl_union_pw_aff_foreach_pw_aff(upa
,
8590 &pw_multi_aff_from_pw_aff_entry
, &upma
) < 0)
8591 upma
= isl_union_pw_multi_aff_free(upma
);
8593 isl_union_pw_aff_free(upa
);
8597 /* Compute the set of elements in the domain of "pa" where it is zero and
8598 * add this set to "uset".
8600 static isl_stat
zero_union_set(__isl_take isl_pw_aff
*pa
, void *user
)
8602 isl_union_set
**uset
= (isl_union_set
**)user
;
8604 *uset
= isl_union_set_add_set(*uset
, isl_pw_aff_zero_set(pa
));
8606 return *uset
? isl_stat_ok
: isl_stat_error
;
8609 /* Return a union set containing those elements in the domain
8610 * of "upa" where it is zero.
8612 __isl_give isl_union_set
*isl_union_pw_aff_zero_union_set(
8613 __isl_take isl_union_pw_aff
*upa
)
8615 isl_union_set
*zero
;
8617 zero
= isl_union_set_empty(isl_union_pw_aff_get_space(upa
));
8618 if (isl_union_pw_aff_foreach_pw_aff(upa
, &zero_union_set
, &zero
) < 0)
8619 zero
= isl_union_set_free(zero
);
8621 isl_union_pw_aff_free(upa
);
8625 /* Internal data structure for isl_union_pw_aff_bind_id,
8626 * storing the parameter that needs to be bound and
8627 * the accumulated results.
8629 struct isl_bind_id_data
{
8631 isl_union_set
*bound
;
8634 /* Bind the piecewise affine function "pa" to the parameter data->id,
8635 * adding the resulting elements in the domain where the expression
8636 * is equal to the parameter to data->bound.
8638 static isl_stat
bind_id(__isl_take isl_pw_aff
*pa
, void *user
)
8640 struct isl_bind_id_data
*data
= user
;
8643 bound
= isl_pw_aff_bind_id(pa
, isl_id_copy(data
->id
));
8644 data
->bound
= isl_union_set_add_set(data
->bound
, bound
);
8646 return data
->bound
? isl_stat_ok
: isl_stat_error
;
8649 /* Bind the union piecewise affine function "upa" to the parameter "id",
8650 * returning the elements in the domain where the expression
8651 * is equal to the parameter.
8653 __isl_give isl_union_set
*isl_union_pw_aff_bind_id(
8654 __isl_take isl_union_pw_aff
*upa
, __isl_take isl_id
*id
)
8656 struct isl_bind_id_data data
= { id
};
8658 data
.bound
= isl_union_set_empty(isl_union_pw_aff_get_space(upa
));
8659 if (isl_union_pw_aff_foreach_pw_aff(upa
, &bind_id
, &data
) < 0)
8660 data
.bound
= isl_union_set_free(data
.bound
);
8662 isl_union_pw_aff_free(upa
);
8667 /* Internal data structure for isl_union_pw_aff_pullback_union_pw_multi_aff.
8668 * upma is the function that is plugged in.
8669 * pa is the current part of the function in which upma is plugged in.
8670 * res collects the results.
8672 struct isl_union_pw_aff_pullback_upma_data
{
8673 isl_union_pw_multi_aff
*upma
;
8675 isl_union_pw_aff
*res
;
8678 /* Check if "pma" can be plugged into data->pa.
8679 * If so, perform the pullback and add the result to data->res.
8681 static isl_stat
pa_pb_pma(__isl_take isl_pw_multi_aff
*pma
, void *user
)
8683 struct isl_union_pw_aff_pullback_upma_data
*data
= user
;
8686 if (!isl_space_tuple_is_equal(data
->pa
->dim
, isl_dim_in
,
8687 pma
->dim
, isl_dim_out
)) {
8688 isl_pw_multi_aff_free(pma
);
8692 pa
= isl_pw_aff_copy(data
->pa
);
8693 pa
= isl_pw_aff_pullback_pw_multi_aff(pa
, pma
);
8695 data
->res
= isl_union_pw_aff_add_pw_aff(data
->res
, pa
);
8697 return data
->res
? isl_stat_ok
: isl_stat_error
;
8700 /* Check if any of the elements of data->upma can be plugged into pa,
8701 * add if so add the result to data->res.
8703 static isl_stat
upa_pb_upma(__isl_take isl_pw_aff
*pa
, void *user
)
8705 struct isl_union_pw_aff_pullback_upma_data
*data
= user
;
8709 r
= isl_union_pw_multi_aff_foreach_pw_multi_aff(data
->upma
,
8711 isl_pw_aff_free(pa
);
8716 /* Compute the pullback of "upa" by the function represented by "upma".
8717 * In other words, plug in "upma" in "upa". The result contains
8718 * expressions defined over the domain space of "upma".
8720 * Run over all pairs of elements in "upa" and "upma", perform
8721 * the pullback when appropriate and collect the results.
8722 * If the hash value were based on the domain space rather than
8723 * the function space, then we could run through all elements
8724 * of "upma" and directly pick out the corresponding element of "upa".
8726 __isl_give isl_union_pw_aff
*isl_union_pw_aff_pullback_union_pw_multi_aff(
8727 __isl_take isl_union_pw_aff
*upa
,
8728 __isl_take isl_union_pw_multi_aff
*upma
)
8730 struct isl_union_pw_aff_pullback_upma_data data
= { NULL
, NULL
};
8733 space
= isl_union_pw_multi_aff_get_space(upma
);
8734 upa
= isl_union_pw_aff_align_params(upa
, space
);
8735 space
= isl_union_pw_aff_get_space(upa
);
8736 upma
= isl_union_pw_multi_aff_align_params(upma
, space
);
8742 data
.res
= isl_union_pw_aff_alloc_same_size(upa
);
8743 if (isl_union_pw_aff_foreach_pw_aff(upa
, &upa_pb_upma
, &data
) < 0)
8744 data
.res
= isl_union_pw_aff_free(data
.res
);
8746 isl_union_pw_aff_free(upa
);
8747 isl_union_pw_multi_aff_free(upma
);
8750 isl_union_pw_aff_free(upa
);
8751 isl_union_pw_multi_aff_free(upma
);
8756 #define BASE union_pw_aff
8758 #define DOMBASE union_set
8760 #include <isl_multi_explicit_domain.c>
8761 #include <isl_multi_union_pw_aff_explicit_domain.c>
8762 #include <isl_multi_templ.c>
8763 #include <isl_multi_un_op_templ.c>
8764 #include <isl_multi_bin_val_templ.c>
8765 #include <isl_multi_align_set.c>
8766 #include <isl_multi_align_union_set.c>
8767 #include <isl_multi_apply_set_explicit_domain_templ.c>
8768 #include <isl_multi_apply_union_set_explicit_domain_templ.c>
8769 #include <isl_multi_arith_templ.c>
8770 #include <isl_multi_bind_templ.c>
8771 #include <isl_multi_coalesce.c>
8772 #include <isl_multi_dim_id_templ.c>
8773 #include <isl_multi_floor.c>
8774 #include <isl_multi_from_base_templ.c>
8775 #include <isl_multi_check_domain_templ.c>
8776 #include <isl_multi_gist.c>
8777 #include <isl_multi_intersect.c>
8778 #include <isl_multi_nan_templ.c>
8779 #include <isl_multi_tuple_id_templ.c>
8780 #include <isl_multi_union_add_templ.c>
8781 #include <isl_multi_zero_space_templ.c>
8783 /* Does "mupa" have a non-trivial explicit domain?
8785 * The explicit domain, if present, is trivial if it represents
8786 * an (obviously) universe parameter set.
8788 isl_bool
isl_multi_union_pw_aff_has_non_trivial_domain(
8789 __isl_keep isl_multi_union_pw_aff
*mupa
)
8791 isl_bool is_params
, trivial
;
8795 return isl_bool_error
;
8796 if (!isl_multi_union_pw_aff_has_explicit_domain(mupa
))
8797 return isl_bool_false
;
8798 is_params
= isl_union_set_is_params(mupa
->u
.dom
);
8799 if (is_params
< 0 || !is_params
)
8800 return isl_bool_not(is_params
);
8801 set
= isl_set_from_union_set(isl_union_set_copy(mupa
->u
.dom
));
8802 trivial
= isl_set_plain_is_universe(set
);
8804 return isl_bool_not(trivial
);
8807 /* Construct a multiple union piecewise affine expression
8808 * in the given space with value zero in each of the output dimensions.
8810 * Since there is no canonical zero value for
8811 * a union piecewise affine expression, we can only construct
8812 * a zero-dimensional "zero" value.
8814 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_zero(
8815 __isl_take isl_space
*space
)
8823 params
= isl_space_is_params(space
);
8827 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
8828 "expecting proper set space", goto error
);
8829 if (!isl_space_is_set(space
))
8830 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
8831 "expecting set space", goto error
);
8832 dim
= isl_space_dim(space
, isl_dim_out
);
8836 isl_die(isl_space_get_ctx(space
), isl_error_invalid
,
8837 "expecting 0D space", goto error
);
8839 return isl_multi_union_pw_aff_alloc(space
);
8841 isl_space_free(space
);
8845 /* Construct and return a multi union piecewise affine expression
8846 * that is equal to the given multi affine expression.
8848 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_from_multi_aff(
8849 __isl_take isl_multi_aff
*ma
)
8851 isl_multi_pw_aff
*mpa
;
8853 mpa
= isl_multi_pw_aff_from_multi_aff(ma
);
8854 return isl_multi_union_pw_aff_from_multi_pw_aff(mpa
);
8857 /* This function performs the same operation as
8858 * isl_multi_union_pw_aff_from_multi_aff, but is considered as a function on an
8859 * isl_multi_aff when exported.
8861 __isl_give isl_multi_union_pw_aff
*isl_multi_aff_to_multi_union_pw_aff(
8862 __isl_take isl_multi_aff
*ma
)
8864 return isl_multi_union_pw_aff_from_multi_aff(ma
);
8867 /* Construct and return a multi union piecewise affine expression
8868 * that is equal to the given multi piecewise affine expression.
8870 * If the resulting multi union piecewise affine expression has
8871 * an explicit domain, then assign it the domain of the input.
8872 * In other cases, the domain is stored in the individual elements.
8874 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_from_multi_pw_aff(
8875 __isl_take isl_multi_pw_aff
*mpa
)
8880 isl_multi_union_pw_aff
*mupa
;
8882 n
= isl_multi_pw_aff_dim(mpa
, isl_dim_out
);
8884 mpa
= isl_multi_pw_aff_free(mpa
);
8888 space
= isl_multi_pw_aff_get_space(mpa
);
8889 space
= isl_space_range(space
);
8890 mupa
= isl_multi_union_pw_aff_alloc(space
);
8892 for (i
= 0; i
< n
; ++i
) {
8894 isl_union_pw_aff
*upa
;
8896 pa
= isl_multi_pw_aff_get_pw_aff(mpa
, i
);
8897 upa
= isl_union_pw_aff_from_pw_aff(pa
);
8898 mupa
= isl_multi_union_pw_aff_restore_check_space(mupa
, i
, upa
);
8900 if (isl_multi_union_pw_aff_has_explicit_domain(mupa
)) {
8902 isl_multi_pw_aff
*copy
;
8904 copy
= isl_multi_pw_aff_copy(mpa
);
8905 dom
= isl_union_set_from_set(isl_multi_pw_aff_domain(copy
));
8906 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, dom
);
8909 isl_multi_pw_aff_free(mpa
);
8914 /* Extract the range space of "pma" and assign it to *space.
8915 * If *space has already been set (through a previous call to this function),
8916 * then check that the range space is the same.
8918 static isl_stat
extract_space(__isl_take isl_pw_multi_aff
*pma
, void *user
)
8920 isl_space
**space
= user
;
8921 isl_space
*pma_space
;
8924 pma_space
= isl_space_range(isl_pw_multi_aff_get_space(pma
));
8925 isl_pw_multi_aff_free(pma
);
8928 return isl_stat_error
;
8934 equal
= isl_space_is_equal(pma_space
, *space
);
8935 isl_space_free(pma_space
);
8938 return isl_stat_error
;
8940 isl_die(isl_space_get_ctx(*space
), isl_error_invalid
,
8941 "range spaces not the same", return isl_stat_error
);
8945 /* Construct and return a multi union piecewise affine expression
8946 * that is equal to the given union piecewise multi affine expression.
8948 * In order to be able to perform the conversion, the input
8949 * needs to be non-empty and may only involve a single range space.
8951 * If the resulting multi union piecewise affine expression has
8952 * an explicit domain, then assign it the domain of the input.
8953 * In other cases, the domain is stored in the individual elements.
8955 __isl_give isl_multi_union_pw_aff
*
8956 isl_multi_union_pw_aff_from_union_pw_multi_aff(
8957 __isl_take isl_union_pw_multi_aff
*upma
)
8959 isl_space
*space
= NULL
;
8960 isl_multi_union_pw_aff
*mupa
;
8964 n
= isl_union_pw_multi_aff_n_pw_multi_aff(upma
);
8968 isl_die(isl_union_pw_multi_aff_get_ctx(upma
), isl_error_invalid
,
8969 "cannot extract range space from empty input",
8971 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma
, &extract_space
,
8978 n
= isl_space_dim(space
, isl_dim_set
);
8980 space
= isl_space_free(space
);
8981 mupa
= isl_multi_union_pw_aff_alloc(space
);
8983 for (i
= 0; i
< n
; ++i
) {
8984 isl_union_pw_aff
*upa
;
8986 upa
= isl_union_pw_multi_aff_get_union_pw_aff(upma
, i
);
8987 mupa
= isl_multi_union_pw_aff_set_union_pw_aff(mupa
, i
, upa
);
8989 if (isl_multi_union_pw_aff_has_explicit_domain(mupa
)) {
8991 isl_union_pw_multi_aff
*copy
;
8993 copy
= isl_union_pw_multi_aff_copy(upma
);
8994 dom
= isl_union_pw_multi_aff_domain(copy
);
8995 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, dom
);
8998 isl_union_pw_multi_aff_free(upma
);
9001 isl_space_free(space
);
9002 isl_union_pw_multi_aff_free(upma
);
9006 /* This function performs the same operation as
9007 * isl_multi_union_pw_aff_from_union_pw_multi_aff,
9008 * but is considered as a function on an isl_union_pw_multi_aff when exported.
9010 __isl_give isl_multi_union_pw_aff
*
9011 isl_union_pw_multi_aff_as_multi_union_pw_aff(
9012 __isl_take isl_union_pw_multi_aff
*upma
)
9014 return isl_multi_union_pw_aff_from_union_pw_multi_aff(upma
);
9017 /* Try and create an isl_multi_union_pw_aff that is equivalent
9018 * to the given isl_union_map.
9019 * The isl_union_map is required to be single-valued in each space.
9020 * Moreover, it cannot be empty and all range spaces need to be the same.
9021 * Otherwise, an error is produced.
9023 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_from_union_map(
9024 __isl_take isl_union_map
*umap
)
9026 isl_union_pw_multi_aff
*upma
;
9028 upma
= isl_union_pw_multi_aff_from_union_map(umap
);
9029 return isl_multi_union_pw_aff_from_union_pw_multi_aff(upma
);
9032 /* This function performs the same operation as
9033 * isl_multi_union_pw_aff_from_union_map,
9034 * but is considered as a function on an isl_union_map when exported.
9036 __isl_give isl_multi_union_pw_aff
*isl_union_map_as_multi_union_pw_aff(
9037 __isl_take isl_union_map
*umap
)
9039 return isl_multi_union_pw_aff_from_union_map(umap
);
9042 /* Return a multiple union piecewise affine expression
9043 * that is equal to "mv" on "domain", assuming "domain" and "mv"
9044 * have been aligned.
9046 * If the resulting multi union piecewise affine expression has
9047 * an explicit domain, then assign it the input domain.
9048 * In other cases, the domain is stored in the individual elements.
9050 static __isl_give isl_multi_union_pw_aff
*
9051 isl_multi_union_pw_aff_multi_val_on_domain_aligned(
9052 __isl_take isl_union_set
*domain
, __isl_take isl_multi_val
*mv
)
9057 isl_multi_union_pw_aff
*mupa
;
9059 n
= isl_multi_val_dim(mv
, isl_dim_set
);
9060 if (!domain
|| n
< 0)
9063 space
= isl_multi_val_get_space(mv
);
9064 mupa
= isl_multi_union_pw_aff_alloc(space
);
9065 for (i
= 0; i
< n
; ++i
) {
9067 isl_union_pw_aff
*upa
;
9069 v
= isl_multi_val_get_val(mv
, i
);
9070 upa
= isl_union_pw_aff_val_on_domain(isl_union_set_copy(domain
),
9072 mupa
= isl_multi_union_pw_aff_set_union_pw_aff(mupa
, i
, upa
);
9074 if (isl_multi_union_pw_aff_has_explicit_domain(mupa
))
9075 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
,
9076 isl_union_set_copy(domain
));
9078 isl_union_set_free(domain
);
9079 isl_multi_val_free(mv
);
9082 isl_union_set_free(domain
);
9083 isl_multi_val_free(mv
);
9087 /* Return a multiple union piecewise affine expression
9088 * that is equal to "mv" on "domain".
9090 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_multi_val_on_domain(
9091 __isl_take isl_union_set
*domain
, __isl_take isl_multi_val
*mv
)
9093 isl_bool equal_params
;
9097 equal_params
= isl_space_has_equal_params(domain
->dim
, mv
->space
);
9098 if (equal_params
< 0)
9101 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(
9103 domain
= isl_union_set_align_params(domain
,
9104 isl_multi_val_get_space(mv
));
9105 mv
= isl_multi_val_align_params(mv
, isl_union_set_get_space(domain
));
9106 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(domain
, mv
);
9108 isl_union_set_free(domain
);
9109 isl_multi_val_free(mv
);
9113 /* Return a multiple union piecewise affine expression
9114 * that is equal to "ma" on "domain".
9116 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_multi_aff_on_domain(
9117 __isl_take isl_union_set
*domain
, __isl_take isl_multi_aff
*ma
)
9119 isl_pw_multi_aff
*pma
;
9121 pma
= isl_pw_multi_aff_from_multi_aff(ma
);
9122 return isl_multi_union_pw_aff_pw_multi_aff_on_domain(domain
, pma
);
9125 /* Return a multiple union piecewise affine expression
9126 * that is equal to "pma" on "domain", assuming "domain" and "pma"
9127 * have been aligned.
9129 * If the resulting multi union piecewise affine expression has
9130 * an explicit domain, then assign it the input domain.
9131 * In other cases, the domain is stored in the individual elements.
9133 static __isl_give isl_multi_union_pw_aff
*
9134 isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(
9135 __isl_take isl_union_set
*domain
, __isl_take isl_pw_multi_aff
*pma
)
9140 isl_multi_union_pw_aff
*mupa
;
9142 n
= isl_pw_multi_aff_dim(pma
, isl_dim_set
);
9143 if (!domain
|| n
< 0)
9145 space
= isl_pw_multi_aff_get_space(pma
);
9146 mupa
= isl_multi_union_pw_aff_alloc(space
);
9147 for (i
= 0; i
< n
; ++i
) {
9149 isl_union_pw_aff
*upa
;
9151 pa
= isl_pw_multi_aff_get_pw_aff(pma
, i
);
9152 upa
= isl_union_pw_aff_pw_aff_on_domain(
9153 isl_union_set_copy(domain
), pa
);
9154 mupa
= isl_multi_union_pw_aff_set_union_pw_aff(mupa
, i
, upa
);
9156 if (isl_multi_union_pw_aff_has_explicit_domain(mupa
))
9157 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
,
9158 isl_union_set_copy(domain
));
9160 isl_union_set_free(domain
);
9161 isl_pw_multi_aff_free(pma
);
9164 isl_union_set_free(domain
);
9165 isl_pw_multi_aff_free(pma
);
9169 /* Return a multiple union piecewise affine expression
9170 * that is equal to "pma" on "domain".
9172 __isl_give isl_multi_union_pw_aff
*
9173 isl_multi_union_pw_aff_pw_multi_aff_on_domain(__isl_take isl_union_set
*domain
,
9174 __isl_take isl_pw_multi_aff
*pma
)
9176 isl_bool equal_params
;
9179 space
= isl_pw_multi_aff_peek_space(pma
);
9180 equal_params
= isl_union_set_space_has_equal_params(domain
, space
);
9181 if (equal_params
< 0)
9184 return isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(
9186 domain
= isl_union_set_align_params(domain
,
9187 isl_pw_multi_aff_get_space(pma
));
9188 pma
= isl_pw_multi_aff_align_params(pma
,
9189 isl_union_set_get_space(domain
));
9190 return isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(domain
,
9193 isl_union_set_free(domain
);
9194 isl_pw_multi_aff_free(pma
);
9198 /* Return a union set containing those elements in the domains
9199 * of the elements of "mupa" where they are all zero.
9201 * If there are no elements, then simply return the entire domain.
9203 __isl_give isl_union_set
*isl_multi_union_pw_aff_zero_union_set(
9204 __isl_take isl_multi_union_pw_aff
*mupa
)
9208 isl_union_pw_aff
*upa
;
9209 isl_union_set
*zero
;
9211 n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
9213 mupa
= isl_multi_union_pw_aff_free(mupa
);
9218 return isl_multi_union_pw_aff_domain(mupa
);
9220 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, 0);
9221 zero
= isl_union_pw_aff_zero_union_set(upa
);
9223 for (i
= 1; i
< n
; ++i
) {
9224 isl_union_set
*zero_i
;
9226 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, i
);
9227 zero_i
= isl_union_pw_aff_zero_union_set(upa
);
9229 zero
= isl_union_set_intersect(zero
, zero_i
);
9232 isl_multi_union_pw_aff_free(mupa
);
9236 /* Construct a union map mapping the shared domain
9237 * of the union piecewise affine expressions to the range of "mupa"
9238 * in the special case of a 0D multi union piecewise affine expression.
9240 * Construct a map between the explicit domain of "mupa" and
9242 * Note that this assumes that the domain consists of explicit elements.
9244 static __isl_give isl_union_map
*isl_union_map_from_multi_union_pw_aff_0D(
9245 __isl_take isl_multi_union_pw_aff
*mupa
)
9249 isl_union_set
*dom
, *ran
;
9251 space
= isl_multi_union_pw_aff_get_space(mupa
);
9252 dom
= isl_multi_union_pw_aff_domain(mupa
);
9253 ran
= isl_union_set_from_set(isl_set_universe(space
));
9255 is_params
= isl_union_set_is_params(dom
);
9257 dom
= isl_union_set_free(dom
);
9259 isl_die(isl_union_set_get_ctx(dom
), isl_error_invalid
,
9260 "cannot create union map from expression without "
9261 "explicit domain elements",
9262 dom
= isl_union_set_free(dom
));
9264 return isl_union_map_from_domain_and_range(dom
, ran
);
9267 /* Construct a union map mapping the shared domain
9268 * of the union piecewise affine expressions to the range of "mupa"
9269 * with each dimension in the range equated to the
9270 * corresponding union piecewise affine expression.
9272 * If the input is zero-dimensional, then construct a mapping
9273 * from its explicit domain.
9275 __isl_give isl_union_map
*isl_union_map_from_multi_union_pw_aff(
9276 __isl_take isl_multi_union_pw_aff
*mupa
)
9281 isl_union_map
*umap
;
9282 isl_union_pw_aff
*upa
;
9284 n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
9286 mupa
= isl_multi_union_pw_aff_free(mupa
);
9291 return isl_union_map_from_multi_union_pw_aff_0D(mupa
);
9293 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, 0);
9294 umap
= isl_union_map_from_union_pw_aff(upa
);
9296 for (i
= 1; i
< n
; ++i
) {
9297 isl_union_map
*umap_i
;
9299 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, i
);
9300 umap_i
= isl_union_map_from_union_pw_aff(upa
);
9301 umap
= isl_union_map_flat_range_product(umap
, umap_i
);
9304 space
= isl_multi_union_pw_aff_get_space(mupa
);
9305 umap
= isl_union_map_reset_range_space(umap
, space
);
9307 isl_multi_union_pw_aff_free(mupa
);
9311 /* Internal data structure for isl_union_pw_multi_aff_reset_range_space.
9312 * "range" is the space from which to set the range space.
9313 * "res" collects the results.
9315 struct isl_union_pw_multi_aff_reset_range_space_data
{
9317 isl_union_pw_multi_aff
*res
;
9320 /* Replace the range space of "pma" by the range space of data->range and
9321 * add the result to data->res.
9323 static isl_stat
reset_range_space(__isl_take isl_pw_multi_aff
*pma
, void *user
)
9325 struct isl_union_pw_multi_aff_reset_range_space_data
*data
= user
;
9328 space
= isl_pw_multi_aff_get_space(pma
);
9329 space
= isl_space_domain(space
);
9330 space
= isl_space_extend_domain_with_range(space
,
9331 isl_space_copy(data
->range
));
9332 pma
= isl_pw_multi_aff_reset_space(pma
, space
);
9333 data
->res
= isl_union_pw_multi_aff_add_pw_multi_aff(data
->res
, pma
);
9335 return data
->res
? isl_stat_ok
: isl_stat_error
;
9338 /* Replace the range space of all the piecewise affine expressions in "upma" by
9339 * the range space of "space".
9341 * This assumes that all these expressions have the same output dimension.
9343 * Since the spaces of the expressions change, so do their hash values.
9344 * We therefore need to create a new isl_union_pw_multi_aff.
9345 * Note that the hash value is currently computed based on the entire
9346 * space even though there can only be a single expression with a given
9349 static __isl_give isl_union_pw_multi_aff
*
9350 isl_union_pw_multi_aff_reset_range_space(
9351 __isl_take isl_union_pw_multi_aff
*upma
, __isl_take isl_space
*space
)
9353 struct isl_union_pw_multi_aff_reset_range_space_data data
= { space
};
9354 isl_space
*space_upma
;
9356 space_upma
= isl_union_pw_multi_aff_get_space(upma
);
9357 data
.res
= isl_union_pw_multi_aff_empty(space_upma
);
9358 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma
,
9359 &reset_range_space
, &data
) < 0)
9360 data
.res
= isl_union_pw_multi_aff_free(data
.res
);
9362 isl_space_free(space
);
9363 isl_union_pw_multi_aff_free(upma
);
9367 /* Construct and return a union piecewise multi affine expression
9368 * that is equal to the given multi union piecewise affine expression,
9369 * in the special case of a 0D multi union piecewise affine expression.
9371 * Construct a union piecewise multi affine expression
9372 * on top of the explicit domain of the input.
9374 __isl_give isl_union_pw_multi_aff
*
9375 isl_union_pw_multi_aff_from_multi_union_pw_aff_0D(
9376 __isl_take isl_multi_union_pw_aff
*mupa
)
9380 isl_union_set
*domain
;
9382 space
= isl_multi_union_pw_aff_get_space(mupa
);
9383 mv
= isl_multi_val_zero(space
);
9384 domain
= isl_multi_union_pw_aff_domain(mupa
);
9385 return isl_union_pw_multi_aff_multi_val_on_domain(domain
, mv
);
9388 /* Construct and return a union piecewise multi affine expression
9389 * that is equal to the given multi union piecewise affine expression.
9391 * If the input is zero-dimensional, then
9392 * construct a union piecewise multi affine expression
9393 * on top of the explicit domain of the input.
9395 __isl_give isl_union_pw_multi_aff
*
9396 isl_union_pw_multi_aff_from_multi_union_pw_aff(
9397 __isl_take isl_multi_union_pw_aff
*mupa
)
9402 isl_union_pw_multi_aff
*upma
;
9403 isl_union_pw_aff
*upa
;
9405 n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
9407 mupa
= isl_multi_union_pw_aff_free(mupa
);
9412 return isl_union_pw_multi_aff_from_multi_union_pw_aff_0D(mupa
);
9414 space
= isl_multi_union_pw_aff_get_space(mupa
);
9415 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, 0);
9416 upma
= isl_union_pw_multi_aff_from_union_pw_aff(upa
);
9418 for (i
= 1; i
< n
; ++i
) {
9419 isl_union_pw_multi_aff
*upma_i
;
9421 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, i
);
9422 upma_i
= isl_union_pw_multi_aff_from_union_pw_aff(upa
);
9423 upma
= isl_union_pw_multi_aff_flat_range_product(upma
, upma_i
);
9426 upma
= isl_union_pw_multi_aff_reset_range_space(upma
, space
);
9428 isl_multi_union_pw_aff_free(mupa
);
9432 /* Intersect the range of "mupa" with "range",
9433 * in the special case where "mupa" is 0D.
9435 * Intersect the domain of "mupa" with the constraints on the parameters
9438 static __isl_give isl_multi_union_pw_aff
*mupa_intersect_range_0D(
9439 __isl_take isl_multi_union_pw_aff
*mupa
, __isl_take isl_set
*range
)
9441 range
= isl_set_params(range
);
9442 mupa
= isl_multi_union_pw_aff_intersect_params(mupa
, range
);
9446 /* Intersect the range of "mupa" with "range".
9447 * That is, keep only those domain elements that have a function value
9450 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_intersect_range(
9451 __isl_take isl_multi_union_pw_aff
*mupa
, __isl_take isl_set
*range
)
9453 isl_union_pw_multi_aff
*upma
;
9454 isl_union_set
*domain
;
9459 n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
9460 if (n
< 0 || !range
)
9463 space
= isl_set_get_space(range
);
9464 match
= isl_space_tuple_is_equal(mupa
->space
, isl_dim_set
,
9465 space
, isl_dim_set
);
9466 isl_space_free(space
);
9470 isl_die(isl_multi_union_pw_aff_get_ctx(mupa
), isl_error_invalid
,
9471 "space don't match", goto error
);
9473 return mupa_intersect_range_0D(mupa
, range
);
9475 upma
= isl_union_pw_multi_aff_from_multi_union_pw_aff(
9476 isl_multi_union_pw_aff_copy(mupa
));
9477 domain
= isl_union_set_from_set(range
);
9478 domain
= isl_union_set_preimage_union_pw_multi_aff(domain
, upma
);
9479 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, domain
);
9483 isl_multi_union_pw_aff_free(mupa
);
9484 isl_set_free(range
);
9488 /* Return the shared domain of the elements of "mupa",
9489 * in the special case where "mupa" is zero-dimensional.
9491 * Return the explicit domain of "mupa".
9492 * Note that this domain may be a parameter set, either
9493 * because "mupa" is meant to live in a set space or
9494 * because no explicit domain has been set.
9496 __isl_give isl_union_set
*isl_multi_union_pw_aff_domain_0D(
9497 __isl_take isl_multi_union_pw_aff
*mupa
)
9501 dom
= isl_multi_union_pw_aff_get_explicit_domain(mupa
);
9502 isl_multi_union_pw_aff_free(mupa
);
9507 /* Return the shared domain of the elements of "mupa".
9509 * If "mupa" is zero-dimensional, then return its explicit domain.
9511 __isl_give isl_union_set
*isl_multi_union_pw_aff_domain(
9512 __isl_take isl_multi_union_pw_aff
*mupa
)
9516 isl_union_pw_aff
*upa
;
9519 n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
9521 mupa
= isl_multi_union_pw_aff_free(mupa
);
9526 return isl_multi_union_pw_aff_domain_0D(mupa
);
9528 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, 0);
9529 dom
= isl_union_pw_aff_domain(upa
);
9530 for (i
= 1; i
< n
; ++i
) {
9531 isl_union_set
*dom_i
;
9533 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, i
);
9534 dom_i
= isl_union_pw_aff_domain(upa
);
9535 dom
= isl_union_set_intersect(dom
, dom_i
);
9538 isl_multi_union_pw_aff_free(mupa
);
9542 /* Apply "aff" to "mupa". The space of "mupa" is equal to the domain of "aff".
9543 * In particular, the spaces have been aligned.
9544 * The result is defined over the shared domain of the elements of "mupa"
9546 * We first extract the parametric constant part of "aff" and
9547 * define that over the shared domain.
9548 * Then we iterate over all input dimensions of "aff" and add the corresponding
9549 * multiples of the elements of "mupa".
9550 * Finally, we consider the integer divisions, calling the function
9551 * recursively to obtain an isl_union_pw_aff corresponding to the
9552 * integer division argument.
9554 static __isl_give isl_union_pw_aff
*multi_union_pw_aff_apply_aff(
9555 __isl_take isl_multi_union_pw_aff
*mupa
, __isl_take isl_aff
*aff
)
9558 isl_size n_in
, n_div
;
9559 isl_union_pw_aff
*upa
;
9560 isl_union_set
*uset
;
9564 n_in
= isl_aff_dim(aff
, isl_dim_in
);
9565 n_div
= isl_aff_dim(aff
, isl_dim_div
);
9566 if (n_in
< 0 || n_div
< 0)
9569 uset
= isl_multi_union_pw_aff_domain(isl_multi_union_pw_aff_copy(mupa
));
9570 cst
= isl_aff_copy(aff
);
9571 cst
= isl_aff_drop_dims(cst
, isl_dim_div
, 0, n_div
);
9572 cst
= isl_aff_drop_dims(cst
, isl_dim_in
, 0, n_in
);
9573 cst
= isl_aff_project_domain_on_params(cst
);
9574 upa
= isl_union_pw_aff_aff_on_domain(uset
, cst
);
9576 for (i
= 0; i
< n_in
; ++i
) {
9577 isl_union_pw_aff
*upa_i
;
9579 if (!isl_aff_involves_dims(aff
, isl_dim_in
, i
, 1))
9581 v
= isl_aff_get_coefficient_val(aff
, isl_dim_in
, i
);
9582 upa_i
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, i
);
9583 upa_i
= isl_union_pw_aff_scale_val(upa_i
, v
);
9584 upa
= isl_union_pw_aff_add(upa
, upa_i
);
9587 for (i
= 0; i
< n_div
; ++i
) {
9589 isl_union_pw_aff
*upa_i
;
9591 if (!isl_aff_involves_dims(aff
, isl_dim_div
, i
, 1))
9593 div
= isl_aff_get_div(aff
, i
);
9594 upa_i
= multi_union_pw_aff_apply_aff(
9595 isl_multi_union_pw_aff_copy(mupa
), div
);
9596 upa_i
= isl_union_pw_aff_floor(upa_i
);
9597 v
= isl_aff_get_coefficient_val(aff
, isl_dim_div
, i
);
9598 upa_i
= isl_union_pw_aff_scale_val(upa_i
, v
);
9599 upa
= isl_union_pw_aff_add(upa
, upa_i
);
9602 isl_multi_union_pw_aff_free(mupa
);
9607 isl_multi_union_pw_aff_free(mupa
);
9612 /* Apply "aff" to "mupa". The space of "mupa" needs to be compatible
9613 * with the domain of "aff".
9614 * Furthermore, the dimension of this space needs to be greater than zero.
9615 * The result is defined over the shared domain of the elements of "mupa"
9617 * We perform these checks and then hand over control to
9618 * multi_union_pw_aff_apply_aff.
9620 __isl_give isl_union_pw_aff
*isl_multi_union_pw_aff_apply_aff(
9621 __isl_take isl_multi_union_pw_aff
*mupa
, __isl_take isl_aff
*aff
)
9624 isl_space
*space1
, *space2
;
9627 mupa
= isl_multi_union_pw_aff_align_params(mupa
,
9628 isl_aff_get_space(aff
));
9629 aff
= isl_aff_align_params(aff
, isl_multi_union_pw_aff_get_space(mupa
));
9633 space1
= isl_multi_union_pw_aff_get_space(mupa
);
9634 space2
= isl_aff_get_domain_space(aff
);
9635 equal
= isl_space_is_equal(space1
, space2
);
9636 isl_space_free(space1
);
9637 isl_space_free(space2
);
9641 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
9642 "spaces don't match", goto error
);
9643 dim
= isl_aff_dim(aff
, isl_dim_in
);
9647 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
9648 "cannot determine domains", goto error
);
9650 return multi_union_pw_aff_apply_aff(mupa
, aff
);
9652 isl_multi_union_pw_aff_free(mupa
);
9657 /* Apply "ma" to "mupa", in the special case where "mupa" is 0D.
9658 * The space of "mupa" is known to be compatible with the domain of "ma".
9660 * Construct an isl_multi_union_pw_aff that is equal to "ma"
9661 * on the domain of "mupa".
9663 static __isl_give isl_multi_union_pw_aff
*mupa_apply_multi_aff_0D(
9664 __isl_take isl_multi_union_pw_aff
*mupa
, __isl_take isl_multi_aff
*ma
)
9668 dom
= isl_multi_union_pw_aff_domain(mupa
);
9669 ma
= isl_multi_aff_project_domain_on_params(ma
);
9671 return isl_multi_union_pw_aff_multi_aff_on_domain(dom
, ma
);
9674 /* Apply "ma" to "mupa". The space of "mupa" needs to be compatible
9675 * with the domain of "ma".
9676 * The result is defined over the shared domain of the elements of "mupa"
9678 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_apply_multi_aff(
9679 __isl_take isl_multi_union_pw_aff
*mupa
, __isl_take isl_multi_aff
*ma
)
9681 isl_space
*space1
, *space2
;
9682 isl_multi_union_pw_aff
*res
;
9685 isl_size n_in
, n_out
;
9687 mupa
= isl_multi_union_pw_aff_align_params(mupa
,
9688 isl_multi_aff_get_space(ma
));
9689 ma
= isl_multi_aff_align_params(ma
,
9690 isl_multi_union_pw_aff_get_space(mupa
));
9691 n_in
= isl_multi_aff_dim(ma
, isl_dim_in
);
9692 n_out
= isl_multi_aff_dim(ma
, isl_dim_out
);
9693 if (!mupa
|| n_in
< 0 || n_out
< 0)
9696 space1
= isl_multi_union_pw_aff_get_space(mupa
);
9697 space2
= isl_multi_aff_get_domain_space(ma
);
9698 equal
= isl_space_is_equal(space1
, space2
);
9699 isl_space_free(space1
);
9700 isl_space_free(space2
);
9704 isl_die(isl_multi_aff_get_ctx(ma
), isl_error_invalid
,
9705 "spaces don't match", goto error
);
9707 return mupa_apply_multi_aff_0D(mupa
, ma
);
9709 space1
= isl_space_range(isl_multi_aff_get_space(ma
));
9710 res
= isl_multi_union_pw_aff_alloc(space1
);
9712 for (i
= 0; i
< n_out
; ++i
) {
9714 isl_union_pw_aff
*upa
;
9716 aff
= isl_multi_aff_get_aff(ma
, i
);
9717 upa
= multi_union_pw_aff_apply_aff(
9718 isl_multi_union_pw_aff_copy(mupa
), aff
);
9719 res
= isl_multi_union_pw_aff_set_union_pw_aff(res
, i
, upa
);
9722 isl_multi_aff_free(ma
);
9723 isl_multi_union_pw_aff_free(mupa
);
9726 isl_multi_union_pw_aff_free(mupa
);
9727 isl_multi_aff_free(ma
);
9731 /* Apply "pa" to "mupa", in the special case where "mupa" is 0D.
9732 * The space of "mupa" is known to be compatible with the domain of "pa".
9734 * Construct an isl_multi_union_pw_aff that is equal to "pa"
9735 * on the domain of "mupa".
9737 static __isl_give isl_union_pw_aff
*isl_multi_union_pw_aff_apply_pw_aff_0D(
9738 __isl_take isl_multi_union_pw_aff
*mupa
, __isl_take isl_pw_aff
*pa
)
9742 dom
= isl_multi_union_pw_aff_domain(mupa
);
9743 pa
= isl_pw_aff_project_domain_on_params(pa
);
9745 return isl_union_pw_aff_pw_aff_on_domain(dom
, pa
);
9748 /* Apply "pa" to "mupa". The space of "mupa" needs to be compatible
9749 * with the domain of "pa".
9750 * Furthermore, the dimension of this space needs to be greater than zero.
9751 * The result is defined over the shared domain of the elements of "mupa"
9753 __isl_give isl_union_pw_aff
*isl_multi_union_pw_aff_apply_pw_aff(
9754 __isl_take isl_multi_union_pw_aff
*mupa
, __isl_take isl_pw_aff
*pa
)
9759 isl_space
*space
, *space2
;
9760 isl_union_pw_aff
*upa
;
9762 mupa
= isl_multi_union_pw_aff_align_params(mupa
,
9763 isl_pw_aff_get_space(pa
));
9764 pa
= isl_pw_aff_align_params(pa
,
9765 isl_multi_union_pw_aff_get_space(mupa
));
9769 space
= isl_multi_union_pw_aff_get_space(mupa
);
9770 space2
= isl_pw_aff_get_domain_space(pa
);
9771 equal
= isl_space_is_equal(space
, space2
);
9772 isl_space_free(space
);
9773 isl_space_free(space2
);
9777 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
9778 "spaces don't match", goto error
);
9779 n_in
= isl_pw_aff_dim(pa
, isl_dim_in
);
9783 return isl_multi_union_pw_aff_apply_pw_aff_0D(mupa
, pa
);
9785 space
= isl_space_params(isl_multi_union_pw_aff_get_space(mupa
));
9786 upa
= isl_union_pw_aff_empty(space
);
9788 for (i
= 0; i
< pa
->n
; ++i
) {
9791 isl_multi_union_pw_aff
*mupa_i
;
9792 isl_union_pw_aff
*upa_i
;
9794 mupa_i
= isl_multi_union_pw_aff_copy(mupa
);
9795 domain
= isl_set_copy(pa
->p
[i
].set
);
9796 mupa_i
= isl_multi_union_pw_aff_intersect_range(mupa_i
, domain
);
9797 aff
= isl_aff_copy(pa
->p
[i
].aff
);
9798 upa_i
= multi_union_pw_aff_apply_aff(mupa_i
, aff
);
9799 upa
= isl_union_pw_aff_union_add(upa
, upa_i
);
9802 isl_multi_union_pw_aff_free(mupa
);
9803 isl_pw_aff_free(pa
);
9806 isl_multi_union_pw_aff_free(mupa
);
9807 isl_pw_aff_free(pa
);
9811 /* Apply "pma" to "mupa", in the special case where "mupa" is 0D.
9812 * The space of "mupa" is known to be compatible with the domain of "pma".
9814 * Construct an isl_multi_union_pw_aff that is equal to "pma"
9815 * on the domain of "mupa".
9817 static __isl_give isl_multi_union_pw_aff
*mupa_apply_pw_multi_aff_0D(
9818 __isl_take isl_multi_union_pw_aff
*mupa
,
9819 __isl_take isl_pw_multi_aff
*pma
)
9823 dom
= isl_multi_union_pw_aff_domain(mupa
);
9824 pma
= isl_pw_multi_aff_project_domain_on_params(pma
);
9826 return isl_multi_union_pw_aff_pw_multi_aff_on_domain(dom
, pma
);
9829 /* Apply "pma" to "mupa". The space of "mupa" needs to be compatible
9830 * with the domain of "pma".
9831 * The result is defined over the shared domain of the elements of "mupa"
9833 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_apply_pw_multi_aff(
9834 __isl_take isl_multi_union_pw_aff
*mupa
,
9835 __isl_take isl_pw_multi_aff
*pma
)
9837 isl_space
*space1
, *space2
;
9838 isl_multi_union_pw_aff
*res
;
9841 isl_size n_in
, n_out
;
9843 mupa
= isl_multi_union_pw_aff_align_params(mupa
,
9844 isl_pw_multi_aff_get_space(pma
));
9845 pma
= isl_pw_multi_aff_align_params(pma
,
9846 isl_multi_union_pw_aff_get_space(mupa
));
9850 space1
= isl_multi_union_pw_aff_get_space(mupa
);
9851 space2
= isl_pw_multi_aff_get_domain_space(pma
);
9852 equal
= isl_space_is_equal(space1
, space2
);
9853 isl_space_free(space1
);
9854 isl_space_free(space2
);
9858 isl_die(isl_pw_multi_aff_get_ctx(pma
), isl_error_invalid
,
9859 "spaces don't match", goto error
);
9860 n_in
= isl_pw_multi_aff_dim(pma
, isl_dim_in
);
9861 n_out
= isl_pw_multi_aff_dim(pma
, isl_dim_out
);
9862 if (n_in
< 0 || n_out
< 0)
9865 return mupa_apply_pw_multi_aff_0D(mupa
, pma
);
9867 space1
= isl_space_range(isl_pw_multi_aff_get_space(pma
));
9868 res
= isl_multi_union_pw_aff_alloc(space1
);
9870 for (i
= 0; i
< n_out
; ++i
) {
9872 isl_union_pw_aff
*upa
;
9874 pa
= isl_pw_multi_aff_get_pw_aff(pma
, i
);
9875 upa
= isl_multi_union_pw_aff_apply_pw_aff(
9876 isl_multi_union_pw_aff_copy(mupa
), pa
);
9877 res
= isl_multi_union_pw_aff_set_union_pw_aff(res
, i
, upa
);
9880 isl_pw_multi_aff_free(pma
);
9881 isl_multi_union_pw_aff_free(mupa
);
9884 isl_multi_union_pw_aff_free(mupa
);
9885 isl_pw_multi_aff_free(pma
);
9889 /* Replace the explicit domain of "mupa" by its preimage under "upma".
9890 * If the explicit domain only keeps track of constraints on the parameters,
9891 * then only update those constraints.
9893 static __isl_give isl_multi_union_pw_aff
*preimage_explicit_domain(
9894 __isl_take isl_multi_union_pw_aff
*mupa
,
9895 __isl_keep isl_union_pw_multi_aff
*upma
)
9899 if (isl_multi_union_pw_aff_check_has_explicit_domain(mupa
) < 0)
9900 return isl_multi_union_pw_aff_free(mupa
);
9902 mupa
= isl_multi_union_pw_aff_cow(mupa
);
9906 is_params
= isl_union_set_is_params(mupa
->u
.dom
);
9908 return isl_multi_union_pw_aff_free(mupa
);
9910 upma
= isl_union_pw_multi_aff_copy(upma
);
9912 mupa
->u
.dom
= isl_union_set_intersect_params(mupa
->u
.dom
,
9913 isl_union_set_params(isl_union_pw_multi_aff_domain(upma
)));
9915 mupa
->u
.dom
= isl_union_set_preimage_union_pw_multi_aff(
9918 return isl_multi_union_pw_aff_free(mupa
);
9922 /* Compute the pullback of "mupa" by the function represented by "upma".
9923 * In other words, plug in "upma" in "mupa". The result contains
9924 * expressions defined over the domain space of "upma".
9926 * Run over all elements of "mupa" and plug in "upma" in each of them.
9928 * If "mupa" has an explicit domain, then it is this domain
9929 * that needs to undergo a pullback instead, i.e., a preimage.
9931 __isl_give isl_multi_union_pw_aff
*
9932 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
9933 __isl_take isl_multi_union_pw_aff
*mupa
,
9934 __isl_take isl_union_pw_multi_aff
*upma
)
9939 mupa
= isl_multi_union_pw_aff_align_params(mupa
,
9940 isl_union_pw_multi_aff_get_space(upma
));
9941 upma
= isl_union_pw_multi_aff_align_params(upma
,
9942 isl_multi_union_pw_aff_get_space(mupa
));
9943 mupa
= isl_multi_union_pw_aff_cow(mupa
);
9944 n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
9948 for (i
= 0; i
< n
; ++i
) {
9949 isl_union_pw_aff
*upa
;
9951 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, i
);
9952 upa
= isl_union_pw_aff_pullback_union_pw_multi_aff(upa
,
9953 isl_union_pw_multi_aff_copy(upma
));
9954 mupa
= isl_multi_union_pw_aff_set_union_pw_aff(mupa
, i
, upa
);
9957 if (isl_multi_union_pw_aff_has_explicit_domain(mupa
))
9958 mupa
= preimage_explicit_domain(mupa
, upma
);
9960 isl_union_pw_multi_aff_free(upma
);
9963 isl_multi_union_pw_aff_free(mupa
);
9964 isl_union_pw_multi_aff_free(upma
);
9968 /* Extract the sequence of elements in "mupa" with domain space "space"
9969 * (ignoring parameters).
9971 * For the elements of "mupa" that are not defined on the specified space,
9972 * the corresponding element in the result is empty.
9974 __isl_give isl_multi_pw_aff
*isl_multi_union_pw_aff_extract_multi_pw_aff(
9975 __isl_keep isl_multi_union_pw_aff
*mupa
, __isl_take isl_space
*space
)
9979 isl_space
*space_mpa
;
9980 isl_multi_pw_aff
*mpa
;
9982 n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
9983 if (n
< 0 || !space
)
9986 space_mpa
= isl_multi_union_pw_aff_get_space(mupa
);
9987 space
= isl_space_replace_params(space
, space_mpa
);
9988 space_mpa
= isl_space_map_from_domain_and_range(isl_space_copy(space
),
9990 mpa
= isl_multi_pw_aff_alloc(space_mpa
);
9992 space
= isl_space_from_domain(space
);
9993 space
= isl_space_add_dims(space
, isl_dim_out
, 1);
9994 for (i
= 0; i
< n
; ++i
) {
9995 isl_union_pw_aff
*upa
;
9998 upa
= isl_multi_union_pw_aff_get_union_pw_aff(mupa
, i
);
9999 pa
= isl_union_pw_aff_extract_pw_aff(upa
,
10000 isl_space_copy(space
));
10001 mpa
= isl_multi_pw_aff_set_pw_aff(mpa
, i
, pa
);
10002 isl_union_pw_aff_free(upa
);
10005 isl_space_free(space
);
10008 isl_space_free(space
);
10012 /* Data structure that specifies how isl_union_pw_multi_aff_un_op
10013 * should modify the base expressions in the input.
10015 * If "filter" is not NULL, then only the base expressions that satisfy "filter"
10016 * are taken into account.
10017 * "fn" is applied to each entry in the input.
10019 struct isl_union_pw_multi_aff_un_op_control
{
10020 isl_bool (*filter
)(__isl_keep isl_pw_multi_aff
*part
);
10021 __isl_give isl_pw_multi_aff
*(*fn
)(__isl_take isl_pw_multi_aff
*pma
);
10024 /* Wrapper for isl_union_pw_multi_aff_un_op filter functions (which do not take
10025 * a second argument) for use as an isl_union_pw_multi_aff_transform
10026 * filter function (which does take a second argument).
10027 * Simply call control->filter without the second argument.
10029 static isl_bool
isl_union_pw_multi_aff_un_op_filter_drop_user(
10030 __isl_take isl_pw_multi_aff
*pma
, void *user
)
10032 struct isl_union_pw_multi_aff_un_op_control
*control
= user
;
10034 return control
->filter(pma
);
10037 /* Wrapper for isl_union_pw_multi_aff_un_op base functions (which do not take
10038 * a second argument) for use as an isl_union_pw_multi_aff_transform
10039 * base function (which does take a second argument).
10040 * Simply call control->fn without the second argument.
10042 static __isl_give isl_pw_multi_aff
*isl_union_pw_multi_aff_un_op_drop_user(
10043 __isl_take isl_pw_multi_aff
*pma
, void *user
)
10045 struct isl_union_pw_multi_aff_un_op_control
*control
= user
;
10047 return control
->fn(pma
);
10050 /* Construct an isl_union_pw_multi_aff that is obtained by
10051 * modifying "upma" according to "control".
10053 * isl_union_pw_multi_aff_transform performs essentially
10054 * the same operation, but takes a filter and a callback function
10055 * of a different form (with an extra argument).
10056 * Call isl_union_pw_multi_aff_transform with wrappers
10057 * that remove this extra argument.
10059 static __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_un_op(
10060 __isl_take isl_union_pw_multi_aff
*upma
,
10061 struct isl_union_pw_multi_aff_un_op_control
*control
)
10063 struct isl_union_pw_multi_aff_transform_control t_control
= {
10064 .filter
= &isl_union_pw_multi_aff_un_op_filter_drop_user
,
10065 .filter_user
= control
,
10066 .fn
= &isl_union_pw_multi_aff_un_op_drop_user
,
10067 .fn_user
= control
,
10070 return isl_union_pw_multi_aff_transform(upma
, &t_control
);
10073 /* For each function in "upma" of the form A -> [B -> C],
10074 * extract the function A -> B and collect the results.
10076 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_range_factor_domain(
10077 __isl_take isl_union_pw_multi_aff
*upma
)
10079 struct isl_union_pw_multi_aff_un_op_control control
= {
10080 .filter
= &isl_pw_multi_aff_range_is_wrapping
,
10081 .fn
= &isl_pw_multi_aff_range_factor_domain
,
10083 return isl_union_pw_multi_aff_un_op(upma
, &control
);
10086 /* For each function in "upma" of the form A -> [B -> C],
10087 * extract the function A -> C and collect the results.
10089 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_range_factor_range(
10090 __isl_take isl_union_pw_multi_aff
*upma
)
10092 struct isl_union_pw_multi_aff_un_op_control control
= {
10093 .filter
= &isl_pw_multi_aff_range_is_wrapping
,
10094 .fn
= &isl_pw_multi_aff_range_factor_range
,
10096 return isl_union_pw_multi_aff_un_op(upma
, &control
);
10099 /* Evaluate the affine function "aff" in the void point "pnt".
10100 * In particular, return the value NaN.
10102 static __isl_give isl_val
*eval_void(__isl_take isl_aff
*aff
,
10103 __isl_take isl_point
*pnt
)
10107 ctx
= isl_point_get_ctx(pnt
);
10109 isl_point_free(pnt
);
10110 return isl_val_nan(ctx
);
10113 /* Evaluate the affine expression "aff"
10114 * in the coordinates (with denominator) "pnt".
10116 static __isl_give isl_val
*eval(__isl_keep isl_vec
*aff
,
10117 __isl_keep isl_vec
*pnt
)
10126 ctx
= isl_vec_get_ctx(aff
);
10129 isl_seq_inner_product(aff
->el
+ 1, pnt
->el
, pnt
->size
, &n
);
10130 isl_int_mul(d
, aff
->el
[0], pnt
->el
[0]);
10131 v
= isl_val_rat_from_isl_int(ctx
, n
, d
);
10132 v
= isl_val_normalize(v
);
10139 /* Check that the domain space of "aff" is equal to "space".
10141 static isl_stat
isl_aff_check_has_domain_space(__isl_keep isl_aff
*aff
,
10142 __isl_keep isl_space
*space
)
10146 ok
= isl_space_is_equal(isl_aff_peek_domain_space(aff
), space
);
10148 return isl_stat_error
;
10150 isl_die(isl_aff_get_ctx(aff
), isl_error_invalid
,
10151 "incompatible spaces", return isl_stat_error
);
10152 return isl_stat_ok
;
10155 /* Evaluate the affine function "aff" in "pnt".
10157 __isl_give isl_val
*isl_aff_eval(__isl_take isl_aff
*aff
,
10158 __isl_take isl_point
*pnt
)
10162 isl_local_space
*ls
;
10164 if (isl_aff_check_has_domain_space(aff
, isl_point_peek_space(pnt
)) < 0)
10166 is_void
= isl_point_is_void(pnt
);
10170 return eval_void(aff
, pnt
);
10172 ls
= isl_aff_get_domain_local_space(aff
);
10173 pnt
= isl_local_space_lift_point(ls
, pnt
);
10175 v
= eval(aff
->v
, isl_point_peek_vec(pnt
));
10178 isl_point_free(pnt
);
10183 isl_point_free(pnt
);