/*
* Copyright 2011 INRIA Saclay
* Copyright 2011 Sven Verdoolaege
- * Copyright 2012 Ecole Normale Superieure
+ * Copyright 2012-2013 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
#include <isl_space_private.h>
#include <isl_local_space_private.h>
#include <isl_mat_private.h>
-#include <isl_list_private.h>
#include <isl/constraint.h>
#include <isl/seq.h>
#include <isl/set.h>
+#include <isl_val_private.h>
#include <isl_config.h>
+#undef BASE
+#define BASE aff
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE pw_aff
+
+#include <isl_list_templ.c>
+
__isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
__isl_take isl_vec *v)
{
return aff;
}
+/* Replace the constant term of "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v)
+{
+ if (!aff || !v)
+ goto error;
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting rational value", goto error);
+
+ if (isl_int_eq(aff->v->el[1], v->n) &&
+ isl_int_eq(aff->v->el[0], v->d)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ goto error;
+
+ if (isl_int_eq(aff->v->el[0], v->d)) {
+ isl_int_set(aff->v->el[1], v->n);
+ } else if (isl_int_is_one(v->d)) {
+ isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
+ } else {
+ isl_seq_scale(aff->v->el + 1,
+ aff->v->el + 1, v->d, aff->v->size - 1);
+ isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
+ isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_val_free(v);
+ return NULL;
+}
+
__isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
{
if (isl_int_is_zero(v))
return aff;
}
+/* Replace the coefficient of the variable of type "type" at position "pos"
+ * of "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+ if (!aff || !v)
+ goto error;
+
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ goto error);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "position out of bounds", goto error);
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting rational value", goto error);
+
+ pos += isl_local_space_offset(aff->ls, type);
+ if (isl_int_eq(aff->v->el[1 + pos], v->n) &&
+ isl_int_eq(aff->v->el[0], v->d)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ goto error;
+
+ if (isl_int_eq(aff->v->el[0], v->d)) {
+ isl_int_set(aff->v->el[1 + pos], v->n);
+ } else if (isl_int_is_one(v->d)) {
+ isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+ } else {
+ isl_seq_scale(aff->v->el + 1,
+ aff->v->el + 1, v->d, aff->v->size - 1);
+ isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+ isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_val_free(v);
+ return NULL;
+}
+
__isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
enum isl_dim_type type, int pos, isl_int v)
{
return list;
}
+/* Check that the domain space of "aff" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ */
+int isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
+ __isl_keep isl_space *space)
+{
+ isl_space *aff_space;
+ int match;
+
+ if (!aff || !space)
+ return -1;
+
+ aff_space = isl_aff_get_domain_space(aff);
+
+ match = isl_space_match(space, isl_dim_param, aff_space, isl_dim_param);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "parameters don't match", goto error);
+ match = isl_space_tuple_match(space, isl_dim_in,
+ aff_space, isl_dim_set);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "domains don't match", goto error);
+ isl_space_free(aff_space);
+ return 0;
+error:
+ isl_space_free(aff_space);
+ return -1;
+}
+
#undef BASE
#define BASE aff
&pw_multi_aff_add);
}
+static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+ return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
+ &isl_multi_aff_sub);
+}
+
+/* Subtract "pma2" from "pma1" and return the result.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+ return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+ &pw_multi_aff_sub);
+}
+
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
{
return NULL;
}
-/* Compute the preimage of the affine expression "src" under "ma"
- * and put the result in "dst". If "has_denom" is set (to one),
+/* Compute the preimage of a range of dimensions in the affine expression "src"
+ * under "ma" and put the result in "dst". The number of dimensions in "src"
+ * that precede the range is given by "n_before". The number of dimensions
+ * in the range is given by the number of output dimensions of "ma".
+ * The number of dimensions that follow the range is given by "n_after".
+ * If "has_denom" is set (to one),
* then "src" and "dst" have an extra initial denominator.
* "n_div_ma" is the number of existentials in "ma"
* "n_div_bset" is the number of existentials in "src"
*
* Let src represent the expression
*
- * (a(p) + b x + c(divs))/d
+ * (a(p) + f_u u + b v + f_w w + c(divs))/d
*
* and let ma represent the expressions
*
- * x_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i
+ * v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i
*
* We start out with the following expression for dst:
*
- * (a(p) + 0 y + 0 divs' + f \sum_i b_i x_i + c(divs))/d
+ * (a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d
*
- * with the multiplication factor f initially equal to 1.
+ * with the multiplication factor f initially equal to 1
+ * and f \sum_i b_i v_i kept separately.
* For each x_i that we substitute, we multiply the numerator
* (and denominator) of dst by c_1 = m_i and add the numerator
* of the x_i expression multiplied by c_2 = f b_i,
* for the next x_j, j > i.
*/
void isl_seq_preimage(isl_int *dst, isl_int *src,
- __isl_keep isl_multi_aff *ma, int n_div_ma, int n_div_bset,
+ __isl_keep isl_multi_aff *ma, int n_before, int n_after,
+ int n_div_ma, int n_div_bmap,
isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom)
{
int i;
int n_param, n_in, n_out;
- int o_div_bset;
+ int o_dst, o_src;
n_param = isl_multi_aff_dim(ma, isl_dim_param);
n_in = isl_multi_aff_dim(ma, isl_dim_in);
n_out = isl_multi_aff_dim(ma, isl_dim_out);
- o_div_bset = has_denom + 1 + n_param + n_in + n_div_ma;
-
- isl_seq_cpy(dst, src, has_denom + 1 + n_param);
- isl_seq_clr(dst + has_denom + 1 + n_param, n_in + n_div_ma);
- isl_seq_cpy(dst + o_div_bset,
- src + has_denom + 1 + n_param + n_out, n_div_bset);
+ isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before);
+ o_dst = o_src = has_denom + 1 + n_param + n_before;
+ isl_seq_clr(dst + o_dst, n_in);
+ o_dst += n_in;
+ o_src += n_out;
+ isl_seq_cpy(dst + o_dst, src + o_src, n_after);
+ o_dst += n_after;
+ o_src += n_after;
+ isl_seq_clr(dst + o_dst, n_div_ma);
+ o_dst += n_div_ma;
+ isl_seq_cpy(dst + o_dst, src + o_src, n_div_bmap);
isl_int_set_si(f, 1);
for (i = 0; i < n_out; ++i) {
- if (isl_int_is_zero(src[has_denom + 1 + n_param + i]))
+ int offset = has_denom + 1 + n_param + n_before + i;
+
+ if (isl_int_is_zero(src[offset]))
continue;
isl_int_set(c1, ma->p[i]->v->el[0]);
- isl_int_mul(c2, f, src[has_denom + 1 + n_param + i]);
+ isl_int_mul(c2, f, src[offset]);
isl_int_gcd(g, c1, c2);
isl_int_divexact(c1, c1, g);
isl_int_divexact(c2, c2, g);
isl_int_mul(f, f, c1);
- isl_seq_combine(dst + has_denom, c1, dst + has_denom,
- c2, ma->p[i]->v->el + 1, ma->p[i]->v->size - 1);
- isl_seq_scale(dst + o_div_bset,
- dst + o_div_bset, c1, n_div_bset);
+ o_dst = has_denom;
+ o_src = 1;
+ isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+ c2, ma->p[i]->v->el + o_src, 1 + n_param);
+ o_dst += 1 + n_param;
+ o_src += 1 + n_param;
+ isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_before);
+ o_dst += n_before;
+ isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+ c2, ma->p[i]->v->el + o_src, n_in);
+ o_dst += n_in;
+ o_src += n_in;
+ isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_after);
+ o_dst += n_after;
+ isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+ c2, ma->p[i]->v->el + o_src, n_div_ma);
+ o_dst += n_div_ma;
+ o_src += n_div_ma;
+ isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_div_bmap);
if (has_denom)
isl_int_mul(dst[0], dst[0], c1);
}
isl_int_init(c2);
isl_int_init(g);
- isl_seq_preimage(res->v->el, aff->v->el, ma, n_div_ma, n_div_aff,
+ isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0, n_div_ma, n_div_aff,
f, c1, c2, g, 1);
isl_int_clear(f);
return NULL;
}
+/* Check that the domain space of "pa" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ */
+int isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
+ __isl_keep isl_space *space)
+{
+ isl_space *pa_space;
+ int match;
+
+ if (!pa || !space)
+ return -1;
+
+ pa_space = isl_pw_aff_get_space(pa);
+
+ match = isl_space_match(space, isl_dim_param, pa_space, isl_dim_param);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "parameters don't match", goto error);
+ match = isl_space_tuple_match(space, isl_dim_in, pa_space, isl_dim_in);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "domains don't match", goto error);
+ isl_space_free(pa_space);
+ return 0;
+error:
+ isl_space_free(pa_space);
+ return -1;
+}
+
#undef BASE
#define BASE pw_aff
#include <isl_multi_templ.c>
+
+/* Scale the first elements of "ma" by the corresponding elements of "vec".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_scale_vec(__isl_take isl_multi_aff *ma,
+ __isl_take isl_vec *vec)
+{
+ int i, n;
+ isl_int v;
+
+ if (!ma || !vec)
+ goto error;
+
+ n = isl_multi_aff_dim(ma, isl_dim_out);
+ if (isl_vec_size(vec) < n)
+ n = isl_vec_size(vec);
+
+ isl_int_init(v);
+ for (i = 0; i < n; ++i) {
+ isl_aff *aff;
+
+ isl_vec_get_element(vec, i, &v);
+
+ aff = isl_multi_aff_get_aff(ma, i);
+ aff = isl_aff_scale(aff, v);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+ isl_int_clear(v);
+
+ isl_vec_free(vec);
+ return ma;
+error:
+ isl_vec_free(vec);
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+/* Scale the first elements of "pma" by the corresponding elements of "vec".
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_vec(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_vec *v)
+{
+ int i;
+
+ pma = isl_pw_multi_aff_cow(pma);
+ if (!pma || !v)
+ goto error;
+
+ for (i = 0; i < pma->n; ++i) {
+ pma->p[i].maff = isl_multi_aff_scale_vec(pma->p[i].maff,
+ isl_vec_copy(v));
+ if (!pma->p[i].maff)
+ goto error;
+ }
+
+ isl_vec_free(v);
+ return pma;
+error:
+ isl_vec_free(v);
+ isl_pw_multi_aff_free(pma);
+ return NULL;
+}
+
+/* This function is called for each entry of an isl_union_pw_multi_aff.
+ * Replace the entry by the result of applying isl_pw_multi_aff_scale_vec
+ * to the original entry with the isl_vec in "user" as extra argument.
+ */
+static int union_pw_multi_aff_scale_vec_entry(void **entry, void *user)
+{
+ isl_pw_multi_aff **pma = (isl_pw_multi_aff **) entry;
+ isl_vec *v = user;
+
+ *pma = isl_pw_multi_aff_scale_vec(*pma, isl_vec_copy(v));
+ if (!*pma)
+ return -1;
+
+ return 0;
+}
+
+/* Scale the first elements of "upma" by the corresponding elements of "vec".
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_vec(
+ __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_vec *v)
+{
+ upma = isl_union_pw_multi_aff_cow(upma);
+ if (!upma || !v)
+ goto error;
+
+ if (isl_hash_table_foreach(upma->dim->ctx, &upma->table,
+ &union_pw_multi_aff_scale_vec_entry, v) < 0)
+ goto error;
+
+ isl_vec_free(v);
+ return upma;
+error:
+ isl_vec_free(v);
+ isl_union_pw_multi_aff_free(upma);
+ return NULL;
+}