Update isl to isl-0.15-86-g595055e
authorTobias Grosser <tobias@grosser.es>
Fri, 24 Jul 2015 13:12:17 +0000 (13:12 +0000)
committerTobias Grosser <tobias@grosser.es>
Fri, 24 Jul 2015 13:12:17 +0000 (13:12 +0000)
Besides a couple of cleanups and refactorings in isl, this change set fixes a
couple of bugs in isl, that can cause issues during code generation.

llvm-svn: 243110

21 files changed:
polly/lib/External/isl/GIT_HEAD_ID
polly/lib/External/isl/Makefile.am
polly/lib/External/isl/Makefile.in
polly/lib/External/isl/doc/manual.pdf
polly/lib/External/isl/doc/user.pod
polly/lib/External/isl/isl_aff.c
polly/lib/External/isl/isl_ast_build.c
polly/lib/External/isl/isl_ast_build_expr.c
polly/lib/External/isl/isl_ast_build_private.h
polly/lib/External/isl/isl_ast_codegen.c
polly/lib/External/isl/isl_coalesce.c
polly/lib/External/isl/isl_convex_hull.c
polly/lib/External/isl/isl_equalities.c
polly/lib/External/isl/isl_fold.c
polly/lib/External/isl/isl_polynomial.c
polly/lib/External/isl/isl_test.c
polly/lib/External/isl/isl_union_neg.c
polly/lib/External/isl/isl_union_templ.c
polly/lib/External/isl/ltmain.sh
polly/lib/External/isl/test_inputs/codegen/cloog/faber.c
polly/lib/External/isl/test_inputs/codegen/separate2.c

index fa98271..a7b0b6c 100644 (file)
@@ -325,6 +325,8 @@ EXTRA_DIST = \
        isl_pw_templ.c \
        isl_union_macro.h \
        isl_union_templ.c \
+       isl_union_single.c \
+       isl_union_multi.c \
        isl_union_eval.c \
        isl_union_neg.c \
        isl.py \
index acd3f02..9e98d2a 100644 (file)
@@ -1067,6 +1067,8 @@ EXTRA_DIST = \
        isl_pw_templ.c \
        isl_union_macro.h \
        isl_union_templ.c \
+       isl_union_single.c \
+       isl_union_multi.c \
        isl_union_eval.c \
        isl_union_neg.c \
        isl.py \
index ca4b618..1840065 100644 (file)
Binary files a/polly/lib/External/isl/doc/manual.pdf and b/polly/lib/External/isl/doc/manual.pdf differ
index 9eb4559..db98c60 100644 (file)
@@ -212,9 +212,6 @@ a regular basic set, rather than a rational basic set.
 
 =over
 
-=item * Objects of type C<isl_union_pw_multi_aff> can no longer contain
-two or more C<isl_pw_multi_aff> objects with the same domain space.
-
 =item * The function C<isl_union_pw_multi_aff_add> now consistently
 computes the sum on the shared definition domain.
 The function C<isl_union_pw_multi_aff_union_add> has been added
@@ -3128,6 +3125,14 @@ is that of the shared parameter space.
 The union expression types defined by C<isl>
 are C<isl_union_pw_aff>, C<isl_union_pw_multi_aff>,
 C<isl_union_pw_qpolynomial> and C<isl_union_pw_qpolynomial_fold>.
+In case of
+C<isl_union_pw_aff>,
+C<isl_union_pw_qpolynomial> and C<isl_union_pw_qpolynomial_fold>,
+there can be at most one base expression for a given domain space.
+In case of
+C<isl_union_pw_multi_aff>,
+there can be multiple such expressions for a given domain space,
+but the domains of these expressions need to be disjoint.
 
 An empty union expression can be created using the following functions.
 
index 29bbe5b..fbbfde6 100644 (file)
@@ -2578,7 +2578,7 @@ __isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
 #undef PARTS
 #define PARTS pw_aff
 
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
 #include <isl_union_neg.c>
 
 static __isl_give isl_set *align_params_pw_pw_set_and(
@@ -4073,7 +4073,7 @@ __isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
 #undef PARTS
 #define PARTS pw_multi_aff
 
-#include <isl_union_templ.c>
+#include <isl_union_multi.c>
 #include <isl_union_neg.c>
 
 /* Given a function "cmp" that returns the set of elements where
@@ -5722,23 +5722,23 @@ struct isl_union_pw_multi_aff_bin_data {
        isl_union_pw_multi_aff *upma2;
        isl_union_pw_multi_aff *res;
        isl_pw_multi_aff *pma;
-       isl_stat (*fn)(void **entry, void *user);
+       isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user);
 };
 
 /* Given an isl_pw_multi_aff from upma1, store it in data->pma
  * and call data->fn for each isl_pw_multi_aff in data->upma2.
  */
-static isl_stat bin_entry(void **entry, void *user)
+static isl_stat bin_entry(__isl_take isl_pw_multi_aff *pma, void *user)
 {
        struct isl_union_pw_multi_aff_bin_data *data = user;
-       isl_pw_multi_aff *pma = *entry;
+       isl_stat r;
 
        data->pma = pma;
-       if (isl_hash_table_foreach(data->upma2->space->ctx, &data->upma2->table,
-                                  data->fn, data) < 0)
-               return isl_stat_error;
+       r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma2,
+                                  data->fn, data);
+       isl_pw_multi_aff_free(pma);
 
-       return isl_stat_ok;
+       return r;
 }
 
 /* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
@@ -5749,7 +5749,7 @@ static isl_stat bin_entry(void **entry, void *user)
 static __isl_give isl_union_pw_multi_aff *bin_op(
        __isl_take isl_union_pw_multi_aff *upma1,
        __isl_take isl_union_pw_multi_aff *upma2,
-       isl_stat (*fn)(void **entry, void *user))
+       isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user))
 {
        isl_space *space;
        struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn };
@@ -5764,7 +5764,7 @@ static __isl_give isl_union_pw_multi_aff *bin_op(
 
        data.upma2 = upma2;
        data.res = isl_union_pw_multi_aff_alloc_same_size(upma1);
-       if (isl_hash_table_foreach(upma1->space->ctx, &upma1->table,
+       if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1,
                                   &bin_entry, &data) < 0)
                goto error;
 
@@ -5827,21 +5827,22 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
                                            &pw_multi_aff_flat_range_product);
 }
 
-/* If data->pma and *entry have the same domain space, then compute
+/* If data->pma and "pma2" have the same domain space, then compute
  * their flat range product and the result to data->res.
  */
-static isl_stat flat_range_product_entry(void **entry, void *user)
+static isl_stat flat_range_product_entry(__isl_take isl_pw_multi_aff *pma2,
+       void *user)
 {
        struct isl_union_pw_multi_aff_bin_data *data = user;
-       isl_pw_multi_aff *pma2 = *entry;
 
        if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
-                                pma2->dim, isl_dim_in))
+                                pma2->dim, isl_dim_in)) {
+               isl_pw_multi_aff_free(pma2);
                return isl_stat_ok;
+       }
 
        pma2 = isl_pw_multi_aff_flat_range_product(
-                                       isl_pw_multi_aff_copy(data->pma),
-                                       isl_pw_multi_aff_copy(pma2));
+                                       isl_pw_multi_aff_copy(data->pma), pma2);
 
        data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
 
