LCOV - code coverage report
Current view: top level - metalib_isl - isl_convex_hull.c (source / functions) Hit Total Coverage
Test: 2018-10-31_point_maint_greina16.lcov Lines: 529 1547 34.2 %
Date: 2018-11-01 11:27:00 Functions: 26 77 33.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008-2009 Katholieke Universiteit Leuven
       3             :  * Copyright 2014      INRIA Rocquencourt
       4             :  *
       5             :  * Use of this software is governed by the MIT license
       6             :  *
       7             :  * Written by Sven Verdoolaege, K.U.Leuven, Departement
       8             :  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
       9             :  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
      10             :  * B.P. 105 - 78153 Le Chesnay, France
      11             :  */
      12             : 
      13             : #include <isl_ctx_private.h>
      14             : #include <isl_map_private.h>
      15             : #include <isl_lp_private.h>
      16             : #include <isl/map.h>
      17             : #include <isl_mat_private.h>
      18             : #include <isl_vec_private.h>
      19             : #include <isl/set.h>
      20             : #include <isl_seq.h>
      21             : #include <isl_options_private.h>
      22             : #include "isl_equalities.h"
      23             : #include "isl_tab.h"
      24             : #include <isl_sort.h>
      25             : 
      26             : #include <bset_to_bmap.c>
      27             : #include <bset_from_bmap.c>
      28             : #include <set_to_map.c>
      29             : 
      30             : static __isl_give isl_basic_set *uset_convex_hull_wrap_bounded(
      31             :         __isl_take isl_set *set);
      32             : 
      33             : /* Remove redundant
      34             :  * constraints.  If the minimal value along the normal of a constraint
      35             :  * is the same if the constraint is removed, then the constraint is redundant.
      36             :  *
      37             :  * Since some constraints may be mutually redundant, sort the constraints
      38             :  * first such that constraints that involve existentially quantified
      39             :  * variables are considered for removal before those that do not.
      40             :  * The sorting is also needed for the use in map_simple_hull.
      41             :  *
      42             :  * Note that isl_tab_detect_implicit_equalities may also end up
      43             :  * marking some constraints as redundant.  Make sure the constraints
      44             :  * are preserved and undo those marking such that isl_tab_detect_redundant
      45             :  * can consider the constraints in the sorted order.
      46             :  *
      47             :  * Alternatively, we could have intersected the basic map with the
      48             :  * corresponding equality and then checked if the dimension was that
      49             :  * of a facet.
      50             :  */
      51  2957316438 : __isl_give isl_basic_map *isl_basic_map_remove_redundancies(
      52             :         __isl_take isl_basic_map *bmap)
      53             : {
      54             :         struct isl_tab *tab;
      55             : 
      56  2957316438 :         if (!bmap)
      57           0 :                 return NULL;
      58             : 
      59  2957316438 :         bmap = isl_basic_map_gauss(bmap, NULL);
      60  2957316438 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
      61           0 :                 return bmap;
      62  2957316438 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NO_REDUNDANT))
      63      110095 :                 return bmap;
      64  2957206343 :         if (bmap->n_ineq <= 1)
      65  2908499075 :                 return bmap;
      66             : 
      67    48707268 :         bmap = isl_basic_map_sort_constraints(bmap);
      68    48707268 :         tab = isl_tab_from_basic_map(bmap, 0);
      69    48707268 :         if (!tab)
      70           0 :                 goto error;
      71    48707268 :         tab->preserve = 1;
      72    48707268 :         if (isl_tab_detect_implicit_equalities(tab) < 0)
      73           0 :                 goto error;
      74    48707268 :         if (isl_tab_restore_redundant(tab) < 0)
      75           0 :                 goto error;
      76    48707268 :         tab->preserve = 0;
      77    48707268 :         if (isl_tab_detect_redundant(tab) < 0)
      78           0 :                 goto error;
      79    48707268 :         bmap = isl_basic_map_update_from_tab(bmap, tab);
      80    48707268 :         isl_tab_free(tab);
      81    48707268 :         if (!bmap)
      82           0 :                 return NULL;
      83    48707268 :         ISL_F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
      84    48707268 :         ISL_F_SET(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
      85    48707268 :         return bmap;
      86             : error:
      87           0 :         isl_tab_free(tab);
      88           0 :         isl_basic_map_free(bmap);
      89           0 :         return NULL;
      90             : }
      91             : 
      92           0 : __isl_give isl_basic_set *isl_basic_set_remove_redundancies(
      93             :         __isl_take isl_basic_set *bset)
      94             : {
      95           0 :         return bset_from_bmap(
      96             :                 isl_basic_map_remove_redundancies(bset_to_bmap(bset)));
      97             : }
      98             : 
      99             : /* Remove redundant constraints in each of the basic maps.
     100             :  */
     101           0 : __isl_give isl_map *isl_map_remove_redundancies(__isl_take isl_map *map)
     102             : {
     103           0 :         return isl_map_inline_foreach_basic_map(map,
     104             :                                             &isl_basic_map_remove_redundancies);
     105             : }
     106             : 
     107           0 : __isl_give isl_set *isl_set_remove_redundancies(__isl_take isl_set *set)
     108             : {
     109           0 :         return isl_map_remove_redundancies(set);
     110             : }
     111             : 
     112             : /* Check if the set set is bound in the direction of the affine
     113             :  * constraint c and if so, set the constant term such that the
     114             :  * resulting constraint is a bounding constraint for the set.
     115             :  */
     116   367832453 : static int uset_is_bound(__isl_keep isl_set *set, isl_int *c, unsigned len)
     117             : {
     118             :         int first;
     119             :         int j;
     120             :         isl_int opt;
     121             :         isl_int opt_denom;
     122             : 
     123   367832453 :         isl_int_init(opt);
     124   367832453 :         isl_int_init(opt_denom);
     125   367832453 :         first = 1;
     126  1579181908 :         for (j = 0; j < set->n; ++j) {
     127             :                 enum isl_lp_result res;
     128             : 
     129  1211349455 :                 if (ISL_F_ISSET(set->p[j], ISL_BASIC_SET_EMPTY))
     130           0 :                         continue;
     131             : 
     132  1211349455 :                 res = isl_basic_set_solve_lp(set->p[j],
     133  1211349455 :                                 0, c, set->ctx->one, &opt, &opt_denom, NULL);
     134  1211349455 :                 if (res == isl_lp_unbounded)
     135           0 :                         break;
     136  1211349455 :                 if (res == isl_lp_error)
     137           0 :                         goto error;
     138  1211349455 :                 if (res == isl_lp_empty) {
     139           0 :                         set->p[j] = isl_basic_set_set_to_empty(set->p[j]);
     140           0 :                         if (!set->p[j])
     141           0 :                                 goto error;
     142           0 :                         continue;
     143             :                 }
     144  1211349455 :                 if (first || isl_int_is_neg(opt)) {
     145   602226357 :                         if (!isl_int_is_one(opt_denom))
     146     2487716 :                                 isl_seq_scale(c, c, opt_denom, len);
     147   602226357 :                         isl_int_sub(c[0], c[0], opt);
     148             :                 }
     149  1211349455 :                 first = 0;
     150             :         }
     151   367832453 :         isl_int_clear(opt);
     152   367832453 :         isl_int_clear(opt_denom);
     153   367832453 :         return j >= set->n;
     154             : error:
     155           0 :         isl_int_clear(opt);
     156           0 :         isl_int_clear(opt_denom);
     157           0 :         return -1;
     158             : }
     159             : 
     160  4613230158 : static struct isl_basic_set *isl_basic_set_add_equality(
     161             :         struct isl_basic_set *bset, isl_int *c)
     162             : {
     163             :         int i;
     164             :         unsigned dim;
     165             : 
     166  4613230158 :         if (!bset)
     167           0 :                 return NULL;
     168             : 
     169  4613230158 :         if (ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY))
     170           0 :                 return bset;
     171             : 
     172  4613230158 :         isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0, goto error);
     173  4613230158 :         isl_assert(bset->ctx, bset->n_div == 0, goto error);
     174  4613230158 :         dim = isl_basic_set_n_dim(bset);
     175  4613230158 :         bset = isl_basic_set_cow(bset);
     176  4613230158 :         bset = isl_basic_set_extend(bset, 0, dim, 0, 1, 0);
     177  4613230158 :         i = isl_basic_set_alloc_equality(bset);
     178  4613230158 :         if (i < 0)
     179           0 :                 goto error;
     180  4613230158 :         isl_seq_cpy(bset->eq[i], c, 1 + dim);
     181  4613230158 :         return bset;
     182             : error:
     183           0 :         isl_basic_set_free(bset);
     184           0 :         return NULL;
     185             : }
     186             : 
     187   645696824 : static __isl_give isl_set *isl_set_add_basic_set_equality(
     188             :         __isl_take isl_set *set, isl_int *c)
     189             : {
     190             :         int i;
     191             : 
     192   645696824 :         set = isl_set_cow(set);
     193   645696824 :         if (!set)
     194           0 :                 return NULL;
     195  2822457582 :         for (i = 0; i < set->n; ++i) {
     196  2176760758 :                 set->p[i] = isl_basic_set_add_equality(set->p[i], c);
     197  2176760758 :                 if (!set->p[i])
     198           0 :                         goto error;
     199             :         }
     200   645696824 :         return set;
     201             : error:
     202           0 :         isl_set_free(set);
     203           0 :         return NULL;
     204             : }
     205             : 
     206             : /* Given a union of basic sets, construct the constraints for wrapping
     207             :  * a facet around one of its ridges.
     208             :  * In particular, if each of n the d-dimensional basic sets i in "set"
     209             :  * contains the origin, satisfies the constraints x_1 >= 0 and x_2 >= 0
     210             :  * and is defined by the constraints
     211             :  *                                  [ 1 ]
     212             :  *                              A_i [ x ]  >= 0
     213             :  *
     214             :  * then the resulting set is of dimension n*(1+d) and has as constraints
     215             :  *
     216             :  *                                  [ a_i ]
     217             :  *                              A_i [ x_i ] >= 0
     218             :  *
     219             :  *                                    a_i   >= 0
     220             :  *
     221             :  *                      \sum_i x_{i,1} = 1
     222             :  */
     223  1128637564 : static __isl_give isl_basic_set *wrap_constraints(__isl_keep isl_set *set)
     224             : {
     225             :         struct isl_basic_set *lp;
     226             :         unsigned n_eq;
     227             :         unsigned n_ineq;
     228             :         int i, j, k;
     229             :         unsigned dim, lp_dim;
     230             : 
     231  1128637564 :         if (!set)
     232           0 :                 return NULL;
     233             : 
     234  1128637564 :         dim = 1 + isl_set_n_dim(set);
     235  1128637564 :         n_eq = 1;
     236  1128637564 :         n_ineq = set->n;
     237  5048629869 :         for (i = 0; i < set->n; ++i) {
     238  3919992305 :                 n_eq += set->p[i]->n_eq;
     239  3919992305 :                 n_ineq += set->p[i]->n_ineq;
     240             :         }
     241  1128637564 :         lp = isl_basic_set_alloc(set->ctx, 0, dim * set->n, 0, n_eq, n_ineq);
     242  1128637564 :         lp = isl_basic_set_set_rational(lp);
     243  1128637564 :         if (!lp)
     244           0 :                 return NULL;
     245  1128637564 :         lp_dim = isl_basic_set_n_dim(lp);
     246  1128637564 :         k = isl_basic_set_alloc_equality(lp);
     247  1128637564 :         isl_int_set_si(lp->eq[k][0], -1);
     248  5048629869 :         for (i = 0; i < set->n; ++i) {
     249  3919992305 :                 isl_int_set_si(lp->eq[k][1+dim*i], 0);
     250  3919992305 :                 isl_int_set_si(lp->eq[k][1+dim*i+1], 1);
     251  3919992305 :                 isl_seq_clr(lp->eq[k]+1+dim*i+2, dim-2);
     252             :         }
     253  5048629869 :         for (i = 0; i < set->n; ++i) {
     254  3919992305 :                 k = isl_basic_set_alloc_inequality(lp);
     255  3919992305 :                 isl_seq_clr(lp->ineq[k], 1+lp_dim);
     256  3919992305 :                 isl_int_set_si(lp->ineq[k][1+dim*i], 1);
     257             : 
     258 14040782857 :                 for (j = 0; j < set->p[i]->n_eq; ++j) {
     259 10120790552 :                         k = isl_basic_set_alloc_equality(lp);
     260 10120790552 :                         isl_seq_clr(lp->eq[k], 1+dim*i);
     261 10120790552 :                         isl_seq_cpy(lp->eq[k]+1+dim*i, set->p[i]->eq[j], dim);
     262 10120790552 :                         isl_seq_clr(lp->eq[k]+1+dim*(i+1), dim*(set->n-i-1));
     263             :                 }
     264             : 
     265  4037844297 :                 for (j = 0; j < set->p[i]->n_ineq; ++j) {
     266   117851992 :                         k = isl_basic_set_alloc_inequality(lp);
     267   117851992 :                         isl_seq_clr(lp->ineq[k], 1+dim*i);
     268   117851992 :                         isl_seq_cpy(lp->ineq[k]+1+dim*i, set->p[i]->ineq[j], dim);
     269   117851992 :                         isl_seq_clr(lp->ineq[k]+1+dim*(i+1), dim*(set->n-i-1));
     270             :                 }
     271             :         }
     272  1128637564 :         return lp;
     273             : }
     274             : 
     275             : /* Given a facet "facet" of the convex hull of "set" and a facet "ridge"
     276             :  * of that facet, compute the other facet of the convex hull that contains
     277             :  * the ridge.
     278             :  *
     279             :  * We first transform the set such that the facet constraint becomes
     280             :  *
     281             :  *                      x_1 >= 0
     282             :  *
     283             :  * I.e., the facet lies in
     284             :  *
     285             :  *                      x_1 = 0
     286             :  *
     287             :  * and on that facet, the constraint that defines the ridge is
     288             :  *
     289             :  *                      x_2 >= 0
     290             :  *
     291             :  * (This transformation is not strictly needed, all that is needed is
     292             :  * that the ridge contains the origin.)
     293             :  *
     294             :  * Since the ridge contains the origin, the cone of the convex hull
     295             :  * will be of the form
     296             :  *
     297             :  *                      x_1 >= 0
     298             :  *                      x_2 >= a x_1
     299             :  *
     300             :  * with this second constraint defining the new facet.
     301             :  * The constant a is obtained by settting x_1 in the cone of the
     302             :  * convex hull to 1 and minimizing x_2.
     303             :  * Now, each element in the cone of the convex hull is the sum
     304             :  * of elements in the cones of the basic sets.
     305             :  * If a_i is the dilation factor of basic set i, then the problem
     306             :  * we need to solve is
     307             :  *
     308             :  *                      min \sum_i x_{i,2}
     309             :  *                      st
     310             :  *                              \sum_i x_{i,1} = 1
     311             :  *                                  a_i   >= 0
     312             :  *                                [ a_i ]
     313             :  *                              A [ x_i ] >= 0
     314             :  *
     315             :  * with
     316             :  *                                  [  1  ]
     317             :  *                              A_i [ x_i ] >= 0
     318             :  *
     319             :  * the constraints of each (transformed) basic set.
     320             :  * If a = n/d, then the constraint defining the new facet (in the transformed
     321             :  * space) is
     322             :  *
     323             :  *                      -n x_1 + d x_2 >= 0
     324             :  *
     325             :  * In the original space, we need to take the same combination of the
     326             :  * corresponding constraints "facet" and "ridge".
     327             :  *
     328             :  * If a = -infty = "-1/0", then we just return the original facet constraint.
     329             :  * This means that the facet is unbounded, but has a bounded intersection
     330             :  * with the union of sets.
     331             :  */
     332  1128637564 : isl_int *isl_set_wrap_facet(__isl_keep isl_set *set,
     333             :         isl_int *facet, isl_int *ridge)
     334             : {
     335             :         int i;
     336             :         isl_ctx *ctx;
     337  1128637564 :         struct isl_mat *T = NULL;
     338  1128637564 :         struct isl_basic_set *lp = NULL;
     339             :         struct isl_vec *obj;
     340             :         enum isl_lp_result res;
     341             :         isl_int num, den;
     342             :         unsigned dim;
     343             : 
     344  1128637564 :         if (!set)
     345           0 :                 return NULL;
     346  1128637564 :         ctx = set->ctx;
     347  1128637564 :         set = isl_set_copy(set);
     348  1128637564 :         set = isl_set_set_rational(set);
     349             : 
     350  1128637564 :         dim = 1 + isl_set_n_dim(set);
     351  1128637564 :         T = isl_mat_alloc(ctx, 3, dim);
     352  1128637564 :         if (!T)
     353           0 :                 goto error;
     354  1128637564 :         isl_int_set_si(T->row[0][0], 1);
     355  1128637564 :         isl_seq_clr(T->row[0]+1, dim - 1);
     356  1128637564 :         isl_seq_cpy(T->row[1], facet, dim);
     357  1128637564 :         isl_seq_cpy(T->row[2], ridge, dim);
     358  1128637564 :         T = isl_mat_right_inverse(T);
     359  1128637564 :         set = isl_set_preimage(set, T);
     360  1128637564 :         T = NULL;
     361  1128637564 :         if (!set)
     362           0 :                 goto error;
     363  1128637564 :         lp = wrap_constraints(set);
     364  1128637564 :         obj = isl_vec_alloc(ctx, 1 + dim*set->n);
     365  1128637564 :         if (!obj)
     366           0 :                 goto error;
     367  1128637564 :         isl_int_set_si(obj->block.data[0], 0);
     368  5048629869 :         for (i = 0; i < set->n; ++i) {
     369  3919992305 :                 isl_seq_clr(obj->block.data + 1 + dim*i, 2);
     370  3919992305 :                 isl_int_set_si(obj->block.data[1 + dim*i+2], 1);
     371  3919992305 :                 isl_seq_clr(obj->block.data + 1 + dim*i+3, dim-3);
     372             :         }
     373  1128637564 :         isl_int_init(num);
     374  1128637564 :         isl_int_init(den);
     375  1128637564 :         res = isl_basic_set_solve_lp(lp, 0,
     376  1128637564 :                             obj->block.data, ctx->one, &num, &den, NULL);
     377  1128637564 :         if (res == isl_lp_ok) {
     378  1128211583 :                 isl_int_neg(num, num);
     379  1128211583 :                 isl_seq_combine(facet, num, facet, den, ridge, dim);
     380  1128211583 :                 isl_seq_normalize(ctx, facet, dim);
     381             :         }
     382  1128637564 :         isl_int_clear(num);
     383  1128637564 :         isl_int_clear(den);
     384  1128637564 :         isl_vec_free(obj);
     385  1128637564 :         isl_basic_set_free(lp);
     386  1128637564 :         isl_set_free(set);
     387  1128637564 :         if (res == isl_lp_error)
     388           0 :                 return NULL;
     389  1128637564 :         isl_assert(ctx, res == isl_lp_ok || res == isl_lp_unbounded, 
     390             :                    return NULL);
     391  1128637564 :         return facet;
     392             : error:
     393           0 :         isl_basic_set_free(lp);
     394           0 :         isl_mat_free(T);
     395           0 :         isl_set_free(set);
     396           0 :         return NULL;
     397             : }
     398             : 
     399             : /* Compute the constraint of a facet of "set".
     400             :  *
     401             :  * We first compute the intersection with a bounding constraint
     402             :  * that is orthogonal to one of the coordinate axes.
     403             :  * If the affine hull of this intersection has only one equality,
     404             :  * we have found a facet.
     405             :  * Otherwise, we wrap the current bounding constraint around
     406             :  * one of the equalities of the face (one that is not equal to
     407             :  * the current bounding constraint).
     408             :  * This process continues until we have found a facet.
     409             :  * The dimension of the intersection increases by at least
     410             :  * one on each iteration, so termination is guaranteed.
     411             :  */
     412   367832453 : static __isl_give isl_mat *initial_facet_constraint(__isl_keep isl_set *set)
     413             : {
     414   367832453 :         struct isl_set *slice = NULL;
     415   367832453 :         struct isl_basic_set *face = NULL;
     416             :         int i;
     417   367832453 :         unsigned dim = isl_set_n_dim(set);
     418             :         int is_bound;
     419   367832453 :         isl_mat *bounds = NULL;
     420             : 
     421   367832453 :         isl_assert(set->ctx, set->n > 0, goto error);
     422   367832453 :         bounds = isl_mat_alloc(set->ctx, 1, 1 + dim);
     423   367832453 :         if (!bounds)
     424           0 :                 return NULL;
     425             : 
     426   367832453 :         isl_seq_clr(bounds->row[0], dim);
     427   367832453 :         isl_int_set_si(bounds->row[0][1 + dim - 1], 1);
     428   367832453 :         is_bound = uset_is_bound(set, bounds->row[0], 1 + dim);
     429   367832453 :         if (is_bound < 0)
     430           0 :                 goto error;
     431   367832453 :         isl_assert(set->ctx, is_bound, goto error);
     432   367832453 :         isl_seq_normalize(set->ctx, bounds->row[0], 1 + dim);
     433   367832453 :         bounds->n_row = 1;
     434             : 
     435             :         for (;;) {
     436   645696824 :                 slice = isl_set_copy(set);
     437   645696824 :                 slice = isl_set_add_basic_set_equality(slice, bounds->row[0]);
     438   645696824 :                 face = isl_set_affine_hull(slice);
     439   645696824 :                 if (!face)
     440           0 :                         goto error;
     441   645696824 :                 if (face->n_eq == 1) {
     442   367832453 :                         isl_basic_set_free(face);
     443   367832453 :                         break;
     444             :                 }
     445   531910762 :                 for (i = 0; i < face->n_eq; ++i)
     446   811191742 :                         if (!isl_seq_eq(bounds->row[0], face->eq[i], 1 + dim) &&
     447   558561960 :                             !isl_seq_is_neg(bounds->row[0],
     448   279280980 :                                                 face->eq[i], 1 + dim))
     449   277864371 :                                 break;
     450   277864371 :                 isl_assert(set->ctx, i < face->n_eq, goto error);
     451   277864371 :                 if (!isl_set_wrap_facet(set, bounds->row[0], face->eq[i]))
     452           0 :                         goto error;
     453   277864371 :                 isl_seq_normalize(set->ctx, bounds->row[0], bounds->n_col);
     454   277864371 :                 isl_basic_set_free(face);
     455   277864371 :         }
     456             : 
     457   367832453 :         return bounds;
     458             : error:
     459           0 :         isl_basic_set_free(face);
     460           0 :         isl_mat_free(bounds);
     461           0 :         return NULL;
     462             : }
     463             : 
     464             : /* Given the bounding constraint "c" of a facet of the convex hull of "set",
     465             :  * compute a hyperplane description of the facet, i.e., compute the facets
     466             :  * of the facet.
     467             :  *
     468             :  * We compute an affine transformation that transforms the constraint
     469             :  *
     470             :  *                        [ 1 ]
     471             :  *                      c [ x ] = 0
     472             :  *
     473             :  * to the constraint
     474             :  *
     475             :  *                         z_1  = 0
     476             :  *
     477             :  * by computing the right inverse U of a matrix that starts with the rows
     478             :  *
     479             :  *                      [ 1 0 ]
     480             :  *                      [  c  ]
     481             :  *
     482             :  * Then
     483             :  *                      [ 1 ]     [ 1 ]
     484             :  *                      [ x ] = U [ z ]
     485             :  * and
     486             :  *                      [ 1 ]     [ 1 ]
     487             :  *                      [ z ] = Q [ x ]
     488             :  *
     489             :  * with Q = U^{-1}
     490             :  * Since z_1 is zero, we can drop this variable as well as the corresponding
     491             :  * column of U to obtain
     492             :  *
     493             :  *                      [ 1 ]      [ 1  ]
     494             :  *                      [ x ] = U' [ z' ]
     495             :  * and
     496             :  *                      [ 1  ]      [ 1 ]
     497             :  *                      [ z' ] = Q' [ x ]
     498             :  *
     499             :  * with Q' equal to Q, but without the corresponding row.
     500             :  * After computing the facets of the facet in the z' space,
     501             :  * we convert them back to the x space through Q.
     502             :  */
     503  1218234700 : static __isl_give isl_basic_set *compute_facet(__isl_keep isl_set *set,
     504             :         isl_int *c)
     505             : {
     506             :         struct isl_mat *m, *U, *Q;
     507  1218234700 :         struct isl_basic_set *facet = NULL;
     508             :         struct isl_ctx *ctx;
     509             :         unsigned dim;
     510             : 
     511  1218234700 :         ctx = set->ctx;
     512  1218234700 :         set = isl_set_copy(set);
     513  1218234700 :         dim = isl_set_n_dim(set);
     514  1218234700 :         m = isl_mat_alloc(set->ctx, 2, 1 + dim);
     515  1218234700 :         if (!m)
     516           0 :                 goto error;
     517  1218234700 :         isl_int_set_si(m->row[0][0], 1);
     518  1218234700 :         isl_seq_clr(m->row[0]+1, dim);
     519  1218234700 :         isl_seq_cpy(m->row[1], c, 1+dim);
     520  1218234700 :         U = isl_mat_right_inverse(m);
     521  1218234700 :         Q = isl_mat_right_inverse(isl_mat_copy(U));
     522  1218234700 :         U = isl_mat_drop_cols(U, 1, 1);
     523  1218234700 :         Q = isl_mat_drop_rows(Q, 1, 1);
     524  1218234700 :         set = isl_set_preimage(set, U);
     525  1218234700 :         facet = uset_convex_hull_wrap_bounded(set);
     526  1218234700 :         facet = isl_basic_set_preimage(facet, Q);
     527  1218234700 :         if (facet && facet->n_eq != 0)
     528           0 :                 isl_die(ctx, isl_error_internal, "unexpected equality",
     529             :                         return isl_basic_set_free(facet));
     530  1218234700 :         return facet;
     531             : error:
     532           0 :         isl_basic_set_free(facet);
     533           0 :         isl_set_free(set);
     534           0 :         return NULL;
     535             : }
     536             : 
     537             : /* Given an initial facet constraint, compute the remaining facets.
     538             :  * We do this by running through all facets found so far and computing
     539             :  * the adjacent facets through wrapping, adding those facets that we
     540             :  * hadn't already found before.
     541             :  *
     542             :  * For each facet we have found so far, we first compute its facets
     543             :  * in the resulting convex hull.  That is, we compute the ridges
     544             :  * of the resulting convex hull contained in the facet.
     545             :  * We also compute the corresponding facet in the current approximation
     546             :  * of the convex hull.  There is no need to wrap around the ridges
     547             :  * in this facet since that would result in a facet that is already
     548             :  * present in the current approximation.
     549             :  *
     550             :  * This function can still be significantly optimized by checking which of
     551             :  * the facets of the basic sets are also facets of the convex hull and
     552             :  * using all the facets so far to help in constructing the facets of the
     553             :  * facets
     554             :  * and/or
     555             :  * using the technique in section "3.1 Ridge Generation" of
     556             :  * "Extended Convex Hull" by Fukuda et al.
     557             :  */
     558   367992152 : static __isl_give isl_basic_set *extend(__isl_take isl_basic_set *hull,
     559             :         __isl_keep isl_set *set)
     560             : {
     561             :         int i, j, f;
     562             :         int k;
     563   367992152 :         struct isl_basic_set *facet = NULL;
     564   367992152 :         struct isl_basic_set *hull_facet = NULL;
     565             :         unsigned dim;
     566             : 
     567   367992152 :         if (!hull)
     568           0 :                 return NULL;
     569             : 
     570   367992152 :         isl_assert(set->ctx, set->n > 0, goto error);
     571             : 
     572   367992152 :         dim = isl_set_n_dim(set);
     573             : 
     574  1586226852 :         for (i = 0; i < hull->n_ineq; ++i) {
     575  1218234700 :                 facet = compute_facet(set, hull->ineq[i]);
     576  1218234700 :                 facet = isl_basic_set_add_equality(facet, hull->ineq[i]);
     577  1218234700 :                 facet = isl_basic_set_gauss(facet, NULL);
     578  1218234700 :                 facet = isl_basic_set_normalize_constraints(facet);
     579  1218234700 :                 hull_facet = isl_basic_set_copy(hull);
     580  1218234700 :                 hull_facet = isl_basic_set_add_equality(hull_facet, hull->ineq[i]);
     581  1218234700 :                 hull_facet = isl_basic_set_gauss(hull_facet, NULL);
     582  1218234700 :                 hull_facet = isl_basic_set_normalize_constraints(hull_facet);
     583  1218234700 :                 if (!facet || !hull_facet)
     584             :                         goto error;
     585  1218234700 :                 hull = isl_basic_set_cow(hull);
     586  1218234700 :                 hull = isl_basic_set_extend_space(hull,
     587             :                         isl_space_copy(hull->dim), 0, 0, facet->n_ineq);
     588  1218234700 :                 if (!hull)
     589           0 :                         goto error;
     590  4137147884 :                 for (j = 0; j < facet->n_ineq; ++j) {
     591  4811182110 :                         for (f = 0; f < hull_facet->n_ineq; ++f)
     592  7922022432 :                                 if (isl_seq_eq(facet->ineq[j],
     593  3961011216 :                                                 hull_facet->ineq[f], 1 + dim))
     594  2068742290 :                                         break;
     595  2918913184 :                         if (f < hull_facet->n_ineq)
     596  2068742290 :                                 continue;
     597   850170894 :                         k = isl_basic_set_alloc_inequality(hull);
     598   850170894 :                         if (k < 0)
     599           0 :                                 goto error;
     600   850170894 :                         isl_seq_cpy(hull->ineq[k], hull->ineq[i], 1+dim);
     601   850170894 :                         if (!isl_set_wrap_facet(set, hull->ineq[k], facet->ineq[j]))
     602           0 :                                 goto error;
     603             :                 }
     604  1218234700 :                 isl_basic_set_free(hull_facet);
     605  1218234700 :                 isl_basic_set_free(facet);
     606             :         }
     607   367992152 :         hull = isl_basic_set_simplify(hull);
     608   367992152 :         hull = isl_basic_set_finalize(hull);
     609   367992152 :         return hull;
     610             : error:
     611           0 :         isl_basic_set_free(hull_facet);
     612           0 :         isl_basic_set_free(facet);
     613           0 :         isl_basic_set_free(hull);
     614           0 :         return NULL;
     615             : }
     616             : 
     617             : /* Special case for computing the convex hull of a one dimensional set.
     618             :  * We simply collect the lower and upper bounds of each basic set
     619             :  * and the biggest of those.
     620             :  */
     621   840281030 : static __isl_give isl_basic_set *convex_hull_1d(__isl_take isl_set *set)
     622             : {
     623   840281030 :         struct isl_mat *c = NULL;
     624   840281030 :         isl_int *lower = NULL;
     625   840281030 :         isl_int *upper = NULL;
     626             :         int i, j, k;
     627             :         isl_int a, b;
     628             :         struct isl_basic_set *hull;
     629             : 
     630  2527040783 :         for (i = 0; i < set->n; ++i) {
     631  1686759753 :                 set->p[i] = isl_basic_set_simplify(set->p[i]);
     632  1686759753 :                 if (!set->p[i])
     633           0 :                         goto error;
     634             :         }
     635   840281030 :         set = isl_set_remove_empty_parts(set);
     636   840281030 :         if (!set)
     637           0 :                 goto error;
     638   840281030 :         isl_assert(set->ctx, set->n > 0, goto error);
     639   840281030 :         c = isl_mat_alloc(set->ctx, 2, 2);
     640   840281030 :         if (!c)
     641           0 :                 goto error;
     642             : 
     643   840281030 :         if (set->p[0]->n_eq > 0) {
     644   839995434 :                 isl_assert(set->ctx, set->p[0]->n_eq == 1, goto error);
     645   839995434 :                 lower = c->row[0];
     646   839995434 :                 upper = c->row[1];
     647   839995434 :                 if (isl_int_is_pos(set->p[0]->eq[0][1])) {
     648   839995434 :                         isl_seq_cpy(lower, set->p[0]->eq[0], 2);
     649   839995434 :                         isl_seq_neg(upper, set->p[0]->eq[0], 2);
     650             :                 } else {
     651           0 :                         isl_seq_neg(lower, set->p[0]->eq[0], 2);
     652           0 :                         isl_seq_cpy(upper, set->p[0]->eq[0], 2);
     653             :                 }
     654             :         } else {
     655      856788 :                 for (j = 0; j < set->p[0]->n_ineq; ++j) {
     656      571192 :                         if (isl_int_is_pos(set->p[0]->ineq[j][1])) {
     657      285596 :                                 lower = c->row[0];
     658      285596 :                                 isl_seq_cpy(lower, set->p[0]->ineq[j], 2);
     659             :                         } else {
     660      285596 :                                 upper = c->row[1];
     661      285596 :                                 isl_seq_cpy(upper, set->p[0]->ineq[j], 2);
     662             :                         }
     663             :                 }
     664             :         }
     665             : 
     666   840281030 :         isl_int_init(a);
     667   840281030 :         isl_int_init(b);
     668  2527040783 :         for (i = 0; i < set->n; ++i) {
     669  1686759753 :                 struct isl_basic_set *bset = set->p[i];
     670  1686759753 :                 int has_lower = 0;
     671  1686759753 :                 int has_upper = 0;
     672             : 
     673  3372922127 :                 for (j = 0; j < bset->n_eq; ++j) {
     674  1686162374 :                         has_lower = 1;
     675  1686162374 :                         has_upper = 1;
     676  1686162374 :                         if (lower) {
     677  1686162374 :                                 isl_int_mul(a, lower[0], bset->eq[j][1]);
     678  1686162374 :                                 isl_int_mul(b, lower[1], bset->eq[j][0]);
     679  1686162374 :                                 if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
     680   428684648 :                                         isl_seq_cpy(lower, bset->eq[j], 2);
     681  1686162374 :                                 if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
     682           0 :                                         isl_seq_neg(lower, bset->eq[j], 2);
     683             :                         }
     684  1686162374 :                         if (upper) {
     685  1686162374 :                                 isl_int_mul(a, upper[0], bset->eq[j][1]);
     686  1686162374 :                                 isl_int_mul(b, upper[1], bset->eq[j][0]);
     687  1686162374 :                                 if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
     688   415192526 :                                         isl_seq_neg(upper, bset->eq[j], 2);
     689  1686162374 :                                 if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
     690           0 :                                         isl_seq_cpy(upper, bset->eq[j], 2);
     691             :                         }
     692             :                 }
     693  1687954511 :                 for (j = 0; j < bset->n_ineq; ++j) {
     694     1194758 :                         if (isl_int_is_pos(bset->ineq[j][1]))
     695      597379 :                                 has_lower = 1;
     696     1194758 :                         if (isl_int_is_neg(bset->ineq[j][1]))
     697      597379 :                                 has_upper = 1;
     698     1194758 :                         if (lower && isl_int_is_pos(bset->ineq[j][1])) {
     699      597379 :                                 isl_int_mul(a, lower[0], bset->ineq[j][1]);
     700      597379 :                                 isl_int_mul(b, lower[1], bset->ineq[j][0]);
     701      597379 :                                 if (isl_int_lt(a, b))
     702      201176 :                                         isl_seq_cpy(lower, bset->ineq[j], 2);
     703             :                         }
     704     1194758 :                         if (upper && isl_int_is_neg(bset->ineq[j][1])) {
     705      597379 :                                 isl_int_mul(a, upper[0], bset->ineq[j][1]);
     706      597379 :                                 isl_int_mul(b, upper[1], bset->ineq[j][0]);
     707      597379 :                                 if (isl_int_gt(a, b))
     708       99108 :                                         isl_seq_cpy(upper, bset->ineq[j], 2);
     709             :                         }
     710             :                 }
     711  1686759753 :                 if (!has_lower)
     712           0 :                         lower = NULL;
     713  1686759753 :                 if (!has_upper)
     714           0 :                         upper = NULL;
     715             :         }
     716   840281030 :         isl_int_clear(a);
     717   840281030 :         isl_int_clear(b);
     718             : 
     719   840281030 :         hull = isl_basic_set_alloc(set->ctx, 0, 1, 0, 0, 2);
     720   840281030 :         hull = isl_basic_set_set_rational(hull);
     721   840281030 :         if (!hull)
     722           0 :                 goto error;
     723   840281030 :         if (lower) {
     724   840281030 :                 k = isl_basic_set_alloc_inequality(hull);
     725   840281030 :                 isl_seq_cpy(hull->ineq[k], lower, 2);
     726             :         }
     727   840281030 :         if (upper) {
     728   840281030 :                 k = isl_basic_set_alloc_inequality(hull);
     729   840281030 :                 isl_seq_cpy(hull->ineq[k], upper, 2);
     730             :         }
     731   840281030 :         hull = isl_basic_set_finalize(hull);
     732   840281030 :         isl_set_free(set);
     733   840281030 :         isl_mat_free(c);
     734   840281030 :         return hull;
     735             : error:
     736           0 :         isl_set_free(set);
     737           0 :         isl_mat_free(c);
     738           0 :         return NULL;
     739             : }
     740             : 
     741        6446 : static __isl_give isl_basic_set *convex_hull_0d(__isl_take isl_set *set)
     742             : {
     743             :         struct isl_basic_set *convex_hull;
     744             : 
     745        6446 :         if (!set)
     746           0 :                 return NULL;
     747             : 
     748        6446 :         if (isl_set_is_empty(set))
     749           0 :                 convex_hull = isl_basic_set_empty(isl_space_copy(set->dim));
     750             :         else
     751        6446 :                 convex_hull = isl_basic_set_universe(isl_space_copy(set->dim));
     752        6446 :         isl_set_free(set);
     753        6446 :         return convex_hull;
     754             : }
     755             : 
     756             : /* Compute the convex hull of a pair of basic sets without any parameters or
     757             :  * integer divisions using Fourier-Motzkin elimination.
     758             :  * The convex hull is the set of all points that can be written as
     759             :  * the sum of points from both basic sets (in homogeneous coordinates).
     760             :  * We set up the constraints in a space with dimensions for each of
     761             :  * the three sets and then project out the dimensions corresponding
     762             :  * to the two original basic sets, retaining only those corresponding
     763             :  * to the convex hull.
     764             :  */
     765           0 : static __isl_give isl_basic_set *convex_hull_pair_elim(
     766             :         __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
     767             : {
     768             :         int i, j, k;
     769             :         struct isl_basic_set *bset[2];
     770           0 :         struct isl_basic_set *hull = NULL;
     771             :         unsigned dim;
     772             : 
     773           0 :         if (!bset1 || !bset2)
     774             :                 goto error;
     775             : 
     776           0 :         dim = isl_basic_set_n_dim(bset1);
     777           0 :         hull = isl_basic_set_alloc(bset1->ctx, 0, 2 + 3 * dim, 0,
     778           0 :                                 1 + dim + bset1->n_eq + bset2->n_eq,
     779           0 :                                 2 + bset1->n_ineq + bset2->n_ineq);
     780           0 :         bset[0] = bset1;
     781           0 :         bset[1] = bset2;
     782           0 :         for (i = 0; i < 2; ++i) {
     783           0 :                 for (j = 0; j < bset[i]->n_eq; ++j) {
     784           0 :                         k = isl_basic_set_alloc_equality(hull);
     785           0 :                         if (k < 0)
     786           0 :                                 goto error;
     787           0 :                         isl_seq_clr(hull->eq[k], (i+1) * (1+dim));
     788           0 :                         isl_seq_clr(hull->eq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
     789           0 :                         isl_seq_cpy(hull->eq[k]+(i+1)*(1+dim), bset[i]->eq[j],
     790             :                                         1+dim);
     791             :                 }
     792           0 :                 for (j = 0; j < bset[i]->n_ineq; ++j) {
     793           0 :                         k = isl_basic_set_alloc_inequality(hull);
     794           0 :                         if (k < 0)
     795           0 :                                 goto error;
     796           0 :                         isl_seq_clr(hull->ineq[k], (i+1) * (1+dim));
     797           0 :                         isl_seq_clr(hull->ineq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
     798           0 :                         isl_seq_cpy(hull->ineq[k]+(i+1)*(1+dim),
     799           0 :                                         bset[i]->ineq[j], 1+dim);
     800             :                 }
     801           0 :                 k = isl_basic_set_alloc_inequality(hull);
     802           0 :                 if (k < 0)
     803           0 :                         goto error;
     804           0 :                 isl_seq_clr(hull->ineq[k], 1+2+3*dim);
     805           0 :                 isl_int_set_si(hull->ineq[k][(i+1)*(1+dim)], 1);
     806             :         }
     807           0 :         for (j = 0; j < 1+dim; ++j) {
     808           0 :                 k = isl_basic_set_alloc_equality(hull);
     809           0 :                 if (k < 0)
     810           0 :                         goto error;
     811           0 :                 isl_seq_clr(hull->eq[k], 1+2+3*dim);
     812           0 :                 isl_int_set_si(hull->eq[k][j], -1);
     813           0 :                 isl_int_set_si(hull->eq[k][1+dim+j], 1);
     814           0 :                 isl_int_set_si(hull->eq[k][2*(1+dim)+j], 1);
     815             :         }
     816           0 :         hull = isl_basic_set_set_rational(hull);
     817           0 :         hull = isl_basic_set_remove_dims(hull, isl_dim_set, dim, 2*(1+dim));
     818           0 :         hull = isl_basic_set_remove_redundancies(hull);
     819           0 :         isl_basic_set_free(bset1);
     820           0 :         isl_basic_set_free(bset2);
     821           0 :         return hull;
     822             : error:
     823           0 :         isl_basic_set_free(bset1);
     824           0 :         isl_basic_set_free(bset2);
     825           0 :         isl_basic_set_free(hull);
     826           0 :         return NULL;
     827             : }
     828             : 
     829             : /* Is the set bounded for each value of the parameters?
     830             :  */
     831      909477 : isl_bool isl_basic_set_is_bounded(__isl_keep isl_basic_set *bset)
     832             : {
     833             :         struct isl_tab *tab;
     834             :         isl_bool bounded;
     835             : 
     836      909477 :         if (!bset)
     837           0 :                 return isl_bool_error;
     838      909477 :         if (isl_basic_set_plain_is_empty(bset))
     839           0 :                 return isl_bool_true;
     840             : 
     841      909477 :         tab = isl_tab_from_recession_cone(bset, 1);
     842      909477 :         bounded = isl_tab_cone_is_bounded(tab);
     843      909477 :         isl_tab_free(tab);
     844      909477 :         return bounded;
     845             : }
     846             : 
     847             : /* Is the image bounded for each value of the parameters and
     848             :  * the domain variables?
     849             :  */
     850           0 : isl_bool isl_basic_map_image_is_bounded(__isl_keep isl_basic_map *bmap)
     851             : {
     852           0 :         unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
     853           0 :         unsigned n_in = isl_basic_map_dim(bmap, isl_dim_in);
     854             :         isl_bool bounded;
     855             : 
     856           0 :         bmap = isl_basic_map_copy(bmap);
     857           0 :         bmap = isl_basic_map_cow(bmap);
     858           0 :         bmap = isl_basic_map_move_dims(bmap, isl_dim_param, nparam,
     859             :                                         isl_dim_in, 0, n_in);
     860           0 :         bounded = isl_basic_set_is_bounded(bset_from_bmap(bmap));
     861           0 :         isl_basic_map_free(bmap);
     862             : 
     863           0 :         return bounded;
     864             : }
     865             : 
     866             : /* Is the set bounded for each value of the parameters?
     867             :  */
     868      101690 : isl_bool isl_set_is_bounded(__isl_keep isl_set *set)
     869             : {
     870             :         int i;
     871             : 
     872      101690 :         if (!set)
     873           0 :                 return isl_bool_error;
     874             : 
     875     1011167 :         for (i = 0; i < set->n; ++i) {
     876      909477 :                 isl_bool bounded = isl_basic_set_is_bounded(set->p[i]);
     877      909477 :                 if (!bounded || bounded < 0)
     878           0 :                         return bounded;
     879             :         }
     880      101690 :         return isl_bool_true;
     881             : }
     882             : 
     883             : /* Compute the lineality space of the convex hull of bset1 and bset2.
     884             :  *
     885             :  * We first compute the intersection of the recession cone of bset1
     886             :  * with the negative of the recession cone of bset2 and then compute
     887             :  * the linear hull of the resulting cone.
     888             :  */
     889           0 : static __isl_give isl_basic_set *induced_lineality_space(
     890             :         __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
     891             : {
     892             :         int i, k;
     893           0 :         struct isl_basic_set *lin = NULL;
     894             :         unsigned dim;
     895             : 
     896           0 :         if (!bset1 || !bset2)
     897             :                 goto error;
     898             : 
     899           0 :         dim = isl_basic_set_total_dim(bset1);
     900           0 :         lin = isl_basic_set_alloc_space(isl_basic_set_get_space(bset1), 0,
     901           0 :                                         bset1->n_eq + bset2->n_eq,
     902           0 :                                         bset1->n_ineq + bset2->n_ineq);
     903           0 :         lin = isl_basic_set_set_rational(lin);
     904           0 :         if (!lin)
     905           0 :                 goto error;
     906           0 :         for (i = 0; i < bset1->n_eq; ++i) {
     907           0 :                 k = isl_basic_set_alloc_equality(lin);
     908           0 :                 if (k < 0)
     909           0 :                         goto error;
     910           0 :                 isl_int_set_si(lin->eq[k][0], 0);
     911           0 :                 isl_seq_cpy(lin->eq[k] + 1, bset1->eq[i] + 1, dim);
     912             :         }
     913           0 :         for (i = 0; i < bset1->n_ineq; ++i) {
     914           0 :                 k = isl_basic_set_alloc_inequality(lin);
     915           0 :                 if (k < 0)
     916           0 :                         goto error;
     917           0 :                 isl_int_set_si(lin->ineq[k][0], 0);
     918           0 :                 isl_seq_cpy(lin->ineq[k] + 1, bset1->ineq[i] + 1, dim);
     919             :         }
     920           0 :         for (i = 0; i < bset2->n_eq; ++i) {
     921           0 :                 k = isl_basic_set_alloc_equality(lin);
     922           0 :                 if (k < 0)
     923           0 :                         goto error;
     924           0 :                 isl_int_set_si(lin->eq[k][0], 0);
     925           0 :                 isl_seq_neg(lin->eq[k] + 1, bset2->eq[i] + 1, dim);
     926             :         }
     927           0 :         for (i = 0; i < bset2->n_ineq; ++i) {
     928           0 :                 k = isl_basic_set_alloc_inequality(lin);
     929           0 :                 if (k < 0)
     930           0 :                         goto error;
     931           0 :                 isl_int_set_si(lin->ineq[k][0], 0);
     932           0 :                 isl_seq_neg(lin->ineq[k] + 1, bset2->ineq[i] + 1, dim);
     933             :         }
     934             : 
     935           0 :         isl_basic_set_free(bset1);
     936           0 :         isl_basic_set_free(bset2);
     937           0 :         return isl_basic_set_affine_hull(lin);
     938             : error:
     939           0 :         isl_basic_set_free(lin);
     940           0 :         isl_basic_set_free(bset1);
     941           0 :         isl_basic_set_free(bset2);
     942           0 :         return NULL;
     943             : }
     944             : 
     945             : static __isl_give isl_basic_set *uset_convex_hull(__isl_take isl_set *set);
     946             : 
     947             : /* Given a set and a linear space "lin" of dimension n > 0,
     948             :  * project the linear space from the set, compute the convex hull
     949             :  * and then map the set back to the original space.
     950             :  *
     951             :  * Let
     952             :  *
     953             :  *      M x = 0
     954             :  *
     955             :  * describe the linear space.  We first compute the Hermite normal
     956             :  * form H = M U of M = H Q, to obtain
     957             :  *
     958             :  *      H Q x = 0
     959             :  *
     960             :  * The last n rows of H will be zero, so the last n variables of x' = Q x
     961             :  * are the one we want to project out.  We do this by transforming each
     962             :  * basic set A x >= b to A U x' >= b and then removing the last n dimensions.
     963             :  * After computing the convex hull in x'_1, i.e., A' x'_1 >= b',
     964             :  * we transform the hull back to the original space as A' Q_1 x >= b',
     965             :  * with Q_1 all but the last n rows of Q.
     966             :  */
     967           0 : static __isl_give isl_basic_set *modulo_lineality(__isl_take isl_set *set,
     968             :         __isl_take isl_basic_set *lin)
     969             : {
     970           0 :         unsigned total = isl_basic_set_total_dim(lin);
     971             :         unsigned lin_dim;
     972             :         struct isl_basic_set *hull;
     973             :         struct isl_mat *M, *U, *Q;
     974             : 
     975           0 :         if (!set || !lin)
     976             :                 goto error;
     977           0 :         lin_dim = total - lin->n_eq;
     978           0 :         M = isl_mat_sub_alloc6(set->ctx, lin->eq, 0, lin->n_eq, 1, total);
     979           0 :         M = isl_mat_left_hermite(M, 0, &U, &Q);
     980           0 :         if (!M)
     981           0 :                 goto error;
     982           0 :         isl_mat_free(M);
     983           0 :         isl_basic_set_free(lin);
     984             : 
     985           0 :         Q = isl_mat_drop_rows(Q, Q->n_row - lin_dim, lin_dim);
     986             : 
     987           0 :         U = isl_mat_lin_to_aff(U);
     988           0 :         Q = isl_mat_lin_to_aff(Q);
     989             : 
     990           0 :         set = isl_set_preimage(set, U);
     991           0 :         set = isl_set_remove_dims(set, isl_dim_set, total - lin_dim, lin_dim);
     992           0 :         hull = uset_convex_hull(set);
     993           0 :         hull = isl_basic_set_preimage(hull, Q);
     994             : 
     995           0 :         return hull;
     996             : error:
     997           0 :         isl_basic_set_free(lin);
     998           0 :         isl_set_free(set);
     999           0 :         return NULL;
    1000             : }
    1001             : 
    1002             : /* Given two polyhedra with as constraints h_{ij} x >= 0 in homegeneous space,
    1003             :  * set up an LP for solving
    1004             :  *
    1005             :  *      \sum_j \alpha_{1j} h_{1j} = \sum_j \alpha_{2j} h_{2j}
    1006             :  *
    1007             :  * \alpha{i0} corresponds to the (implicit) positivity constraint 1 >= 0
    1008             :  * The next \alpha{ij} correspond to the equalities and come in pairs.
    1009             :  * The final \alpha{ij} correspond to the inequalities.
    1010             :  */
    1011           0 : static __isl_give isl_basic_set *valid_direction_lp(
    1012             :         __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
    1013             : {
    1014             :         isl_space *dim;
    1015             :         struct isl_basic_set *lp;
    1016             :         unsigned d;
    1017             :         int n;
    1018             :         int i, j, k;
    1019             : 
    1020           0 :         if (!bset1 || !bset2)
    1021             :                 goto error;
    1022           0 :         d = 1 + isl_basic_set_total_dim(bset1);
    1023           0 :         n = 2 +
    1024           0 :             2 * bset1->n_eq + bset1->n_ineq + 2 * bset2->n_eq + bset2->n_ineq;
    1025           0 :         dim = isl_space_set_alloc(bset1->ctx, 0, n);
    1026           0 :         lp = isl_basic_set_alloc_space(dim, 0, d, n);
    1027           0 :         if (!lp)
    1028           0 :                 goto error;
    1029           0 :         for (i = 0; i < n; ++i) {
    1030           0 :                 k = isl_basic_set_alloc_inequality(lp);
    1031           0 :                 if (k < 0)
    1032           0 :                         goto error;
    1033           0 :                 isl_seq_clr(lp->ineq[k] + 1, n);
    1034           0 :                 isl_int_set_si(lp->ineq[k][0], -1);
    1035           0 :                 isl_int_set_si(lp->ineq[k][1 + i], 1);
    1036             :         }
    1037           0 :         for (i = 0; i < d; ++i) {
    1038           0 :                 k = isl_basic_set_alloc_equality(lp);
    1039           0 :                 if (k < 0)
    1040           0 :                         goto error;
    1041           0 :                 n = 0;
    1042           0 :                 isl_int_set_si(lp->eq[k][n], 0); n++;
    1043             :                 /* positivity constraint 1 >= 0 */
    1044           0 :                 isl_int_set_si(lp->eq[k][n], i == 0); n++;
    1045           0 :                 for (j = 0; j < bset1->n_eq; ++j) {
    1046           0 :                         isl_int_set(lp->eq[k][n], bset1->eq[j][i]); n++;
    1047           0 :                         isl_int_neg(lp->eq[k][n], bset1->eq[j][i]); n++;
    1048             :                 }
    1049           0 :                 for (j = 0; j < bset1->n_ineq; ++j) {
    1050           0 :                         isl_int_set(lp->eq[k][n], bset1->ineq[j][i]); n++;
    1051             :                 }
    1052             :                 /* positivity constraint 1 >= 0 */
    1053           0 :                 isl_int_set_si(lp->eq[k][n], -(i == 0)); n++;
    1054           0 :                 for (j = 0; j < bset2->n_eq; ++j) {
    1055           0 :                         isl_int_neg(lp->eq[k][n], bset2->eq[j][i]); n++;
    1056           0 :                         isl_int_set(lp->eq[k][n], bset2->eq[j][i]); n++;
    1057             :                 }
    1058           0 :                 for (j = 0; j < bset2->n_ineq; ++j) {
    1059           0 :                         isl_int_neg(lp->eq[k][n], bset2->ineq[j][i]); n++;
    1060             :                 }
    1061             :         }
    1062           0 :         lp = isl_basic_set_gauss(lp, NULL);
    1063           0 :         isl_basic_set_free(bset1);
    1064           0 :         isl_basic_set_free(bset2);
    1065           0 :         return lp;
    1066             : error:
    1067           0 :         isl_basic_set_free(bset1);
    1068           0 :         isl_basic_set_free(bset2);
    1069           0 :         return NULL;
    1070             : }
    1071             : 
    1072             : /* Compute a vector s in the homogeneous space such that <s, r> > 0
    1073             :  * for all rays in the homogeneous space of the two cones that correspond
    1074             :  * to the input polyhedra bset1 and bset2.
    1075             :  *
    1076             :  * We compute s as a vector that satisfies
    1077             :  *
    1078             :  *      s = \sum_j \alpha_{ij} h_{ij}   for i = 1,2                     (*)
    1079             :  *
    1080             :  * with h_{ij} the normals of the facets of polyhedron i
    1081             :  * (including the "positivity constraint" 1 >= 0) and \alpha_{ij}
    1082             :  * strictly positive numbers.  For simplicity we impose \alpha_{ij} >= 1.
    1083             :  * We first set up an LP with as variables the \alpha{ij}.
    1084             :  * In this formulation, for each polyhedron i,
    1085             :  * the first constraint is the positivity constraint, followed by pairs
    1086             :  * of variables for the equalities, followed by variables for the inequalities.
    1087             :  * We then simply pick a feasible solution and compute s using (*).
    1088             :  *
    1089             :  * Note that we simply pick any valid direction and make no attempt
    1090             :  * to pick a "good" or even the "best" valid direction.
    1091             :  */
    1092           0 : static __isl_give isl_vec *valid_direction(
    1093             :         __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
    1094             : {
    1095             :         struct isl_basic_set *lp;
    1096             :         struct isl_tab *tab;
    1097           0 :         struct isl_vec *sample = NULL;
    1098             :         struct isl_vec *dir;
    1099             :         unsigned d;
    1100             :         int i;
    1101             :         int n;
    1102             : 
    1103           0 :         if (!bset1 || !bset2)
    1104             :                 goto error;
    1105           0 :         lp = valid_direction_lp(isl_basic_set_copy(bset1),
    1106             :                                 isl_basic_set_copy(bset2));
    1107           0 :         tab = isl_tab_from_basic_set(lp, 0);
    1108           0 :         sample = isl_tab_get_sample_value(tab);
    1109           0 :         isl_tab_free(tab);
    1110           0 :         isl_basic_set_free(lp);
    1111           0 :         if (!sample)
    1112           0 :                 goto error;
    1113           0 :         d = isl_basic_set_total_dim(bset1);
    1114           0 :         dir = isl_vec_alloc(bset1->ctx, 1 + d);
    1115           0 :         if (!dir)
    1116           0 :                 goto error;
    1117           0 :         isl_seq_clr(dir->block.data + 1, dir->size - 1);
    1118           0 :         n = 1;
    1119             :         /* positivity constraint 1 >= 0 */
    1120           0 :         isl_int_set(dir->block.data[0], sample->block.data[n]); n++;
    1121           0 :         for (i = 0; i < bset1->n_eq; ++i) {
    1122           0 :                 isl_int_sub(sample->block.data[n],
    1123             :                             sample->block.data[n], sample->block.data[n+1]);
    1124           0 :                 isl_seq_combine(dir->block.data,
    1125           0 :                                 bset1->ctx->one, dir->block.data,
    1126           0 :                                 sample->block.data[n], bset1->eq[i], 1 + d);
    1127             : 
    1128           0 :                 n += 2;
    1129             :         }
    1130           0 :         for (i = 0; i < bset1->n_ineq; ++i)
    1131           0 :                 isl_seq_combine(dir->block.data,
    1132           0 :                                 bset1->ctx->one, dir->block.data,
    1133           0 :                                 sample->block.data[n++], bset1->ineq[i], 1 + d);
    1134           0 :         isl_vec_free(sample);
    1135           0 :         isl_seq_normalize(bset1->ctx, dir->el, dir->size);
    1136           0 :         isl_basic_set_free(bset1);
    1137           0 :         isl_basic_set_free(bset2);
    1138           0 :         return dir;
    1139             : error:
    1140           0 :         isl_vec_free(sample);
    1141           0 :         isl_basic_set_free(bset1);
    1142           0 :         isl_basic_set_free(bset2);
    1143           0 :         return NULL;
    1144             : }
    1145             : 
    1146             : /* Given a polyhedron b_i + A_i x >= 0 and a map T = S^{-1},
    1147             :  * compute b_i' + A_i' x' >= 0, with
    1148             :  *
    1149             :  *      [ b_i A_i ]        [ y' ]                             [ y' ]
    1150             :  *      [  1   0  ] S^{-1} [ x' ] >= 0       or      [ b_i' A_i' ] [ x' ] >= 0
    1151             :  *
    1152             :  * In particular, add the "positivity constraint" and then perform
    1153             :  * the mapping.
    1154             :  */
    1155           0 : static __isl_give isl_basic_set *homogeneous_map(__isl_take isl_basic_set *bset,
    1156             :         __isl_take isl_mat *T)
    1157             : {
    1158             :         int k;
    1159             : 
    1160           0 :         if (!bset)
    1161           0 :                 goto error;
    1162           0 :         bset = isl_basic_set_extend_constraints(bset, 0, 1);
    1163           0 :         k = isl_basic_set_alloc_inequality(bset);
    1164           0 :         if (k < 0)
    1165           0 :                 goto error;
    1166           0 :         isl_seq_clr(bset->ineq[k] + 1, isl_basic_set_total_dim(bset));
    1167           0 :         isl_int_set_si(bset->ineq[k][0], 1);
    1168           0 :         bset = isl_basic_set_preimage(bset, T);
    1169           0 :         return bset;
    1170             : error:
    1171           0 :         isl_mat_free(T);
    1172           0 :         isl_basic_set_free(bset);
    1173           0 :         return NULL;
    1174             : }
    1175             : 
    1176             : /* Compute the convex hull of a pair of basic sets without any parameters or
    1177             :  * integer divisions, where the convex hull is known to be pointed,
    1178             :  * but the basic sets may be unbounded.
    1179             :  *
    1180             :  * We turn this problem into the computation of a convex hull of a pair
    1181             :  * _bounded_ polyhedra by "changing the direction of the homogeneous
    1182             :  * dimension".  This idea is due to Matthias Koeppe.
    1183             :  *
    1184             :  * Consider the cones in homogeneous space that correspond to the
    1185             :  * input polyhedra.  The rays of these cones are also rays of the
    1186             :  * polyhedra if the coordinate that corresponds to the homogeneous
    1187             :  * dimension is zero.  That is, if the inner product of the rays
    1188             :  * with the homogeneous direction is zero.
    1189             :  * The cones in the homogeneous space can also be considered to
    1190             :  * correspond to other pairs of polyhedra by chosing a different
    1191             :  * homogeneous direction.  To ensure that both of these polyhedra
    1192             :  * are bounded, we need to make sure that all rays of the cones
    1193             :  * correspond to vertices and not to rays.
    1194             :  * Let s be a direction such that <s, r> > 0 for all rays r of both cones.
    1195             :  * Then using s as a homogeneous direction, we obtain a pair of polytopes.
    1196             :  * The vector s is computed in valid_direction.
    1197             :  *
    1198             :  * Note that we need to consider _all_ rays of the cones and not just
    1199             :  * the rays that correspond to rays in the polyhedra.  If we were to
    1200             :  * only consider those rays and turn them into vertices, then we
    1201             :  * may inadvertently turn some vertices into rays.
    1202             :  *
    1203             :  * The standard homogeneous direction is the unit vector in the 0th coordinate.
    1204             :  * We therefore transform the two polyhedra such that the selected
    1205             :  * direction is mapped onto this standard direction and then proceed
    1206             :  * with the normal computation.
    1207             :  * Let S be a non-singular square matrix with s as its first row,
    1208             :  * then we want to map the polyhedra to the space
    1209             :  *
    1210             :  *      [ y' ]     [ y ]                [ y ]          [ y' ]
    1211             :  *      [ x' ] = S [ x ]        i.e.,   [ x ] = S^{-1} [ x' ]
    1212             :  *
    1213             :  * We take S to be the unimodular completion of s to limit the growth
    1214             :  * of the coefficients in the following computations.
    1215             :  *
    1216             :  * Let b_i + A_i x >= 0 be the constraints of polyhedron i.
    1217             :  * We first move to the homogeneous dimension
    1218             :  *
    1219             :  *      b_i y + A_i x >= 0           [ b_i A_i ] [ y ]    [ 0 ]
    1220             :  *          y         >= 0   or      [  1   0  ] [ x ] >= [ 0 ]
    1221             :  *
    1222             :  * Then we change directoin
    1223             :  *
    1224             :  *      [ b_i A_i ]        [ y' ]                             [ y' ]
    1225             :  *      [  1   0  ] S^{-1} [ x' ] >= 0       or      [ b_i' A_i' ] [ x' ] >= 0
    1226             :  *
    1227             :  * Then we compute the convex hull of the polytopes b_i' + A_i' x' >= 0
    1228             :  * resulting in b' + A' x' >= 0, which we then convert back
    1229             :  *
    1230             :  *                  [ y ]                       [ y ]
    1231             :  *      [ b' A' ] S [ x ] >= 0       or      [ b A ] [ x ] >= 0
    1232             :  *
    1233             :  * The polyhedron b + A x >= 0 is then the convex hull of the input polyhedra.
    1234             :  */
    1235           0 : static __isl_give isl_basic_set *convex_hull_pair_pointed(
    1236             :         __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
    1237             : {
    1238           0 :         struct isl_ctx *ctx = NULL;
    1239           0 :         struct isl_vec *dir = NULL;
    1240           0 :         struct isl_mat *T = NULL;
    1241           0 :         struct isl_mat *T2 = NULL;
    1242             :         struct isl_basic_set *hull;
    1243             :         struct isl_set *set;
    1244             : 
    1245           0 :         if (!bset1 || !bset2)
    1246             :                 goto error;
    1247           0 :         ctx = isl_basic_set_get_ctx(bset1);
    1248           0 :         dir = valid_direction(isl_basic_set_copy(bset1),
    1249             :                                 isl_basic_set_copy(bset2));
    1250           0 :         if (!dir)
    1251           0 :                 goto error;
    1252           0 :         T = isl_mat_alloc(ctx, dir->size, dir->size);
    1253           0 :         if (!T)
    1254           0 :                 goto error;
    1255           0 :         isl_seq_cpy(T->row[0], dir->block.data, dir->size);
    1256           0 :         T = isl_mat_unimodular_complete(T, 1);
    1257           0 :         T2 = isl_mat_right_inverse(isl_mat_copy(T));
    1258             : 
    1259           0 :         bset1 = homogeneous_map(bset1, isl_mat_copy(T2));
    1260           0 :         bset2 = homogeneous_map(bset2, T2);
    1261           0 :         set = isl_set_alloc_space(isl_basic_set_get_space(bset1), 2, 0);
    1262           0 :         set = isl_set_add_basic_set(set, bset1);
    1263           0 :         set = isl_set_add_basic_set(set, bset2);
    1264           0 :         hull = uset_convex_hull(set);
    1265           0 :         hull = isl_basic_set_preimage(hull, T);
    1266             :          
    1267           0 :         isl_vec_free(dir);
    1268             : 
    1269           0 :         return hull;
    1270             : error:
    1271           0 :         isl_vec_free(dir);
    1272           0 :         isl_basic_set_free(bset1);
    1273           0 :         isl_basic_set_free(bset2);
    1274           0 :         return NULL;
    1275             : }
    1276             : 
    1277             : static __isl_give isl_basic_set *uset_convex_hull_wrap(__isl_take isl_set *set);
    1278             : static __isl_give isl_basic_set *modulo_affine_hull(
    1279             :         __isl_take isl_set *set, __isl_take isl_basic_set *affine_hull);
    1280             : 
    1281             : /* Compute the convex hull of a pair of basic sets without any parameters or
    1282             :  * integer divisions.
    1283             :  *
    1284             :  * This function is called from uset_convex_hull_unbounded, which
    1285             :  * means that the complete convex hull is unbounded.  Some pairs
    1286             :  * of basic sets may still be bounded, though.
    1287             :  * They may even lie inside a lower dimensional space, in which
    1288             :  * case they need to be handled inside their affine hull since
    1289             :  * the main algorithm assumes that the result is full-dimensional.
    1290             :  *
    1291             :  * If the convex hull of the two basic sets would have a non-trivial
    1292             :  * lineality space, we first project out this lineality space.
    1293             :  */
    1294           0 : static __isl_give isl_basic_set *convex_hull_pair(
    1295             :         __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
    1296             : {
    1297             :         isl_basic_set *lin, *aff;
    1298             :         int bounded1, bounded2;
    1299             : 
    1300           0 :         if (bset1->ctx->opt->convex == ISL_CONVEX_HULL_FM)
    1301           0 :                 return convex_hull_pair_elim(bset1, bset2);
    1302             : 
    1303           0 :         aff = isl_set_affine_hull(isl_basic_set_union(isl_basic_set_copy(bset1),
    1304             :                                                     isl_basic_set_copy(bset2)));
    1305           0 :         if (!aff)
    1306           0 :                 goto error;
    1307           0 :         if (aff->n_eq != 0) 
    1308           0 :                 return modulo_affine_hull(isl_basic_set_union(bset1, bset2), aff);
    1309           0 :         isl_basic_set_free(aff);
    1310             : 
    1311           0 :         bounded1 = isl_basic_set_is_bounded(bset1);
    1312           0 :         bounded2 = isl_basic_set_is_bounded(bset2);
    1313             : 
    1314           0 :         if (bounded1 < 0 || bounded2 < 0)
    1315             :                 goto error;
    1316             : 
    1317           0 :         if (bounded1 && bounded2)
    1318           0 :                 return uset_convex_hull_wrap(isl_basic_set_union(bset1, bset2));
    1319             : 
    1320           0 :         if (bounded1 || bounded2)
    1321           0 :                 return convex_hull_pair_pointed(bset1, bset2);
    1322             : 
    1323           0 :         lin = induced_lineality_space(isl_basic_set_copy(bset1),
    1324             :                                       isl_basic_set_copy(bset2));
    1325           0 :         if (!lin)
    1326           0 :                 goto error;
    1327           0 :         if (isl_basic_set_plain_is_universe(lin)) {
    1328           0 :                 isl_basic_set_free(bset1);
    1329           0 :                 isl_basic_set_free(bset2);
    1330           0 :                 return lin;
    1331             :         }
    1332           0 :         if (lin->n_eq < isl_basic_set_total_dim(lin)) {
    1333             :                 struct isl_set *set;
    1334           0 :                 set = isl_set_alloc_space(isl_basic_set_get_space(bset1), 2, 0);
    1335           0 :                 set = isl_set_add_basic_set(set, bset1);
    1336           0 :                 set = isl_set_add_basic_set(set, bset2);
    1337           0 :                 return modulo_lineality(set, lin);
    1338             :         }
    1339           0 :         isl_basic_set_free(lin);
    1340             : 
    1341           0 :         return convex_hull_pair_pointed(bset1, bset2);
    1342             : error:
    1343           0 :         isl_basic_set_free(bset1);
    1344           0 :         isl_basic_set_free(bset2);
    1345           0 :         return NULL;
    1346             : }
    1347             : 
    1348             : /* Compute the lineality space of a basic set.
    1349             :  * We basically just drop the constants and turn every inequality
    1350             :  * into an equality.
    1351             :  * Any explicit representations of local variables are removed
    1352             :  * because they may no longer be valid representations
    1353             :  * in the lineality space.
    1354             :  */
    1355           0 : __isl_give isl_basic_set *isl_basic_set_lineality_space(
    1356             :         __isl_take isl_basic_set *bset)
    1357             : {
    1358             :         int i, k;
    1359           0 :         struct isl_basic_set *lin = NULL;
    1360             :         unsigned n_div, dim;
    1361             : 
    1362           0 :         if (!bset)
    1363           0 :                 goto error;
    1364           0 :         n_div = isl_basic_set_dim(bset, isl_dim_div);
    1365           0 :         dim = isl_basic_set_total_dim(bset);
    1366             : 
    1367           0 :         lin = isl_basic_set_alloc_space(isl_basic_set_get_space(bset),
    1368             :                                         n_div, dim, 0);
    1369           0 :         for (i = 0; i < n_div; ++i)
    1370           0 :                 if (isl_basic_set_alloc_div(lin) < 0)
    1371           0 :                         goto error;
    1372           0 :         if (!lin)
    1373           0 :                 goto error;
    1374           0 :         for (i = 0; i < bset->n_eq; ++i) {
    1375           0 :                 k = isl_basic_set_alloc_equality(lin);
    1376           0 :                 if (k < 0)
    1377           0 :                         goto error;
    1378           0 :                 isl_int_set_si(lin->eq[k][0], 0);
    1379           0 :                 isl_seq_cpy(lin->eq[k] + 1, bset->eq[i] + 1, dim);
    1380             :         }
    1381           0 :         lin = isl_basic_set_gauss(lin, NULL);
    1382           0 :         if (!lin)
    1383           0 :                 goto error;
    1384           0 :         for (i = 0; i < bset->n_ineq && lin->n_eq < dim; ++i) {
    1385           0 :                 k = isl_basic_set_alloc_equality(lin);
    1386           0 :                 if (k < 0)
    1387           0 :                         goto error;
    1388           0 :                 isl_int_set_si(lin->eq[k][0], 0);
    1389           0 :                 isl_seq_cpy(lin->eq[k] + 1, bset->ineq[i] + 1, dim);
    1390           0 :                 lin = isl_basic_set_gauss(lin, NULL);
    1391           0 :                 if (!lin)
    1392           0 :                         goto error;
    1393             :         }
    1394           0 :         isl_basic_set_free(bset);
    1395           0 :         return lin;
    1396             : error:
    1397           0 :         isl_basic_set_free(lin);
    1398           0 :         isl_basic_set_free(bset);
    1399           0 :         return NULL;
    1400             : }
    1401             : 
    1402             : /* Compute the (linear) hull of the lineality spaces of the basic sets in the
    1403             :  * set "set".
    1404             :  */
    1405           0 : __isl_give isl_basic_set *isl_set_combined_lineality_space(
    1406             :         __isl_take isl_set *set)
    1407             : {
    1408             :         int i;
    1409           0 :         struct isl_set *lin = NULL;
    1410             : 
    1411           0 :         if (!set)
    1412           0 :                 return NULL;
    1413           0 :         if (set->n == 0) {
    1414           0 :                 isl_space *space = isl_set_get_space(set);
    1415           0 :                 isl_set_free(set);
    1416           0 :                 return isl_basic_set_empty(space);
    1417             :         }
    1418             : 
    1419           0 :         lin = isl_set_alloc_space(isl_set_get_space(set), set->n, 0);
    1420           0 :         for (i = 0; i < set->n; ++i)
    1421           0 :                 lin = isl_set_add_basic_set(lin,
    1422           0 :                     isl_basic_set_lineality_space(isl_basic_set_copy(set->p[i])));
    1423           0 :         isl_set_free(set);
    1424           0 :         return isl_set_affine_hull(lin);
    1425             : }
    1426             : 
    1427             : /* Compute the convex hull of a set without any parameters or
    1428             :  * integer divisions.
    1429             :  * In each step, we combined two basic sets until only one
    1430             :  * basic set is left.
    1431             :  * The input basic sets are assumed not to have a non-trivial
    1432             :  * lineality space.  If any of the intermediate results has
    1433             :  * a non-trivial lineality space, it is projected out.
    1434             :  */
    1435           0 : static __isl_give isl_basic_set *uset_convex_hull_unbounded(
    1436             :         __isl_take isl_set *set)
    1437             : {
    1438             :         isl_basic_set_list *list;
    1439             : 
    1440           0 :         list = isl_set_get_basic_set_list(set);
    1441           0 :         isl_set_free(set);
    1442             : 
    1443           0 :         while (list) {
    1444             :                 int n;
    1445             :                 struct isl_basic_set *t;
    1446             :                 isl_basic_set *bset1, *bset2;
    1447             : 
    1448           0 :                 n = isl_basic_set_list_n_basic_set(list);
    1449           0 :                 if (n < 2)
    1450           0 :                         isl_die(isl_basic_set_list_get_ctx(list),
    1451             :                                 isl_error_internal,
    1452             :                                 "expecting at least two elements", goto error);
    1453           0 :                 bset1 = isl_basic_set_list_get_basic_set(list, n - 1);
    1454           0 :                 bset2 = isl_basic_set_list_get_basic_set(list, n - 2);
    1455           0 :                 bset1 = convex_hull_pair(bset1, bset2);
    1456           0 :                 if (n == 2) {
    1457           0 :                         isl_basic_set_list_free(list);
    1458           0 :                         return bset1;
    1459             :                 }
    1460           0 :                 bset1 = isl_basic_set_underlying_set(bset1);
    1461           0 :                 list = isl_basic_set_list_drop(list, n - 2, 2);
    1462           0 :                 list = isl_basic_set_list_add(list, bset1);
    1463             : 
    1464           0 :                 t = isl_basic_set_list_get_basic_set(list, n - 2);
    1465           0 :                 t = isl_basic_set_lineality_space(t);
    1466           0 :                 if (!t)
    1467           0 :                         goto error;
    1468           0 :                 if (isl_basic_set_plain_is_universe(t)) {
    1469           0 :                         isl_basic_set_list_free(list);
    1470           0 :                         return t;
    1471             :                 }
    1472           0 :                 if (t->n_eq < isl_basic_set_total_dim(t)) {
    1473           0 :                         set = isl_basic_set_list_union(list);
    1474           0 :                         return modulo_lineality(set, t);
    1475             :                 }
    1476           0 :                 isl_basic_set_free(t);
    1477             :         }
    1478             : 
    1479           0 :         return NULL;
    1480             : error:
    1481           0 :         isl_basic_set_list_free(list);
    1482           0 :         return NULL;
    1483             : }
    1484             : 
    1485             : /* Compute an initial hull for wrapping containing a single initial
    1486             :  * facet.
    1487             :  * This function assumes that the given set is bounded.
    1488             :  */
    1489   367832453 : static __isl_give isl_basic_set *initial_hull(__isl_take isl_basic_set *hull,
    1490             :         __isl_keep isl_set *set)
    1491             : {
    1492   367832453 :         struct isl_mat *bounds = NULL;
    1493             :         unsigned dim;
    1494             :         int k;
    1495             : 
    1496   367832453 :         if (!hull)
    1497           0 :                 goto error;
    1498   367832453 :         bounds = initial_facet_constraint(set);
    1499   367832453 :         if (!bounds)
    1500           0 :                 goto error;
    1501   367832453 :         k = isl_basic_set_alloc_inequality(hull);
    1502   367832453 :         if (k < 0)
    1503           0 :                 goto error;
    1504   367832453 :         dim = isl_set_n_dim(set);
    1505   367832453 :         isl_assert(set->ctx, 1 + dim == bounds->n_col, goto error);
    1506   367832453 :         isl_seq_cpy(hull->ineq[k], bounds->row[0], bounds->n_col);
    1507   367832453 :         isl_mat_free(bounds);
    1508             : 
    1509   367832453 :         return hull;
    1510             : error:
    1511           0 :         isl_basic_set_free(hull);
    1512           0 :         isl_mat_free(bounds);
    1513           0 :         return NULL;
    1514             : }
    1515             : 
    1516             : struct max_constraint {
    1517             :         struct isl_mat *c;
    1518             :         int             count;
    1519             :         int             ineq;
    1520             : };
    1521             : 
    1522      342849 : static int max_constraint_equal(const void *entry, const void *val)
    1523             : {
    1524      342849 :         struct max_constraint *a = (struct max_constraint *)entry;
    1525      342849 :         isl_int *b = (isl_int *)val;
    1526             : 
    1527      342849 :         return isl_seq_eq(a->c->row[0] + 1, b, a->c->n_col - 1);
    1528             : }
    1529             : 
    1530     1048409 : static void update_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
    1531             :         isl_int *con, unsigned len, int n, int ineq)
    1532             : {
    1533             :         struct isl_hash_table_entry *entry;
    1534             :         struct max_constraint *c;
    1535             :         uint32_t c_hash;
    1536             : 
    1537     1048409 :         c_hash = isl_seq_get_hash(con + 1, len);
    1538     1048409 :         entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
    1539             :                         con + 1, 0);
    1540     1048409 :         if (!entry)
    1541      705739 :                 return;
    1542      342670 :         c = entry->data;
    1543      342670 :         if (c->count < n) {
    1544        1131 :                 isl_hash_table_remove(ctx, table, entry);
    1545        1131 :                 return;
    1546             :         }
    1547      341539 :         c->count++;
    1548      341539 :         if (isl_int_gt(c->c->row[0][0], con[0]))
    1549      145262 :                 return;
    1550      196277 :         if (isl_int_eq(c->c->row[0][0], con[0])) {
    1551      132807 :                 if (ineq)
    1552          76 :                         c->ineq = ineq;
    1553      132807 :                 return;
    1554             :         }
    1555       63470 :         c->c = isl_mat_cow(c->c);
    1556       63470 :         isl_int_set(c->c->row[0][0], con[0]);
    1557       63470 :         c->ineq = ineq;
    1558             : }
    1559             : 
    1560             : /* Check whether the constraint hash table "table" contains the constraint
    1561             :  * "con".
    1562             :  */
    1563         179 : static int has_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
    1564             :         isl_int *con, unsigned len, int n)
    1565             : {
    1566             :         struct isl_hash_table_entry *entry;
    1567             :         struct max_constraint *c;
    1568             :         uint32_t c_hash;
    1569             : 
    1570         179 :         c_hash = isl_seq_get_hash(con + 1, len);
    1571         179 :         entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
    1572             :                         con + 1, 0);
    1573         179 :         if (!entry)
    1574           0 :                 return 0;
    1575         179 :         c = entry->data;
    1576         179 :         if (c->count < n)
    1577           0 :                 return 0;
    1578         179 :         return isl_int_eq(c->c->row[0][0], con[0]);
    1579             : }
    1580             : 
    1581             : /* Are the constraints of "bset" known to be facets?
    1582             :  * If there are any equality constraints, then they are not.
    1583             :  * If there may be redundant constraints, then those
    1584             :  * redundant constraints are not facets.
    1585             :  */
    1586  1211686914 : static isl_bool has_facets(__isl_keep isl_basic_set *bset)
    1587             : {
    1588             :         int n_eq;
    1589             : 
    1590  1211686914 :         n_eq = isl_basic_set_n_equality(bset);
    1591  1211686914 :         if (n_eq < 0)
    1592           0 :                 return isl_bool_error;
    1593  1211686914 :         if (n_eq != 0)
    1594  1211485018 :                 return isl_bool_false;
    1595      201896 :         return ISL_F_ISSET(bset, ISL_BASIC_SET_NO_REDUNDANT);
    1596             : }
    1597             : 
    1598             : /* Check for inequality constraints of a basic set without equalities
    1599             :  * or redundant constraints
    1600             :  * such that the same or more stringent copies of the constraint appear
    1601             :  * in all of the basic sets.  Such constraints are necessarily facet
    1602             :  * constraints of the convex hull.
    1603             :  *
    1604             :  * If the resulting basic set is by chance identical to one of
    1605             :  * the basic sets in "set", then we know that this basic set contains
    1606             :  * all other basic sets and is therefore the convex hull of set.
    1607             :  * In this case we set *is_hull to 1.
    1608             :  */
    1609   367992152 : static __isl_give isl_basic_set *common_constraints(
    1610             :         __isl_take isl_basic_set *hull, __isl_keep isl_set *set, int *is_hull)
    1611             : {
    1612             :         int i, j, s, n;
    1613             :         int min_constraints;
    1614             :         int best;
    1615   367992152 :         struct max_constraint *constraints = NULL;
    1616   367992152 :         struct isl_hash_table *table = NULL;
    1617             :         unsigned total;
    1618             : 
    1619   367992152 :         *is_hull = 0;
    1620             : 
    1621  1579398578 :         for (i = 0; i < set->n; ++i) {
    1622  1211607279 :                 isl_bool facets = has_facets(set->p[i]);
    1623  1211607279 :                 if (facets < 0)
    1624           0 :                         return isl_basic_set_free(hull);
    1625  1211607279 :                 if (facets)
    1626      200853 :                         break;
    1627             :         }
    1628   367992152 :         if (i >= set->n)
    1629   367791299 :                 return hull;
    1630      200853 :         min_constraints = set->p[i]->n_ineq;
    1631      200853 :         best = i;
    1632      280488 :         for (i = best + 1; i < set->n; ++i) {
    1633       79635 :                 isl_bool facets = has_facets(set->p[i]);
    1634       79635 :                 if (facets < 0)
    1635           0 :                         return isl_basic_set_free(hull);
    1636       79635 :                 if (!facets)
    1637       79374 :                         continue;
    1638         261 :                 if (set->p[i]->n_ineq >= min_constraints)
    1639         241 :                         continue;
    1640          20 :                 min_constraints = set->p[i]->n_ineq;
    1641          20 :                 best = i;
    1642             :         }
    1643      200853 :         constraints = isl_calloc_array(hull->ctx, struct max_constraint,
    1644             :                                         min_constraints);
    1645      200853 :         if (!constraints)
    1646           0 :                 return hull;
    1647      200853 :         table = isl_alloc_type(hull->ctx, struct isl_hash_table);
    1648      200853 :         if (isl_hash_table_init(hull->ctx, table, min_constraints))
    1649           0 :                 goto error;
    1650             : 
    1651      200853 :         total = isl_space_dim(set->dim, isl_dim_all);
    1652      953501 :         for (i = 0; i < set->p[best]->n_ineq; ++i) {
    1653     2257944 :                 constraints[i].c = isl_mat_sub_alloc6(hull->ctx,
    1654     1505296 :                         set->p[best]->ineq + i, 0, 1, 0, 1 + total);
    1655      752648 :                 if (!constraints[i].c)
    1656           0 :                         goto error;
    1657      752648 :                 constraints[i].ineq = 1;
    1658             :         }
    1659      953501 :         for (i = 0; i < min_constraints; ++i) {
    1660             :                 struct isl_hash_table_entry *entry;
    1661             :                 uint32_t c_hash;
    1662      752648 :                 c_hash = isl_seq_get_hash(constraints[i].c->row[0] + 1, total);
    1663      752648 :                 entry = isl_hash_table_find(hull->ctx, table, c_hash,
    1664      752648 :                         max_constraint_equal, constraints[i].c->row[0] + 1, 1);
    1665      752648 :                 if (!entry)
    1666           0 :                         goto error;
    1667      752648 :                 isl_assert(hull->ctx, !entry->data, goto error);
    1668      752648 :                 entry->data = &constraints[i];
    1669             :         }
    1670             : 
    1671      200853 :         n = 0;
    1672      628192 :         for (s = 0; s < set->n; ++s) {
    1673      427339 :                 if (s == best)
    1674      200853 :                         continue;
    1675             : 
    1676      730467 :                 for (i = 0; i < set->p[s]->n_eq; ++i) {
    1677      503981 :                         isl_int *eq = set->p[s]->eq[i];
    1678     1511943 :                         for (j = 0; j < 2; ++j) {
    1679     1007962 :                                 isl_seq_neg(eq, eq, 1 + total);
    1680     1007962 :                                 update_constraint(hull->ctx, table,
    1681             :                                                             eq, total, n, 0);
    1682             :                         }
    1683             :                 }
    1684      266933 :                 for (i = 0; i < set->p[s]->n_ineq; ++i) {
    1685       40447 :                         isl_int *ineq = set->p[s]->ineq[i];
    1686       40447 :                         update_constraint(hull->ctx, table, ineq, total, n,
    1687       40447 :                                 set->p[s]->n_eq == 0);
    1688             :                 }
    1689      226486 :                 ++n;
    1690             :         }
    1691             : 
    1692      953501 :         for (i = 0; i < min_constraints; ++i) {
    1693      752648 :                 if (constraints[i].count < n)
    1694      459379 :                         continue;
    1695      293269 :                 if (!constraints[i].ineq)
    1696       61916 :                         continue;
    1697      231353 :                 j = isl_basic_set_alloc_inequality(hull);
    1698      231353 :                 if (j < 0)
    1699           0 :                         goto error;
    1700      231353 :                 isl_seq_cpy(hull->ineq[j], constraints[i].c->row[0], 1 + total);
    1701             :         }
    1702             : 
    1703      628192 :         for (s = 0; s < set->n; ++s) {
    1704      427339 :                 if (set->p[s]->n_eq)
    1705      226225 :                         continue;
    1706      201114 :                 if (set->p[s]->n_ineq != hull->n_ineq)
    1707      201026 :                         continue;
    1708         179 :                 for (i = 0; i < set->p[s]->n_ineq; ++i) {
    1709         179 :                         isl_int *ineq = set->p[s]->ineq[i];
    1710         179 :                         if (!has_constraint(hull->ctx, table, ineq, total, n))
    1711          88 :                                 break;
    1712             :                 }
    1713          88 :                 if (i == set->p[s]->n_ineq)
    1714           0 :                         *is_hull = 1;
    1715             :         }
    1716             : 
    1717      200853 :         isl_hash_table_clear(table);
    1718      953501 :         for (i = 0; i < min_constraints; ++i)
    1719      752648 :                 isl_mat_free(constraints[i].c);
    1720      200853 :         free(constraints);
    1721      200853 :         free(table);
    1722      200853 :         return hull;
    1723             : error:
    1724           0 :         isl_hash_table_clear(table);
    1725           0 :         free(table);
    1726           0 :         if (constraints)
    1727           0 :                 for (i = 0; i < min_constraints; ++i)
    1728           0 :                         isl_mat_free(constraints[i].c);
    1729           0 :         free(constraints);
    1730           0 :         return hull;
    1731             : }
    1732             : 
    1733             : /* Create a template for the convex hull of "set" and fill it up
    1734             :  * obvious facet constraints, if any.  If the result happens to
    1735             :  * be the convex hull of "set" then *is_hull is set to 1.
    1736             :  */
    1737   367992152 : static __isl_give isl_basic_set *proto_hull(__isl_keep isl_set *set,
    1738             :         int *is_hull)
    1739             : {
    1740             :         struct isl_basic_set *hull;
    1741             :         unsigned n_ineq;
    1742             :         int i;
    1743             : 
    1744   367992152 :         n_ineq = 1;
    1745  1579679066 :         for (i = 0; i < set->n; ++i) {
    1746  1211686914 :                 n_ineq += set->p[i]->n_eq;
    1747  1211686914 :                 n_ineq += set->p[i]->n_ineq;
    1748             :         }
    1749   367992152 :         hull = isl_basic_set_alloc_space(isl_space_copy(set->dim), 0, 0, n_ineq);
    1750   367992152 :         hull = isl_basic_set_set_rational(hull);
    1751   367992152 :         if (!hull)
    1752           0 :                 return NULL;
    1753   367992152 :         return common_constraints(hull, set, is_hull);
    1754             : }
    1755             : 
    1756   367992152 : static __isl_give isl_basic_set *uset_convex_hull_wrap(__isl_take isl_set *set)
    1757             : {
    1758             :         struct isl_basic_set *hull;
    1759             :         int is_hull;
    1760             : 
    1761   367992152 :         hull = proto_hull(set, &is_hull);
    1762   367992152 :         if (hull && !is_hull) {
    1763   367992152 :                 if (hull->n_ineq == 0)
    1764   367832453 :                         hull = initial_hull(hull, set);
    1765   367992152 :                 hull = extend(hull, set);
    1766             :         }
    1767   367992152 :         isl_set_free(set);
    1768             : 
    1769   367992152 :         return hull;
    1770             : }
    1771             : 
    1772             : /* Compute the convex hull of a set without any parameters or
    1773             :  * integer divisions.  Depending on whether the set is bounded,
    1774             :  * we pass control to the wrapping based convex hull or
    1775             :  * the Fourier-Motzkin elimination based convex hull.
    1776             :  * We also handle a few special cases before checking the boundedness.
    1777             :  */
    1778      112938 : static __isl_give isl_basic_set *uset_convex_hull(__isl_take isl_set *set)
    1779             : {
    1780             :         isl_bool bounded;
    1781      112938 :         struct isl_basic_set *convex_hull = NULL;
    1782             :         struct isl_basic_set *lin;
    1783             : 
    1784      112938 :         if (isl_set_n_dim(set) == 0)
    1785        6446 :                 return convex_hull_0d(set);
    1786             : 
    1787      106492 :         set = isl_set_coalesce(set);
    1788      106492 :         set = isl_set_set_rational(set);
    1789             : 
    1790      106492 :         if (!set)
    1791           0 :                 return NULL;
    1792      106492 :         if (set->n == 1) {
    1793        1272 :                 convex_hull = isl_basic_set_copy(set->p[0]);
    1794        1272 :                 isl_set_free(set);
    1795        1272 :                 return convex_hull;
    1796             :         }
    1797      105220 :         if (isl_set_n_dim(set) == 1)
    1798        3530 :                 return convex_hull_1d(set);
    1799             : 
    1800      101690 :         bounded = isl_set_is_bounded(set);
    1801      101690 :         if (bounded < 0)
    1802           0 :                 goto error;
    1803      101690 :         if (bounded && set->ctx->opt->convex == ISL_CONVEX_HULL_WRAP)
    1804      101690 :                 return uset_convex_hull_wrap(set);
    1805             : 
    1806           0 :         lin = isl_set_combined_lineality_space(isl_set_copy(set));
    1807           0 :         if (!lin)
    1808           0 :                 goto error;
    1809           0 :         if (isl_basic_set_plain_is_universe(lin)) {
    1810           0 :                 isl_set_free(set);
    1811           0 :                 return lin;
    1812             :         }
    1813           0 :         if (lin->n_eq < isl_basic_set_total_dim(lin))
    1814           0 :                 return modulo_lineality(set, lin);
    1815           0 :         isl_basic_set_free(lin);
    1816             : 
    1817           0 :         return uset_convex_hull_unbounded(set);
    1818             : error:
    1819           0 :         isl_set_free(set);
    1820           0 :         isl_basic_set_free(convex_hull);
    1821           0 :         return NULL;
    1822             : }
    1823             : 
    1824             : /* This is the core procedure, where "set" is a "pure" set, i.e.,
    1825             :  * without parameters or divs and where the convex hull of set is
    1826             :  * known to be full-dimensional.
    1827             :  */
    1828  1218234700 : static __isl_give isl_basic_set *uset_convex_hull_wrap_bounded(
    1829             :         __isl_take isl_set *set)
    1830             : {
    1831  1218234700 :         struct isl_basic_set *convex_hull = NULL;
    1832             : 
    1833  1218234700 :         if (!set)
    1834           0 :                 goto error;
    1835             : 
    1836  1218234700 :         if (isl_set_n_dim(set) == 0) {
    1837           0 :                 convex_hull = isl_basic_set_universe(isl_space_copy(set->dim));
    1838           0 :                 isl_set_free(set);
    1839           0 :                 convex_hull = isl_basic_set_set_rational(convex_hull);
    1840           0 :                 return convex_hull;
    1841             :         }
    1842             : 
    1843  1218234700 :         set = isl_set_set_rational(set);
    1844  1218234700 :         set = isl_set_coalesce(set);
    1845  1218234700 :         if (!set)
    1846           0 :                 goto error;
    1847  1218234700 :         if (set->n == 1) {
    1848    10066738 :                 convex_hull = isl_basic_set_copy(set->p[0]);
    1849    10066738 :                 isl_set_free(set);
    1850    10066738 :                 convex_hull = isl_basic_map_remove_redundancies(convex_hull);
    1851    10066738 :                 return convex_hull;
    1852             :         }
    1853  1208167962 :         if (isl_set_n_dim(set) == 1)
    1854   840277500 :                 return convex_hull_1d(set);
    1855             : 
    1856   367890462 :         return uset_convex_hull_wrap(set);
    1857             : error:
    1858           0 :         isl_set_free(set);
    1859           0 :         return NULL;
    1860             : }
    1861             : 
    1862             : /* Compute the convex hull of set "set" with affine hull "affine_hull",
    1863             :  * We first remove the equalities (transforming the set), compute the
    1864             :  * convex hull of the transformed set and then add the equalities back
    1865             :  * (after performing the inverse transformation.
    1866             :  */
    1867       71070 : static __isl_give isl_basic_set *modulo_affine_hull(
    1868             :         __isl_take isl_set *set, __isl_take isl_basic_set *affine_hull)
    1869             : {
    1870             :         struct isl_mat *T;
    1871             :         struct isl_mat *T2;
    1872             :         struct isl_basic_set *dummy;
    1873             :         struct isl_basic_set *convex_hull;
    1874             : 
    1875       71070 :         dummy = isl_basic_set_remove_equalities(
    1876       71070 :                         isl_basic_set_copy(affine_hull), &T, &T2);
    1877       71070 :         if (!dummy)
    1878           0 :                 goto error;
    1879       71070 :         isl_basic_set_free(dummy);
    1880       71070 :         set = isl_set_preimage(set, T);
    1881       71070 :         convex_hull = uset_convex_hull(set);
    1882       71070 :         convex_hull = isl_basic_set_preimage(convex_hull, T2);
    1883       71070 :         convex_hull = isl_basic_set_intersect(convex_hull, affine_hull);
    1884       71070 :         return convex_hull;
    1885             : error:
    1886           0 :         isl_mat_free(T);
    1887           0 :         isl_mat_free(T2);
    1888           0 :         isl_basic_set_free(affine_hull);
    1889           0 :         isl_set_free(set);
    1890           0 :         return NULL;
    1891             : }
    1892             : 
    1893             : /* Return an empty basic map living in the same space as "map".
    1894             :  */
    1895           0 : static __isl_give isl_basic_map *replace_map_by_empty_basic_map(
    1896             :         __isl_take isl_map *map)
    1897             : {
    1898             :         isl_space *space;
    1899             : 
    1900           0 :         space = isl_map_get_space(map);
    1901           0 :         isl_map_free(map);
    1902           0 :         return isl_basic_map_empty(space);
    1903             : }
    1904             : 
    1905             : /* Compute the convex hull of a map.
    1906             :  *
    1907             :  * The implementation was inspired by "Extended Convex Hull" by Fukuda et al.,
    1908             :  * specifically, the wrapping of facets to obtain new facets.
    1909             :  */
    1910      112938 : __isl_give isl_basic_map *isl_map_convex_hull(__isl_take isl_map *map)
    1911             : {
    1912             :         struct isl_basic_set *bset;
    1913      112938 :         struct isl_basic_map *model = NULL;
    1914      112938 :         struct isl_basic_set *affine_hull = NULL;
    1915      112938 :         struct isl_basic_map *convex_hull = NULL;
    1916      112938 :         struct isl_set *set = NULL;
    1917             : 
    1918      112938 :         map = isl_map_detect_equalities(map);
    1919      112938 :         map = isl_map_align_divs_internal(map);
    1920      112938 :         if (!map)
    1921           0 :                 goto error;
    1922             : 
    1923      112938 :         if (map->n == 0)
    1924           0 :                 return replace_map_by_empty_basic_map(map);
    1925             : 
    1926      112938 :         model = isl_basic_map_copy(map->p[0]);
    1927      112938 :         set = isl_map_underlying_set(map);
    1928      112938 :         if (!set)
    1929           0 :                 goto error;
    1930             : 
    1931      112938 :         affine_hull = isl_set_affine_hull(isl_set_copy(set));
    1932      112938 :         if (!affine_hull)
    1933           0 :                 goto error;
    1934      112938 :         if (affine_hull->n_eq != 0)
    1935       71070 :                 bset = modulo_affine_hull(set, affine_hull);
    1936             :         else {
    1937       41868 :                 isl_basic_set_free(affine_hull);
    1938       41868 :                 bset = uset_convex_hull(set);
    1939             :         }
    1940             : 
    1941      112938 :         convex_hull = isl_basic_map_overlying_set(bset, model);
    1942      112938 :         if (!convex_hull)
    1943           0 :                 return NULL;
    1944             : 
    1945      112938 :         ISL_F_SET(convex_hull, ISL_BASIC_MAP_NO_IMPLICIT);
    1946      112938 :         ISL_F_SET(convex_hull, ISL_BASIC_MAP_ALL_EQUALITIES);
    1947      112938 :         ISL_F_CLR(convex_hull, ISL_BASIC_MAP_RATIONAL);
    1948      112938 :         return convex_hull;
    1949             : error:
    1950           0 :         isl_set_free(set);
    1951           0 :         isl_basic_map_free(model);
    1952           0 :         return NULL;
    1953             : }
    1954             : 
    1955      112938 : struct isl_basic_set *isl_set_convex_hull(struct isl_set *set)
    1956             : {
    1957      112938 :         return bset_from_bmap(isl_map_convex_hull(set_to_map(set)));
    1958             : }
    1959             : 
    1960           0 : __isl_give isl_basic_map *isl_map_polyhedral_hull(__isl_take isl_map *map)
    1961             : {
    1962             :         isl_basic_map *hull;
    1963             : 
    1964           0 :         hull = isl_map_convex_hull(map);
    1965           0 :         return isl_basic_map_remove_divs(hull);
    1966             : }
    1967             : 
    1968           0 : __isl_give isl_basic_set *isl_set_polyhedral_hull(__isl_take isl_set *set)
    1969             : {
    1970           0 :         return bset_from_bmap(isl_map_polyhedral_hull(set_to_map(set)));
    1971             : }
    1972             : 
    1973             : struct sh_data_entry {
    1974             :         struct isl_hash_table   *table;
    1975             :         struct isl_tab          *tab;
    1976             : };
    1977             : 
    1978             : /* Holds the data needed during the simple hull computation.
    1979             :  * In particular,
    1980             :  *      n               the number of basic sets in the original set
    1981             :  *      hull_table      a hash table of already computed constraints
    1982             :  *                      in the simple hull
    1983             :  *      p               for each basic set,
    1984             :  *              table           a hash table of the constraints
    1985             :  *              tab             the tableau corresponding to the basic set
    1986             :  */
    1987             : struct sh_data {
    1988             :         struct isl_ctx          *ctx;
    1989             :         unsigned                n;
    1990             :         struct isl_hash_table   *hull_table;
    1991             :         struct sh_data_entry    p[1];
    1992             : };
    1993             : 
    1994           0 : static void sh_data_free(struct sh_data *data)
    1995             : {
    1996             :         int i;
    1997             : 
    1998           0 :         if (!data)
    1999           0 :                 return;
    2000           0 :         isl_hash_table_free(data->ctx, data->hull_table);
    2001           0 :         for (i = 0; i < data->n; ++i) {
    2002           0 :                 isl_hash_table_free(data->ctx, data->p[i].table);
    2003           0 :                 isl_tab_free(data->p[i].tab);
    2004             :         }
    2005           0 :         free(data);
    2006             : }
    2007             : 
    2008             : struct ineq_cmp_data {
    2009             :         unsigned        len;
    2010             :         isl_int         *p;
    2011             : };
    2012             : 
    2013           0 : static int has_ineq(const void *entry, const void *val)
    2014             : {
    2015           0 :         isl_int *row = (isl_int *)entry;
    2016           0 :         struct ineq_cmp_data *v = (struct ineq_cmp_data *)val;
    2017             : 
    2018           0 :         return isl_seq_eq(row + 1, v->p + 1, v->len) ||
    2019           0 :                isl_seq_is_neg(row + 1, v->p + 1, v->len);
    2020             : }
    2021             : 
    2022           0 : static int hash_ineq(struct isl_ctx *ctx, struct isl_hash_table *table,
    2023             :                         isl_int *ineq, unsigned len)
    2024             : {
    2025             :         uint32_t c_hash;
    2026             :         struct ineq_cmp_data v;
    2027             :         struct isl_hash_table_entry *entry;
    2028             : 
    2029           0 :         v.len = len;
    2030           0 :         v.p = ineq;
    2031           0 :         c_hash = isl_seq_get_hash(ineq + 1, len);
    2032           0 :         entry = isl_hash_table_find(ctx, table, c_hash, has_ineq, &v, 1);
    2033           0 :         if (!entry)
    2034           0 :                 return - 1;
    2035           0 :         entry->data = ineq;
    2036           0 :         return 0;
    2037             : }
    2038             : 
    2039             : /* Fill hash table "table" with the constraints of "bset".
    2040             :  * Equalities are added as two inequalities.
    2041             :  * The value in the hash table is a pointer to the (in)equality of "bset".
    2042             :  */
    2043           0 : static int hash_basic_set(struct isl_hash_table *table,
    2044             :         __isl_keep isl_basic_set *bset)
    2045             : {
    2046             :         int i, j;
    2047           0 :         unsigned dim = isl_basic_set_total_dim(bset);
    2048             : 
    2049           0 :         for (i = 0; i < bset->n_eq; ++i) {
    2050           0 :                 for (j = 0; j < 2; ++j) {
    2051           0 :                         isl_seq_neg(bset->eq[i], bset->eq[i], 1 + dim);
    2052           0 :                         if (hash_ineq(bset->ctx, table, bset->eq[i], dim) < 0)
    2053           0 :                                 return -1;
    2054             :                 }
    2055             :         }
    2056           0 :         for (i = 0; i < bset->n_ineq; ++i) {
    2057           0 :                 if (hash_ineq(bset->ctx, table, bset->ineq[i], dim) < 0)
    2058           0 :                         return -1;
    2059             :         }
    2060           0 :         return 0;
    2061             : }
    2062             : 
    2063           0 : static struct sh_data *sh_data_alloc(__isl_keep isl_set *set, unsigned n_ineq)
    2064             : {
    2065             :         struct sh_data *data;
    2066             :         int i;
    2067             : 
    2068           0 :         data = isl_calloc(set->ctx, struct sh_data,
    2069             :                 sizeof(struct sh_data) +
    2070             :                 (set->n - 1) * sizeof(struct sh_data_entry));
    2071           0 :         if (!data)
    2072           0 :                 return NULL;
    2073           0 :         data->ctx = set->ctx;
    2074           0 :         data->n = set->n;
    2075           0 :         data->hull_table = isl_hash_table_alloc(set->ctx, n_ineq);
    2076           0 :         if (!data->hull_table)
    2077           0 :                 goto error;
    2078           0 :         for (i = 0; i < set->n; ++i) {
    2079           0 :                 data->p[i].table = isl_hash_table_alloc(set->ctx,
    2080           0 :                                     2 * set->p[i]->n_eq + set->p[i]->n_ineq);
    2081           0 :                 if (!data->p[i].table)
    2082           0 :                         goto error;
    2083           0 :                 if (hash_basic_set(data->p[i].table, set->p[i]) < 0)
    2084           0 :                         goto error;
    2085             :         }
    2086           0 :         return data;
    2087             : error:
    2088           0 :         sh_data_free(data);
    2089           0 :         return NULL;
    2090             : }
    2091             : 
    2092             : /* Check if inequality "ineq" is a bound for basic set "j" or if
    2093             :  * it can be relaxed (by increasing the constant term) to become
    2094             :  * a bound for that basic set.  In the latter case, the constant
    2095             :  * term is updated.
    2096             :  * Relaxation of the constant term is only allowed if "shift" is set.
    2097             :  *
    2098             :  * Return 1 if "ineq" is a bound
    2099             :  *        0 if "ineq" may attain arbitrarily small values on basic set "j"
    2100             :  *       -1 if some error occurred
    2101             :  */
    2102           0 : static int is_bound(struct sh_data *data, __isl_keep isl_set *set, int j,
    2103             :         isl_int *ineq, int shift)
    2104             : {
    2105             :         enum isl_lp_result res;
    2106             :         isl_int opt;
    2107             : 
    2108           0 :         if (!data->p[j].tab) {
    2109           0 :                 data->p[j].tab = isl_tab_from_basic_set(set->p[j], 0);
    2110           0 :                 if (!data->p[j].tab)
    2111           0 :                         return -1;
    2112             :         }
    2113             : 
    2114           0 :         isl_int_init(opt);
    2115             : 
    2116           0 :         res = isl_tab_min(data->p[j].tab, ineq, data->ctx->one,
    2117             :                                 &opt, NULL, 0);
    2118           0 :         if (res == isl_lp_ok && isl_int_is_neg(opt)) {
    2119           0 :                 if (shift)
    2120           0 :                         isl_int_sub(ineq[0], ineq[0], opt);
    2121             :                 else
    2122           0 :                         res = isl_lp_unbounded;
    2123             :         }
    2124             : 
    2125           0 :         isl_int_clear(opt);
    2126             : 
    2127           0 :         return (res == isl_lp_ok || res == isl_lp_empty) ? 1 :
    2128           0 :                res == isl_lp_unbounded ? 0 : -1;
    2129             : }
    2130             : 
    2131             : /* Set the constant term of "ineq" to the maximum of those of the constraints
    2132             :  * in the basic sets of "set" following "i" that are parallel to "ineq".
    2133             :  * That is, if any of the basic sets of "set" following "i" have a more
    2134             :  * relaxed copy of "ineq", then replace "ineq" by the most relaxed copy.
    2135             :  * "c_hash" is the hash value of the linear part of "ineq".
    2136             :  * "v" has been set up for use by has_ineq.
    2137             :  *
    2138             :  * Note that the two inequality constraints corresponding to an equality are
    2139             :  * represented by the same inequality constraint in data->p[j].table
    2140             :  * (but with different hash values).  This means the constraint (or at
    2141             :  * least its constant term) may need to be temporarily negated to get
    2142             :  * the actually hashed constraint.
    2143             :  */
    2144           0 : static void set_max_constant_term(struct sh_data *data, __isl_keep isl_set *set,
    2145             :         int i, isl_int *ineq, uint32_t c_hash, struct ineq_cmp_data *v)
    2146             : {
    2147             :         int j;
    2148             :         isl_ctx *ctx;
    2149             :         struct isl_hash_table_entry *entry;
    2150             : 
    2151           0 :         ctx = isl_set_get_ctx(set);
    2152           0 :         for (j = i + 1; j < set->n; ++j) {
    2153             :                 int neg;
    2154             :                 isl_int *ineq_j;
    2155             : 
    2156           0 :                 entry = isl_hash_table_find(ctx, data->p[j].table,
    2157             :                                                 c_hash, &has_ineq, v, 0);
    2158           0 :                 if (!entry)
    2159           0 :                         continue;
    2160             : 
    2161           0 :                 ineq_j = entry->data;
    2162           0 :                 neg = isl_seq_is_neg(ineq_j + 1, ineq + 1, v->len);
    2163           0 :                 if (neg)
    2164           0 :                         isl_int_neg(ineq_j[0], ineq_j[0]);
    2165           0 :                 if (isl_int_gt(ineq_j[0], ineq[0]))
    2166           0 :                         isl_int_set(ineq[0], ineq_j[0]);
    2167           0 :                 if (neg)
    2168           0 :                         isl_int_neg(ineq_j[0], ineq_j[0]);
    2169             :         }
    2170           0 : }
    2171             : 
    2172             : /* Check if inequality "ineq" from basic set "i" is or can be relaxed to
    2173             :  * become a bound on the whole set.  If so, add the (relaxed) inequality
    2174             :  * to "hull".  Relaxation is only allowed if "shift" is set.
    2175             :  *
    2176             :  * We first check if "hull" already contains a translate of the inequality.
    2177             :  * If so, we are done.
    2178             :  * Then, we check if any of the previous basic sets contains a translate
    2179             :  * of the inequality.  If so, then we have already considered this
    2180             :  * inequality and we are done.
    2181             :  * Otherwise, for each basic set other than "i", we check if the inequality
    2182             :  * is a bound on the basic set, but first replace the constant term
    2183             :  * by the maximal value of any translate of the inequality in any
    2184             :  * of the following basic sets.
    2185             :  * For previous basic sets, we know that they do not contain a translate
    2186             :  * of the inequality, so we directly call is_bound.
    2187             :  * For following basic sets, we first check if a translate of the
    2188             :  * inequality appears in its description.  If so, the constant term
    2189             :  * of the inequality has already been updated with respect to this
    2190             :  * translate and the inequality is therefore known to be a bound
    2191             :  * of this basic set.
    2192             :  */
    2193           0 : static __isl_give isl_basic_set *add_bound(__isl_take isl_basic_set *hull,
    2194             :         struct sh_data *data, __isl_keep isl_set *set, int i, isl_int *ineq,
    2195             :         int shift)
    2196             : {
    2197             :         uint32_t c_hash;
    2198             :         struct ineq_cmp_data v;
    2199             :         struct isl_hash_table_entry *entry;
    2200             :         int j, k;
    2201             : 
    2202           0 :         if (!hull)
    2203           0 :                 return NULL;
    2204             : 
    2205           0 :         v.len = isl_basic_set_total_dim(hull);
    2206           0 :         v.p = ineq;
    2207           0 :         c_hash = isl_seq_get_hash(ineq + 1, v.len);
    2208             : 
    2209           0 :         entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
    2210             :                                         has_ineq, &v, 0);
    2211           0 :         if (entry)
    2212           0 :                 return hull;
    2213             : 
    2214           0 :         for (j = 0; j < i; ++j) {
    2215           0 :                 entry = isl_hash_table_find(hull->ctx, data->p[j].table,
    2216             :                                                 c_hash, has_ineq, &v, 0);
    2217           0 :                 if (entry)
    2218           0 :                         break;
    2219             :         }
    2220           0 :         if (j < i)
    2221           0 :                 return hull;
    2222             : 
    2223           0 :         k = isl_basic_set_alloc_inequality(hull);
    2224           0 :         if (k < 0)
    2225           0 :                 goto error;
    2226           0 :         isl_seq_cpy(hull->ineq[k], ineq, 1 + v.len);
    2227             : 
    2228           0 :         set_max_constant_term(data, set, i, hull->ineq[k], c_hash, &v);
    2229           0 :         for (j = 0; j < i; ++j) {
    2230             :                 int bound;
    2231           0 :                 bound = is_bound(data, set, j, hull->ineq[k], shift);
    2232           0 :                 if (bound < 0)
    2233           0 :                         goto error;
    2234           0 :                 if (!bound)
    2235           0 :                         break;
    2236             :         }
    2237           0 :         if (j < i) {
    2238           0 :                 isl_basic_set_free_inequality(hull, 1);
    2239           0 :                 return hull;
    2240             :         }
    2241             : 
    2242           0 :         for (j = i + 1; j < set->n; ++j) {
    2243             :                 int bound;
    2244           0 :                 entry = isl_hash_table_find(hull->ctx, data->p[j].table,
    2245             :                                                 c_hash, has_ineq, &v, 0);
    2246           0 :                 if (entry)
    2247           0 :                         continue;
    2248           0 :                 bound = is_bound(data, set, j, hull->ineq[k], shift);
    2249           0 :                 if (bound < 0)
    2250           0 :                         goto error;
    2251           0 :                 if (!bound)
    2252           0 :                         break;
    2253             :         }
    2254           0 :         if (j < set->n) {
    2255           0 :                 isl_basic_set_free_inequality(hull, 1);
    2256           0 :                 return hull;
    2257             :         }
    2258             : 
    2259           0 :         entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
    2260             :                                         has_ineq, &v, 1);
    2261           0 :         if (!entry)
    2262           0 :                 goto error;
    2263           0 :         entry->data = hull->ineq[k];
    2264             : 
    2265           0 :         return hull;
    2266             : error:
    2267           0 :         isl_basic_set_free(hull);
    2268           0 :         return NULL;
    2269             : }
    2270             : 
    2271             : /* Check if any inequality from basic set "i" is or can be relaxed to
    2272             :  * become a bound on the whole set.  If so, add the (relaxed) inequality
    2273             :  * to "hull".  Relaxation is only allowed if "shift" is set.
    2274             :  */
    2275           0 : static __isl_give isl_basic_set *add_bounds(__isl_take isl_basic_set *bset,
    2276             :         struct sh_data *data, __isl_keep isl_set *set, int i, int shift)
    2277             : {
    2278             :         int j, k;
    2279           0 :         unsigned dim = isl_basic_set_total_dim(bset);
    2280             : 
    2281           0 :         for (j = 0; j < set->p[i]->n_eq; ++j) {
    2282           0 :                 for (k = 0; k < 2; ++k) {
    2283           0 :                         isl_seq_neg(set->p[i]->eq[j], set->p[i]->eq[j], 1+dim);
    2284           0 :                         bset = add_bound(bset, data, set, i, set->p[i]->eq[j],
    2285             :                                             shift);
    2286             :                 }
    2287             :         }
    2288           0 :         for (j = 0; j < set->p[i]->n_ineq; ++j)
    2289           0 :                 bset = add_bound(bset, data, set, i, set->p[i]->ineq[j], shift);
    2290           0 :         return bset;
    2291             : }
    2292             : 
    2293             : /* Compute a superset of the convex hull of set that is described
    2294             :  * by only (translates of) the constraints in the constituents of set.
    2295             :  * Translation is only allowed if "shift" is set.
    2296             :  */
    2297           0 : static __isl_give isl_basic_set *uset_simple_hull(__isl_take isl_set *set,
    2298             :         int shift)
    2299             : {
    2300           0 :         struct sh_data *data = NULL;
    2301           0 :         struct isl_basic_set *hull = NULL;
    2302             :         unsigned n_ineq;
    2303             :         int i;
    2304             : 
    2305           0 :         if (!set)
    2306           0 :                 return NULL;
    2307             : 
    2308           0 :         n_ineq = 0;
    2309           0 :         for (i = 0; i < set->n; ++i) {
    2310           0 :                 if (!set->p[i])
    2311           0 :                         goto error;
    2312           0 :                 n_ineq += 2 * set->p[i]->n_eq + set->p[i]->n_ineq;
    2313             :         }
    2314             : 
    2315           0 :         hull = isl_basic_set_alloc_space(isl_space_copy(set->dim), 0, 0, n_ineq);
    2316           0 :         if (!hull)
    2317           0 :                 goto error;
    2318             : 
    2319           0 :         data = sh_data_alloc(set, n_ineq);
    2320           0 :         if (!data)
    2321           0 :                 goto error;
    2322             : 
    2323           0 :         for (i = 0; i < set->n; ++i)
    2324           0 :                 hull = add_bounds(hull, data, set, i, shift);
    2325             : 
    2326           0 :         sh_data_free(data);
    2327           0 :         isl_set_free(set);
    2328             : 
    2329           0 :         return hull;
    2330             : error:
    2331           0 :         sh_data_free(data);
    2332           0 :         isl_basic_set_free(hull);
    2333           0 :         isl_set_free(set);
    2334           0 :         return NULL;
    2335             : }
    2336             : 
    2337             : /* Compute a superset of the convex hull of map that is described
    2338             :  * by only (translates of) the constraints in the constituents of map.
    2339             :  * Handle trivial cases where map is NULL or contains at most one disjunct.
    2340             :  */
    2341           0 : static __isl_give isl_basic_map *map_simple_hull_trivial(
    2342             :         __isl_take isl_map *map)
    2343             : {
    2344             :         isl_basic_map *hull;
    2345             : 
    2346           0 :         if (!map)
    2347           0 :                 return NULL;
    2348           0 :         if (map->n == 0)
    2349           0 :                 return replace_map_by_empty_basic_map(map);
    2350             : 
    2351           0 :         hull = isl_basic_map_copy(map->p[0]);
    2352           0 :         isl_map_free(map);
    2353           0 :         return hull;
    2354             : }
    2355             : 
    2356             : /* Return a copy of the simple hull cached inside "map".
    2357             :  * "shift" determines whether to return the cached unshifted or shifted
    2358             :  * simple hull.
    2359             :  */
    2360           0 : static __isl_give isl_basic_map *cached_simple_hull(__isl_take isl_map *map,
    2361             :         int shift)
    2362             : {
    2363             :         isl_basic_map *hull;
    2364             : 
    2365           0 :         hull = isl_basic_map_copy(map->cached_simple_hull[shift]);
    2366           0 :         isl_map_free(map);
    2367             : 
    2368           0 :         return hull;
    2369             : }
    2370             : 
    2371             : /* Compute a superset of the convex hull of map that is described
    2372             :  * by only (translates of) the constraints in the constituents of map.
    2373             :  * Translation is only allowed if "shift" is set.
    2374             :  *
    2375             :  * The constraints are sorted while removing redundant constraints
    2376             :  * in order to indicate a preference of which constraints should
    2377             :  * be preserved.  In particular, pairs of constraints that are
    2378             :  * sorted together are preferred to either both be preserved
    2379             :  * or both be removed.  The sorting is performed inside
    2380             :  * isl_basic_map_remove_redundancies.
    2381             :  *
    2382             :  * The result of the computation is stored in map->cached_simple_hull[shift]
    2383             :  * such that it can be reused in subsequent calls.  The cache is cleared
    2384             :  * whenever the map is modified (in isl_map_cow).
    2385             :  * Note that the results need to be stored in the input map for there
    2386             :  * to be any chance that they may get reused.  In particular, they
    2387             :  * are stored in a copy of the input map that is saved before
    2388             :  * the integer division alignment.
    2389             :  */
    2390           0 : static __isl_give isl_basic_map *map_simple_hull(__isl_take isl_map *map,
    2391             :         int shift)
    2392             : {
    2393           0 :         struct isl_set *set = NULL;
    2394           0 :         struct isl_basic_map *model = NULL;
    2395             :         struct isl_basic_map *hull;
    2396             :         struct isl_basic_map *affine_hull;
    2397           0 :         struct isl_basic_set *bset = NULL;
    2398             :         isl_map *input;
    2399             : 
    2400           0 :         if (!map || map->n <= 1)
    2401           0 :                 return map_simple_hull_trivial(map);
    2402             : 
    2403           0 :         if (map->cached_simple_hull[shift])
    2404           0 :                 return cached_simple_hull(map, shift);
    2405             : 
    2406           0 :         map = isl_map_detect_equalities(map);
    2407           0 :         if (!map || map->n <= 1)
    2408           0 :                 return map_simple_hull_trivial(map);
    2409           0 :         affine_hull = isl_map_affine_hull(isl_map_copy(map));
    2410           0 :         input = isl_map_copy(map);
    2411           0 :         map = isl_map_align_divs_internal(map);
    2412           0 :         model = map ? isl_basic_map_copy(map->p[0]) : NULL;
    2413             : 
    2414           0 :         set = isl_map_underlying_set(map);
    2415             : 
    2416           0 :         bset = uset_simple_hull(set, shift);
    2417             : 
    2418           0 :         hull = isl_basic_map_overlying_set(bset, model);
    2419             : 
    2420           0 :         hull = isl_basic_map_intersect(hull, affine_hull);
    2421           0 :         hull = isl_basic_map_remove_redundancies(hull);
    2422             : 
    2423           0 :         if (hull) {
    2424           0 :                 ISL_F_SET(hull, ISL_BASIC_MAP_NO_IMPLICIT);
    2425           0 :                 ISL_F_SET(hull, ISL_BASIC_MAP_ALL_EQUALITIES);
    2426             :         }
    2427             : 
    2428           0 :         hull = isl_basic_map_finalize(hull);
    2429           0 :         if (input)
    2430           0 :                 input->cached_simple_hull[shift] = isl_basic_map_copy(hull);
    2431           0 :         isl_map_free(input);
    2432             : 
    2433           0 :         return hull;
    2434             : }
    2435             : 
    2436             : /* Compute a superset of the convex hull of map that is described
    2437             :  * by only translates of the constraints in the constituents of map.
    2438             :  */
    2439           0 : __isl_give isl_basic_map *isl_map_simple_hull(__isl_take isl_map *map)
    2440             : {
    2441           0 :         return map_simple_hull(map, 1);
    2442             : }
    2443             : 
    2444           0 : struct isl_basic_set *isl_set_simple_hull(struct isl_set *set)
    2445             : {
    2446           0 :         return bset_from_bmap(isl_map_simple_hull(set_to_map(set)));
    2447             : }
    2448             : 
    2449             : /* Compute a superset of the convex hull of map that is described
    2450             :  * by only the constraints in the constituents of map.
    2451             :  */
    2452           0 : __isl_give isl_basic_map *isl_map_unshifted_simple_hull(
    2453             :         __isl_take isl_map *map)
    2454             : {
    2455           0 :         return map_simple_hull(map, 0);
    2456             : }
    2457             : 
    2458           0 : __isl_give isl_basic_set *isl_set_unshifted_simple_hull(
    2459             :         __isl_take isl_set *set)
    2460             : {
    2461           0 :         return isl_map_unshifted_simple_hull(set);
    2462             : }
    2463             : 
    2464             : /* Drop all inequalities from "bmap1" that do not also appear in "bmap2".
    2465             :  * A constraint that appears with different constant terms
    2466             :  * in "bmap1" and "bmap2" is also kept, with the least restrictive
    2467             :  * (i.e., greatest) constant term.
    2468             :  * "bmap1" and "bmap2" are assumed to have the same (known)
    2469             :  * integer divisions.
    2470             :  * The constraints of both "bmap1" and "bmap2" are assumed
    2471             :  * to have been sorted using isl_basic_map_sort_constraints.
    2472             :  *
    2473             :  * Run through the inequality constraints of "bmap1" and "bmap2"
    2474             :  * in sorted order.
    2475             :  * Each constraint of "bmap1" without a matching constraint in "bmap2"
    2476             :  * is removed.
    2477             :  * If a match is found, the constraint is kept.  If needed, the constant
    2478             :  * term of the constraint is adjusted.
    2479             :  */
    2480           0 : static __isl_give isl_basic_map *select_shared_inequalities(
    2481             :         __isl_take isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
    2482             : {
    2483             :         int i1, i2;
    2484             : 
    2485           0 :         bmap1 = isl_basic_map_cow(bmap1);
    2486           0 :         if (!bmap1 || !bmap2)
    2487           0 :                 return isl_basic_map_free(bmap1);
    2488             : 
    2489           0 :         i1 = bmap1->n_ineq - 1;
    2490           0 :         i2 = bmap2->n_ineq - 1;
    2491           0 :         while (bmap1 && i1 >= 0 && i2 >= 0) {
    2492             :                 int cmp;
    2493             : 
    2494           0 :                 cmp = isl_basic_map_constraint_cmp(bmap1, bmap1->ineq[i1],
    2495           0 :                                                         bmap2->ineq[i2]);
    2496           0 :                 if (cmp < 0) {
    2497           0 :                         --i2;
    2498           0 :                         continue;
    2499             :                 }
    2500           0 :                 if (cmp > 0) {
    2501           0 :                         if (isl_basic_map_drop_inequality(bmap1, i1) < 0)
    2502           0 :                                 bmap1 = isl_basic_map_free(bmap1);
    2503           0 :                         --i1;
    2504           0 :                         continue;
    2505             :                 }
    2506           0 :                 if (isl_int_lt(bmap1->ineq[i1][0], bmap2->ineq[i2][0]))
    2507           0 :                         isl_int_set(bmap1->ineq[i1][0], bmap2->ineq[i2][0]);
    2508           0 :                 --i1;
    2509           0 :                 --i2;
    2510             :         }
    2511           0 :         for (; i1 >= 0; --i1)
    2512           0 :                 if (isl_basic_map_drop_inequality(bmap1, i1) < 0)
    2513           0 :                         bmap1 = isl_basic_map_free(bmap1);
    2514             : 
    2515           0 :         return bmap1;
    2516             : }
    2517             : 
    2518             : /* Drop all equalities from "bmap1" that do not also appear in "bmap2".
    2519             :  * "bmap1" and "bmap2" are assumed to have the same (known)
    2520             :  * integer divisions.
    2521             :  *
    2522             :  * Run through the equality constraints of "bmap1" and "bmap2".
    2523             :  * Each constraint of "bmap1" without a matching constraint in "bmap2"
    2524             :  * is removed.
    2525             :  */
    2526           0 : static __isl_give isl_basic_map *select_shared_equalities(
    2527             :         __isl_take isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
    2528             : {
    2529             :         int i1, i2;
    2530             :         unsigned total;
    2531             : 
    2532           0 :         bmap1 = isl_basic_map_cow(bmap1);
    2533           0 :         if (!bmap1 || !bmap2)
    2534           0 :                 return isl_basic_map_free(bmap1);
    2535             : 
    2536           0 :         total = isl_basic_map_total_dim(bmap1);
    2537             : 
    2538           0 :         i1 = bmap1->n_eq - 1;
    2539           0 :         i2 = bmap2->n_eq - 1;
    2540           0 :         while (bmap1 && i1 >= 0 && i2 >= 0) {
    2541             :                 int last1, last2;
    2542             : 
    2543           0 :                 last1 = isl_seq_last_non_zero(bmap1->eq[i1] + 1, total);
    2544           0 :                 last2 = isl_seq_last_non_zero(bmap2->eq[i2] + 1, total);
    2545           0 :                 if (last1 > last2) {
    2546           0 :                         --i2;
    2547           0 :                         continue;
    2548             :                 }
    2549           0 :                 if (last1 < last2) {
    2550           0 :                         if (isl_basic_map_drop_equality(bmap1, i1) < 0)
    2551           0 :                                 bmap1 = isl_basic_map_free(bmap1);
    2552           0 :                         --i1;
    2553           0 :                         continue;
    2554             :                 }
    2555           0 :                 if (!isl_seq_eq(bmap1->eq[i1], bmap2->eq[i2], 1 + total)) {
    2556           0 :                         if (isl_basic_map_drop_equality(bmap1, i1) < 0)
    2557           0 :                                 bmap1 = isl_basic_map_free(bmap1);
    2558             :                 }
    2559           0 :                 --i1;
    2560           0 :                 --i2;
    2561             :         }
    2562           0 :         for (; i1 >= 0; --i1)
    2563           0 :                 if (isl_basic_map_drop_equality(bmap1, i1) < 0)
    2564           0 :                         bmap1 = isl_basic_map_free(bmap1);
    2565             : 
    2566           0 :         return bmap1;
    2567             : }
    2568             : 
    2569             : /* Compute a superset of "bmap1" and "bmap2" that is described
    2570             :  * by only the constraints that appear in both "bmap1" and "bmap2".
    2571             :  *
    2572             :  * First drop constraints that involve unknown integer divisions
    2573             :  * since it is not trivial to check whether two such integer divisions
    2574             :  * in different basic maps are the same.
    2575             :  * Then align the remaining (known) divs and sort the constraints.
    2576             :  * Finally drop all inequalities and equalities from "bmap1" that
    2577             :  * do not also appear in "bmap2".
    2578             :  */
    2579           0 : __isl_give isl_basic_map *isl_basic_map_plain_unshifted_simple_hull(
    2580             :         __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
    2581             : {
    2582           0 :         bmap1 = isl_basic_map_drop_constraint_involving_unknown_divs(bmap1);
    2583           0 :         bmap2 = isl_basic_map_drop_constraint_involving_unknown_divs(bmap2);
    2584           0 :         bmap2 = isl_basic_map_align_divs(bmap2, bmap1);
    2585           0 :         bmap1 = isl_basic_map_align_divs(bmap1, bmap2);
    2586           0 :         bmap1 = isl_basic_map_gauss(bmap1, NULL);
    2587           0 :         bmap2 = isl_basic_map_gauss(bmap2, NULL);
    2588           0 :         bmap1 = isl_basic_map_sort_constraints(bmap1);
    2589           0 :         bmap2 = isl_basic_map_sort_constraints(bmap2);
    2590             : 
    2591           0 :         bmap1 = select_shared_inequalities(bmap1, bmap2);
    2592           0 :         bmap1 = select_shared_equalities(bmap1, bmap2);
    2593             : 
    2594           0 :         isl_basic_map_free(bmap2);
    2595           0 :         bmap1 = isl_basic_map_finalize(bmap1);
    2596           0 :         return bmap1;
    2597             : }
    2598             : 
    2599             : /* Compute a superset of the convex hull of "map" that is described
    2600             :  * by only the constraints in the constituents of "map".
    2601             :  * In particular, the result is composed of constraints that appear
    2602             :  * in each of the basic maps of "map"
    2603             :  *
    2604             :  * Constraints that involve unknown integer divisions are dropped
    2605             :  * since it is not trivial to check whether two such integer divisions
    2606             :  * in different basic maps are the same.
    2607             :  *
    2608             :  * The hull is initialized from the first basic map and then
    2609             :  * updated with respect to the other basic maps in turn.
    2610             :  */
    2611           0 : __isl_give isl_basic_map *isl_map_plain_unshifted_simple_hull(
    2612             :         __isl_take isl_map *map)
    2613             : {
    2614             :         int i;
    2615             :         isl_basic_map *hull;
    2616             : 
    2617           0 :         if (!map)
    2618           0 :                 return NULL;
    2619           0 :         if (map->n <= 1)
    2620           0 :                 return map_simple_hull_trivial(map);
    2621           0 :         map = isl_map_drop_constraint_involving_unknown_divs(map);
    2622           0 :         hull = isl_basic_map_copy(map->p[0]);
    2623           0 :         for (i = 1; i < map->n; ++i) {
    2624             :                 isl_basic_map *bmap_i;
    2625             : 
    2626           0 :                 bmap_i = isl_basic_map_copy(map->p[i]);
    2627           0 :                 hull = isl_basic_map_plain_unshifted_simple_hull(hull, bmap_i);
    2628             :         }
    2629             : 
    2630           0 :         isl_map_free(map);
    2631           0 :         return hull;
    2632             : }
    2633             : 
    2634             : /* Compute a superset of the convex hull of "set" that is described
    2635             :  * by only the constraints in the constituents of "set".
    2636             :  * In particular, the result is composed of constraints that appear
    2637             :  * in each of the basic sets of "set"
    2638             :  */
    2639           0 : __isl_give isl_basic_set *isl_set_plain_unshifted_simple_hull(
    2640             :         __isl_take isl_set *set)
    2641             : {
    2642           0 :         return isl_map_plain_unshifted_simple_hull(set);
    2643             : }
    2644             : 
    2645             : /* Check if "ineq" is a bound on "set" and, if so, add it to "hull".
    2646             :  *
    2647             :  * For each basic set in "set", we first check if the basic set
    2648             :  * contains a translate of "ineq".  If this translate is more relaxed,
    2649             :  * then we assume that "ineq" is not a bound on this basic set.
    2650             :  * Otherwise, we know that it is a bound.
    2651             :  * If the basic set does not contain a translate of "ineq", then
    2652             :  * we call is_bound to perform the test.
    2653             :  */
    2654           0 : static __isl_give isl_basic_set *add_bound_from_constraint(
    2655             :         __isl_take isl_basic_set *hull, struct sh_data *data,
    2656             :         __isl_keep isl_set *set, isl_int *ineq)
    2657             : {
    2658             :         int i, k;
    2659             :         isl_ctx *ctx;
    2660             :         uint32_t c_hash;
    2661             :         struct ineq_cmp_data v;
    2662             : 
    2663           0 :         if (!hull || !set)
    2664           0 :                 return isl_basic_set_free(hull);
    2665             : 
    2666           0 :         v.len = isl_basic_set_total_dim(hull);
    2667           0 :         v.p = ineq;
    2668           0 :         c_hash = isl_seq_get_hash(ineq + 1, v.len);
    2669             : 
    2670           0 :         ctx = isl_basic_set_get_ctx(hull);
    2671           0 :         for (i = 0; i < set->n; ++i) {
    2672             :                 int bound;
    2673             :                 struct isl_hash_table_entry *entry;
    2674             : 
    2675           0 :                 entry = isl_hash_table_find(ctx, data->p[i].table,
    2676             :                                                 c_hash, &has_ineq, &v, 0);
    2677           0 :                 if (entry) {
    2678           0 :                         isl_int *ineq_i = entry->data;
    2679             :                         int neg, more_relaxed;
    2680             : 
    2681           0 :                         neg = isl_seq_is_neg(ineq_i + 1, ineq + 1, v.len);
    2682           0 :                         if (neg)
    2683           0 :                                 isl_int_neg(ineq_i[0], ineq_i[0]);
    2684           0 :                         more_relaxed = isl_int_gt(ineq_i[0], ineq[0]);
    2685           0 :                         if (neg)
    2686           0 :                                 isl_int_neg(ineq_i[0], ineq_i[0]);
    2687           0 :                         if (more_relaxed)
    2688           0 :                                 break;
    2689             :                         else
    2690           0 :                                 continue;
    2691             :                 }
    2692           0 :                 bound = is_bound(data, set, i, ineq, 0);
    2693           0 :                 if (bound < 0)
    2694           0 :                         return isl_basic_set_free(hull);
    2695           0 :                 if (!bound)
    2696           0 :                         break;
    2697             :         }
    2698           0 :         if (i < set->n)
    2699           0 :                 return hull;
    2700             : 
    2701           0 :         k = isl_basic_set_alloc_inequality(hull);
    2702           0 :         if (k < 0)
    2703           0 :                 return isl_basic_set_free(hull);
    2704           0 :         isl_seq_cpy(hull->ineq[k], ineq, 1 + v.len);
    2705             : 
    2706           0 :         return hull;
    2707             : }
    2708             : 
    2709             : /* Compute a superset of the convex hull of "set" that is described
    2710             :  * by only some of the "n_ineq" constraints in the list "ineq", where "set"
    2711             :  * has no parameters or integer divisions.
    2712             :  *
    2713             :  * The inequalities in "ineq" are assumed to have been sorted such
    2714             :  * that constraints with the same linear part appear together and
    2715             :  * that among constraints with the same linear part, those with
    2716             :  * smaller constant term appear first.
    2717             :  *
    2718             :  * We reuse the same data structure that is used by uset_simple_hull,
    2719             :  * but we do not need the hull table since we will not consider the
    2720             :  * same constraint more than once.  We therefore allocate it with zero size.
    2721             :  *
    2722             :  * We run through the constraints and try to add them one by one,
    2723             :  * skipping identical constraints.  If we have added a constraint and
    2724             :  * the next constraint is a more relaxed translate, then we skip this
    2725             :  * next constraint as well.
    2726             :  */
    2727           0 : static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_constraints(
    2728             :         __isl_take isl_set *set, int n_ineq, isl_int **ineq)
    2729             : {
    2730             :         int i;
    2731           0 :         int last_added = 0;
    2732           0 :         struct sh_data *data = NULL;
    2733           0 :         isl_basic_set *hull = NULL;
    2734             :         unsigned dim;
    2735             : 
    2736           0 :         hull = isl_basic_set_alloc_space(isl_set_get_space(set), 0, 0, n_ineq);
    2737           0 :         if (!hull)
    2738           0 :                 goto error;
    2739             : 
    2740           0 :         data = sh_data_alloc(set, 0);
    2741           0 :         if (!data)
    2742           0 :                 goto error;
    2743             : 
    2744           0 :         dim = isl_set_dim(set, isl_dim_set);
    2745           0 :         for (i = 0; i < n_ineq; ++i) {
    2746           0 :                 int hull_n_ineq = hull->n_ineq;
    2747             :                 int parallel;
    2748             : 
    2749           0 :                 parallel = i > 0 && isl_seq_eq(ineq[i - 1] + 1, ineq[i] + 1,
    2750             :                                                 dim);
    2751           0 :                 if (parallel &&
    2752           0 :                     (last_added || isl_int_eq(ineq[i - 1][0], ineq[i][0])))
    2753           0 :                         continue;
    2754           0 :                 hull = add_bound_from_constraint(hull, data, set, ineq[i]);
    2755           0 :                 if (!hull)
    2756           0 :                         goto error;
    2757           0 :                 last_added = hull->n_ineq > hull_n_ineq;
    2758             :         }
    2759             : 
    2760           0 :         sh_data_free(data);
    2761           0 :         isl_set_free(set);
    2762           0 :         return hull;
    2763             : error:
    2764           0 :         sh_data_free(data);
    2765           0 :         isl_set_free(set);
    2766           0 :         isl_basic_set_free(hull);
    2767           0 :         return NULL;
    2768             : }
    2769             : 
    2770             : /* Collect pointers to all the inequalities in the elements of "list"
    2771             :  * in "ineq".  For equalities, store both a pointer to the equality and
    2772             :  * a pointer to its opposite, which is first copied to "mat".
    2773             :  * "ineq" and "mat" are assumed to have been preallocated to the right size
    2774             :  * (the number of inequalities + 2 times the number of equalites and
    2775             :  * the number of equalities, respectively).
    2776             :  */
    2777           0 : static __isl_give isl_mat *collect_inequalities(__isl_take isl_mat *mat,
    2778             :         __isl_keep isl_basic_set_list *list, isl_int **ineq)
    2779             : {
    2780             :         int i, j, n, n_eq, n_ineq;
    2781             : 
    2782           0 :         if (!mat)
    2783           0 :                 return NULL;
    2784             : 
    2785           0 :         n_eq = 0;
    2786           0 :         n_ineq = 0;
    2787           0 :         n = isl_basic_set_list_n_basic_set(list);
    2788           0 :         for (i = 0; i < n; ++i) {
    2789             :                 isl_basic_set *bset;
    2790           0 :                 bset = isl_basic_set_list_get_basic_set(list, i);
    2791           0 :                 if (!bset)
    2792           0 :                         return isl_mat_free(mat);
    2793           0 :                 for (j = 0; j < bset->n_eq; ++j) {
    2794           0 :                         ineq[n_ineq++] = mat->row[n_eq];
    2795           0 :                         ineq[n_ineq++] = bset->eq[j];
    2796           0 :                         isl_seq_neg(mat->row[n_eq++], bset->eq[j], mat->n_col);
    2797             :                 }
    2798           0 :                 for (j = 0; j < bset->n_ineq; ++j)
    2799           0 :                         ineq[n_ineq++] = bset->ineq[j];
    2800           0 :                 isl_basic_set_free(bset);
    2801             :         }
    2802             : 
    2803           0 :         return mat;
    2804             : }
    2805             : 
    2806             : /* Comparison routine for use as an isl_sort callback.
    2807             :  *
    2808             :  * Constraints with the same linear part are sorted together and
    2809             :  * among constraints with the same linear part, those with smaller
    2810             :  * constant term are sorted first.
    2811             :  */
    2812           0 : static int cmp_ineq(const void *a, const void *b, void *arg)
    2813             : {
    2814           0 :         unsigned dim = *(unsigned *) arg;
    2815           0 :         isl_int * const *ineq1 = a;
    2816           0 :         isl_int * const *ineq2 = b;
    2817             :         int cmp;
    2818             : 
    2819           0 :         cmp = isl_seq_cmp((*ineq1) + 1, (*ineq2) + 1, dim);
    2820           0 :         if (cmp != 0)
    2821           0 :                 return cmp;
    2822           0 :         return isl_int_cmp((*ineq1)[0], (*ineq2)[0]);
    2823             : }
    2824             : 
    2825             : /* Compute a superset of the convex hull of "set" that is described
    2826             :  * by only constraints in the elements of "list", where "set" has
    2827             :  * no parameters or integer divisions.
    2828             :  *
    2829             :  * We collect all the constraints in those elements and then
    2830             :  * sort the constraints such that constraints with the same linear part
    2831             :  * are sorted together and that those with smaller constant term are
    2832             :  * sorted first.
    2833             :  */
    2834           0 : static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_basic_set_list(
    2835             :         __isl_take isl_set *set, __isl_take isl_basic_set_list *list)
    2836             : {
    2837             :         int i, n, n_eq, n_ineq;
    2838             :         unsigned dim;
    2839             :         isl_ctx *ctx;
    2840           0 :         isl_mat *mat = NULL;
    2841           0 :         isl_int **ineq = NULL;
    2842             :         isl_basic_set *hull;
    2843             : 
    2844           0 :         if (!set)
    2845           0 :                 goto error;
    2846           0 :         ctx = isl_set_get_ctx(set);
    2847             : 
    2848           0 :         n_eq = 0;
    2849           0 :         n_ineq = 0;
    2850           0 :         n = isl_basic_set_list_n_basic_set(list);
    2851           0 :         for (i = 0; i < n; ++i) {
    2852             :                 isl_basic_set *bset;
    2853           0 :                 bset = isl_basic_set_list_get_basic_set(list, i);
    2854           0 :                 if (!bset)
    2855           0 :                         goto error;
    2856           0 :                 n_eq += bset->n_eq;
    2857           0 :                 n_ineq += 2 * bset->n_eq + bset->n_ineq;
    2858           0 :                 isl_basic_set_free(bset);
    2859             :         }
    2860             : 
    2861           0 :         ineq = isl_alloc_array(ctx, isl_int *, n_ineq);
    2862           0 :         if (n_ineq > 0 && !ineq)
    2863           0 :                 goto error;
    2864             : 
    2865           0 :         dim = isl_set_dim(set, isl_dim_set);
    2866           0 :         mat = isl_mat_alloc(ctx, n_eq, 1 + dim);
    2867           0 :         mat = collect_inequalities(mat, list, ineq);
    2868           0 :         if (!mat)
    2869           0 :                 goto error;
    2870             : 
    2871           0 :         if (isl_sort(ineq, n_ineq, sizeof(ineq[0]), &cmp_ineq, &dim) < 0)
    2872           0 :                 goto error;
    2873             : 
    2874           0 :         hull = uset_unshifted_simple_hull_from_constraints(set, n_ineq, ineq);
    2875             : 
    2876           0 :         isl_mat_free(mat);
    2877           0 :         free(ineq);
    2878           0 :         isl_basic_set_list_free(list);
    2879           0 :         return hull;
    2880             : error:
    2881           0 :         isl_mat_free(mat);
    2882           0 :         free(ineq);
    2883           0 :         isl_set_free(set);
    2884           0 :         isl_basic_set_list_free(list);
    2885           0 :         return NULL;
    2886             : }
    2887             : 
    2888             : /* Compute a superset of the convex hull of "map" that is described
    2889             :  * by only constraints in the elements of "list".
    2890             :  *
    2891             :  * If the list is empty, then we can only describe the universe set.
    2892             :  * If the input map is empty, then all constraints are valid, so
    2893             :  * we return the intersection of the elements in "list".
    2894             :  *
    2895             :  * Otherwise, we align all divs and temporarily treat them
    2896             :  * as regular variables, computing the unshifted simple hull in
    2897             :  * uset_unshifted_simple_hull_from_basic_set_list.
    2898             :  */
    2899           0 : static __isl_give isl_basic_map *map_unshifted_simple_hull_from_basic_map_list(
    2900             :         __isl_take isl_map *map, __isl_take isl_basic_map_list *list)
    2901             : {
    2902             :         isl_basic_map *model;
    2903             :         isl_basic_map *hull;
    2904             :         isl_set *set;
    2905             :         isl_basic_set_list *bset_list;
    2906             : 
    2907           0 :         if (!map || !list)
    2908             :                 goto error;
    2909             : 
    2910           0 :         if (isl_basic_map_list_n_basic_map(list) == 0) {
    2911             :                 isl_space *space;
    2912             : 
    2913           0 :                 space = isl_map_get_space(map);
    2914           0 :                 isl_map_free(map);
    2915           0 :                 isl_basic_map_list_free(list);
    2916           0 :                 return isl_basic_map_universe(space);
    2917             :         }
    2918           0 :         if (isl_map_plain_is_empty(map)) {
    2919           0 :                 isl_map_free(map);
    2920           0 :                 return isl_basic_map_list_intersect(list);
    2921             :         }
    2922             : 
    2923           0 :         map = isl_map_align_divs_to_basic_map_list(map, list);
    2924           0 :         if (!map)
    2925           0 :                 goto error;
    2926           0 :         list = isl_basic_map_list_align_divs_to_basic_map(list, map->p[0]);
    2927             : 
    2928           0 :         model = isl_basic_map_list_get_basic_map(list, 0);
    2929             : 
    2930           0 :         set = isl_map_underlying_set(map);
    2931           0 :         bset_list = isl_basic_map_list_underlying_set(list);
    2932             : 
    2933           0 :         hull = uset_unshifted_simple_hull_from_basic_set_list(set, bset_list);
    2934           0 :         hull = isl_basic_map_overlying_set(hull, model);
    2935             : 
    2936           0 :         return hull;
    2937             : error:
    2938           0 :         isl_map_free(map);
    2939           0 :         isl_basic_map_list_free(list);
    2940           0 :         return NULL;
    2941             : }
    2942             : 
    2943             : /* Return a sequence of the basic maps that make up the maps in "list".
    2944             :  */
    2945           0 : static __isl_give isl_basic_map_list *collect_basic_maps(
    2946             :         __isl_take isl_map_list *list)
    2947             : {
    2948             :         int i, n;
    2949             :         isl_ctx *ctx;
    2950             :         isl_basic_map_list *bmap_list;
    2951             : 
    2952           0 :         if (!list)
    2953           0 :                 return NULL;
    2954           0 :         n = isl_map_list_n_map(list);
    2955           0 :         ctx = isl_map_list_get_ctx(list);
    2956           0 :         bmap_list = isl_basic_map_list_alloc(ctx, 0);
    2957             : 
    2958           0 :         for (i = 0; i < n; ++i) {
    2959             :                 isl_map *map;
    2960             :                 isl_basic_map_list *list_i;
    2961             : 
    2962           0 :                 map = isl_map_list_get_map(list, i);
    2963           0 :                 map = isl_map_compute_divs(map);
    2964           0 :                 list_i = isl_map_get_basic_map_list(map);
    2965           0 :                 isl_map_free(map);
    2966           0 :                 bmap_list = isl_basic_map_list_concat(bmap_list, list_i);
    2967             :         }
    2968             : 
    2969           0 :         isl_map_list_free(list);
    2970           0 :         return bmap_list;
    2971             : }
    2972             : 
    2973             : /* Compute a superset of the convex hull of "map" that is described
    2974             :  * by only constraints in the elements of "list".
    2975             :  *
    2976             :  * If "map" is the universe, then the convex hull (and therefore
    2977             :  * any superset of the convexhull) is the universe as well.
    2978             :  *
    2979             :  * Otherwise, we collect all the basic maps in the map list and
    2980             :  * continue with map_unshifted_simple_hull_from_basic_map_list.
    2981             :  */
    2982           0 : __isl_give isl_basic_map *isl_map_unshifted_simple_hull_from_map_list(
    2983             :         __isl_take isl_map *map, __isl_take isl_map_list *list)
    2984             : {
    2985             :         isl_basic_map_list *bmap_list;
    2986             :         int is_universe;
    2987             : 
    2988           0 :         is_universe = isl_map_plain_is_universe(map);
    2989           0 :         if (is_universe < 0)
    2990           0 :                 map = isl_map_free(map);
    2991           0 :         if (is_universe < 0 || is_universe) {
    2992           0 :                 isl_map_list_free(list);
    2993           0 :                 return isl_map_unshifted_simple_hull(map);
    2994             :         }
    2995             : 
    2996           0 :         bmap_list = collect_basic_maps(list);
    2997           0 :         return map_unshifted_simple_hull_from_basic_map_list(map, bmap_list);
    2998             : }
    2999             : 
    3000             : /* Compute a superset of the convex hull of "set" that is described
    3001             :  * by only constraints in the elements of "list".
    3002             :  */
    3003           0 : __isl_give isl_basic_set *isl_set_unshifted_simple_hull_from_set_list(
    3004             :         __isl_take isl_set *set, __isl_take isl_set_list *list)
    3005             : {
    3006           0 :         return isl_map_unshifted_simple_hull_from_map_list(set, list);
    3007             : }
    3008             : 
    3009             : /* Given a set "set", return parametric bounds on the dimension "dim".
    3010             :  */
    3011           0 : static struct isl_basic_set *set_bounds(struct isl_set *set, int dim)
    3012             : {
    3013           0 :         unsigned set_dim = isl_set_dim(set, isl_dim_set);
    3014           0 :         set = isl_set_copy(set);
    3015           0 :         set = isl_set_eliminate_dims(set, dim + 1, set_dim - (dim + 1));
    3016           0 :         set = isl_set_eliminate_dims(set, 0, dim);
    3017           0 :         return isl_set_convex_hull(set);
    3018             : }
    3019             : 
    3020             : /* Computes a "simple hull" and then check if each dimension in the
    3021             :  * resulting hull is bounded by a symbolic constant.  If not, the
    3022             :  * hull is intersected with the corresponding bounds on the whole set.
    3023             :  */
    3024           0 : __isl_give isl_basic_set *isl_set_bounded_simple_hull(__isl_take isl_set *set)
    3025             : {
    3026             :         int i, j;
    3027             :         struct isl_basic_set *hull;
    3028             :         unsigned nparam, left;
    3029           0 :         int removed_divs = 0;
    3030             : 
    3031           0 :         hull = isl_set_simple_hull(isl_set_copy(set));
    3032           0 :         if (!hull)
    3033           0 :                 goto error;
    3034             : 
    3035           0 :         nparam = isl_basic_set_dim(hull, isl_dim_param);
    3036           0 :         for (i = 0; i < isl_basic_set_dim(hull, isl_dim_set); ++i) {
    3037           0 :                 int lower = 0, upper = 0;
    3038             :                 struct isl_basic_set *bounds;
    3039             : 
    3040           0 :                 left = isl_basic_set_total_dim(hull) - nparam - i - 1;
    3041           0 :                 for (j = 0; j < hull->n_eq; ++j) {
    3042           0 :                         if (isl_int_is_zero(hull->eq[j][1 + nparam + i]))
    3043           0 :                                 continue;
    3044           0 :                         if (isl_seq_first_non_zero(hull->eq[j]+1+nparam+i+1,
    3045             :                                                     left) == -1)
    3046           0 :                                 break;
    3047             :                 }
    3048           0 :                 if (j < hull->n_eq)
    3049           0 :                         continue;
    3050             : 
    3051           0 :                 for (j = 0; j < hull->n_ineq; ++j) {
    3052           0 :                         if (isl_int_is_zero(hull->ineq[j][1 + nparam + i]))
    3053           0 :                                 continue;
    3054           0 :                         if (isl_seq_first_non_zero(hull->ineq[j]+1+nparam+i+1,
    3055           0 :                                                     left) != -1 ||
    3056           0 :                             isl_seq_first_non_zero(hull->ineq[j]+1+nparam,
    3057             :                                                     i) != -1)
    3058           0 :                                 continue;
    3059           0 :                         if (isl_int_is_pos(hull->ineq[j][1 + nparam + i]))
    3060           0 :                                 lower = 1;
    3061             :                         else
    3062           0 :                                 upper = 1;
    3063           0 :                         if (lower && upper)
    3064           0 :                                 break;
    3065             :                 }
    3066             : 
    3067           0 :                 if (lower && upper)
    3068           0 :                         continue;
    3069             : 
    3070           0 :                 if (!removed_divs) {
    3071           0 :                         set = isl_set_remove_divs(set);
    3072           0 :                         if (!set)
    3073           0 :                                 goto error;
    3074           0 :                         removed_divs = 1;
    3075             :                 }
    3076           0 :                 bounds = set_bounds(set, i);
    3077           0 :                 hull = isl_basic_set_intersect(hull, bounds);
    3078           0 :                 if (!hull)
    3079           0 :                         goto error;
    3080             :         }
    3081             : 
    3082           0 :         isl_set_free(set);
    3083           0 :         return hull;
    3084             : error:
    3085           0 :         isl_set_free(set);
    3086           0 :         isl_basic_set_free(hull);
    3087           0 :         return NULL;
    3088             : }

Generated by: LCOV version 1.12