isl_set_dim_residue_class: correctly consider all basic sets in the set
authorSven Verdoolaege <skimo@kotnet.org>
Tue, 21 Aug 2012 09:37:57 +0000 (11:37 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Sun, 2 Sep 2012 08:55:07 +0000 (10:55 +0200)
This commit fixes two closely related problems.
Due to a typo, isl_set_dim_residue_class would only consider one of
the basic sets in the input set.  The information obtained from the
individual basic sets was also combined incorrectly.
In particular, the code would insist that all basic sets have the
same residue if they have the same modulo and not consider adjusting
the modulo of the combined basic sets to accommodate for the difference
in residues.

Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
isl_equalities.c
isl_test.c

index 68d2c89..78078d4 100644 (file)
@@ -670,20 +670,15 @@ int isl_set_dim_residue_class(struct isl_set *set,
        isl_int_init(r);
 
        for (i = 1; i < set->n; ++i) {
-               if (isl_basic_set_dim_residue_class(set->p[0], pos, &m, &r) < 0)
+               if (isl_basic_set_dim_residue_class(set->p[i], pos, &m, &r) < 0)
                        goto error;
                isl_int_gcd(*modulo, *modulo, m);
+               isl_int_sub(m, *residue, r);
+               isl_int_gcd(*modulo, *modulo, m);
                if (!isl_int_is_zero(*modulo))
                        isl_int_fdiv_r(*residue, *residue, *modulo);
                if (isl_int_is_one(*modulo))
                        break;
-               if (!isl_int_is_zero(*modulo))
-                       isl_int_fdiv_r(r, r, *modulo);
-               if (isl_int_ne(*residue, r)) {
-                       isl_int_set_si(*modulo, 1);
-                       isl_int_set_si(*residue, 0);
-                       break;
-               }
        }
 
        isl_int_clear(m);
index 05c8364..5c267f2 100644 (file)
@@ -2980,6 +2980,34 @@ int test_eliminate(isl_ctx *ctx)
        return 0;
 }
 
+/* Check that isl_set_dim_residue_class detects that the values of j
+ * in the set below are all odd and that it does not detect any spurious
+ * strides.
+ */
+static int test_residue_class(isl_ctx *ctx)
+{
+       const char *str;
+       isl_set *set;
+       isl_int m, r;
+       int res;
+
+       str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
+               "[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
+       set = isl_set_read_from_str(ctx, str);
+       isl_int_init(m);
+       isl_int_init(r);
+       res = isl_set_dim_residue_class(set, 1, &m, &r);
+       if (res >= 0 &&
+           (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
+               isl_die(ctx, isl_error_unknown, "incorrect residue class",
+                       res = -1);
+       isl_int_clear(r);
+       isl_int_clear(m);
+       isl_set_free(set);
+
+       return res;
+}
+
 int test_align_parameters(isl_ctx *ctx)
 {
        const char *str;
@@ -3017,6 +3045,7 @@ struct {
 } tests [] = {
        { "align parameters", &test_align_parameters },
        { "eliminate", &test_eliminate },
+       { "reisdue class", &test_residue_class },
        { "div", &test_div },
        { "slice", &test_slice },
        { "fixed power", &test_fixed_power },