@@ -7118,18 +7119,18 @@ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_multi_val_on_domain(
 /* Compute the pullback of data->pma by the function represented by "pma2",
  * provided the spaces match, and add the results to data->res.
  */
-static isl_stat pullback_entry(void **entry, void *user)
+static isl_stat pullback_entry(__isl_take isl_pw_multi_aff *pma2, void *user)
 {
        struct isl_union_pw_multi_aff_bin_data *data = user;
-       isl_pw_multi_aff *pma2 = *entry;
 
        if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
-                                pma2->dim, isl_dim_out))
+                                pma2->dim, isl_dim_out)) {
+               isl_pw_multi_aff_free(pma2);
                return isl_stat_ok;
+       }
 
        pma2 = isl_pw_multi_aff_pullback_pw_multi_aff(
-                                       isl_pw_multi_aff_copy(data->pma),
-                                       isl_pw_multi_aff_copy(pma2));
+                                       isl_pw_multi_aff_copy(data->pma), pma2);
 
        data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
        if (!data->res)
@@ -7265,18 +7266,11 @@ static __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_domain_space(
        return data.res;
 }
 
-/* Replace the entry of isl_union_pw_aff to which "entry" points
- * by its floor.
+/* Return the floor of "pa".
  */
-static isl_stat floor_entry(void **entry, void *user)
+static __isl_give isl_pw_aff *floor_entry(__isl_take isl_pw_aff *pa, void *user)
 {
-       isl_pw_aff **pa = (isl_pw_aff **) entry;
-
-       *pa = isl_pw_aff_floor(*pa);
-       if (!*pa)
-               return isl_stat_error;
-
-       return isl_stat_ok;
+       return isl_pw_aff_floor(pa);
 }
 
 /* Given f, return floor(f).
@@ -7284,17 +7278,7 @@ static isl_stat floor_entry(void **entry, void *user)
 __isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
        __isl_take isl_union_pw_aff *upa)
 {
-       isl_ctx *ctx;
-
-       upa = isl_union_pw_aff_cow(upa);
-       if (!upa)
-               return NULL;
-
-       ctx = isl_union_pw_aff_get_ctx(upa);
-       if (isl_hash_table_foreach(ctx, &upa->table, &floor_entry, NULL) < 0)
-               upa = isl_union_pw_aff_free(upa);
-
-       return upa;
+       return isl_union_pw_aff_transform_inplace(upa, &floor_entry, NULL);
 }
 
 /* Compute
@@ -7618,17 +7602,17 @@ struct isl_union_pw_aff_pullback_upma_data {
 /* Check if "pma" can be plugged into data->pa.
  * If so, perform the pullback and add the result to data->res.
  */
-static isl_stat pa_pb_pma(void **entry, void *user)
+static isl_stat pa_pb_pma(__isl_take isl_pw_multi_aff *pma, void *user)
 {
        struct isl_union_pw_aff_pullback_upma_data *data = user;
-       isl_pw_multi_aff *pma = *entry;
        isl_pw_aff *pa;
 
        if (!isl_space_tuple_is_equal(data->pa->dim, isl_dim_in,
-                                pma->dim, isl_dim_out))
+                                pma->dim, isl_dim_out)) {
+               isl_pw_multi_aff_free(pma);
                return isl_stat_ok;
+       }
 
-       pma = isl_pw_multi_aff_copy(pma);
        pa = isl_pw_aff_copy(data->pa);
        pa = isl_pw_aff_pullback_pw_multi_aff(pa, pma);
 
@@ -7640,19 +7624,17 @@ static isl_stat pa_pb_pma(void **entry, void *user)
 /* Check if any of the elements of data->upma can be plugged into pa,
  * add if so add the result to data->res.
  */
-static isl_stat upa_pb_upma(void **entry, void *user)
+static isl_stat upa_pb_upma(__isl_take isl_pw_aff *pa, void *user)
 {
        struct isl_union_pw_aff_pullback_upma_data *data = user;
-       isl_ctx *ctx;
-       isl_pw_aff *pa = *entry;
+       isl_stat r;
 
        data->pa = pa;
-       ctx = isl_union_pw_multi_aff_get_ctx(data->upma);
-       if (isl_hash_table_foreach(ctx, &data->upma->table,
-                                  &pa_pb_pma, data) < 0)
-               return isl_stat_error;
+       r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma,
+                                  &pa_pb_pma, data);
+       isl_pw_aff_free(pa);
 
-       return isl_stat_ok;
+       return r;
 }
 
 /* Compute the pullback of "upa" by the function represented by "upma".
@@ -7670,7 +7652,6 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
        __isl_take isl_union_pw_multi_aff *upma)
 {
        struct isl_union_pw_aff_pullback_upma_data data = { NULL, NULL };
-       isl_ctx *ctx;
        isl_space *space;
 
        space = isl_union_pw_multi_aff_get_space(upma);
@@ -7681,10 +7662,9 @@ __isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
        if (!upa || !upma)
                goto error;
 
-       ctx = isl_union_pw_aff_get_ctx(upa);
        data.upma = upma;
        data.res = isl_union_pw_aff_alloc_same_size(upa);
-       if (isl_hash_table_foreach(ctx, &upa->table, &upa_pb_upma, &data) < 0)
+       if (isl_union_pw_aff_foreach_pw_aff(upa, &upa_pb_upma, &data) < 0)
                data.res = isl_union_pw_aff_free(data.res);
 
        isl_union_pw_aff_free(upa);
index febc7d4..381d8f6 100644 (file)
@@ -825,6 +825,10 @@ static __isl_give isl_ast_build *update_values(
  * Otherwise, we would indirectly intersect the build domain with itself,
  * which can lead to inefficiencies, in particular if the build domain
  * contains any unknown divs.
+ *
+ * The pending and generated sets are not updated by this function to
+ * match the updated domain.
+ * The caller still needs to call isl_ast_build_set_pending_generated.
  */
 __isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
        __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
@@ -835,12 +839,10 @@ __isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
        if (!build)
                goto error;
 
-       bounds = isl_basic_set_preimage_multi_aff(bounds,
-                                       isl_multi_aff_copy(build->values));
        build = update_values(build, isl_basic_set_copy(bounds));
        if (!build)
                goto error;
-       set = isl_set_from_basic_set(isl_basic_set_copy(bounds));
+       set = isl_set_from_basic_set(bounds);
        if (isl_ast_build_has_affine_value(build, build->depth)) {
                set = isl_set_eliminate(set, isl_dim_set, build->depth, 1);
                set = isl_set_compute_divs(set);
@@ -848,24 +850,11 @@ __isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
                                                        isl_set_copy(set));
                build->domain = isl_set_intersect(build->domain, set);
        } else {
-               isl_basic_set *generated, *pending;
-
-               pending = isl_basic_set_copy(bounds);
-               pending = isl_basic_set_drop_constraints_involving_dims(pending,
-                                       isl_dim_set, build->depth, 1);
-               build->pending = isl_set_intersect(build->pending,
-                                       isl_set_from_basic_set(pending));
-               generated = isl_basic_set_copy(bounds);
-               generated = isl_basic_set_drop_constraints_not_involving_dims(
-                                   generated, isl_dim_set, build->depth, 1);
-               build->generated = isl_set_intersect(build->generated,
-                                       isl_set_from_basic_set(generated));
                build->domain = isl_set_intersect(build->domain, set);
                build = isl_ast_build_include_stride(build);
                if (!build)
                        goto error;
        }
