00001 #include "isl_lp.h"
00002 #include "isl_map.h"
00003 #include "isl_map_private.h"
00004 #include "isl_mat.h"
00005 #include "isl_set.h"
00006 #include "isl_seq.h"
00007 #include "isl_equalities.h"
00008 #include "isl_tab.h"
00009
00010 static struct isl_basic_set *uset_convex_hull_wrap_bounded(struct isl_set *set);
00011
00012 static void swap_ineq(struct isl_basic_map *bmap, unsigned i, unsigned j)
00013 {
00014 isl_int *t;
00015
00016 if (i != j) {
00017 t = bmap->ineq[i];
00018 bmap->ineq[i] = bmap->ineq[j];
00019 bmap->ineq[j] = t;
00020 }
00021 }
00022
00023
00024
00025
00026
00027
00028 int isl_basic_map_constraint_is_redundant(struct isl_basic_map **bmap,
00029 isl_int *c, isl_int *opt_n, isl_int *opt_d)
00030 {
00031 enum isl_lp_result res;
00032 unsigned total;
00033 int i, j;
00034
00035 if (!bmap)
00036 return -1;
00037
00038 total = isl_basic_map_total_dim(*bmap);
00039 for (i = 0; i < total; ++i) {
00040 int sign;
00041 if (isl_int_is_zero(c[1+i]))
00042 continue;
00043 sign = isl_int_sgn(c[1+i]);
00044 for (j = 0; j < (*bmap)->n_ineq; ++j)
00045 if (sign == isl_int_sgn((*bmap)->ineq[j][1+i]))
00046 break;
00047 if (j == (*bmap)->n_ineq)
00048 break;
00049 }
00050 if (i < total)
00051 return 0;
00052
00053 res = isl_solve_lp(*bmap, 0, c, (*bmap)->ctx->one, opt_n, opt_d);
00054 if (res == isl_lp_unbounded)
00055 return 0;
00056 if (res == isl_lp_error)
00057 return -1;
00058 if (res == isl_lp_empty) {
00059 *bmap = isl_basic_map_set_to_empty(*bmap);
00060 return 0;
00061 }
00062 return !isl_int_is_neg(*opt_n);
00063 }
00064
00065 int isl_basic_set_constraint_is_redundant(struct isl_basic_set **bset,
00066 isl_int *c, isl_int *opt_n, isl_int *opt_d)
00067 {
00068 return isl_basic_map_constraint_is_redundant(
00069 (struct isl_basic_map **)bset, c, opt_n, opt_d);
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 struct isl_basic_map *isl_basic_map_convex_hull(struct isl_basic_map *bmap)
00081 {
00082 struct isl_tab *tab;
00083
00084 if (!bmap)
00085 return NULL;
00086
00087 bmap = isl_basic_map_gauss(bmap, NULL);
00088 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
00089 return bmap;
00090 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NO_REDUNDANT))
00091 return bmap;
00092 if (bmap->n_ineq <= 1)
00093 return bmap;
00094
00095 tab = isl_tab_from_basic_map(bmap);
00096 tab = isl_tab_detect_equalities(bmap->ctx, tab);
00097 tab = isl_tab_detect_redundant(bmap->ctx, tab);
00098 bmap = isl_basic_map_update_from_tab(bmap, tab);
00099 isl_tab_free(bmap->ctx, tab);
00100 ISL_F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
00101 ISL_F_SET(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
00102 return bmap;
00103 }
00104
00105 struct isl_basic_set *isl_basic_set_convex_hull(struct isl_basic_set *bset)
00106 {
00107 return (struct isl_basic_set *)
00108 isl_basic_map_convex_hull((struct isl_basic_map *)bset);
00109 }
00110
00111
00112
00113
00114
00115 static int uset_is_bound(struct isl_ctx *ctx, struct isl_set *set,
00116 isl_int *c, unsigned len)
00117 {
00118 int first;
00119 int j;
00120 isl_int opt;
00121 isl_int opt_denom;
00122
00123 isl_int_init(opt);
00124 isl_int_init(opt_denom);
00125 first = 1;
00126 for (j = 0; j < set->n; ++j) {
00127 enum isl_lp_result res;
00128
00129 if (ISL_F_ISSET(set->p[j], ISL_BASIC_SET_EMPTY))
00130 continue;
00131
00132 res = isl_solve_lp((struct isl_basic_map*)set->p[j],
00133 0, c, ctx->one, &opt, &opt_denom);
00134 if (res == isl_lp_unbounded)
00135 break;
00136 if (res == isl_lp_error)
00137 goto error;
00138 if (res == isl_lp_empty) {
00139 set->p[j] = isl_basic_set_set_to_empty(set->p[j]);
00140 if (!set->p[j])
00141 goto error;
00142 continue;
00143 }
00144 if (!isl_int_is_one(opt_denom))
00145 isl_seq_scale(c, c, opt_denom, len);
00146 if (first || isl_int_is_neg(opt))
00147 isl_int_sub(c[0], c[0], opt);
00148 first = 0;
00149 }
00150 isl_int_clear(opt);
00151 isl_int_clear(opt_denom);
00152 return j >= set->n;
00153 error:
00154 isl_int_clear(opt);
00155 isl_int_clear(opt_denom);
00156 return -1;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166 static int is_independent_bound(struct isl_ctx *ctx,
00167 struct isl_set *set, isl_int *c,
00168 struct isl_mat *dirs, int n)
00169 {
00170 int is_bound;
00171 int i = 0;
00172
00173 isl_seq_cpy(dirs->row[n]+1, c+1, dirs->n_col-1);
00174 if (n != 0) {
00175 int pos = isl_seq_first_non_zero(dirs->row[n]+1, dirs->n_col-1);
00176 if (pos < 0)
00177 return 0;
00178 for (i = 0; i < n; ++i) {
00179 int pos_i;
00180 pos_i = isl_seq_first_non_zero(dirs->row[i]+1, dirs->n_col-1);
00181 if (pos_i < pos)
00182 continue;
00183 if (pos_i > pos)
00184 break;
00185 isl_seq_elim(dirs->row[n]+1, dirs->row[i]+1, pos,
00186 dirs->n_col-1, NULL);
00187 pos = isl_seq_first_non_zero(dirs->row[n]+1, dirs->n_col-1);
00188 if (pos < 0)
00189 return 0;
00190 }
00191 }
00192
00193 is_bound = uset_is_bound(ctx, set, dirs->row[n], dirs->n_col);
00194 if (is_bound != 1)
00195 return is_bound;
00196 if (i < n) {
00197 int k;
00198 isl_int *t = dirs->row[n];
00199 for (k = n; k > i; --k)
00200 dirs->row[k] = dirs->row[k-1];
00201 dirs->row[i] = t;
00202 }
00203 return 1;
00204 }
00205
00206
00207
00208
00209
00210 static struct isl_mat *independent_bounds(struct isl_ctx *ctx,
00211 struct isl_set *set)
00212 {
00213 int i, j, n;
00214 struct isl_mat *dirs = NULL;
00215 unsigned dim = isl_set_n_dim(set);
00216
00217 dirs = isl_mat_alloc(ctx, dim, 1+dim);
00218 if (!dirs)
00219 goto error;
00220
00221 n = 0;
00222 for (i = 0; n < dim && i < set->n; ++i) {
00223 int f;
00224 struct isl_basic_set *bset = set->p[i];
00225
00226 for (j = 0; n < dim && j < bset->n_eq; ++j) {
00227 f = is_independent_bound(ctx, set, bset->eq[j],
00228 dirs, n);
00229 if (f < 0)
00230 goto error;
00231 if (f)
00232 ++n;
00233 }
00234 for (j = 0; n < dim && j < bset->n_ineq; ++j) {
00235 f = is_independent_bound(ctx, set, bset->ineq[j],
00236 dirs, n);
00237 if (f < 0)
00238 goto error;
00239 if (f)
00240 ++n;
00241 }
00242 }
00243 dirs->n_row = n;
00244 return dirs;
00245 error:
00246 isl_mat_free(ctx, dirs);
00247 return NULL;
00248 }
00249
00250 static struct isl_basic_set *isl_basic_set_set_rational(
00251 struct isl_basic_set *bset)
00252 {
00253 if (!bset)
00254 return NULL;
00255
00256 if (ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
00257 return bset;
00258
00259 bset = isl_basic_set_cow(bset);
00260 if (!bset)
00261 return NULL;
00262
00263 ISL_F_SET(bset, ISL_BASIC_MAP_RATIONAL);
00264
00265 return isl_basic_set_finalize(bset);
00266 }
00267
00268 static struct isl_set *isl_set_set_rational(struct isl_set *set)
00269 {
00270 int i;
00271
00272 set = isl_set_cow(set);
00273 if (!set)
00274 return NULL;
00275 for (i = 0; i < set->n; ++i) {
00276 set->p[i] = isl_basic_set_set_rational(set->p[i]);
00277 if (!set->p[i])
00278 goto error;
00279 }
00280 return set;
00281 error:
00282 isl_set_free(set);
00283 return NULL;
00284 }
00285
00286 static struct isl_basic_set *isl_basic_set_add_equality(struct isl_ctx *ctx,
00287 struct isl_basic_set *bset, isl_int *c)
00288 {
00289 int i;
00290 unsigned total;
00291 unsigned dim;
00292
00293 if (ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY))
00294 return bset;
00295
00296 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
00297 isl_assert(ctx, bset->n_div == 0, goto error);
00298 dim = isl_basic_set_n_dim(bset);
00299 bset = isl_basic_set_cow(bset);
00300 bset = isl_basic_set_extend(bset, 0, dim, 0, 1, 0);
00301 i = isl_basic_set_alloc_equality(bset);
00302 if (i < 0)
00303 goto error;
00304 isl_seq_cpy(bset->eq[i], c, 1 + dim);
00305 return bset;
00306 error:
00307 isl_basic_set_free(bset);
00308 return NULL;
00309 }
00310
00311 static struct isl_set *isl_set_add_equality(struct isl_ctx *ctx,
00312 struct isl_set *set, isl_int *c)
00313 {
00314 int i;
00315
00316 set = isl_set_cow(set);
00317 if (!set)
00318 return NULL;
00319 for (i = 0; i < set->n; ++i) {
00320 set->p[i] = isl_basic_set_add_equality(ctx, set->p[i], c);
00321 if (!set->p[i])
00322 goto error;
00323 }
00324 return set;
00325 error:
00326 isl_set_free(set);
00327 return NULL;
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 static struct isl_basic_set *wrap_constraints(struct isl_set *set)
00348 {
00349 struct isl_basic_set *lp;
00350 unsigned n_eq;
00351 unsigned n_ineq;
00352 int i, j, k;
00353 unsigned dim, lp_dim;
00354
00355 if (!set)
00356 return NULL;
00357
00358 dim = 1 + isl_set_n_dim(set);
00359 n_eq = 1;
00360 n_ineq = set->n;
00361 for (i = 0; i < set->n; ++i) {
00362 n_eq += set->p[i]->n_eq;
00363 n_ineq += set->p[i]->n_ineq;
00364 }
00365 lp = isl_basic_set_alloc(set->ctx, 0, dim * set->n, 0, n_eq, n_ineq);
00366 if (!lp)
00367 return NULL;
00368 lp_dim = isl_basic_set_n_dim(lp);
00369 k = isl_basic_set_alloc_equality(lp);
00370 isl_int_set_si(lp->eq[k][0], -1);
00371 for (i = 0; i < set->n; ++i) {
00372 isl_int_set_si(lp->eq[k][1+dim*i], 0);
00373 isl_int_set_si(lp->eq[k][1+dim*i+1], 1);
00374 isl_seq_clr(lp->eq[k]+1+dim*i+2, dim-2);
00375 }
00376 for (i = 0; i < set->n; ++i) {
00377 k = isl_basic_set_alloc_inequality(lp);
00378 isl_seq_clr(lp->ineq[k], 1+lp_dim);
00379 isl_int_set_si(lp->ineq[k][1+dim*i], 1);
00380
00381 for (j = 0; j < set->p[i]->n_eq; ++j) {
00382 k = isl_basic_set_alloc_equality(lp);
00383 isl_seq_clr(lp->eq[k], 1+dim*i);
00384 isl_seq_cpy(lp->eq[k]+1+dim*i, set->p[i]->eq[j], dim);
00385 isl_seq_clr(lp->eq[k]+1+dim*(i+1), dim*(set->n-i-1));
00386 }
00387
00388 for (j = 0; j < set->p[i]->n_ineq; ++j) {
00389 k = isl_basic_set_alloc_inequality(lp);
00390 isl_seq_clr(lp->ineq[k], 1+dim*i);
00391 isl_seq_cpy(lp->ineq[k]+1+dim*i, set->p[i]->ineq[j], dim);
00392 isl_seq_clr(lp->ineq[k]+1+dim*(i+1), dim*(set->n-i-1));
00393 }
00394 }
00395 return lp;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 static isl_int *wrap_facet(struct isl_set *set, isl_int *facet, isl_int *ridge)
00455 {
00456 int i;
00457 struct isl_mat *T = NULL;
00458 struct isl_basic_set *lp = NULL;
00459 struct isl_vec *obj;
00460 enum isl_lp_result res;
00461 isl_int num, den;
00462 unsigned dim;
00463
00464 set = isl_set_copy(set);
00465
00466 dim = 1 + isl_set_n_dim(set);
00467 T = isl_mat_alloc(set->ctx, 3, dim);
00468 if (!T)
00469 goto error;
00470 isl_int_set_si(T->row[0][0], 1);
00471 isl_seq_clr(T->row[0]+1, dim - 1);
00472 isl_seq_cpy(T->row[1], facet, dim);
00473 isl_seq_cpy(T->row[2], ridge, dim);
00474 T = isl_mat_right_inverse(set->ctx, T);
00475 set = isl_set_preimage(set, T);
00476 T = NULL;
00477 if (!set)
00478 goto error;
00479 lp = wrap_constraints(set);
00480 obj = isl_vec_alloc(set->ctx, 1 + dim*set->n);
00481 if (!obj)
00482 goto error;
00483 isl_int_set_si(obj->block.data[0], 0);
00484 for (i = 0; i < set->n; ++i) {
00485 isl_seq_clr(obj->block.data + 1 + dim*i, 2);
00486 isl_int_set_si(obj->block.data[1 + dim*i+2], 1);
00487 isl_seq_clr(obj->block.data + 1 + dim*i+3, dim-3);
00488 }
00489 isl_int_init(num);
00490 isl_int_init(den);
00491 res = isl_solve_lp((struct isl_basic_map *)lp, 0,
00492 obj->block.data, set->ctx->one, &num, &den);
00493 if (res == isl_lp_ok) {
00494 isl_int_neg(num, num);
00495 isl_seq_combine(facet, num, facet, den, ridge, dim);
00496 }
00497 isl_int_clear(num);
00498 isl_int_clear(den);
00499 isl_vec_free(set->ctx, obj);
00500 isl_basic_set_free(lp);
00501 isl_set_free(set);
00502 isl_assert(set->ctx, res == isl_lp_ok, return NULL);
00503 return facet;
00504 error:
00505 isl_basic_set_free(lp);
00506 isl_mat_free(set->ctx, T);
00507 isl_set_free(set);
00508 return NULL;
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 static struct isl_mat *initial_facet_constraint(struct isl_ctx *ctx,
00524 struct isl_set *set, struct isl_mat *bounds)
00525 {
00526 struct isl_set *slice = NULL;
00527 struct isl_basic_set *face = NULL;
00528 struct isl_mat *m, *U, *Q;
00529 int i;
00530 unsigned dim = isl_set_n_dim(set);
00531
00532 isl_assert(ctx, set->n > 0, goto error);
00533 isl_assert(ctx, bounds->n_row == dim, goto error);
00534
00535 while (bounds->n_row > 1) {
00536 slice = isl_set_copy(set);
00537 slice = isl_set_add_equality(ctx, slice, bounds->row[0]);
00538 face = isl_set_affine_hull(slice);
00539 if (!face)
00540 goto error;
00541 if (face->n_eq == 1) {
00542 isl_basic_set_free(face);
00543 break;
00544 }
00545 m = isl_mat_alloc(ctx, 1 + face->n_eq, 1 + dim);
00546 if (!m)
00547 goto error;
00548 isl_int_set_si(m->row[0][0], 1);
00549 isl_seq_clr(m->row[0]+1, dim);
00550 for (i = 0; i < face->n_eq; ++i)
00551 isl_seq_cpy(m->row[1 + i], face->eq[i], 1 + dim);
00552 U = isl_mat_right_inverse(ctx, m);
00553 Q = isl_mat_right_inverse(ctx, isl_mat_copy(ctx, U));
00554 U = isl_mat_drop_cols(ctx, U, 1 + face->n_eq,
00555 dim - face->n_eq);
00556 Q = isl_mat_drop_rows(ctx, Q, 1 + face->n_eq,
00557 dim - face->n_eq);
00558 U = isl_mat_drop_cols(ctx, U, 0, 1);
00559 Q = isl_mat_drop_rows(ctx, Q, 0, 1);
00560 bounds = isl_mat_product(ctx, bounds, U);
00561 bounds = isl_mat_product(ctx, bounds, Q);
00562 while (isl_seq_first_non_zero(bounds->row[bounds->n_row-1],
00563 bounds->n_col) == -1) {
00564 bounds->n_row--;
00565 isl_assert(ctx, bounds->n_row > 1, goto error);
00566 }
00567 if (!wrap_facet(set, bounds->row[0],
00568 bounds->row[bounds->n_row-1]))
00569 goto error;
00570 isl_basic_set_free(face);
00571 bounds->n_row--;
00572 }
00573 return bounds;
00574 error:
00575 isl_basic_set_free(face);
00576 isl_mat_free(ctx, bounds);
00577 return NULL;
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 static struct isl_basic_set *compute_facet(struct isl_set *set, isl_int *c)
00620 {
00621 struct isl_mat *m, *U, *Q;
00622 struct isl_basic_set *facet = NULL;
00623 struct isl_ctx *ctx;
00624 unsigned dim;
00625
00626 ctx = set->ctx;
00627 set = isl_set_copy(set);
00628 dim = isl_set_n_dim(set);
00629 m = isl_mat_alloc(set->ctx, 2, 1 + dim);
00630 if (!m)
00631 goto error;
00632 isl_int_set_si(m->row[0][0], 1);
00633 isl_seq_clr(m->row[0]+1, dim);
00634 isl_seq_cpy(m->row[1], c, 1+dim);
00635 U = isl_mat_right_inverse(set->ctx, m);
00636 Q = isl_mat_right_inverse(set->ctx, isl_mat_copy(set->ctx, U));
00637 U = isl_mat_drop_cols(set->ctx, U, 1, 1);
00638 Q = isl_mat_drop_rows(set->ctx, Q, 1, 1);
00639 set = isl_set_preimage(set, U);
00640 facet = uset_convex_hull_wrap_bounded(set);
00641 facet = isl_basic_set_preimage(facet, Q);
00642 isl_assert(ctx, facet->n_eq == 0, goto error);
00643 return facet;
00644 error:
00645 isl_basic_set_free(facet);
00646 isl_set_free(set);
00647 return NULL;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 static struct isl_basic_set *extend(struct isl_basic_set *hull,
00672 struct isl_set *set)
00673 {
00674 int i, j, f;
00675 int k;
00676 struct isl_basic_set *facet = NULL;
00677 struct isl_basic_set *hull_facet = NULL;
00678 unsigned total;
00679 unsigned dim;
00680
00681 isl_assert(set->ctx, set->n > 0, goto error);
00682
00683 dim = isl_set_n_dim(set);
00684
00685 for (i = 0; i < hull->n_ineq; ++i) {
00686 facet = compute_facet(set, hull->ineq[i]);
00687 facet = isl_basic_set_add_equality(facet->ctx, facet, hull->ineq[i]);
00688 facet = isl_basic_set_gauss(facet, NULL);
00689 facet = isl_basic_set_normalize_constraints(facet);
00690 hull_facet = isl_basic_set_copy(hull);
00691 hull_facet = isl_basic_set_add_equality(hull_facet->ctx, hull_facet, hull->ineq[i]);
00692 hull_facet = isl_basic_set_gauss(hull_facet, NULL);
00693 hull_facet = isl_basic_set_normalize_constraints(hull_facet);
00694 if (!facet)
00695 goto error;
00696 hull = isl_basic_set_cow(hull);
00697 hull = isl_basic_set_extend_dim(hull,
00698 isl_dim_copy(hull->dim), 0, 0, facet->n_ineq);
00699 for (j = 0; j < facet->n_ineq; ++j) {
00700 for (f = 0; f < hull_facet->n_ineq; ++f)
00701 if (isl_seq_eq(facet->ineq[j],
00702 hull_facet->ineq[f], 1 + dim))
00703 break;
00704 if (f < hull_facet->n_ineq)
00705 continue;
00706 k = isl_basic_set_alloc_inequality(hull);
00707 if (k < 0)
00708 goto error;
00709 isl_seq_cpy(hull->ineq[k], hull->ineq[i], 1+dim);
00710 if (!wrap_facet(set, hull->ineq[k], facet->ineq[j]))
00711 goto error;
00712 }
00713 isl_basic_set_free(hull_facet);
00714 isl_basic_set_free(facet);
00715 }
00716 hull = isl_basic_set_simplify(hull);
00717 hull = isl_basic_set_finalize(hull);
00718 return hull;
00719 error:
00720 isl_basic_set_free(hull_facet);
00721 isl_basic_set_free(facet);
00722 isl_basic_set_free(hull);
00723 return NULL;
00724 }
00725
00726
00727
00728
00729
00730 static struct isl_basic_set *convex_hull_1d(struct isl_ctx *ctx,
00731 struct isl_set *set)
00732 {
00733 struct isl_mat *c = NULL;
00734 isl_int *lower = NULL;
00735 isl_int *upper = NULL;
00736 int i, j, k;
00737 isl_int a, b;
00738 struct isl_basic_set *hull;
00739
00740 for (i = 0; i < set->n; ++i) {
00741 set->p[i] = isl_basic_set_simplify(set->p[i]);
00742 if (!set->p[i])
00743 goto error;
00744 }
00745 set = isl_set_remove_empty_parts(set);
00746 if (!set)
00747 goto error;
00748 isl_assert(ctx, set->n > 0, goto error);
00749 c = isl_mat_alloc(ctx, 2, 2);
00750 if (!c)
00751 goto error;
00752
00753 if (set->p[0]->n_eq > 0) {
00754 isl_assert(ctx, set->p[0]->n_eq == 1, goto error);
00755 lower = c->row[0];
00756 upper = c->row[1];
00757 if (isl_int_is_pos(set->p[0]->eq[0][1])) {
00758 isl_seq_cpy(lower, set->p[0]->eq[0], 2);
00759 isl_seq_neg(upper, set->p[0]->eq[0], 2);
00760 } else {
00761 isl_seq_neg(lower, set->p[0]->eq[0], 2);
00762 isl_seq_cpy(upper, set->p[0]->eq[0], 2);
00763 }
00764 } else {
00765 for (j = 0; j < set->p[0]->n_ineq; ++j) {
00766 if (isl_int_is_pos(set->p[0]->ineq[j][1])) {
00767 lower = c->row[0];
00768 isl_seq_cpy(lower, set->p[0]->ineq[j], 2);
00769 } else {
00770 upper = c->row[1];
00771 isl_seq_cpy(upper, set->p[0]->ineq[j], 2);
00772 }
00773 }
00774 }
00775
00776 isl_int_init(a);
00777 isl_int_init(b);
00778 for (i = 0; i < set->n; ++i) {
00779 struct isl_basic_set *bset = set->p[i];
00780 int has_lower = 0;
00781 int has_upper = 0;
00782
00783 for (j = 0; j < bset->n_eq; ++j) {
00784 has_lower = 1;
00785 has_upper = 1;
00786 if (lower) {
00787 isl_int_mul(a, lower[0], bset->eq[j][1]);
00788 isl_int_mul(b, lower[1], bset->eq[j][0]);
00789 if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
00790 isl_seq_cpy(lower, bset->eq[j], 2);
00791 if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
00792 isl_seq_neg(lower, bset->eq[j], 2);
00793 }
00794 if (upper) {
00795 isl_int_mul(a, upper[0], bset->eq[j][1]);
00796 isl_int_mul(b, upper[1], bset->eq[j][0]);
00797 if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
00798 isl_seq_neg(upper, bset->eq[j], 2);
00799 if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
00800 isl_seq_cpy(upper, bset->eq[j], 2);
00801 }
00802 }
00803 for (j = 0; j < bset->n_ineq; ++j) {
00804 if (isl_int_is_pos(bset->ineq[j][1]))
00805 has_lower = 1;
00806 if (isl_int_is_neg(bset->ineq[j][1]))
00807 has_upper = 1;
00808 if (lower && isl_int_is_pos(bset->ineq[j][1])) {
00809 isl_int_mul(a, lower[0], bset->ineq[j][1]);
00810 isl_int_mul(b, lower[1], bset->ineq[j][0]);
00811 if (isl_int_lt(a, b))
00812 isl_seq_cpy(lower, bset->ineq[j], 2);
00813 }
00814 if (upper && isl_int_is_neg(bset->ineq[j][1])) {
00815 isl_int_mul(a, upper[0], bset->ineq[j][1]);
00816 isl_int_mul(b, upper[1], bset->ineq[j][0]);
00817 if (isl_int_gt(a, b))
00818 isl_seq_cpy(upper, bset->ineq[j], 2);
00819 }
00820 }
00821 if (!has_lower)
00822 lower = NULL;
00823 if (!has_upper)
00824 upper = NULL;
00825 }
00826 isl_int_clear(a);
00827 isl_int_clear(b);
00828
00829 hull = isl_basic_set_alloc(ctx, 0, 1, 0, 0, 2);
00830 hull = isl_basic_set_set_rational(hull);
00831 if (!hull)
00832 goto error;
00833 if (lower) {
00834 k = isl_basic_set_alloc_inequality(hull);
00835 isl_seq_cpy(hull->ineq[k], lower, 2);
00836 }
00837 if (upper) {
00838 k = isl_basic_set_alloc_inequality(hull);
00839 isl_seq_cpy(hull->ineq[k], upper, 2);
00840 }
00841 hull = isl_basic_set_finalize(hull);
00842 isl_set_free(set);
00843 isl_mat_free(ctx, c);
00844 return hull;
00845 error:
00846 isl_set_free(set);
00847 isl_mat_free(ctx, c);
00848 return NULL;
00849 }
00850
00851
00852 static struct isl_set *set_project_out(struct isl_ctx *ctx,
00853 struct isl_set *set, unsigned n)
00854 {
00855 return isl_set_remove_dims(set, isl_set_n_dim(set) - n, n);
00856 }
00857
00858 static struct isl_basic_set *convex_hull_0d(struct isl_set *set)
00859 {
00860 struct isl_basic_set *convex_hull;
00861
00862 if (!set)
00863 return NULL;
00864
00865 if (isl_set_is_empty(set))
00866 convex_hull = isl_basic_set_empty(isl_dim_copy(set->dim));
00867 else
00868 convex_hull = isl_basic_set_universe(isl_dim_copy(set->dim));
00869 isl_set_free(set);
00870 return convex_hull;
00871 }
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 static struct isl_basic_set *convex_hull_pair_elim(struct isl_basic_set *bset1,
00883 struct isl_basic_set *bset2)
00884 {
00885 int i, j, k;
00886 struct isl_basic_set *bset[2];
00887 struct isl_basic_set *hull = NULL;
00888 unsigned dim;
00889
00890 if (!bset1 || !bset2)
00891 goto error;
00892
00893 dim = isl_basic_set_n_dim(bset1);
00894 hull = isl_basic_set_alloc(bset1->ctx, 0, 2 + 3 * dim, 0,
00895 1 + dim + bset1->n_eq + bset2->n_eq,
00896 2 + bset1->n_ineq + bset2->n_ineq);
00897 bset[0] = bset1;
00898 bset[1] = bset2;
00899 for (i = 0; i < 2; ++i) {
00900 for (j = 0; j < bset[i]->n_eq; ++j) {
00901 k = isl_basic_set_alloc_equality(hull);
00902 if (k < 0)
00903 goto error;
00904 isl_seq_clr(hull->eq[k], (i+1) * (1+dim));
00905 isl_seq_clr(hull->eq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
00906 isl_seq_cpy(hull->eq[k]+(i+1)*(1+dim), bset[i]->eq[j],
00907 1+dim);
00908 }
00909 for (j = 0; j < bset[i]->n_ineq; ++j) {
00910 k = isl_basic_set_alloc_inequality(hull);
00911 if (k < 0)
00912 goto error;
00913 isl_seq_clr(hull->ineq[k], (i+1) * (1+dim));
00914 isl_seq_clr(hull->ineq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
00915 isl_seq_cpy(hull->ineq[k]+(i+1)*(1+dim),
00916 bset[i]->ineq[j], 1+dim);
00917 }
00918 k = isl_basic_set_alloc_inequality(hull);
00919 if (k < 0)
00920 goto error;
00921 isl_seq_clr(hull->ineq[k], 1+2+3*dim);
00922 isl_int_set_si(hull->ineq[k][(i+1)*(1+dim)], 1);
00923 }
00924 for (j = 0; j < 1+dim; ++j) {
00925 k = isl_basic_set_alloc_equality(hull);
00926 if (k < 0)
00927 goto error;
00928 isl_seq_clr(hull->eq[k], 1+2+3*dim);
00929 isl_int_set_si(hull->eq[k][j], -1);
00930 isl_int_set_si(hull->eq[k][1+dim+j], 1);
00931 isl_int_set_si(hull->eq[k][2*(1+dim)+j], 1);
00932 }
00933 hull = isl_basic_set_set_rational(hull);
00934 hull = isl_basic_set_remove_dims(hull, dim, 2*(1+dim));
00935 hull = isl_basic_set_convex_hull(hull);
00936 isl_basic_set_free(bset1);
00937 isl_basic_set_free(bset2);
00938 return hull;
00939 error:
00940 isl_basic_set_free(bset1);
00941 isl_basic_set_free(bset2);
00942 isl_basic_set_free(hull);
00943 return NULL;
00944 }
00945
00946 static int isl_basic_set_is_bounded(struct isl_basic_set *bset)
00947 {
00948 struct isl_tab *tab;
00949 int bounded;
00950
00951 tab = isl_tab_from_recession_cone((struct isl_basic_map *)bset);
00952 bounded = isl_tab_cone_is_bounded(bset->ctx, tab);
00953 isl_tab_free(bset->ctx, tab);
00954 return bounded;
00955 }
00956
00957 static int isl_set_is_bounded(struct isl_set *set)
00958 {
00959 int i;
00960
00961 for (i = 0; i < set->n; ++i) {
00962 int bounded = isl_basic_set_is_bounded(set->p[i]);
00963 if (!bounded || bounded < 0)
00964 return bounded;
00965 }
00966 return 1;
00967 }
00968
00969
00970
00971
00972
00973
00974
00975 static struct isl_basic_set *induced_lineality_space(
00976 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
00977 {
00978 int i, k;
00979 struct isl_basic_set *lin = NULL;
00980 unsigned dim;
00981
00982 if (!bset1 || !bset2)
00983 goto error;
00984
00985 dim = isl_basic_set_total_dim(bset1);
00986 lin = isl_basic_set_alloc_dim(isl_basic_set_get_dim(bset1), 0,
00987 bset1->n_eq + bset2->n_eq,
00988 bset1->n_ineq + bset2->n_ineq);
00989 lin = isl_basic_set_set_rational(lin);
00990 if (!lin)
00991 goto error;
00992 for (i = 0; i < bset1->n_eq; ++i) {
00993 k = isl_basic_set_alloc_equality(lin);
00994 if (k < 0)
00995 goto error;
00996 isl_int_set_si(lin->eq[k][0], 0);
00997 isl_seq_cpy(lin->eq[k] + 1, bset1->eq[i] + 1, dim);
00998 }
00999 for (i = 0; i < bset1->n_ineq; ++i) {
01000 k = isl_basic_set_alloc_inequality(lin);
01001 if (k < 0)
01002 goto error;
01003 isl_int_set_si(lin->ineq[k][0], 0);
01004 isl_seq_cpy(lin->ineq[k] + 1, bset1->ineq[i] + 1, dim);
01005 }
01006 for (i = 0; i < bset2->n_eq; ++i) {
01007 k = isl_basic_set_alloc_equality(lin);
01008 if (k < 0)
01009 goto error;
01010 isl_int_set_si(lin->eq[k][0], 0);
01011 isl_seq_neg(lin->eq[k] + 1, bset2->eq[i] + 1, dim);
01012 }
01013 for (i = 0; i < bset2->n_ineq; ++i) {
01014 k = isl_basic_set_alloc_inequality(lin);
01015 if (k < 0)
01016 goto error;
01017 isl_int_set_si(lin->ineq[k][0], 0);
01018 isl_seq_neg(lin->ineq[k] + 1, bset2->ineq[i] + 1, dim);
01019 }
01020
01021 isl_basic_set_free(bset1);
01022 isl_basic_set_free(bset2);
01023 return isl_basic_set_affine_hull(lin);
01024 error:
01025 isl_basic_set_free(lin);
01026 isl_basic_set_free(bset1);
01027 isl_basic_set_free(bset2);
01028 return NULL;
01029 }
01030
01031 static struct isl_basic_set *uset_convex_hull(struct isl_set *set);
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 static struct isl_basic_set *modulo_lineality(struct isl_set *set,
01054 struct isl_basic_set *lin)
01055 {
01056 unsigned total = isl_basic_set_total_dim(lin);
01057 unsigned lin_dim;
01058 struct isl_basic_set *hull;
01059 struct isl_mat *M, *U, *Q;
01060
01061 if (!set || !lin)
01062 goto error;
01063 lin_dim = total - lin->n_eq;
01064 M = isl_mat_sub_alloc(set->ctx, lin->eq, 0, lin->n_eq, 1, total);
01065 M = isl_mat_left_hermite(set->ctx, M, 0, &U, &Q);
01066 if (!M)
01067 goto error;
01068 isl_mat_free(set->ctx, M);
01069 isl_basic_set_free(lin);
01070
01071 isl_mat_drop_rows(set->ctx, Q, Q->n_row - lin_dim, lin_dim);
01072
01073 U = isl_mat_lin_to_aff(set->ctx, U);
01074 Q = isl_mat_lin_to_aff(set->ctx, Q);
01075
01076 set = isl_set_preimage(set, U);
01077 set = isl_set_remove_dims(set, total - lin_dim, lin_dim);
01078 hull = uset_convex_hull(set);
01079 hull = isl_basic_set_preimage(hull, Q);
01080
01081 return hull;
01082 error:
01083 isl_basic_set_free(lin);
01084 isl_set_free(set);
01085 return NULL;
01086 }
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 static struct isl_basic_set *valid_direction_lp(
01098 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
01099 {
01100 struct isl_dim *dim;
01101 struct isl_basic_set *lp;
01102 unsigned d;
01103 int n;
01104 int i, j, k;
01105
01106 if (!bset1 || !bset2)
01107 goto error;
01108 d = 1 + isl_basic_set_total_dim(bset1);
01109 n = 2 +
01110 2 * bset1->n_eq + bset1->n_ineq + 2 * bset2->n_eq + bset2->n_ineq;
01111 dim = isl_dim_set_alloc(bset1->ctx, 0, n);
01112 lp = isl_basic_set_alloc_dim(dim, 0, d, n);
01113 if (!lp)
01114 goto error;
01115 for (i = 0; i < n; ++i) {
01116 k = isl_basic_set_alloc_inequality(lp);
01117 if (k < 0)
01118 goto error;
01119 isl_seq_clr(lp->ineq[k] + 1, n);
01120 isl_int_set_si(lp->ineq[k][0], -1);
01121 isl_int_set_si(lp->ineq[k][1 + i], 1);
01122 }
01123 for (i = 0; i < d; ++i) {
01124 k = isl_basic_set_alloc_equality(lp);
01125 if (k < 0)
01126 goto error;
01127 n = 0;
01128 isl_int_set_si(lp->eq[k][n++], 0);
01129
01130 isl_int_set_si(lp->eq[k][n++], i == 0);
01131 for (j = 0; j < bset1->n_eq; ++j) {
01132 isl_int_set(lp->eq[k][n++], bset1->eq[j][i]);
01133 isl_int_neg(lp->eq[k][n++], bset1->eq[j][i]);
01134 }
01135 for (j = 0; j < bset1->n_ineq; ++j)
01136 isl_int_set(lp->eq[k][n++], bset1->ineq[j][i]);
01137
01138 isl_int_set_si(lp->eq[k][n++], -(i == 0));
01139 for (j = 0; j < bset2->n_eq; ++j) {
01140 isl_int_neg(lp->eq[k][n++], bset2->eq[j][i]);
01141 isl_int_set(lp->eq[k][n++], bset2->eq[j][i]);
01142 }
01143 for (j = 0; j < bset2->n_ineq; ++j)
01144 isl_int_neg(lp->eq[k][n++], bset2->ineq[j][i]);
01145 }
01146 lp = isl_basic_set_gauss(lp, NULL);
01147 isl_basic_set_free(bset1);
01148 isl_basic_set_free(bset2);
01149 return lp;
01150 error:
01151 isl_basic_set_free(bset1);
01152 isl_basic_set_free(bset2);
01153 return NULL;
01154 }
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 static struct isl_vec *valid_direction(
01177 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
01178 {
01179 struct isl_ctx *ctx = NULL;
01180 struct isl_basic_set *lp;
01181 struct isl_tab *tab;
01182 struct isl_vec *sample = NULL;
01183 struct isl_vec *dir;
01184 unsigned d;
01185 int i;
01186 int n;
01187
01188 if (!bset1 || !bset2)
01189 goto error;
01190 ctx = bset1->ctx;
01191 lp = valid_direction_lp(isl_basic_set_copy(bset1),
01192 isl_basic_set_copy(bset2));
01193 tab = isl_tab_from_basic_set(lp);
01194 sample = isl_tab_get_sample_value(ctx, tab);
01195 isl_tab_free(ctx, tab);
01196 isl_basic_set_free(lp);
01197 if (!sample)
01198 goto error;
01199 d = isl_basic_set_total_dim(bset1);
01200 dir = isl_vec_alloc(ctx, 1 + d);
01201 if (!dir)
01202 goto error;
01203 isl_seq_clr(dir->block.data + 1, dir->size - 1);
01204 n = 1;
01205
01206 isl_int_set(dir->block.data[0], sample->block.data[n++]);
01207 for (i = 0; i < bset1->n_eq; ++i) {
01208 isl_int_sub(sample->block.data[n],
01209 sample->block.data[n], sample->block.data[n+1]);
01210 isl_seq_combine(dir->block.data,
01211 bset1->ctx->one, dir->block.data,
01212 sample->block.data[n], bset1->eq[i], 1 + d);
01213
01214 n += 2;
01215 }
01216 for (i = 0; i < bset1->n_ineq; ++i)
01217 isl_seq_combine(dir->block.data,
01218 bset1->ctx->one, dir->block.data,
01219 sample->block.data[n++], bset1->ineq[i], 1 + d);
01220 isl_vec_free(ctx, sample);
01221 isl_basic_set_free(bset1);
01222 isl_basic_set_free(bset2);
01223 isl_seq_normalize(dir->block.data + 1, dir->size - 1);
01224 return dir;
01225 error:
01226 isl_vec_free(ctx, sample);
01227 isl_basic_set_free(bset1);
01228 isl_basic_set_free(bset2);
01229 return NULL;
01230 }
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 static struct isl_basic_set *homogeneous_map(struct isl_basic_set *bset,
01242 struct isl_mat *T)
01243 {
01244 struct isl_ctx *ctx = NULL;
01245 int k;
01246
01247 if (!bset)
01248 goto error;
01249 ctx = bset->ctx;
01250 bset = isl_basic_set_extend_constraints(bset, 0, 1);
01251 k = isl_basic_set_alloc_inequality(bset);
01252 if (k < 0)
01253 goto error;
01254 isl_seq_clr(bset->ineq[k] + 1, isl_basic_set_total_dim(bset));
01255 isl_int_set_si(bset->ineq[k][0], 1);
01256 bset = isl_basic_set_preimage(bset, T);
01257 return bset;
01258 error:
01259 isl_mat_free(ctx, T);
01260 isl_basic_set_free(bset);
01261 return NULL;
01262 }
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 static struct isl_basic_set *convex_hull_pair_pointed(
01324 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
01325 {
01326 struct isl_ctx *ctx = NULL;
01327 struct isl_vec *dir = NULL;
01328 struct isl_mat *T = NULL;
01329 struct isl_mat *T2 = NULL;
01330 struct isl_basic_set *hull;
01331 struct isl_set *set;
01332
01333 if (!bset1 || !bset2)
01334 goto error;
01335 ctx = bset1->ctx;
01336 dir = valid_direction(isl_basic_set_copy(bset1),
01337 isl_basic_set_copy(bset2));
01338 if (!dir)
01339 goto error;
01340 T = isl_mat_alloc(bset1->ctx, dir->size, dir->size);
01341 if (!T)
01342 goto error;
01343 isl_seq_cpy(T->row[0], dir->block.data, dir->size);
01344 T = isl_mat_unimodular_complete(ctx, T, 1);
01345 T2 = isl_mat_right_inverse(ctx, isl_mat_copy(ctx, T));
01346
01347 bset1 = homogeneous_map(bset1, isl_mat_copy(ctx, T2));
01348 bset2 = homogeneous_map(bset2, T2);
01349 set = isl_set_alloc_dim(isl_basic_set_get_dim(bset1), 2, 0);
01350 set = isl_set_add(set, bset1);
01351 set = isl_set_add(set, bset2);
01352 hull = uset_convex_hull(set);
01353 hull = isl_basic_set_preimage(hull, T);
01354
01355 isl_vec_free(ctx, dir);
01356
01357 return hull;
01358 error:
01359 isl_vec_free(ctx, dir);
01360 isl_basic_set_free(bset1);
01361 isl_basic_set_free(bset2);
01362 return NULL;
01363 }
01364
01365
01366
01367
01368
01369
01370
01371 static struct isl_basic_set *convex_hull_pair(struct isl_basic_set *bset1,
01372 struct isl_basic_set *bset2)
01373 {
01374 struct isl_basic_set *lin;
01375
01376 if (isl_basic_set_is_bounded(bset1) || isl_basic_set_is_bounded(bset2))
01377 return convex_hull_pair_pointed(bset1, bset2);
01378
01379 lin = induced_lineality_space(isl_basic_set_copy(bset1),
01380 isl_basic_set_copy(bset2));
01381 if (!lin)
01382 goto error;
01383 if (isl_basic_set_is_universe(lin)) {
01384 isl_basic_set_free(bset1);
01385 isl_basic_set_free(bset2);
01386 return lin;
01387 }
01388 if (lin->n_eq < isl_basic_set_total_dim(lin)) {
01389 struct isl_set *set;
01390 set = isl_set_alloc_dim(isl_basic_set_get_dim(bset1), 2, 0);
01391 set = isl_set_add(set, bset1);
01392 set = isl_set_add(set, bset2);
01393 return modulo_lineality(set, lin);
01394 }
01395 isl_basic_set_free(lin);
01396
01397 return convex_hull_pair_pointed(bset1, bset2);
01398 error:
01399 isl_basic_set_free(bset1);
01400 isl_basic_set_free(bset2);
01401 return NULL;
01402 }
01403
01404
01405
01406
01407
01408 static struct isl_basic_set *ubasic_set_lineality_space(
01409 struct isl_basic_set *bset)
01410 {
01411 int i, k;
01412 struct isl_basic_set *lin = NULL;
01413 unsigned dim;
01414
01415 if (!bset)
01416 goto error;
01417 dim = isl_basic_set_total_dim(bset);
01418
01419 lin = isl_basic_set_alloc_dim(isl_basic_set_get_dim(bset), 0, dim, 0);
01420 if (!lin)
01421 goto error;
01422 for (i = 0; i < bset->n_eq; ++i) {
01423 k = isl_basic_set_alloc_equality(lin);
01424 if (k < 0)
01425 goto error;
01426 isl_int_set_si(lin->eq[k][0], 0);
01427 isl_seq_cpy(lin->eq[k] + 1, bset->eq[i] + 1, dim);
01428 }
01429 lin = isl_basic_set_gauss(lin, NULL);
01430 if (!lin)
01431 goto error;
01432 for (i = 0; i < bset->n_ineq && lin->n_eq < dim; ++i) {
01433 k = isl_basic_set_alloc_equality(lin);
01434 if (k < 0)
01435 goto error;
01436 isl_int_set_si(lin->eq[k][0], 0);
01437 isl_seq_cpy(lin->eq[k] + 1, bset->ineq[i] + 1, dim);
01438 lin = isl_basic_set_gauss(lin, NULL);
01439 if (!lin)
01440 goto error;
01441 }
01442 isl_basic_set_free(bset);
01443 return lin;
01444 error:
01445 isl_basic_set_free(lin);
01446 isl_basic_set_free(bset);
01447 return NULL;
01448 }
01449
01450
01451
01452
01453 static struct isl_basic_set *uset_combined_lineality_space(struct isl_set *set)
01454 {
01455 int i;
01456 struct isl_set *lin = NULL;
01457
01458 if (!set)
01459 return NULL;
01460 if (set->n == 0) {
01461 struct isl_dim *dim = isl_set_get_dim(set);
01462 isl_set_free(set);
01463 return isl_basic_set_empty(dim);
01464 }
01465
01466 lin = isl_set_alloc_dim(isl_set_get_dim(set), set->n, 0);
01467 for (i = 0; i < set->n; ++i)
01468 lin = isl_set_add(lin,
01469 ubasic_set_lineality_space(isl_basic_set_copy(set->p[i])));
01470 isl_set_free(set);
01471 return isl_set_affine_hull(lin);
01472 }
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482 static struct isl_basic_set *uset_convex_hull_unbounded(struct isl_set *set)
01483 {
01484 struct isl_basic_set *convex_hull = NULL;
01485
01486 convex_hull = isl_set_copy_basic_set(set);
01487 set = isl_set_drop_basic_set(set, convex_hull);
01488 if (!set)
01489 goto error;
01490 while (set->n > 0) {
01491 struct isl_basic_set *t;
01492 t = isl_set_copy_basic_set(set);
01493 if (!t)
01494 goto error;
01495 set = isl_set_drop_basic_set(set, t);
01496 if (!set)
01497 goto error;
01498 convex_hull = convex_hull_pair(convex_hull, t);
01499 if (set->n == 0)
01500 break;
01501 t = ubasic_set_lineality_space(isl_basic_set_copy(convex_hull));
01502 if (!t)
01503 goto error;
01504 if (isl_basic_set_is_universe(t)) {
01505 isl_basic_set_free(convex_hull);
01506 convex_hull = t;
01507 break;
01508 }
01509 if (t->n_eq < isl_basic_set_total_dim(t)) {
01510 set = isl_set_add(set, convex_hull);
01511 return modulo_lineality(set, t);
01512 }
01513 isl_basic_set_free(t);
01514 }
01515 isl_set_free(set);
01516 return convex_hull;
01517 error:
01518 isl_set_free(set);
01519 isl_basic_set_free(convex_hull);
01520 return NULL;
01521 }
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532 static struct isl_basic_set *initial_hull(struct isl_basic_set *hull,
01533 struct isl_set *set)
01534 {
01535 struct isl_mat *bounds = NULL;
01536 unsigned dim;
01537 int k;
01538
01539 if (!hull)
01540 goto error;
01541 bounds = independent_bounds(set->ctx, set);
01542 if (!bounds)
01543 goto error;
01544 isl_assert(set->ctx, bounds->n_row == isl_set_n_dim(set), goto error);
01545 bounds = initial_facet_constraint(set->ctx, set, bounds);
01546 if (!bounds)
01547 goto error;
01548 k = isl_basic_set_alloc_inequality(hull);
01549 if (k < 0)
01550 goto error;
01551 dim = isl_set_n_dim(set);
01552 isl_assert(set->ctx, 1 + dim == bounds->n_col, goto error);
01553 isl_seq_cpy(hull->ineq[k], bounds->row[0], bounds->n_col);
01554 isl_mat_free(set->ctx, bounds);
01555
01556 return hull;
01557 error:
01558 isl_basic_set_free(hull);
01559 isl_mat_free(set->ctx, bounds);
01560 return NULL;
01561 }
01562
01563 struct max_constraint {
01564 struct isl_mat *c;
01565 int count;
01566 int ineq;
01567 };
01568
01569 static int max_constraint_equal(const void *entry, const void *val)
01570 {
01571 struct max_constraint *a = (struct max_constraint *)entry;
01572 isl_int *b = (isl_int *)val;
01573
01574 return isl_seq_eq(a->c->row[0] + 1, b, a->c->n_col - 1);
01575 }
01576
01577 static void update_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
01578 isl_int *con, unsigned len, int n, int ineq)
01579 {
01580 struct isl_hash_table_entry *entry;
01581 struct max_constraint *c;
01582 uint32_t c_hash;
01583
01584 c_hash = isl_seq_hash(con + 1, len, isl_hash_init());
01585 entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
01586 con + 1, 0);
01587 if (!entry)
01588 return;
01589 c = entry->data;
01590 if (c->count < n) {
01591 isl_hash_table_remove(ctx, table, entry);
01592 return;
01593 }
01594 c->count++;
01595 if (isl_int_gt(c->c->row[0][0], con[0]))
01596 return;
01597 if (isl_int_eq(c->c->row[0][0], con[0])) {
01598 if (ineq)
01599 c->ineq = ineq;
01600 return;
01601 }
01602 c->c = isl_mat_cow(ctx, c->c);
01603 isl_int_set(c->c->row[0][0], con[0]);
01604 c->ineq = ineq;
01605 }
01606
01607
01608
01609
01610 static int has_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
01611 isl_int *con, unsigned len, int n)
01612 {
01613 struct isl_hash_table_entry *entry;
01614 struct max_constraint *c;
01615 uint32_t c_hash;
01616
01617 c_hash = isl_seq_hash(con + 1, len, isl_hash_init());
01618 entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
01619 con + 1, 0);
01620 if (!entry)
01621 return 0;
01622 c = entry->data;
01623 if (c->count < n)
01624 return 0;
01625 return isl_int_eq(c->c->row[0][0], con[0]);
01626 }
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638 static struct isl_basic_set *common_constraints(struct isl_basic_set *hull,
01639 struct isl_set *set, int *is_hull)
01640 {
01641 int i, j, s, n;
01642 int min_constraints;
01643 int best;
01644 struct max_constraint *constraints = NULL;
01645 struct isl_hash_table *table = NULL;
01646 unsigned total;
01647
01648 *is_hull = 0;
01649
01650 for (i = 0; i < set->n; ++i)
01651 if (set->p[i]->n_eq == 0)
01652 break;
01653 if (i >= set->n)
01654 return hull;
01655 min_constraints = set->p[i]->n_ineq;
01656 best = i;
01657 for (i = best + 1; i < set->n; ++i) {
01658 if (set->p[i]->n_eq != 0)
01659 continue;
01660 if (set->p[i]->n_ineq >= min_constraints)
01661 continue;
01662 min_constraints = set->p[i]->n_ineq;
01663 best = i;
01664 }
01665 constraints = isl_calloc_array(hull->ctx, struct max_constraint,
01666 min_constraints);
01667 if (!constraints)
01668 return hull;
01669 table = isl_alloc_type(hull->ctx, struct isl_hash_table);
01670 if (isl_hash_table_init(hull->ctx, table, min_constraints))
01671 goto error;
01672
01673 total = isl_dim_total(set->dim);
01674 for (i = 0; i < set->p[best]->n_ineq; ++i) {
01675 constraints[i].c = isl_mat_sub_alloc(hull->ctx,
01676 set->p[best]->ineq + i, 0, 1, 0, 1 + total);
01677 if (!constraints[i].c)
01678 goto error;
01679 constraints[i].ineq = 1;
01680 }
01681 for (i = 0; i < min_constraints; ++i) {
01682 struct isl_hash_table_entry *entry;
01683 uint32_t c_hash;
01684 c_hash = isl_seq_hash(constraints[i].c->row[0] + 1, total,
01685 isl_hash_init());
01686 entry = isl_hash_table_find(hull->ctx, table, c_hash,
01687 max_constraint_equal, constraints[i].c->row[0] + 1, 1);
01688 if (!entry)
01689 goto error;
01690 isl_assert(hull->ctx, !entry->data, goto error);
01691 entry->data = &constraints[i];
01692 }
01693
01694 n = 0;
01695 for (s = 0; s < set->n; ++s) {
01696 if (s == best)
01697 continue;
01698
01699 for (i = 0; i < set->p[s]->n_eq; ++i) {
01700 isl_int *eq = set->p[s]->eq[i];
01701 for (j = 0; j < 2; ++j) {
01702 isl_seq_neg(eq, eq, 1 + total);
01703 update_constraint(hull->ctx, table,
01704 eq, total, n, 0);
01705 }
01706 }
01707 for (i = 0; i < set->p[s]->n_ineq; ++i) {
01708 isl_int *ineq = set->p[s]->ineq[i];
01709 update_constraint(hull->ctx, table, ineq, total, n,
01710 set->p[s]->n_eq == 0);
01711 }
01712 ++n;
01713 }
01714
01715 for (i = 0; i < min_constraints; ++i) {
01716 if (constraints[i].count < n)
01717 continue;
01718 if (!constraints[i].ineq)
01719 continue;
01720 j = isl_basic_set_alloc_inequality(hull);
01721 if (j < 0)
01722 goto error;
01723 isl_seq_cpy(hull->ineq[j], constraints[i].c->row[0], 1 + total);
01724 }
01725
01726 for (s = 0; s < set->n; ++s) {
01727 if (set->p[s]->n_eq)
01728 continue;
01729 if (set->p[s]->n_ineq != hull->n_ineq)
01730 continue;
01731 for (i = 0; i < set->p[s]->n_ineq; ++i) {
01732 isl_int *ineq = set->p[s]->ineq[i];
01733 if (!has_constraint(hull->ctx, table, ineq, total, n))
01734 break;
01735 }
01736 if (i == set->p[s]->n_ineq)
01737 *is_hull = 1;
01738 }
01739
01740 isl_hash_table_clear(table);
01741 for (i = 0; i < min_constraints; ++i)
01742 isl_mat_free(hull->ctx, constraints[i].c);
01743 free(constraints);
01744 free(table);
01745 return hull;
01746 error:
01747 isl_hash_table_clear(table);
01748 free(table);
01749 if (constraints)
01750 for (i = 0; i < min_constraints; ++i)
01751 isl_mat_free(hull->ctx, constraints[i].c);
01752 free(constraints);
01753 return hull;
01754 }
01755
01756
01757
01758
01759
01760 static struct isl_basic_set *proto_hull(struct isl_set *set, int *is_hull)
01761 {
01762 struct isl_basic_set *hull;
01763 unsigned n_ineq;
01764 int i;
01765
01766 n_ineq = 1;
01767 for (i = 0; i < set->n; ++i) {
01768 n_ineq += set->p[i]->n_eq;
01769 n_ineq += set->p[i]->n_ineq;
01770 }
01771 hull = isl_basic_set_alloc_dim(isl_dim_copy(set->dim), 0, 0, n_ineq);
01772 hull = isl_basic_set_set_rational(hull);
01773 if (!hull)
01774 return NULL;
01775 return common_constraints(hull, set, is_hull);
01776 }
01777
01778 static struct isl_basic_set *uset_convex_hull_wrap(struct isl_set *set)
01779 {
01780 struct isl_basic_set *hull;
01781 int is_hull;
01782
01783 hull = proto_hull(set, &is_hull);
01784 if (hull && !is_hull) {
01785 if (hull->n_ineq == 0)
01786 hull = initial_hull(hull, set);
01787 hull = extend(hull, set);
01788 }
01789 isl_set_free(set);
01790
01791 return hull;
01792 }
01793
01794
01795
01796
01797
01798
01799
01800 static struct isl_basic_set *uset_convex_hull(struct isl_set *set)
01801 {
01802 int i;
01803 struct isl_basic_set *convex_hull = NULL;
01804 struct isl_basic_set *lin;
01805
01806 if (isl_set_n_dim(set) == 0)
01807 return convex_hull_0d(set);
01808
01809 set = isl_set_coalesce(set);
01810 set = isl_set_set_rational(set);
01811
01812 if (!set)
01813 goto error;
01814 if (!set)
01815 return NULL;
01816 if (set->n == 1) {
01817 convex_hull = isl_basic_set_copy(set->p[0]);
01818 isl_set_free(set);
01819 return convex_hull;
01820 }
01821 if (isl_set_n_dim(set) == 1)
01822 return convex_hull_1d(set->ctx, set);
01823
01824 if (isl_set_is_bounded(set))
01825 return uset_convex_hull_wrap(set);
01826
01827 lin = uset_combined_lineality_space(isl_set_copy(set));
01828 if (!lin)
01829 goto error;
01830 if (isl_basic_set_is_universe(lin)) {
01831 isl_set_free(set);
01832 return lin;
01833 }
01834 if (lin->n_eq < isl_basic_set_total_dim(lin))
01835 return modulo_lineality(set, lin);
01836 isl_basic_set_free(lin);
01837
01838 return uset_convex_hull_unbounded(set);
01839 error:
01840 isl_set_free(set);
01841 isl_basic_set_free(convex_hull);
01842 return NULL;
01843 }
01844
01845
01846
01847
01848
01849 static struct isl_basic_set *uset_convex_hull_wrap_bounded(struct isl_set *set)
01850 {
01851 int i;
01852 struct isl_basic_set *convex_hull = NULL;
01853
01854 if (isl_set_n_dim(set) == 0) {
01855 convex_hull = isl_basic_set_universe(isl_dim_copy(set->dim));
01856 isl_set_free(set);
01857 convex_hull = isl_basic_set_set_rational(convex_hull);
01858 return convex_hull;
01859 }
01860
01861 set = isl_set_set_rational(set);
01862
01863 if (!set)
01864 goto error;
01865 set = isl_set_normalize(set);
01866 if (!set)
01867 goto error;
01868 if (set->n == 1) {
01869 convex_hull = isl_basic_set_copy(set->p[0]);
01870 isl_set_free(set);
01871 return convex_hull;
01872 }
01873 if (isl_set_n_dim(set) == 1)
01874 return convex_hull_1d(set->ctx, set);
01875
01876 return uset_convex_hull_wrap(set);
01877 error:
01878 isl_set_free(set);
01879 return NULL;
01880 }
01881
01882
01883
01884
01885
01886
01887 static struct isl_basic_set *modulo_affine_hull(struct isl_ctx *ctx,
01888 struct isl_set *set, struct isl_basic_set *affine_hull)
01889 {
01890 struct isl_mat *T;
01891 struct isl_mat *T2;
01892 struct isl_basic_set *dummy;
01893 struct isl_basic_set *convex_hull;
01894
01895 dummy = isl_basic_set_remove_equalities(
01896 isl_basic_set_copy(affine_hull), &T, &T2);
01897 if (!dummy)
01898 goto error;
01899 isl_basic_set_free(dummy);
01900 set = isl_set_preimage(set, T);
01901 convex_hull = uset_convex_hull(set);
01902 convex_hull = isl_basic_set_preimage(convex_hull, T2);
01903 convex_hull = isl_basic_set_intersect(convex_hull, affine_hull);
01904 return convex_hull;
01905 error:
01906 isl_basic_set_free(affine_hull);
01907 isl_set_free(set);
01908 return NULL;
01909 }
01910
01911
01912
01913
01914
01915
01916 struct isl_basic_map *isl_map_convex_hull(struct isl_map *map)
01917 {
01918 struct isl_basic_set *bset;
01919 struct isl_basic_map *model = NULL;
01920 struct isl_basic_set *affine_hull = NULL;
01921 struct isl_basic_map *convex_hull = NULL;
01922 struct isl_set *set = NULL;
01923 struct isl_ctx *ctx;
01924
01925 if (!map)
01926 goto error;
01927
01928 ctx = map->ctx;
01929 if (map->n == 0) {
01930 convex_hull = isl_basic_map_empty_like_map(map);
01931 isl_map_free(map);
01932 return convex_hull;
01933 }
01934
01935 map = isl_map_detect_equalities(map);
01936 map = isl_map_align_divs(map);
01937 model = isl_basic_map_copy(map->p[0]);
01938 set = isl_map_underlying_set(map);
01939 if (!set)
01940 goto error;
01941
01942 affine_hull = isl_set_affine_hull(isl_set_copy(set));
01943 if (!affine_hull)
01944 goto error;
01945 if (affine_hull->n_eq != 0)
01946 bset = modulo_affine_hull(ctx, set, affine_hull);
01947 else {
01948 isl_basic_set_free(affine_hull);
01949 bset = uset_convex_hull(set);
01950 }
01951
01952 convex_hull = isl_basic_map_overlying_set(bset, model);
01953
01954 ISL_F_SET(convex_hull, ISL_BASIC_MAP_NO_IMPLICIT);
01955 ISL_F_SET(convex_hull, ISL_BASIC_MAP_ALL_EQUALITIES);
01956 ISL_F_CLR(convex_hull, ISL_BASIC_MAP_RATIONAL);
01957 return convex_hull;
01958 error:
01959 isl_set_free(set);
01960 isl_basic_map_free(model);
01961 return NULL;
01962 }
01963
01964 struct isl_basic_set *isl_set_convex_hull(struct isl_set *set)
01965 {
01966 return (struct isl_basic_set *)
01967 isl_map_convex_hull((struct isl_map *)set);
01968 }
01969
01970 struct sh_data_entry {
01971 struct isl_hash_table *table;
01972 struct isl_tab *tab;
01973 };
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984 struct sh_data {
01985 struct isl_ctx *ctx;
01986 unsigned n;
01987 struct isl_hash_table *hull_table;
01988 struct sh_data_entry p[0];
01989 };
01990
01991 static void sh_data_free(struct sh_data *data)
01992 {
01993 int i;
01994
01995 if (!data)
01996 return;
01997 isl_hash_table_free(data->ctx, data->hull_table);
01998 for (i = 0; i < data->n; ++i) {
01999 isl_hash_table_free(data->ctx, data->p[i].table);
02000 isl_tab_free(data->ctx, data->p[i].tab);
02001 }
02002 free(data);
02003 }
02004
02005 struct ineq_cmp_data {
02006 unsigned len;
02007 isl_int *p;
02008 };
02009
02010 static int has_ineq(const void *entry, const void *val)
02011 {
02012 isl_int *row = (isl_int *)entry;
02013 struct ineq_cmp_data *v = (struct ineq_cmp_data *)val;
02014
02015 return isl_seq_eq(row + 1, v->p + 1, v->len) ||
02016 isl_seq_is_neg(row + 1, v->p + 1, v->len);
02017 }
02018
02019 static int hash_ineq(struct isl_ctx *ctx, struct isl_hash_table *table,
02020 isl_int *ineq, unsigned len)
02021 {
02022 uint32_t c_hash;
02023 struct ineq_cmp_data v;
02024 struct isl_hash_table_entry *entry;
02025
02026 v.len = len;
02027 v.p = ineq;
02028 c_hash = isl_seq_hash(ineq + 1, len, isl_hash_init());
02029 entry = isl_hash_table_find(ctx, table, c_hash, has_ineq, &v, 1);
02030 if (!entry)
02031 return - 1;
02032 entry->data = ineq;
02033 return 0;
02034 }
02035
02036
02037
02038
02039
02040 static int hash_basic_set(struct isl_hash_table *table,
02041 struct isl_basic_set *bset)
02042 {
02043 int i, j;
02044 unsigned dim = isl_basic_set_total_dim(bset);
02045
02046 for (i = 0; i < bset->n_eq; ++i) {
02047 for (j = 0; j < 2; ++j) {
02048 isl_seq_neg(bset->eq[i], bset->eq[i], 1 + dim);
02049 if (hash_ineq(bset->ctx, table, bset->eq[i], dim) < 0)
02050 return -1;
02051 }
02052 }
02053 for (i = 0; i < bset->n_ineq; ++i) {
02054 if (hash_ineq(bset->ctx, table, bset->ineq[i], dim) < 0)
02055 return -1;
02056 }
02057 return 0;
02058 }
02059
02060 static struct sh_data *sh_data_alloc(struct isl_set *set, unsigned n_ineq)
02061 {
02062 struct sh_data *data;
02063 int i;
02064
02065 data = isl_calloc(set->ctx, struct sh_data,
02066 sizeof(struct sh_data) + set->n * sizeof(struct sh_data_entry));
02067 if (!data)
02068 return NULL;
02069 data->ctx = set->ctx;
02070 data->n = set->n;
02071 data->hull_table = isl_hash_table_alloc(set->ctx, n_ineq);
02072 if (!data->hull_table)
02073 goto error;
02074 for (i = 0; i < set->n; ++i) {
02075 data->p[i].table = isl_hash_table_alloc(set->ctx,
02076 2 * set->p[i]->n_eq + set->p[i]->n_ineq);
02077 if (!data->p[i].table)
02078 goto error;
02079 if (hash_basic_set(data->p[i].table, set->p[i]) < 0)
02080 goto error;
02081 }
02082 return data;
02083 error:
02084 sh_data_free(data);
02085 return NULL;
02086 }
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096 static int is_bound(struct sh_data *data, struct isl_set *set, int j,
02097 isl_int *ineq)
02098 {
02099 enum isl_lp_result res;
02100 isl_int opt;
02101
02102 if (!data->p[j].tab) {
02103 data->p[j].tab = isl_tab_from_basic_set(set->p[j]);
02104 if (!data->p[j].tab)
02105 return -1;
02106 }
02107
02108 isl_int_init(opt);
02109
02110 res = isl_tab_min(data->ctx, data->p[j].tab, ineq, data->ctx->one,
02111 &opt, NULL);
02112 if (res == isl_lp_ok && isl_int_is_neg(opt))
02113 isl_int_sub(ineq[0], ineq[0], opt);
02114
02115 isl_int_clear(opt);
02116
02117 return res == isl_lp_ok ? 1 :
02118 res == isl_lp_unbounded ? 0 : -1;
02119 }
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138 static struct isl_basic_set *add_bound(struct isl_basic_set *hull,
02139 struct sh_data *data, struct isl_set *set, int i, isl_int *ineq)
02140 {
02141 uint32_t c_hash;
02142 struct ineq_cmp_data v;
02143 struct isl_hash_table_entry *entry;
02144 int j, k;
02145
02146 if (!hull)
02147 return NULL;
02148
02149 v.len = isl_basic_set_total_dim(hull);
02150 v.p = ineq;
02151 c_hash = isl_seq_hash(ineq + 1, v.len, isl_hash_init());
02152
02153 entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
02154 has_ineq, &v, 0);
02155 if (entry)
02156 return hull;
02157
02158 for (j = 0; j < i; ++j) {
02159 entry = isl_hash_table_find(hull->ctx, data->p[j].table,
02160 c_hash, has_ineq, &v, 0);
02161 if (entry)
02162 break;
02163 }
02164 if (j < i)
02165 return hull;
02166
02167 k = isl_basic_set_alloc_inequality(hull);
02168 isl_seq_cpy(hull->ineq[k], ineq, 1 + v.len);
02169 if (k < 0)
02170 goto error;
02171
02172 for (j = 0; j < i; ++j) {
02173 int bound;
02174 bound = is_bound(data, set, j, hull->ineq[k]);
02175 if (bound < 0)
02176 goto error;
02177 if (!bound)
02178 break;
02179 }
02180 if (j < i) {
02181 isl_basic_set_free_inequality(hull, 1);
02182 return hull;
02183 }
02184
02185 for (j = i + 1; j < set->n; ++j) {
02186 int bound, neg;
02187 isl_int *ineq_j;
02188 entry = isl_hash_table_find(hull->ctx, data->p[j].table,
02189 c_hash, has_ineq, &v, 0);
02190 if (entry) {
02191 ineq_j = entry->data;
02192 neg = isl_seq_is_neg(ineq_j + 1,
02193 hull->ineq[k] + 1, v.len);
02194 if (neg)
02195 isl_int_neg(ineq_j[0], ineq_j[0]);
02196 if (isl_int_gt(ineq_j[0], hull->ineq[k][0]))
02197 isl_int_set(hull->ineq[k][0], ineq_j[0]);
02198 if (neg)
02199 isl_int_neg(ineq_j[0], ineq_j[0]);
02200 continue;
02201 }
02202 bound = is_bound(data, set, j, hull->ineq[k]);
02203 if (bound < 0)
02204 goto error;
02205 if (!bound)
02206 break;
02207 }
02208 if (j < set->n) {
02209 isl_basic_set_free_inequality(hull, 1);
02210 return hull;
02211 }
02212
02213 entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
02214 has_ineq, &v, 1);
02215 if (!entry)
02216 goto error;
02217 entry->data = hull->ineq[k];
02218
02219 return hull;
02220 error:
02221 isl_basic_set_free(hull);
02222 return NULL;
02223 }
02224
02225
02226
02227
02228
02229 static struct isl_basic_set *add_bounds(struct isl_basic_set *bset,
02230 struct sh_data *data, struct isl_set *set, int i)
02231 {
02232 int j, k;
02233 unsigned dim = isl_basic_set_total_dim(bset);
02234
02235 for (j = 0; j < set->p[i]->n_eq; ++j) {
02236 for (k = 0; k < 2; ++k) {
02237 isl_seq_neg(set->p[i]->eq[j], set->p[i]->eq[j], 1+dim);
02238 add_bound(bset, data, set, i, set->p[i]->eq[j]);
02239 }
02240 }
02241 for (j = 0; j < set->p[i]->n_ineq; ++j)
02242 add_bound(bset, data, set, i, set->p[i]->ineq[j]);
02243 return bset;
02244 }
02245
02246
02247
02248
02249 static struct isl_basic_set *uset_simple_hull(struct isl_set *set)
02250 {
02251 struct sh_data *data = NULL;
02252 struct isl_basic_set *hull = NULL;
02253 unsigned n_ineq;
02254 int i, j;
02255
02256 if (!set)
02257 return NULL;
02258
02259 n_ineq = 0;
02260 for (i = 0; i < set->n; ++i) {
02261 if (!set->p[i])
02262 goto error;
02263 n_ineq += 2 * set->p[i]->n_eq + set->p[i]->n_ineq;
02264 }
02265
02266 hull = isl_basic_set_alloc_dim(isl_dim_copy(set->dim), 0, 0, n_ineq);
02267 if (!hull)
02268 goto error;
02269
02270 data = sh_data_alloc(set, n_ineq);
02271 if (!data)
02272 goto error;
02273
02274 for (i = 0; i < set->n; ++i)
02275 hull = add_bounds(hull, data, set, i);
02276
02277 sh_data_free(data);
02278 isl_set_free(set);
02279
02280 return hull;
02281 error:
02282 sh_data_free(data);
02283 isl_basic_set_free(hull);
02284 isl_set_free(set);
02285 return NULL;
02286 }
02287
02288
02289
02290
02291 struct isl_basic_map *isl_map_simple_hull(struct isl_map *map)
02292 {
02293 struct isl_set *set = NULL;
02294 struct isl_basic_map *model = NULL;
02295 struct isl_basic_map *hull;
02296 struct isl_basic_map *affine_hull;
02297 struct isl_basic_set *bset = NULL;
02298
02299 if (!map)
02300 return NULL;
02301 if (map->n == 0) {
02302 hull = isl_basic_map_empty_like_map(map);
02303 isl_map_free(map);
02304 return hull;
02305 }
02306 if (map->n == 1) {
02307 hull = isl_basic_map_copy(map->p[0]);
02308 isl_map_free(map);
02309 return hull;
02310 }
02311
02312 map = isl_map_detect_equalities(map);
02313 affine_hull = isl_map_affine_hull(isl_map_copy(map));
02314 map = isl_map_align_divs(map);
02315 model = isl_basic_map_copy(map->p[0]);
02316
02317 set = isl_map_underlying_set(map);
02318
02319 bset = uset_simple_hull(set);
02320
02321 hull = isl_basic_map_overlying_set(bset, model);
02322
02323 hull = isl_basic_map_intersect(hull, affine_hull);
02324 hull = isl_basic_map_convex_hull(hull);
02325 ISL_F_SET(hull, ISL_BASIC_MAP_NO_IMPLICIT);
02326 ISL_F_SET(hull, ISL_BASIC_MAP_ALL_EQUALITIES);
02327
02328 return hull;
02329 }
02330
02331 struct isl_basic_set *isl_set_simple_hull(struct isl_set *set)
02332 {
02333 return (struct isl_basic_set *)
02334 isl_map_simple_hull((struct isl_map *)set);
02335 }
02336
02337
02338
02339 static struct isl_basic_set *set_bounds(struct isl_set *set, int dim)
02340 {
02341 unsigned set_dim = isl_set_dim(set, isl_dim_set);
02342 set = isl_set_copy(set);
02343 set = isl_set_eliminate_dims(set, dim + 1, set_dim - (dim + 1));
02344 set = isl_set_eliminate_dims(set, 0, dim);
02345 return isl_set_convex_hull(set);
02346 }
02347
02348
02349
02350
02351
02352 struct isl_basic_set *isl_set_bounded_simple_hull(struct isl_set *set)
02353 {
02354 int i, j;
02355 struct isl_basic_set *hull;
02356 unsigned nparam, left;
02357 int removed_divs = 0;
02358
02359 hull = isl_set_simple_hull(isl_set_copy(set));
02360 if (!hull)
02361 goto error;
02362
02363 nparam = isl_basic_set_dim(hull, isl_dim_param);
02364 for (i = 0; i < isl_basic_set_dim(hull, isl_dim_set); ++i) {
02365 int lower = 0, upper = 0;
02366 struct isl_basic_set *bounds;
02367
02368 left = isl_basic_set_total_dim(hull) - nparam - i - 1;
02369 for (j = 0; j < hull->n_eq; ++j) {
02370 if (isl_int_is_zero(hull->eq[j][1 + nparam + i]))
02371 continue;
02372 if (isl_seq_first_non_zero(hull->eq[j]+1+nparam+i+1,
02373 left) == -1)
02374 break;
02375 }
02376 if (j < hull->n_eq)
02377 continue;
02378
02379 for (j = 0; j < hull->n_ineq; ++j) {
02380 if (isl_int_is_zero(hull->ineq[j][1 + nparam + i]))
02381 continue;
02382 if (isl_seq_first_non_zero(hull->ineq[j]+1+nparam+i+1,
02383 left) != -1 ||
02384 isl_seq_first_non_zero(hull->ineq[j]+1+nparam,
02385 i) != -1)
02386 continue;
02387 if (isl_int_is_pos(hull->ineq[j][1 + nparam + i]))
02388 lower = 1;
02389 else
02390 upper = 1;
02391 if (lower && upper)
02392 break;
02393 }
02394
02395 if (lower && upper)
02396 continue;
02397
02398 if (!removed_divs) {
02399 set = isl_set_remove_divs(set);
02400 if (!set)
02401 goto error;
02402 removed_divs = 1;
02403 }
02404 bounds = set_bounds(set, i);
02405 hull = isl_basic_set_intersect(hull, bounds);
02406 if (!hull)
02407 goto error;
02408 }
02409
02410 isl_set_free(set);
02411 return hull;
02412 error:
02413 isl_set_free(set);
02414 return NULL;
02415 }