~ubuntu-branches/ubuntu/vivid/cloog/vivid

« back to all changes in this revision

Viewing changes to isl/isl_affine_hull.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-10-17 15:54:24 UTC
  • mfrom: (3.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20131017155424-3q1gw7yhddylfkpj
Tags: 0.18.1-1
* New upstream version.
* Add a comment to build-depend on libpod-latex-perl | perl (<< 5.17.0),
  when the documentation is built. Closes: #711681.
* Use dh_autotools-dev to update config.{sub,guess}. Closes: #719957.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright 2008-2009 Katholieke Universiteit Leuven
 
3
 * Copyright 2010      INRIA Saclay
 
4
 * Copyright 2012      Ecole Normale Superieure
3
5
 *
4
6
 * Use of this software is governed by the MIT license
5
7
 *
6
8
 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7
9
 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
 
10
 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
 
11
 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
 
12
 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
8
13
 */
9
14
 
10
15
#include <isl_ctx_private.h>
1126
1131
                isl_basic_map_detect_equalities((isl_basic_map *)bset);
1127
1132
}
1128
1133
 
1129
 
__isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
1130
 
        __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
1131
 
{
1132
 
        struct isl_basic_map *bmap;
1133
 
        int i;
1134
 
 
1135
 
        if (!map)
1136
 
                return NULL;
1137
 
 
1138
 
        for (i = 0; i < map->n; ++i) {
1139
 
                bmap = isl_basic_map_copy(map->p[i]);
1140
 
                bmap = fn(bmap);
1141
 
                if (!bmap)
1142
 
                        goto error;
1143
 
                isl_basic_map_free(map->p[i]);
1144
 
                map->p[i] = bmap;
1145
 
        }
1146
 
 
1147
 
        return map;
1148
 
error:
1149
 
        isl_map_free(map);
1150
 
        return NULL;
1151
 
}
1152
 
 
1153
1134
__isl_give isl_map *isl_map_detect_equalities(__isl_take isl_map *map)
1154
1135
{
1155
1136
        return isl_map_inline_foreach_basic_map(map,
1181
1162
                isl_basic_map_affine_hull((struct isl_basic_map *)bset);
1182
1163
}
1183
1164
 
1184
 
struct isl_basic_map *isl_map_affine_hull(struct isl_map *map)
 
1165
/* Given a rational affine matrix "M", add stride constraints to "bmap"
 
1166
 * that ensure that
 
1167
 *
 
1168
 *              M(x)
 
1169
 *
 
1170
 * is an integer vector.  The variables x include all the variables
 
1171
 * of "bmap" except the unknown divs.
 
1172
 *
 
1173
 * If d is the common denominator of M, then we need to impose that
 
1174
 *
 
1175
 *              d M(x) = 0      mod d
 
1176
 *
 
1177
 * or
 
1178
 *
 
1179
 *              exists alpha : d M(x) = d alpha
 
1180
 *
 
1181
 * This function is similar to add_strides in isl_morph.c
 
1182
 */
 
1183
static __isl_give isl_basic_map *add_strides(__isl_take isl_basic_map *bmap,
 
1184
        __isl_keep isl_mat *M, int n_known)
 
1185
{
 
1186
        int i, div, k;
 
1187
        isl_int gcd;
 
1188
 
 
1189
        if (isl_int_is_one(M->row[0][0]))
 
1190
                return bmap;
 
1191
 
 
1192
        bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
 
1193
                                        M->n_row - 1, M->n_row - 1, 0);
 
1194
 
 
1195
        isl_int_init(gcd);
 
1196
        for (i = 1; i < M->n_row; ++i) {
 
1197
                isl_seq_gcd(M->row[i], M->n_col, &gcd);
 
1198
                if (isl_int_is_divisible_by(gcd, M->row[0][0]))
 
1199
                        continue;
 
1200
                div = isl_basic_map_alloc_div(bmap);
 
1201
                if (div < 0)
 
1202
                        goto error;
 
1203
                isl_int_set_si(bmap->div[div][0], 0);
 
1204
                k = isl_basic_map_alloc_equality(bmap);
 
1205
                if (k < 0)
 
1206
                        goto error;
 
1207
                isl_seq_cpy(bmap->eq[k], M->row[i], M->n_col);
 
1208
                isl_seq_clr(bmap->eq[k] + M->n_col, bmap->n_div - n_known);
 
1209
                isl_int_set(bmap->eq[k][M->n_col - n_known + div],
 
1210
                            M->row[0][0]);
 
1211
        }
 
1212
        isl_int_clear(gcd);
 
1213
 
 
1214
        return bmap;
 
1215
error:
 
1216
        isl_int_clear(gcd);
 
1217
        isl_basic_map_free(bmap);
 
1218
        return NULL;
 
1219
}
 