-       isl_basic_set_free(bounds);
 
        if (!build->domain || !build->pending || !build->generated)
                return isl_ast_build_free(build);
@@ -877,6 +866,49 @@ error:
        return NULL;
 }
 
+/* Update the pending and generated sets of "build" according to "bounds".
+ * If the build has an affine value at the current depth,
+ * then isl_ast_build_set_loop_bounds has already set the pending set.
+ * Otherwise, do it here.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_pending_generated(
+       __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+       isl_basic_set *generated, *pending;
+
+       if (!build)
+               goto error;
+
+       if (isl_ast_build_has_affine_value(build, build->depth)) {
+               isl_basic_set_free(bounds);
+               return build;
+       }
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       pending = isl_basic_set_copy(bounds);
+       pending = isl_basic_set_drop_constraints_involving_dims(pending,
+                               isl_dim_set, build->depth, 1);
+       build->pending = isl_set_intersect(build->pending,
+                               isl_set_from_basic_set(pending));
+       generated = bounds;
+       generated = isl_basic_set_drop_constraints_not_involving_dims(
+                           generated, isl_dim_set, build->depth, 1);
+       build->generated = isl_set_intersect(build->generated,
+                               isl_set_from_basic_set(generated));
+
+       if (!build->pending || !build->generated)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_ast_build_free(build);
+       isl_basic_set_free(bounds);
+       return NULL;
+}
+
 /* Intersect build->domain with "set", where "set" is specified
  * in terms of the internal schedule domain.
  */
@@ -2193,6 +2225,18 @@ __isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build,
                                        isl_multi_aff_copy(build->values));
 }
 
+/* Plug in the known affine values of outer loop iterators in "bset".
+ */
+__isl_give isl_basic_set *isl_ast_build_specialize_basic_set(
+       __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+       if (!build)
+               return isl_basic_set_free(bset);
+
+       return isl_basic_set_preimage_multi_aff(bset,
+                                       isl_multi_aff_copy(build->values));
+}
+
 /* Simplify the map "map" based on what we know about
  * the iterators of already generated loops.
  *
index 29eb53f..59fe841 100644 (file)
@@ -1453,7 +1453,7 @@ __isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
                return NULL;
        n = isl_constraint_list_n_constraint(list);
        if (n == 0) {
-               isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+               isl_ctx *ctx = isl_constraint_list_get_ctx(list);
                isl_constraint_list_free(list);
                return isl_ast_expr_alloc_int_si(ctx, 1);
        }
index 59eec25..25b5687 100644 (file)
@@ -221,6 +221,8 @@ __isl_give isl_ast_build *isl_ast_build_product(
        __isl_take isl_ast_build *build, __isl_take isl_space *embedding);
 __isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
        __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds);
+__isl_give isl_ast_build *isl_ast_build_set_pending_generated(
+       __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds);
 __isl_give isl_ast_build *isl_ast_build_detect_strides(
        __isl_take isl_ast_build *build, __isl_take isl_set *set);
 __isl_give isl_ast_build *isl_ast_build_include_stride(
@@ -270,6 +272,8 @@ int isl_ast_build_has_isolated(__isl_keep isl_ast_build *build);
 __isl_give isl_set *isl_ast_build_get_isolated(
        __isl_keep isl_ast_build *build);
 
+__isl_give isl_basic_set *isl_ast_build_specialize_basic_set(
+       __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
 __isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set(
        __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
 __isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build,
index 2b791a5..2cb6401 100644 (file)
@@ -1450,12 +1450,17 @@ static __isl_give isl_ast_graft *create_node_scaled(
        depth = isl_ast_build_get_depth(build);
        sub_build = isl_ast_build_copy(build);
        bounds = isl_basic_set_remove_redundancies(bounds);
+       bounds = isl_ast_build_specialize_basic_set(sub_build, bounds);
        sub_build = isl_ast_build_set_loop_bounds(sub_build,
                                                isl_basic_set_copy(bounds));
        degenerate = isl_ast_build_has_value(sub_build);
        eliminated = isl_ast_build_has_affine_value(sub_build, depth);
        if (degenerate < 0 || eliminated < 0)
                executed = isl_union_map_free(executed);
+       if (!degenerate)
+               bounds = isl_ast_build_compute_gist_basic_set(build, bounds);
+       sub_build = isl_ast_build_set_pending_generated(sub_build,
+                                               isl_basic_set_copy(bounds));
        if (eliminated)
                executed = plug_in_values(executed, sub_build);
        else
@@ -1481,8 +1486,6 @@ static __isl_give isl_ast_graft *create_node_scaled(
        graft = isl_ast_graft_alloc_from_children(children,
                            isl_set_copy(guard), enforced, build, sub_build);
 
-       if (!degenerate)
-               bounds = isl_ast_build_compute_gist_basic_set(build, bounds);
        if (!eliminated) {
                isl_ast_build *for_build;
 
index 9b0e47f..a1993d6 100644 (file)
@@ -2142,18 +2142,26 @@ error:
        return NULL;
 }
 
-/* Add variables to "tab" corresponding to the elements in "list"
- * that are not set to NaN.
+/* Add variables to info->bmap and info->tab corresponding to the elements
+ * in "list" that are not set to NaN.
+ * "extra_var" is the number of these elements.
  * "dim" is the offset in the variables of "tab" where we should
  * start considering the elements in "list".
  * When this function returns, the total number of variables in "tab"
  * is equal to "dim" plus the number of elements in "list".
  */
-static int add_sub_vars(struct isl_tab *tab, __isl_keep isl_aff_list *list,
-       int dim)
+static int add_sub_vars(struct isl_coalesce_info *info,
+       __isl_keep isl_aff_list *list, int dim, int extra_var)
 {
        int i, n;
+       isl_space *space;
 
+       space = isl_basic_map_get_space(info->bmap);
+       info->bmap = isl_basic_map_cow(info->bmap);
+       info->bmap = isl_basic_map_extend_space(info->bmap, space,
+                                               extra_var, 0, 0);
+       if (!info->bmap)
+               return -1;
        n = isl_aff_list_n_aff(list);
        for (i = 0; i < n; ++i) {
                int is_nan;
@@ -2164,9 +2172,15 @@ static int add_sub_vars(struct isl_tab *tab, __isl_keep isl_aff_list *list,
                isl_aff_free(aff);
                if (is_nan < 0)
                        return -1;
+               if (is_nan)
+                       continue;
 
-               if (!is_nan && isl_tab_insert_var(tab, dim + i) < 0)
+               if (isl_tab_insert_var(info->tab, dim + i) < 0)
                        return -1;
+               if (isl_basic_map_alloc_div(info->bmap) < 0)
+                       return -1;
+               if (i != n - 1)
+                       isl_basic_map_swap_div(info->bmap, i, n - 1);
        }
 
        return 0;
@@ -2217,53 +2231,33 @@ error:
        return -1;
 }
 
-/* Add variables to info->tab corresponding to the elements in "list"
- * that are not set to NaN.  The value of the added variable
- * is fixed to the purely affine expression defined by the element.
+/* Add variables to info->tab and info->bmap corresponding to the elements
+ * in "list" that are not set to NaN.  The value of the added variable
+ * in info->tab is fixed to the purely affine expression defined by the element.
  * "dim" is the offset in the variables of info->tab where we should
  * start considering the elements in "list".
  * When this function returns, the total number of variables in info->tab
  * is equal to "dim" plus the number of elements in "list".
- * Additionally, add the div constraints that have been added info->bmap
- * after the tableau was constructed to info->tab.  These constraints
- * start at position "n_ineq" in info->bmap.
- * The constraints need to be added to the tableau before
- * the equalities assigning the purely affine expression
- * because the position needs to match that in info->bmap.
- * They are frozen because the corresponding added equality is a consequence
- * of the two div constraints and the other equalities, meaning that
- * the div constraints would otherwise get marked as redundant,
- * while they are only redundant with respect to the extra equalities
- * added to the tableau, which do not appear explicitly in the basic map.
  */
 static int add_subs(struct isl_coalesce_info *info,
-       __isl_keep isl_aff_list *list, int dim, int n_ineq)
+       __isl_keep isl_aff_list *list, int dim)
 {
-       int i, extra_var, extra_con;
+       int extra_var;
        int n;
-       unsigned n_eq = info->bmap->n_eq;
 
        if (!list)
                return -1;
 
        n = isl_aff_list_n_aff(list);
        extra_var = n - (info->tab->n_var - dim);
-       extra_con = info->bmap->n_ineq - n_ineq;
 
        if (isl_tab_extend_vars(info->tab, extra_var) < 0)
                return -1;
-       if (isl_tab_extend_cons(info->tab, extra_con + 2 * extra_var) < 0)
+       if (isl_tab_extend_cons(info->tab, 2 * extra_var) < 0)
                return -1;
-       if (add_sub_vars(info->tab, list, dim) < 0)
+       if (add_sub_vars(info, list, dim, extra_var) < 0)
                return -1;
 
-       for (i = n_ineq; i < info->bmap->n_ineq; ++i) {
-               if (isl_tab_add_ineq(info->tab, info->bmap->ineq[i]) < 0)
-                       return -1;
-               if (isl_tab_freeze_constraint(info->tab, n_eq + i) < 0)
-                       return -1;
-       }
-
        return add_sub_equalities(info->tab, list, dim);
 }
 