1220
 
 
1221
/* If there are any equalities that involve (multiple) unknown divs,
 
1222
 * then extract the stride information encoded by those equalities
 
1223
 * and make it explicitly available in "bmap".
 
1224
 *
 
1225
 * We first sort the divs so that the unknown divs appear last and
 
1226
 * then we count how many equalities involve these divs.
 
1227
 *
 
1228
 * Let these equalities be of the form
 
1229
 *
 
1230
 *              A(x) + B y = 0
 
1231
 *
 
1232
 * where y represents the unknown divs and x the remaining variables.
 
1233
 * Let [H 0] be the Hermite Normal Form of B, i.e.,
 
1234
 *
 
1235
 *              B = [H 0] Q
 
1236
 *
 
1237
 * Then x is a solution of the equalities iff
 
1238
 *
 
1239
 *              H^-1 A(x) (= - [I 0] Q y)
 
1240
 *
 
1241
 * is an integer vector.  Let d be the common denominator of H^-1.
 
1242
 * We impose
 
1243
 *
 
1244
 *              d H^-1 A(x) = d alpha
 
1245
 *
 
1246
 * in add_strides, with alpha fresh existentially quantified variables.
 
1247
 */
 
1248
static __isl_give isl_basic_map *isl_basic_map_make_strides_explicit(
 
1249
        __isl_take isl_basic_map *bmap)
 
1250
{
 
1251
        int known;
 
1252
        int n_known;
 
1253
        int n, n_col;
 
1254
        int total;
 
1255
        isl_ctx *ctx;
 
1256
        isl_mat *A, *B, *M;
 
1257
 
 
1258
        known = isl_basic_map_divs_known(bmap);
 
1259
        if (known < 0)
 
1260
                return isl_basic_map_free(bmap);
 
1261
        if (known)
 
1262
                return bmap;
 
1263
        bmap = isl_basic_map_sort_divs(bmap);
 
1264
        bmap = isl_basic_map_gauss(bmap, NULL);
 
1265
        if (!bmap)
 
1266
                return NULL;
 
1267
 
 
1268
        for (n_known = 0; n_known < bmap->n_div; ++n_known)
 
1269
                if (isl_int_is_zero(bmap->div[n_known][0]))
 
1270
                        break;
 
1271
        ctx = isl_basic_map_get_ctx(bmap);
 
1272
        total = isl_space_dim(bmap->dim, isl_dim_all);
 
1273
        for (n = 0; n < bmap->n_eq; ++n)
 
1274
                if (isl_seq_first_non_zero(bmap->eq[n] + 1 + total + n_known,
 
1275
                                            bmap->n_div - n_known) == -1)
 
1276
                        break;
 
1277
        if (n == 0)
 
1278
                return bmap;
 
1279
        B = isl_mat_sub_alloc6(ctx, bmap->eq, 0, n, 0, 1 + total + n_known);
 
1280
        n_col = bmap->n_div - n_known;
 
1281
        A = isl_mat_sub_alloc6(ctx, bmap->eq, 0, n, 1 + total + n_known, n_col);
 
1282
        A = isl_mat_left_hermite(A, 0, NULL, NULL);
 
1283
        A = isl_mat_drop_cols(A, n, n_col - n);
 
1284
        A = isl_mat_lin_to_aff(A);
 
1285
        A = isl_mat_right_inverse(A);
 
1286
        B = isl_mat_insert_zero_rows(B, 0, 1);
 
1287
        B = isl_mat_set_element_si(B, 0, 0, 1);
 
1288
        M = isl_mat_product(A, B);
 
1289
        if (!M)
 
1290
                return isl_basic_map_free(bmap);
 
1291
        bmap = add_strides(bmap, M, n_known);
 
1292
        bmap = isl_basic_map_gauss(bmap, NULL);
 
1293
        isl_mat_free(M);
 
1294
 
 
1295
        return bmap;
 
1296
}
 
1297
 
 
1298
/* Compute the affine hull of each basic map in "map" separately
 
1299
 * and make all stride information explicit so that we can remove
 
1300
 * all unknown divs without losing this information.
 
1301
 * The result is also guaranteed to be gaussed.
 
1302
 *
 
1303
 * In simple cases where a div is determined by an equality,
 
1304
 * calling isl_basic_map_gauss is enough to make the stride information
 
1305
 * explicit, as it will derive an explicit representation for the div
 
1306
 * from the equality.  If, however, the stride information
 
1307
 * is encoded through multiple unknown divs then we need to make
 
1308
 * some extra effort in isl_basic_map_make_strides_explicit.
 
1309
 */
 