@@ -2273,9 +2267,6 @@ static int add_subs(struct isl_coalesce_info *info,
  * is equal to the number of integer divisions in "i", while the number
  * of NaN elements in the list is equal to the number of integer divisions
  * in "j".
- * Adding extra integer divisions to "j" through isl_basic_map_align_divs
- * also adds the corresponding div constraints.  These need to be added
- * to the corresponding tableau as well in add_subs to maintain consistency.
  *
  * If no coalescing can be performed, then we need to revert basic map "j"
  * to its original state.  We do the same if basic map "i" gets dropped
@@ -2290,19 +2281,13 @@ static enum isl_change coalesce_with_subs(int i, int j,
        struct isl_tab_undo *snap;
        unsigned dim;
        enum isl_change change;
-       int n_ineq;
 
        bmap_j = isl_basic_map_copy(info[j].bmap);
-       n_ineq = info[j].bmap->n_ineq;
-       info[j].bmap = isl_basic_map_align_divs(info[j].bmap, info[i].bmap);
-       if (!info[j].bmap)
-               goto error;
-
        snap = isl_tab_snap(info[j].tab);
 
        dim = isl_basic_map_dim(bmap_j, isl_dim_all);
        dim -= isl_basic_map_dim(bmap_j, isl_dim_div);
-       if (add_subs(&info[j], list, dim, n_ineq) < 0)
+       if (add_subs(&info[j], list, dim) < 0)
                goto error;
 
        change = coalesce_local_pair(i, j, info);
index b5ca0d9..a61462e 100644 (file)
@@ -2326,6 +2326,25 @@ error:
 
 /* Compute a superset of the convex hull of map that is described
  * by only (translates of) the constraints in the constituents of map.
+ * Handle trivial cases where map is NULL or contains at most one disjunct.
+ */
+static __isl_give isl_basic_map *map_simple_hull_trivial(
+       __isl_take isl_map *map)
+{
+       isl_basic_map *hull;
+
+       if (!map)
+               return NULL;
+       if (map->n == 0)
+               return replace_map_by_empty_basic_map(map);
+
+       hull = isl_basic_map_copy(map->p[0]);
+       isl_map_free(map);
+       return hull;
+}
+
+/* Compute a superset of the convex hull of map that is described
+ * by only (translates of) the constraints in the constituents of map.
  * Translation is only allowed if "shift" is set.
  */
 static __isl_give isl_basic_map *map_simple_hull(__isl_take isl_map *map,
@@ -2337,17 +2356,12 @@ static __isl_give isl_basic_map *map_simple_hull(__isl_take isl_map *map,
        struct isl_basic_map *affine_hull;
        struct isl_basic_set *bset = NULL;
 
-       if (!map)
-               return NULL;
-       if (map->n == 0)
-               return replace_map_by_empty_basic_map(map);
-       if (map->n == 1) {
-               hull = isl_basic_map_copy(map->p[0]);
-               isl_map_free(map);
-               return hull;
-       }
+       if (!map || map->n <= 1)
+               return map_simple_hull_trivial(map);
 
        map = isl_map_detect_equalities(map);
+       if (!map || map->n <= 1)
+               return map_simple_hull_trivial(map);
        affine_hull = isl_map_affine_hull(isl_map_copy(map));
        map = isl_map_align_divs(map);
        model = map ? isl_basic_map_copy(map->p[0]) : NULL;
index 44cf8f0..dbba7fa 100644 (file)
@@ -514,7 +514,7 @@ __isl_give isl_mat *isl_mat_variable_compression(__isl_take isl_mat *B,
                                isl_mat_free(U);
                                if (T2) {
                                        isl_mat_free(*T2);
-                                       *T2 = NULL;
+                                       *T2 = isl_mat_alloc(ctx, 0, 1 + dim);
                                }
                                return isl_mat_alloc(ctx, 1 + dim, 0);
                        }
index d61d41f..c2162cf 100644 (file)
@@ -684,7 +684,7 @@ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist_params(
 
 #define NO_SUB
 
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
 #include <isl_union_eval.c>
 
 __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
index 8c9522b..277912a 100644 (file)
@@ -2817,7 +2817,7 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_qpolynomial(
 #undef PARTS
 #define PARTS pw_qpolynomial
 
-#include <isl_union_templ.c>
+#include <isl_union_single.c>
 #include <isl_union_eval.c>
 #include <isl_union_neg.c>
 
@@ -4772,31 +4772,19 @@ error:
        return NULL;
 }
 
-static isl_stat poly_entry(void **entry, void *user)
+static __isl_give isl_pw_qpolynomial *poly_entry(
+       __isl_take isl_pw_qpolynomial *pwqp, void *user)
 {
        int *sign = user;
-       isl_pw_qpolynomial **pwqp = (isl_pw_qpolynomial **)entry;
 
-       *pwqp = isl_pw_qpolynomial_to_polynomial(*pwqp, *sign);
-
-       return *pwqp ? isl_stat_ok : isl_stat_error;
+       return isl_pw_qpolynomial_to_polynomial(pwqp, *sign);
 }
 
 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_to_polynomial(
        __isl_take isl_union_pw_qpolynomial *upwqp, int sign)
 {
-       upwqp = isl_union_pw_qpolynomial_cow(upwqp);
-       if (!upwqp)
-               return NULL;
-
-       if (isl_hash_table_foreach(upwqp->space->ctx, &upwqp->table,
-                                  &poly_entry, &sign) < 0)
-               goto error;
-
-       return upwqp;
-error:
-       isl_union_pw_qpolynomial_free(upwqp);
-       return NULL;
+       return isl_union_pw_qpolynomial_transform_inplace(upwqp,
+                                  &poly_entry, &sign);
 }
 
 __isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
index 250128f..a618e9d 100644 (file)
@@ -1105,6 +1105,30 @@ int test_affine_hull(struct isl_ctx *ctx)
        return 0;
 }
 
+static int test_simple_hull(struct isl_ctx *ctx)
+{
+       const char *str;
+       isl_set *set;
+       isl_basic_set *bset;
+       isl_bool is_empty;
+
+       str = "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x;"
+               "[y, x] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }";
+       set = isl_set_read_from_str(ctx, str);
+       bset = isl_set_simple_hull(set);
+       is_empty = isl_basic_set_is_empty(bset);
+       isl_basic_set_free(bset);
+
+       if (is_empty == isl_bool_error)
+               return -1;
+
+       if (is_empty == isl_bool_false)
+               isl_die(ctx, isl_error_unknown, "Empty set should be detected",
+                       return -1);
+
+       return 0;
+}
+
 void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
 {
        char *filename;
@@ -1598,6 +1622,7 @@ struct {
                "32e0 >= -31 + i2 and 32e0 <= 30 + i2 and 32e0 <= 31 + i1 and "
                "32e0 <= 31 + i0)) or "
                "i0 >= 0 }" },
+       { 1, "{ [a, b, c] : 2b = 1 + a and 2c = 2 + a; [0, 0, 0] }" },
 };
 
 /* A specialized coalescing test case that would result
@@ -3896,6 +3921,17 @@ struct {
        { &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
          "{ B[x] -> [2] : x >= 0 }",
          "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
+       { &isl_union_pw_multi_aff_pullback_union_pw_multi_aff,
+         "{ A[] -> B[0]; C[x] -> B[1] : x < 10; C[y] -> B[2] : y >= 10 }",
+         "{ D[i] -> A[] : i < 0; D[i] -> C[i + 5] : i >= 0 }",
+         "{ D[i] -> B[0] : i < 0; D[i] -> B[1] : 0 <= i < 5; "
+           "D[i] -> B[2] : i >= 5 }" },
+       { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+         "{ B[x] -> C[2] : x > 0 }",
+         "{ B[x] -> A[1] : x <= 0; B[x] -> C[2] : x > 0 }" },
+       { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+         "{ B[x] -> A[2] : x >= 0 }",
+         "{ B[x] -> A[1] : x < 0; B[x] -> A[2] : x > 0; B[0] -> A[3] }" },
 };
 
 /* Perform some basic tests of binary operations on
@@ -3928,6 +3964,47 @@ static int test_bin_upma(isl_ctx *ctx)
        return 0;
 }
 
+struct {
+       __isl_give isl_union_pw_multi_aff *(*fn)(
+               __isl_take isl_union_pw_multi_aff *upma1,
+               __isl_take isl_union_pw_multi_aff *upma2);
+       const char *arg1;
+       const char *arg2;
+} upma_bin_fail_tests[] = {
+       { &isl_union_pw_multi_aff_union_add, "{ B[x] -> A[1] : x <= 0 }",
+         "{ B[x] -> C[2] : x >= 0 }" },
+};
+
+/* Perform some basic tests of binary operations on
+ * isl_union_pw_multi_aff objects that are expected to fail.
+ */
+static int test_bin_upma_fail(isl_ctx *ctx)
+{
+       int i, n;
+       isl_union_pw_multi_aff *upma1, *upma2;
+       int on_error;
+
+       on_error = isl_options_get_on_error(ctx);
+       isl_options_set_on_error(ctx, ISL_ON_ERROR_CONTINUE);
+       n = ARRAY_SIZE(upma_bin_fail_tests);
+       for (i = 0; i < n; ++i) {
+               upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
+                                               upma_bin_fail_tests[i].arg1);
+               upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
+                                               upma_bin_fail_tests[i].arg2);
+               upma1 = upma_bin_fail_tests[i].fn(upma1, upma2);
+               isl_union_pw_multi_aff_free(upma1);
+               if (upma1)
+                       break;
+       }
+       isl_options_set_on_error(ctx, on_error);
+       if (i < n)
+               isl_die(ctx, isl_error_unknown,
+                       "operation not expected to succeed", return -1);
+
+       return 0;
+}
+
 int test_aff(isl_ctx *ctx)
 {
        const char *str;
@@ -3941,6 +4018,8 @@ int test_aff(isl_ctx *ctx)
                return -1;
        if (test_bin_upma(ctx) < 0)
                return -1;
+       if (test_bin_upma_fail(ctx) < 0)
+               return -1;
 
        space = isl_space_set_alloc(ctx, 0, 1);
        ls = isl_local_space_from_space(space);
@@ -5986,6 +6065,7 @@ struct {
        { "parse", &test_parse },
        { "single-valued", &test_sv },
        { "affine hull", &test_affine_hull },
+       { "simple_hull", &test_simple_hull },
        { "coalesce", &test_coalesce },
        { "factorize", &test_factorize },
        { "subset", &test_subset },
index 4a3e7bb..386b8dc 100644 (file)
 
 #include <isl_union_macro.h>
 
-/* Replace *entry by its opposite.
- *
- * Return isl_stat_ok on success and isl_stat_error on error.
+/* Return the opposite of "part".
  */
-static isl_stat FN(UNION,neg_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,neg_entry)(__isl_take PART *part, void *user)
 {
-       PW **pw = (PW **) entry;
-
-       *pw = FN(PW,neg)(*pw);
-
-       return *pw ? isl_stat_ok : isl_stat_error;
+       return FN(PART,neg)(part);
 }
 
 /* Return the opposite of "u".
  */
 __isl_give UNION *FN(UNION,neg)(__isl_take UNION *u)
 {
-       u = FN(UNION,cow)(u);
-       if (!u)
-               return NULL;
-
-       if (isl_hash_table_foreach(u->space->ctx, &u->table,
-                                  &FN(UNION,neg_entry), NULL) < 0)
-               return FN(UNION,free)(u);
-
-       return u;
+       return FN(UNION,transform_inplace)(u, &FN(UNION,neg_entry), NULL);
 }
index d6f1743..463b7bd 100644 (file)
  * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
  */
 
-#include <isl_hash_private.h>
-#include <isl_union_macro.h>
-
-/* A union of expressions defined over different domain spaces.
- * "space" describes the parameters.
- * The entries of "table" are keyed on the domain space of the entry.
- */
-struct UNION {
-       int ref;
-#ifdef HAS_TYPE
-       enum isl_fold type;
-#endif
-       isl_space *space;
-
-       struct isl_hash_table   table;
-};
-
 __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u);
 
 isl_ctx *FN(UNION,get_ctx)(__isl_keep UNION *u)
@@ -120,113 +103,6 @@ __isl_give UNION *FN(UNION,copy)(__isl_keep UNION *u)
        return u;
 }
 
-/* Return the number of base expressions in "u".
- */
-int FN(FN(UNION,n),PARTS)(__isl_keep UNION *u)
-{
-       return u ? u->table.n : 0;
-}
-
-S(UNION,foreach_data)
-{
-       isl_stat (*fn)(__isl_take PART *part, void *user);
-       void *user;
-};
-
-static isl_stat FN(UNION,call_on_copy)(void **entry, void *user)
-{
-       PART *part = *entry;
-       S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
-
-       return data->fn(FN(PART,copy)(part), data->user);
-}
-
-isl_stat FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
-       isl_stat (*fn)(__isl_take PART *part, void *user), void *user)
-{
-       S(UNION,foreach_data) data = { fn, user };
-
-       if (!u)
-               return isl_stat_error;
-
-       return isl_hash_table_foreach(u->space->ctx, &u->table,
-                                     &FN(UNION,call_on_copy), &data);
-}
-
-/* Is the domain space of "entry" equal to the domain of "space"?
- */
-static int FN(UNION,has_same_domain_space)(const void *entry, const void *val)
-{
-       PART *part = (PART *)entry;
-       isl_space *space = (isl_space *) val;
-
-       if (isl_space_is_set(space))
-               return isl_space_is_set(part->dim);
-
-       return isl_space_tuple_is_equal(part->dim, isl_dim_in,
-                                       space, isl_dim_in);
-}
-
-/* Return the entry, if any, in "u" that lives in "space".
- * If "reserve" is set, then an entry is created if it does not exist yet.
- * Return NULL on error and isl_hash_table_entry_none if no entry was found.
- * Note that when "reserve" is set, the function will never return
- * isl_hash_table_entry_none.
- *
- * First look for the entry (if any) with the same domain space.
- * If it exists, then check if the range space also matches.
- */
-static struct isl_hash_table_entry *FN(UNION,find_part_entry)(
-       __isl_keep UNION *u, __isl_keep isl_space *space, int reserve)
-{
-       isl_ctx *ctx;
-       uint32_t hash;
-       struct isl_hash_table_entry *entry;
-       isl_bool equal;
-       PART *part;
-
-       if (!u || !space)
-               return NULL;
-
-       ctx = FN(UNION,get_ctx)(u);
-       hash = isl_space_get_domain_hash(space);
-       entry = isl_hash_table_find(ctx, &u->table, hash,
-                       &FN(UNION,has_same_domain_space), space, reserve);
-       if (!entry)
-               return reserve ? NULL : isl_hash_table_entry_none;
-       if (reserve && !entry->data)
-               return entry;
-       part = entry->data;
-       equal = isl_space_tuple_is_equal(part->dim, isl_dim_out,
-                                           space, isl_dim_out);
-       if (equal < 0)
-               return NULL;
-       if (equal)
-               return entry;
-       if (!reserve)
-               return isl_hash_table_entry_none;
-       isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
-               "union expression can only contain a single "
-               "expression over a given domain", return NULL);
-}
-
-/* Remove "part_entry" from the hash table of "u".
- */
-static __isl_give UNION *FN(UNION,remove_part_entry)(__isl_take UNION *u,
-       struct isl_hash_table_entry *part_entry)
-{
-       isl_ctx *ctx;
-
-       if (!u || !part_entry)
-               return FN(UNION,free)(u);
-
-       ctx = FN(UNION,get_ctx)(u);
-       isl_hash_table_remove(ctx, &u->table, part_entry);
-       FN(PART,free)(part_entry->data);
-
-       return u;
-}
-
 /* Extract the element of "u" living in "space" (ignoring parameters).
  *
  * Return the ZERO element if "u" does not contain any element
@@ -266,7 +142,8 @@ error:
 
 /* Add "part" to "u".
  * If "disjoint" is set, then "u" is not allowed to already have
- * a part that is defined on the same space as "part".
+ * a part that is defined over a domain that overlaps with the domain
+ * of "part".
  * Otherwise, compute the union sum of "part" and the part in "u"
  * defined on the same space.
  */
@@ -295,6 +172,8 @@ static __isl_give UNION *FN(UNION,add_part_generic)(__isl_take UNION *u,
        if (!u)
                goto error;
 
+       if (FN(UNION,check_disjoint_domain_other)(u, part) < 0)
+               goto error;
        entry = FN(UNION,find_part_entry)(u, part->dim, 1);
        if (!entry)
                goto error;
@@ -302,10 +181,9 @@ static __isl_give UNION *FN(UNION,add_part_generic)(__isl_take UNION *u,
        if (!entry->data)
                entry->data = part;
        else {
-               if (disjoint)
-                       isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
-                               "additional part should live on separate "
-                               "space", goto error);
+               if (disjoint &&
+                   FN(UNION,check_disjoint_domain)(entry->data, part) < 0)
+                       goto error;
                entry->data = FN(PART,union_add_)(entry->data,
                                                FN(PART,copy)(part));
                if (!entry->data)
@@ -365,19 +243,6 @@ static __isl_give UNION *FN(UNION,alloc_same_size)(__isl_keep UNION *u)
        return FN(UNION,alloc_same_size_on_space)(u, FN(UNION,get_space)(u));
 }
 
-/* Call "fn" on each part entry of "u".
- */
-static isl_stat FN(UNION,foreach_inplace)(__isl_keep UNION *u,
-       isl_stat (*fn)(void **part, void *user), void *user)
-{
-       isl_ctx *ctx;
-
-       if (!u)
-               return isl_stat_error;
-       ctx = FN(UNION,get_ctx)(u);
-       return isl_hash_table_foreach(ctx, &u->table, fn, user);
-}
-
 /* Internal data structure for isl_union_*_transform_space.
  * "fn' is applied to each entry in the input.
  * "res" collects the results.
@@ -430,6 +295,43 @@ static __isl_give UNION *FN(UNION,transform)(__isl_take UNION *u,
        return FN(UNION,transform_space)(u, FN(UNION,get_space)(u), fn, user);
 }
 
+/* Apply data->fn to *part and store the result back into *part.
+ */
+static isl_stat FN(UNION,transform_inplace_entry)(void **part, void *user)
+{
+       S(UNION,transform_data) *data = (S(UNION,transform_data) *) user;
+
+       *part = data->fn(*part, data->user);
+       if (!*part)
+               return isl_stat_error;
+       return isl_stat_ok;
+}
+
+/* Update "u" by applying "fn" to each entry.
+ * This operation is assumed not to change the number of entries nor
+ * the spaces of the entries.
+ *
+ * If there is only one reference to "u", then change "u" inplace.
+ * Otherwise, create a new UNION from "u" and discard the original.
+ */
+static __isl_give UNION *FN(UNION,transform_inplace)(__isl_take UNION *u,
+       __isl_give PART *(*fn)(__isl_take PART *part, void *user), void *user)
+{
+       isl_bool single_ref;
+
+       single_ref = FN(UNION,has_single_reference)(u);
+       if (single_ref < 0)
+               return FN(UNION,free)(u);
+       if (single_ref) {
+               S(UNION,transform_data) data = { fn, user };
+               if (FN(UNION,foreach_inplace)(u,
+                               &FN(UNION,transform_inplace_entry), &data) < 0)
+                       return FN(UNION,free)(u);
+               return u;
+       }
+       return FN(UNION,transform)(u, fn, user);
+}
+
 /* An isl_union_*_transform callback for use in isl_union_*_dup
  * that simply returns "part".
  */
@@ -455,13 +357,6 @@ __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u)
        return FN(UNION,dup)(u);
 }
 