1310
static __isl_give isl_map *isl_map_local_affine_hull(__isl_take isl_map *map)
1185
1311
{
1186
1312
        int i;
 
1313
 
 
1314
        map = isl_map_cow(map);
 
1315
        if (!map)
 
1316
                return NULL;
 
1317
 
 
1318
        for (i = 0; i < map->n; ++i) {
 
1319
                map->p[i] = isl_basic_map_affine_hull(map->p[i]);
 
1320
                map->p[i] = isl_basic_map_gauss(map->p[i], NULL);
 
1321
                map->p[i] = isl_basic_map_make_strides_explicit(map->p[i]);
 
1322
                if (!map->p[i])
 
1323
                        return isl_map_free(map);
 
1324
        }
 
1325
 
 
1326
        return map;
 
1327
}
 
1328
 
 
1329
static __isl_give isl_set *isl_set_local_affine_hull(__isl_take isl_set *set)
 
1330
{
 
1331
        return isl_map_local_affine_hull(set);
 
1332
}
 
1333
 
 
1334
/* Compute the affine hull of "map".
 
1335
 *
 
1336
 * We first compute the affine hull of each basic map separately.
 
1337
 * Then we align the divs and recompute the affine hulls of the basic
 
1338
 * maps since some of them may now have extra divs.
 
1339
 * In order to avoid performing parametric integer programming to
 
1340
 * compute explicit expressions for the divs, possible leading to
 
1341
 * an explosion in the number of basic maps, we first drop all unknown
 
1342
 * divs before aligning the divs.  Note that isl_map_local_affine_hull tries
 
1343
 * to make sure that all stride information is explicitly available
 
1344
 * in terms of known divs.  This involves calling isl_basic_set_gauss,
 
1345
 * which is also needed because affine_hull assumes its input has been gaussed,
 
1346
 * while isl_map_affine_hull may be called on input that has not been gaussed,
 
1347
 * in particular from initial_facet_constraint.
 
1348
 * Similarly, align_divs may reorder some divs so that we need to
 
1349
 * gauss the result again.
 
1350
 * Finally, we combine the individual affine hulls into a single
 
1351
 * affine hull.
 
1352
 */
 
1353
__isl_give isl_basic_map *isl_map_affine_hull(__isl_take isl_map *map)
 
1354
{
1187
1355
        struct isl_basic_map *model = NULL;
1188
1356
        struct isl_basic_map *hull = NULL;
1189
1357
        struct isl_set *set;
 
1358
        isl_basic_set *bset;
1190
1359
 
1191
1360
        map = isl_map_detect_equalities(map);
 
1361
        map = isl_map_local_affine_hull(map);
 
1362
        map = isl_map_remove_empty_parts(map);
 
1363
        map = isl_map_remove_unknown_divs(map);
1192
1364
        map = isl_map_align_divs(map);
1193
1365
 
1194
1366
        if (!map)
1203
1375
        model = isl_basic_map_copy(map->p[0]);
1204
1376
        set = isl_map_underlying_set(map);
1205
1377
        set = isl_set_cow(set);
 
1378
        set = isl_set_local_affine_hull(set);
1206
1379
        if (!set)
1207
1380
                goto error;
1208
1381
 
1209
 
        for (i = 0; i < set->n; ++i) {
1210
 
                set->p[i] = isl_basic_set_cow(set->p[i]);
1211
 
                set->p[i] = isl_basic_set_affine_hull(set->p[i]);
1212
 
                set->p[i] = isl_basic_set_gauss(set->p[i], NULL);
1213
 
                if (!set->p[i])
1214
 
                        goto error;
1215
 
        }
1216
 
        set = isl_set_remove_empty_parts(set);
1217
 
        if (set->n == 0) {
1218
 
                hull = isl_basic_map_empty_like(model);
1219
 
                isl_basic_map_free(model);
1220
 
        } else {
1221
 
                struct isl_basic_set *bset;
1222
 
                while (set->n > 1) {
1223
 
                        set->p[0] = affine_hull(set->p[0], set->p[--set->n]);
1224
 
                        if (!set->p[0])
1225
 
                                goto error;
1226
 
                }
1227
 
                bset = isl_basic_set_copy(set->p[0]);
1228
 
                hull = isl_basic_map_overlying_set(bset, model);
1229
 
        }
 
1382
        while (set->n > 1)
 
1383
                set->p[0] = affine_hull(set->p[0], set->p[--set->n]);
 
1384
 
 
1385
        bset = isl_basic_set_copy(set->p[0]);
 
1386
        hull = isl_basic_map_overlying_set(bset, model);
1230
1387
        isl_set_free(set);
1231
1388
        hull = isl_basic_map_simplify(hull);
1232
1389
        return isl_basic_map_finalize(hull);