-static isl_stat FN(UNION,free_u_entry)(void **entry, void *user)
-{
-       PART *part = *entry;
-       FN(PART,free)(part);
-       return isl_stat_ok;
-}
-
 __isl_null UNION *FN(UNION,free)(__isl_take UNION *u)
 {
        if (!u)
@@ -605,34 +500,34 @@ S(UNION,match_bin_data) {
        __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *);
 };
 
-/* Check if data->u2 has an element living in the same space as *entry.
+/* Check if data->u2 has an element living in the same space as "part".
  * If so, call data->fn on the two elements and add the result to
  * data->res.
  */
-static isl_stat FN(UNION,match_bin_entry)(void **entry, void *user)
+static isl_stat FN(UNION,match_bin_entry)(__isl_take PART *part, void *user)
 {
        S(UNION,match_bin_data) *data = user;
        struct isl_hash_table_entry *entry2;
        isl_space *space;
-       PART *part = *entry;
        PART *part2;
 
        space = FN(PART,get_space)(part);
        entry2 = FN(UNION,find_part_entry)(data->u2, space, 0);
        isl_space_free(space);
        if (!entry2)
-               return isl_stat_error;
-       if (entry2 == isl_hash_table_entry_none)
+               goto error;
+       if (entry2 == isl_hash_table_entry_none) {
+               FN(PART,free)(part);
                return isl_stat_ok;
+       }
 
        part2 = entry2->data;
        if (!isl_space_tuple_is_equal(part->dim, isl_dim_out,
                                        part2->dim, isl_dim_out))
                isl_die(FN(UNION,get_ctx)(data->u2), isl_error_invalid,
                        "entries should have the same range space",
-                       return isl_stat_error);
+                       goto error);
 
-       part = FN(PART, copy)(part);
        part = data->fn(part, FN(PART, copy)(entry2->data));
 
        data->res = FN(FN(UNION,add),PARTS)(data->res, part);
@@ -640,6 +535,9 @@ static isl_stat FN(UNION,match_bin_entry)(void **entry, void *user)
                return isl_stat_error;
 
        return isl_stat_ok;
+error:
+       FN(PART,free)(part);
+       return isl_stat_error;
 }
 
 /* This function is currently only used from isl_polynomial.c
@@ -666,7 +564,7 @@ static __isl_give UNION *FN(UNION,match_bin_op)(__isl_take UNION *u1,
 
        data.u2 = u2;
        data.res = FN(UNION,alloc_same_size)(u1);
-       if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
+       if (FN(FN(UNION,foreach),PARTS)(u1,
                                    &FN(UNION,match_bin_entry), &data) < 0)
                goto error;
 
@@ -773,29 +671,29 @@ static int FN(UNION,set_has_dim)(const void *entry, const void *val)
 }
 
 /* Find the set in data->uset that lives in the same space as the domain
- * of *entry, apply data->fn to *entry and this set (if any), and add
+ * of "part", apply data->fn to *entry and this set (if any), and add
  * the result to data->res.
  */
-static isl_stat FN(UNION,match_domain_entry)(void **entry, void *user)
+static isl_stat FN(UNION,match_domain_entry)(__isl_take PART *part, void *user)
 {
        S(UNION,match_domain_data) *data = user;
        uint32_t hash;
        struct isl_hash_table_entry *entry2;
-       PW *pw = *entry;
        isl_space *space;
 
-       space = FN(PW,get_domain_space)(pw);
+       space = FN(PART,get_domain_space)(part);
        hash = isl_space_get_hash(space);
        entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
                                     hash, &FN(UNION,set_has_dim), space, 0);
        isl_space_free(space);
-       if (!entry2)
+       if (!entry2) {
+               FN(PART,free)(part);
                return isl_stat_ok;
+       }
 
-       pw = FN(PW,copy)(pw);
-       pw = data->fn(pw, isl_set_copy(entry2->data));
+       part = data->fn(part, isl_set_copy(entry2->data));
 
-       data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
+       data->res = FN(FN(UNION,add),PARTS)(data->res, part);
        if (!data->res)
                return isl_stat_error;
 
@@ -820,7 +718,7 @@ static __isl_give UNION *FN(UNION,match_domain_op)(__isl_take UNION *u,
 
        data.uset = uset;
        data.res = FN(UNION,alloc_same_size)(u);
-       if (isl_hash_table_foreach(u->space->ctx, &u->table,
+       if (FN(FN(UNION,foreach),PARTS)(u,
                                   &FN(UNION,match_domain_entry), &data) < 0)
                goto error;
 
@@ -958,16 +856,12 @@ static __isl_give UNION *FN(UNION,negate_type)(__isl_take UNION *u)
 }
 #endif
 
-static isl_stat FN(UNION,mul_isl_int_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,mul_isl_int_entry)(__isl_take PART *part,
+       void *user)
 {
-       PW **pw = (PW **)entry;
        isl_int *v = user;
 
-       *pw = FN(PW,mul_isl_int)(*pw, *v);
-       if (!*pw)
-               return isl_stat_error;
-
-       return isl_stat_ok;
+       return FN(PW,mul_isl_int)(part, *v);
 }
 
 __isl_give UNION *FN(UNION,mul_isl_int)(__isl_take UNION *u, isl_int v)
@@ -987,36 +881,21 @@ __isl_give UNION *FN(UNION,mul_isl_int)(__isl_take UNION *u, isl_int v)
                return zero;
        }
 
-       u = FN(UNION,cow)(u);
+       u = FN(UNION,transform_inplace)(u, &FN(UNION,mul_isl_int_entry), &v);
        if (isl_int_is_neg(v))
                u = FN(UNION,negate_type)(u);
-       if (!u)
-               return NULL;
-
-       if (isl_hash_table_foreach(u->space->ctx, &u->table,
-                                   &FN(UNION,mul_isl_int_entry), &v) < 0)
-               goto error;
 
        return u;
-error:
-       FN(UNION,free)(u);
-       return NULL;
 }
 
-/* Multiply *entry by the isl_val "user".
- *
- * Return 0 on success and -1 on error.
+/* Multiply "part" by the isl_val "user" and return the result.
  */
-static isl_stat FN(UNION,scale_val_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,scale_val_entry)(__isl_take PART *part,
+       void *user)
 {
-       PW **pw = (PW **)entry;
        isl_val *v = user;
 
-       *pw = FN(PW,scale_val)(*pw, isl_val_copy(v));
-       if (!*pw)
-               return isl_stat_error;
-
-       return isl_stat_ok;
+       return FN(PART,scale_val)(part, isl_val_copy(v));
 }
 
 /* Multiply "u" by "v" and return the result.
@@ -1048,15 +927,9 @@ __isl_give UNION *FN(UNION,scale_val)(__isl_take UNION *u,
                isl_die(isl_val_get_ctx(v), isl_error_invalid,
                        "expecting rational factor", goto error);
 
-       u = FN(UNION,cow)(u);
+       u = FN(UNION,transform_inplace)(u, &FN(UNION,scale_val_entry), v);
        if (isl_val_is_neg(v))
                u = FN(UNION,negate_type)(u);
-       if (!u)
-               return NULL;
-
-       if (isl_hash_table_foreach(u->space->ctx, &u->table,
-                                   &FN(UNION,scale_val_entry), v) < 0)
-               goto error;
 
        isl_val_free(v);
        return u;
@@ -1066,20 +939,14 @@ error:
        return NULL;
 }
 
-/* Divide *entry by the isl_val "user".
- *
- * Return 0 on success and -1 on error.
+/* Divide "part" by the isl_val "user" and return the result.
  */
-static isl_stat FN(UNION,scale_down_val_entry)(void **entry, void *user)
+static __isl_give PART *FN(UNION,scale_down_val_entry)(__isl_take PART *part,
+       void *user)
 {
-       PW **pw = (PW **)entry;
        isl_val *v = user;
 
-       *pw = FN(PW,scale_down_val)(*pw, isl_val_copy(v));
-       if (!*pw)
-               return isl_stat_error;
-
-       return isl_stat_ok;
+       return FN(PART,scale_down_val)(part, isl_val_copy(v));
 }
 
 /* Divide "u" by "v" and return the result.
@@ -1101,15 +968,9 @@ __isl_give UNION *FN(UNION,scale_down_val)(__isl_take UNION *u,
                isl_die(isl_val_get_ctx(v), isl_error_invalid,
                        "cannot scale down by zero", goto error);
 
-       u = FN(UNION,cow)(u);
+       u = FN(UNION,transform_inplace)(u, &FN(UNION,scale_down_val_entry), v);
        if (isl_val_is_neg(v))
                u = FN(UNION,negate_type)(u);
-       if (!u)
-               return NULL;
-
-       if (isl_hash_table_foreach(FN(UNION,get_ctx)(u), &u->table,
-                                   &FN(UNION,scale_down_val_entry), v) < 0)
-               goto error;
 
        isl_val_free(v);
        return u;
@@ -1150,6 +1011,7 @@ static isl_stat FN(UNION,plain_is_equal_entry)(void **entry, void *user)
 isl_bool FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
 {
        S(UNION,plain_is_equal_data) data = { NULL, isl_bool_true };
+       int n1, n2;
 
        if (!u1 || !u2)
                return isl_bool_error;
@@ -1157,6 +1019,12 @@ isl_bool FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
                return isl_bool_true;
        if (u1->table.n != u2->table.n)
                return isl_bool_false;
+       n1 = FN(FN(UNION,n),PARTS)(u1);
+       n2 = FN(FN(UNION,n),PARTS)(u2);
+       if (n1 < 0 || n2 < 0)
+               return isl_bool_error;
+       if (n1 != n2)
+               return isl_bool_false;
 
        u1 = FN(UNION,copy)(u1);
        u2 = FN(UNION,copy)(u2);
index bffda54..c29db36 100644 (file)
@@ -70,7 +70,7 @@
 #         compiler:            $LTCC
 #         compiler flags:              $LTCFLAGS
 #         linker:              $LD (gnu? $with_gnu_ld)
-#         $progname:   (GNU libtool) 2.4.2 Debian-2.4.2-1.11
+#         $progname:   (GNU libtool) 2.4.2 Debian-2.4.2-1.10ubuntu1
 #         automake:    $automake_version
 #         autoconf:    $autoconf_version
 #
@@ -80,7 +80,7 @@
 
 PROGRAM=libtool
 PACKAGE=libtool
-VERSION="2.4.2 Debian-2.4.2-1.11"
+VERSION="2.4.2 Debian-2.4.2-1.10ubuntu1"
 TIMESTAMP=""
 package_revision=1.3337
 
index 934aa82..ab54229 100644 (file)
@@ -85,7 +85,7 @@
         for (int c2 = max(c1 + 24, -2 * c1 + 30); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
           S1(c0, c1, c2);
       }
-    if (c0 >= 79 && c0 % 14 >= 9) {
+    if (c0 >= 70 && c0 % 14 >= 9) {
       for (int c2 = max(c0 / 14 + 19, -((3 * c0 + 14) / 14) + c0 / 14 + 44); c2 <= -((3 * c0 + 17) / 14) + c0 / 14 + 51; c2 += 1)
         S1(c0, c0 / 14 - 5, c2);
     } else if (c0 <= 69 && c0 % 14 >= 9) {
index 8166821..0fba4f1 100644 (file)
@@ -2,7 +2,7 @@ if ((length - 1) % 16 <= 14)
   for (int c0 = 0; c0 <= 1; c0 += 1)
     for (int c5 = 0; c5 <= 31; c5 += 1)
       for (int c6 = max(0, 2 * ((length - 1) % 16) + 2 * c5 - 60); c6 <= 30; c6 += 1) {
-        if (length + c5 >= ((length - 1) % 32) + 2 && (length - 1) % 32 >= c5 && 2 * ((length - 1) % 32) + c6 >= 2 * c5 && 2 * c5 + 30 >= 2 * ((length - 1) % 32) + c6 && 2 * ((length - 1) % 32) + c6 == 2 * ((length - 1) % 16) + 2 * c5 && (2 * c5 - c6) % 32 == 0)
+        if (2 * length + c6 >= 2 * ((length - 1) % 16) + 4 && 2 * ((length - 1) % 16) >= c6 && 2 * ((length - 1) % 16) + 2 * c5 >= c6 && c6 + 62 >= 2 * ((length - 1) % 16) + 2 * c5 && 2 * ((length - 1) % 16) + 2 * c5 == 2 * ((length - 1) % 32) + c6 && (2 * c5 - c6) % 32 == 0)
           S_3(c0, 0, (c6 / 2) - ((length - 1) % 16) + length - 1);
         if (length <= 16 && length >= c5 + 1 && c6 >= 1 && length >= c6)
           S_0(c0, c5, c6 - 1);