LCOV - code coverage report
Current view: top level - metalib_isl - isl_map_simplify.c (source / functions) Hit Total Coverage
Test: 2018-10-31_point_maint_greina16.lcov Lines: 508 2424 21.0 %
Date: 2018-11-01 11:27:00 Functions: 42 147 28.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008-2009 Katholieke Universiteit Leuven
       3             :  * Copyright 2012-2013 Ecole Normale Superieure
       4             :  * Copyright 2014-2015 INRIA Rocquencourt
       5             :  * Copyright 2016      Sven Verdoolaege
       6             :  *
       7             :  * Use of this software is governed by the MIT license
       8             :  *
       9             :  * Written by Sven Verdoolaege, K.U.Leuven, Departement
      10             :  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
      11             :  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
      12             :  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
      13             :  * B.P. 105 - 78153 Le Chesnay, France
      14             :  */
      15             : 
      16             : #include <isl_ctx_private.h>
      17             : #include <isl_map_private.h>
      18             : #include "isl_equalities.h"
      19             : #include <isl/map.h>
      20             : #include <isl_seq.h>
      21             : #include "isl_tab.h"
      22             : #include <isl_space_private.h>
      23             : #include <isl_mat_private.h>
      24             : #include <isl_vec_private.h>
      25             : 
      26             : #include <bset_to_bmap.c>
      27             : #include <bset_from_bmap.c>
      28             : #include <set_to_map.c>
      29             : #include <set_from_map.c>
      30             : 
      31 10848825273 : static void swap_equality(struct isl_basic_map *bmap, int a, int b)
      32             : {
      33 10848825273 :         isl_int *t = bmap->eq[a];
      34 10848825273 :         bmap->eq[a] = bmap->eq[b];
      35 10848825273 :         bmap->eq[b] = t;
      36 10848825273 : }
      37             : 
      38    30940916 : static void swap_inequality(struct isl_basic_map *bmap, int a, int b)
      39             : {
      40    30940916 :         if (a != b) {
      41    30940916 :                 isl_int *t = bmap->ineq[a];
      42    30940916 :                 bmap->ineq[a] = bmap->ineq[b];
      43    30940916 :                 bmap->ineq[b] = t;
      44             :         }
      45    30940916 : }
      46             : 
      47 19194043916 : __isl_give isl_basic_map *isl_basic_map_normalize_constraints(
      48             :         __isl_take isl_basic_map *bmap)
      49             : {
      50             :         int i;
      51             :         isl_int gcd;
      52 19194043916 :         unsigned total = isl_basic_map_total_dim(bmap);
      53             : 
      54 19194043916 :         if (!bmap)
      55           0 :                 return NULL;
      56             : 
      57 19194043916 :         isl_int_init(gcd);
      58 54241642462 :         for (i = bmap->n_eq - 1; i >= 0; --i) {
      59 35523001973 :                 isl_seq_gcd(bmap->eq[i]+1, total, &gcd);
      60 35523001973 :                 if (isl_int_is_zero(gcd)) {
      61  1576581836 :                         if (!isl_int_is_zero(bmap->eq[i][0])) {
      62   474390804 :                                 bmap = isl_basic_map_set_to_empty(bmap);
      63   474390804 :                                 break;
      64             :                         }
      65  1102191032 :                         isl_basic_map_drop_equality(bmap, i);
      66  1102191032 :                         continue;
      67             :                 }
      68 33946420137 :                 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
      69 33543505272 :                         isl_int_gcd(gcd, gcd, bmap->eq[i][0]);
      70 33946420137 :                 if (isl_int_is_one(gcd))
      71 30540955301 :                         continue;
      72  3405464836 :                 if (!isl_int_is_divisible_by(bmap->eq[i][0], gcd)) {
      73     1012623 :                         bmap = isl_basic_map_set_to_empty(bmap);
      74     1012623 :                         break;
      75             :                 }
      76  3404452213 :                 isl_seq_scale_down(bmap->eq[i], bmap->eq[i], gcd, 1+total);
      77             :         }
      78             : 
      79 33137036911 :         for (i = bmap->n_ineq - 1; i >= 0; --i) {
      80 13962593570 :                 isl_seq_gcd(bmap->ineq[i]+1, total, &gcd);
      81 13962593570 :                 if (isl_int_is_zero(gcd)) {
      82  1309153033 :                         if (isl_int_is_neg(bmap->ineq[i][0])) {
      83    19600575 :                                 bmap = isl_basic_map_set_to_empty(bmap);
      84    19600575 :                                 break;
      85             :                         }
      86  1289552458 :                         isl_basic_map_drop_inequality(bmap, i);
      87  1289552458 :                         continue;
      88             :                 }
      89 12653440537 :                 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
      90  9497125210 :                         isl_int_gcd(gcd, gcd, bmap->ineq[i][0]);
      91 12653440537 :                 if (isl_int_is_one(gcd))
      92 12582698644 :                         continue;
      93    70741893 :                 isl_int_fdiv_q(bmap->ineq[i][0], bmap->ineq[i][0], gcd);
      94    70741893 :                 isl_seq_scale_down(bmap->ineq[i]+1, bmap->ineq[i]+1, gcd, total);
      95             :         }
      96 19194043916 :         isl_int_clear(gcd);
      97             : 
      98 19194043916 :         return bmap;
      99             : }
     100             : 
     101  2979789573 : __isl_give isl_basic_set *isl_basic_set_normalize_constraints(
     102             :         __isl_take isl_basic_set *bset)
     103             : {
     104  2979789573 :         isl_basic_map *bmap = bset_to_bmap(bset);
     105  2979789573 :         return bset_from_bmap(isl_basic_map_normalize_constraints(bmap));
     106             : }
     107             : 
     108             : /* Reduce the coefficient of the variable at position "pos"
     109             :  * in integer division "div", such that it lies in the half-open
     110             :  * interval (1/2,1/2], extracting any excess value from this integer division.
     111             :  * "pos" is as determined by isl_basic_map_offset, i.e., pos == 0
     112             :  * corresponds to the constant term.
     113             :  *
     114             :  * That is, the integer division is of the form
     115             :  *
     116             :  *      floor((... + (c * d + r) * x_pos + ...)/d)
     117             :  *
     118             :  * with -d < 2 * r <= d.
     119             :  * Replace it by
     120             :  *
     121             :  *      floor((... + r * x_pos + ...)/d) + c * x_pos
     122             :  *
     123             :  * If 2 * ((c * d + r) % d) <= d, then c = floor((c * d + r)/d).
     124             :  * Otherwise, c = floor((c * d + r)/d) + 1.
     125             :  *
     126             :  * This is the same normalization that is performed by isl_aff_floor.
     127             :  */
     128           0 : static __isl_give isl_basic_map *reduce_coefficient_in_div(
     129             :         __isl_take isl_basic_map *bmap, int div, int pos)
     130             : {
     131             :         isl_int shift;
     132             :         int add_one;
     133             : 
     134           0 :         isl_int_init(shift);
     135           0 :         isl_int_fdiv_r(shift, bmap->div[div][1 + pos], bmap->div[div][0]);
     136           0 :         isl_int_mul_ui(shift, shift, 2);
     137           0 :         add_one = isl_int_gt(shift, bmap->div[div][0]);
     138           0 :         isl_int_fdiv_q(shift, bmap->div[div][1 + pos], bmap->div[div][0]);
     139           0 :         if (add_one)
     140           0 :                 isl_int_add_ui(shift, shift, 1);
     141           0 :         isl_int_neg(shift, shift);
     142           0 :         bmap = isl_basic_map_shift_div(bmap, div, pos, shift);
     143           0 :         isl_int_clear(shift);
     144             : 
     145           0 :         return bmap;
     146             : }
     147             : 
     148             : /* Does the coefficient of the variable at position "pos"
     149             :  * in integer division "div" need to be reduced?
     150             :  * That is, does it lie outside the half-open interval (1/2,1/2]?
     151             :  * The coefficient c/d lies outside this interval if abs(2 * c) >= d and
     152             :  * 2 * c != d.
     153             :  */
     154           0 : static isl_bool needs_reduction(__isl_keep isl_basic_map *bmap, int div,
     155             :         int pos)
     156             : {
     157             :         isl_bool r;
     158             : 
     159           0 :         if (isl_int_is_zero(bmap->div[div][1 + pos]))
     160           0 :                 return isl_bool_false;
     161             : 
     162           0 :         isl_int_mul_ui(bmap->div[div][1 + pos], bmap->div[div][1 + pos], 2);
     163           0 :         r = isl_int_abs_ge(bmap->div[div][1 + pos], bmap->div[div][0]) &&
     164           0 :             !isl_int_eq(bmap->div[div][1 + pos], bmap->div[div][0]);
     165           0 :         isl_int_divexact_ui(bmap->div[div][1 + pos],
     166             :                             bmap->div[div][1 + pos], 2);
     167             : 
     168           0 :         return r;
     169             : }
     170             : 
     171             : /* Reduce the coefficients (including the constant term) of
     172             :  * integer division "div", if needed.
     173             :  * In particular, make sure all coefficients lie in
     174             :  * the half-open interval (1/2,1/2].
     175             :  */
     176           0 : static __isl_give isl_basic_map *reduce_div_coefficients_of_div(
     177             :         __isl_take isl_basic_map *bmap, int div)
     178             : {
     179             :         int i;
     180           0 :         unsigned total = 1 + isl_basic_map_total_dim(bmap);
     181             : 
     182           0 :         for (i = 0; i < total; ++i) {
     183             :                 isl_bool reduce;
     184             : 
     185           0 :                 reduce = needs_reduction(bmap, div, i);
     186           0 :                 if (reduce < 0)
     187           0 :                         return isl_basic_map_free(bmap);
     188           0 :                 if (!reduce)
     189           0 :                         continue;
     190           0 :                 bmap = reduce_coefficient_in_div(bmap, div, i);
     191           0 :                 if (!bmap)
     192           0 :                         break;
     193             :         }
     194             : 
     195           0 :         return bmap;
     196             : }
     197             : 
     198             : /* Reduce the coefficients (including the constant term) of
     199             :  * the known integer divisions, if needed
     200             :  * In particular, make sure all coefficients lie in
     201             :  * the half-open interval (1/2,1/2].
     202             :  */
     203 16214254343 : static __isl_give isl_basic_map *reduce_div_coefficients(
     204             :         __isl_take isl_basic_map *bmap)
     205             : {
     206             :         int i;
     207             : 
     208 16214254343 :         if (!bmap)
     209           0 :                 return NULL;
     210 16214254343 :         if (bmap->n_div == 0)
     211 16214254343 :                 return bmap;
     212             : 
     213           0 :         for (i = 0; i < bmap->n_div; ++i) {
     214           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
     215           0 :                         continue;
     216           0 :                 bmap = reduce_div_coefficients_of_div(bmap, i);
     217           0 :                 if (!bmap)
     218           0 :                         break;
     219             :         }
     220             : 
     221           0 :         return bmap;
     222             : }
     223             : 
     224             : /* Remove any common factor in numerator and denominator of the div expression,
     225             :  * not taking into account the constant term.
     226             :  * That is, if the div is of the form
     227             :  *
     228             :  *      floor((a + m f(x))/(m d))
     229             :  *
     230             :  * then replace it by
     231             :  *
     232             :  *      floor((floor(a/m) + f(x))/d)
     233             :  *
     234             :  * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
     235             :  * and can therefore not influence the result of the floor.
     236             :  */
     237           0 : static void normalize_div_expression(__isl_keep isl_basic_map *bmap, int div)
     238             : {
     239           0 :         unsigned total = isl_basic_map_total_dim(bmap);
     240           0 :         isl_ctx *ctx = bmap->ctx;
     241             : 
     242           0 :         if (isl_int_is_zero(bmap->div[div][0]))
     243           0 :                 return;
     244           0 :         isl_seq_gcd(bmap->div[div] + 2, total, &ctx->normalize_gcd);
     245           0 :         isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, bmap->div[div][0]);
     246           0 :         if (isl_int_is_one(ctx->normalize_gcd))
     247           0 :                 return;
     248           0 :         isl_int_fdiv_q(bmap->div[div][1], bmap->div[div][1],
     249             :                         ctx->normalize_gcd);
     250           0 :         isl_int_divexact(bmap->div[div][0], bmap->div[div][0],
     251             :                         ctx->normalize_gcd);
     252           0 :         isl_seq_scale_down(bmap->div[div] + 2, bmap->div[div] + 2,
     253           0 :                         ctx->normalize_gcd, total);
     254             : }
     255             : 
     256             : /* Remove any common factor in numerator and denominator of a div expression,
     257             :  * not taking into account the constant term.
     258             :  * That is, look for any div of the form
     259             :  *
     260             :  *      floor((a + m f(x))/(m d))
     261             :  *
     262             :  * and replace it by
     263             :  *
     264             :  *      floor((floor(a/m) + f(x))/d)
     265             :  *
     266             :  * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
     267             :  * and can therefore not influence the result of the floor.
     268             :  */
     269 16214254343 : static __isl_give isl_basic_map *normalize_div_expressions(
     270             :         __isl_take isl_basic_map *bmap)
     271             : {
     272             :         int i;
     273             : 
     274 16214254343 :         if (!bmap)
     275           0 :                 return NULL;
     276 16214254343 :         if (bmap->n_div == 0)
     277 16214254343 :                 return bmap;
     278             : 
     279           0 :         for (i = 0; i < bmap->n_div; ++i)
     280           0 :                 normalize_div_expression(bmap, i);
     281             : 
     282           0 :         return bmap;
     283             : }
     284             : 
     285             : /* Assumes divs have been ordered if keep_divs is set.
     286             :  */
     287 62338595215 : static void eliminate_var_using_equality(struct isl_basic_map *bmap,
     288             :         unsigned pos, isl_int *eq, int keep_divs, int *progress)
     289             : {
     290             :         unsigned total;
     291             :         unsigned space_total;
     292             :         int k;
     293             :         int last_div;
     294             : 
     295 62338595215 :         total = isl_basic_map_total_dim(bmap);
     296 62338595215 :         space_total = isl_space_dim(bmap->dim, isl_dim_all);
     297 62338595215 :         last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
     298 >34603*10^7 :         for (k = 0; k < bmap->n_eq; ++k) {
     299 >28369*10^7 :                 if (bmap->eq[k] == eq)
     300 62338595215 :                         continue;
     301 >22135*10^7 :                 if (isl_int_is_zero(bmap->eq[k][1+pos]))
     302 >19484*10^7 :                         continue;
     303 26511451875 :                 if (progress)
     304 10108038752 :                         *progress = 1;
     305 26511451875 :                 isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL);
     306 26511451875 :                 isl_seq_normalize(bmap->ctx, bmap->eq[k], 1 + total);
     307             :         }
     308             : 
     309 >11834*10^7 :         for (k = 0; k < bmap->n_ineq; ++k) {
     310 56006708240 :                 if (isl_int_is_zero(bmap->ineq[k][1+pos]))
     311 48459366240 :                         continue;
     312  7547342000 :                 if (progress)
     313   489853963 :                         *progress = 1;
     314  7547342000 :                 isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL);
     315  7547342000 :                 isl_seq_normalize(bmap->ctx, bmap->ineq[k], 1 + total);
     316  7547342000 :                 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
     317             :         }
     318             : 
     319 62338595215 :         for (k = 0; k < bmap->n_div; ++k) {
     320           0 :                 if (isl_int_is_zero(bmap->div[k][0]))
     321           0 :                         continue;
     322           0 :                 if (isl_int_is_zero(bmap->div[k][1+1+pos]))
     323           0 :                         continue;
     324           0 :                 if (progress)
     325           0 :                         *progress = 1;
     326             :                 /* We need to be careful about circular definitions,
     327             :                  * so for now we just remove the definition of div k
     328             :                  * if the equality contains any divs.
     329             :                  * If keep_divs is set, then the divs have been ordered
     330             :                  * and we can keep the definition as long as the result
     331             :                  * is still ordered.
     332             :                  */
     333           0 :                 if (last_div == -1 || (keep_divs && last_div < k)) {
     334           0 :                         isl_seq_elim(bmap->div[k]+1, eq,
     335           0 :                                         1+pos, 1+total, &bmap->div[k][0]);
     336           0 :                         normalize_div_expression(bmap, k);
     337             :                 } else
     338           0 :                         isl_seq_clr(bmap->div[k], 1 + total);
     339           0 :                 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
     340             :         }
     341 62338595215 : }
     342             : 
     343             : /* Assumes divs have been ordered if keep_divs is set.
     344             :  */
     345           0 : static __isl_give isl_basic_map *eliminate_div(__isl_take isl_basic_map *bmap,
     346             :         isl_int *eq, unsigned div, int keep_divs)
     347             : {
     348           0 :         unsigned pos = isl_space_dim(bmap->dim, isl_dim_all) + div;
     349             : 
     350           0 :         eliminate_var_using_equality(bmap, pos, eq, keep_divs, NULL);
     351             : 
     352           0 :         bmap = isl_basic_map_drop_div(bmap, div);
     353             : 
     354           0 :         return bmap;
     355             : }
     356             : 
     357             : /* Check if elimination of div "div" using equality "eq" would not
     358             :  * result in a div depending on a later div.
     359             :  */
     360           0 : static isl_bool ok_to_eliminate_div(__isl_keep isl_basic_map *bmap, isl_int *eq,
     361             :         unsigned div)
     362             : {
     363             :         int k;
     364             :         int last_div;
     365           0 :         unsigned space_total = isl_space_dim(bmap->dim, isl_dim_all);
     366           0 :         unsigned pos = space_total + div;
     367             : 
     368           0 :         last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
     369           0 :         if (last_div < 0 || last_div <= div)
     370           0 :                 return isl_bool_true;
     371             : 
     372           0 :         for (k = 0; k <= last_div; ++k) {
     373           0 :                 if (isl_int_is_zero(bmap->div[k][0]))
     374           0 :                         continue;
     375           0 :                 if (!isl_int_is_zero(bmap->div[k][1 + 1 + pos]))
     376           0 :                         return isl_bool_false;
     377             :         }
     378             : 
     379           0 :         return isl_bool_true;
     380             : }
     381             : 
     382             : /* Eliminate divs based on equalities
     383             :  */
     384 16214254561 : static __isl_give isl_basic_map *eliminate_divs_eq(
     385             :         __isl_take isl_basic_map *bmap, int *progress)
     386             : {
     387             :         int d;
     388             :         int i;
     389 16214254561 :         int modified = 0;
     390             :         unsigned off;
     391             : 
     392 16214254561 :         bmap = isl_basic_map_order_divs(bmap);
     393             : 
     394 16214254561 :         if (!bmap)
     395           0 :                 return NULL;
     396             : 
     397 16214254561 :         off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
     398             : 
     399 16214254561 :         for (d = bmap->n_div - 1; d >= 0 ; --d) {
     400           0 :                 for (i = 0; i < bmap->n_eq; ++i) {
     401             :                         isl_bool ok;
     402             : 
     403           0 :                         if (!isl_int_is_one(bmap->eq[i][off + d]) &&
     404           0 :                             !isl_int_is_negone(bmap->eq[i][off + d]))
     405           0 :                                 continue;
     406           0 :                         ok = ok_to_eliminate_div(bmap, bmap->eq[i], d);
     407           0 :                         if (ok < 0)
     408           0 :                                 return isl_basic_map_free(bmap);
     409           0 :                         if (!ok)
     410           0 :                                 continue;
     411           0 :                         modified = 1;
     412           0 :                         *progress = 1;
     413           0 :                         bmap = eliminate_div(bmap, bmap->eq[i], d, 1);
     414           0 :                         if (isl_basic_map_drop_equality(bmap, i) < 0)
     415           0 :                                 return isl_basic_map_free(bmap);
     416           0 :                         break;
     417             :                 }
     418             :         }
     419 16214254561 :         if (modified)
     420           0 :                 return eliminate_divs_eq(bmap, progress);
     421 16214254561 :         return bmap;
     422             : }
     423             : 
     424             : /* Eliminate divs based on inequalities
     425             :  */
     426 16214254343 : static __isl_give isl_basic_map *eliminate_divs_ineq(
     427             :         __isl_take isl_basic_map *bmap, int *progress)
     428             : {
     429             :         int d;
     430             :         int i;
     431             :         unsigned off;
     432             :         struct isl_ctx *ctx;
     433             : 
     434 16214254343 :         if (!bmap)
     435           0 :                 return NULL;
     436             : 
     437 16214254343 :         ctx = bmap->ctx;
     438 16214254343 :         off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
     439             : 
     440 16214254343 :         for (d = bmap->n_div - 1; d >= 0 ; --d) {
     441           0 :                 for (i = 0; i < bmap->n_eq; ++i)
     442           0 :                         if (!isl_int_is_zero(bmap->eq[i][off + d]))
     443             :                                 break;
     444           0 :                 if (i < bmap->n_eq)
     445           0 :                         continue;
     446           0 :                 for (i = 0; i < bmap->n_ineq; ++i)
     447           0 :                         if (isl_int_abs_gt(bmap->ineq[i][off + d], ctx->one))
     448           0 :                                 break;
     449           0 :                 if (i < bmap->n_ineq)
     450           0 :                         continue;
     451           0 :                 *progress = 1;
     452           0 :                 bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1);
     453           0 :                 if (!bmap || ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
     454             :                         break;
     455           0 :                 bmap = isl_basic_map_drop_div(bmap, d);
     456           0 :                 if (!bmap)
     457           0 :                         break;
     458             :         }
     459 16214254343 :         return bmap;
     460             : }
     461             : 
     462             : /* Does the equality constraint at position "eq" in "bmap" involve
     463             :  * any local variables in the range [first, first + n)
     464             :  * that are not marked as having an explicit representation?
     465             :  */
     466           0 : static isl_bool bmap_eq_involves_unknown_divs(__isl_keep isl_basic_map *bmap,
     467             :         int eq, unsigned first, unsigned n)
     468             : {
     469             :         unsigned o_div;
     470             :         int i;
     471             : 
     472           0 :         if (!bmap)
     473           0 :                 return isl_bool_error;
     474             : 
     475           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
     476           0 :         for (i = 0; i < n; ++i) {
     477             :                 isl_bool unknown;
     478             : 
     479           0 :                 if (isl_int_is_zero(bmap->eq[eq][o_div + first + i]))
     480           0 :                         continue;
     481           0 :                 unknown = isl_basic_map_div_is_marked_unknown(bmap, first + i);
     482           0 :                 if (unknown < 0)
     483           0 :                         return isl_bool_error;
     484           0 :                 if (unknown)
     485           0 :                         return isl_bool_true;
     486             :         }
     487             : 
     488           0 :         return isl_bool_false;
     489             : }
     490             : 
     491             : /* The last local variable involved in the equality constraint
     492             :  * at position "eq" in "bmap" is the local variable at position "div".
     493             :  * It can therefore be used to extract an explicit representation
     494             :  * for that variable.
     495             :  * Do so unless the local variable already has an explicit representation or
     496             :  * the explicit representation would involve any other local variables
     497             :  * that in turn do not have an explicit representation.
     498             :  * An equality constraint involving local variables without an explicit
     499             :  * representation can be used in isl_basic_map_drop_redundant_divs
     500             :  * to separate out an independent local variable.  Introducing
     501             :  * an explicit representation here would block this transformation,
     502             :  * while the partial explicit representation in itself is not very useful.
     503             :  * Set *progress if anything is changed.
     504             :  *
     505             :  * The equality constraint is of the form
     506             :  *
     507             :  *      f(x) + n e >= 0
     508             :  *
     509             :  * with n a positive number.  The explicit representation derived from
     510             :  * this constraint is
     511             :  *
     512             :  *      floor((-f(x))/n)
     513             :  */
     514           0 : static __isl_give isl_basic_map *set_div_from_eq(__isl_take isl_basic_map *bmap,
     515             :         int div, int eq, int *progress)
     516             : {
     517             :         unsigned total, o_div;
     518             :         isl_bool involves;
     519             : 
     520           0 :         if (!bmap)
     521           0 :                 return NULL;
     522             : 
     523           0 :         if (!isl_int_is_zero(bmap->div[div][0]))
     524           0 :                 return bmap;
     525             : 
     526           0 :         involves = bmap_eq_involves_unknown_divs(bmap, eq, 0, div);
     527           0 :         if (involves < 0)
     528           0 :                 return isl_basic_map_free(bmap);
     529           0 :         if (involves)
     530           0 :                 return bmap;
     531             : 
     532           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
     533           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
     534           0 :         isl_seq_neg(bmap->div[div] + 1, bmap->eq[eq], 1 + total);
     535           0 :         isl_int_set_si(bmap->div[div][1 + o_div + div], 0);
     536           0 :         isl_int_set(bmap->div[div][0], bmap->eq[eq][o_div + div]);
     537           0 :         if (progress)
     538           0 :                 *progress = 1;
     539           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
     540             : 
     541           0 :         return bmap;
     542             : }
     543             : 
     544             : /* Perform fangcheng (Gaussian elimination) on the equality
     545             :  * constraints of "bmap".
     546             :  * That is, put them into row-echelon form, starting from the last column
     547             :  * backward and use them to eliminate the corresponding coefficients
     548             :  * from all constraints.
     549             :  *
     550             :  * If "progress" is not NULL, then it gets set if the elimination
     551             :  * result in any changes.
     552             :  * The elimination process may result in some equality constraints
     553             :  * getting interchanged or removed.
     554             :  * If "swap" or "drop" are not NULL, then they get called when
     555             :  * two equality constraints get interchanged or
     556             :  * when a number of final equality constraints get removed.
     557             :  * As a special case, if the input turns out to be empty,
     558             :  * then drop gets called with the number of removed equality
     559             :  * constraints set to the total number of equality constraints.
     560             :  * If "swap" or "drop" are not NULL, then the local variables (if any)
     561             :  * are assumed to be in a valid order.
     562             :  */
     563 30448952040 : __isl_give isl_basic_map *isl_basic_map_gauss5(__isl_take isl_basic_map *bmap,
     564             :         int *progress,
     565             :         isl_stat (*swap)(unsigned a, unsigned b, void *user),
     566             :         isl_stat (*drop)(unsigned n, void *user), void *user)
     567             : {
     568             :         int k;
     569             :         int done;
     570             :         int last_var;
     571             :         unsigned total_var;
     572             :         unsigned total;
     573             :         unsigned n_drop;
     574             : 
     575 30448952040 :         if (!swap && !drop)
     576 30448899974 :                 bmap = isl_basic_map_order_divs(bmap);
     577             : 
     578 30448952040 :         if (!bmap)
     579           0 :                 return NULL;
     580             : 
     581 30448952040 :         total = isl_basic_map_total_dim(bmap);
     582 30448952040 :         total_var = total - bmap->n_div;
     583             : 
     584 30448952040 :         last_var = total - 1;
     585 92786271998 :         for (done = 0; done < bmap->n_eq; ++done) {
     586 >11071*10^7 :                 for (; last_var >= 0; --last_var) {
     587 >28195*10^7 :                         for (k = done; k < bmap->n_eq; ++k)
     588 >23890*10^7 :                                 if (!isl_int_is_zero(bmap->eq[k][1+last_var]))
     589             :                                         break;
     590 >10538*10^7 :                         if (k < bmap->n_eq)
     591 62337319958 :                                 break;
     592             :                 }
     593 67668298380 :                 if (last_var < 0)
     594  5330978422 :                         break;
     595 62337319958 :                 if (k != done) {
     596 10848825273 :                         swap_equality(bmap, k, done);
     597 10848825273 :                         if (swap && swap(k, done, user) < 0)
     598           0 :                                 return isl_basic_map_free(bmap);
     599             :                 }
     600 62337319958 :                 if (isl_int_is_neg(bmap->eq[done][1+last_var]))
     601  5745305914 :                         isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total);
     602             : 
     603 62337319958 :                 eliminate_var_using_equality(bmap, last_var, bmap->eq[done], 1,
     604             :                                                 progress);
     605             : 
     606 62337319958 :                 if (last_var >= total_var)
     607           0 :                         bmap = set_div_from_eq(bmap, last_var - total_var,
     608             :                                                 done, progress);
     609 62337319958 :                 if (!bmap)
     610           0 :                         return NULL;
     611             :         }
     612 30448952040 :         if (done == bmap->n_eq)
     613 25117973618 :                 return bmap;
     614 17476516574 :         for (k = done; k < bmap->n_eq; ++k) {
     615  5683201980 :                 if (isl_int_is_zero(bmap->eq[k][0]))
     616  3407279865 :                         continue;
     617  2275922115 :                 if (drop && drop(bmap->n_eq, user) < 0)
     618           0 :                         return isl_basic_map_free(bmap);
     619  2275922115 :                 return isl_basic_map_set_to_empty(bmap);
     620             :         }
     621  3055056307 :         n_drop = bmap->n_eq - done;
     622  3055056307 :         isl_basic_map_free_equality(bmap, n_drop);
     623  3055056307 :         if (drop && drop(n_drop, user) < 0)
     624           0 :                 return isl_basic_map_free(bmap);
     625  3055056307 :         return bmap;
     626             : }
     627             : 
     628 30448899974 : __isl_give isl_basic_map *isl_basic_map_gauss(__isl_take isl_basic_map *bmap,
     629             :         int *progress)
     630             : {
     631 30448899974 :         return isl_basic_map_gauss5(bmap, progress, NULL, NULL, NULL);
     632             : }
     633             : 
     634  2458845818 : __isl_give isl_basic_set *isl_basic_set_gauss(
     635             :         __isl_take isl_basic_set *bset, int *progress)
     636             : {
     637  2458845818 :         return bset_from_bmap(isl_basic_map_gauss(bset_to_bmap(bset),
     638             :                                                         progress));
     639             : }
     640             : 
     641             : 
     642  1992419621 : static unsigned int round_up(unsigned int v)
     643             : {
     644  1992419621 :         int old_v = v;
     645             : 
     646  7532214623 :         while (v) {
     647  3547375381 :                 old_v = v;
     648  3547375381 :                 v ^= v & -v;
     649             :         }
     650  1992419621 :         return old_v << 1;
     651             : }
     652             : 
     653             : /* Hash table of inequalities in a basic map.
     654             :  * "index" is an array of addresses of inequalities in the basic map, some
     655             :  * of which are NULL.  The inequalities are hashed on the coefficients
     656             :  * except the constant term.
     657             :  * "size" is the number of elements in the array and is always a power of two
     658             :  * "bits" is the number of bits need to represent an index into the array.
     659             :  * "total" is the total dimension of the basic map.
     660             :  */
     661             : struct isl_constraint_index {
     662             :         unsigned int size;
     663             :         int bits;
     664             :         isl_int ***index;
     665             :         unsigned total;
     666             : };
     667             : 
     668             : /* Fill in the "ci" data structure for holding the inequalities of "bmap".
     669             :  */
     670  1992419621 : static isl_stat create_constraint_index(struct isl_constraint_index *ci,
     671             :         __isl_keep isl_basic_map *bmap)
     672             : {
     673             :         isl_ctx *ctx;
     674             : 
     675  1992419621 :         ci->index = NULL;
     676  1992419621 :         if (!bmap)
     677           0 :                 return isl_stat_error;
     678  1992419621 :         ci->total = isl_basic_set_total_dim(bmap);
     679  1992419621 :         if (bmap->n_ineq == 0)
     680           0 :                 return isl_stat_ok;
     681  1992419621 :         ci->size = round_up(4 * (bmap->n_ineq + 1) / 3 - 1);
     682  1992419621 :         ci->bits = ffs(ci->size) - 1;
     683  1992419621 :         ctx = isl_basic_map_get_ctx(bmap);
     684  1992419621 :         ci->index = isl_calloc_array(ctx, isl_int **, ci->size);
     685  1992419621 :         if (!ci->index)
     686           0 :                 return isl_stat_error;
     687             : 
     688  1992419621 :         return isl_stat_ok;
     689             : }
     690             : 
     691             : /* Free the memory allocated by create_constraint_index.
     692             :  */
     693  1992419621 : static void constraint_index_free(struct isl_constraint_index *ci)
     694             : {
     695  1992419621 :         free(ci->index);
     696  1992419621 : }
     697             : 
     698             : /* Return the position in ci->index that contains the address of
     699             :  * an inequality that is equal to *ineq up to the constant term,
     700             :  * provided this address is not identical to "ineq".
     701             :  * If there is no such inequality, then return the position where
     702             :  * such an inequality should be inserted.
     703             :  */
     704 10103746287 : static int hash_index_ineq(struct isl_constraint_index *ci, isl_int **ineq)
     705             : {
     706             :         int h;
     707 10103746287 :         uint32_t hash = isl_seq_get_hash_bits((*ineq) + 1, ci->total, ci->bits);
     708 15149639054 :         for (h = hash; ci->index[h]; h = (h+1) % ci->size)
     709 12170524815 :                 if (ineq != ci->index[h] &&
     710  5825045912 :                     isl_seq_eq((*ineq) + 1, ci->index[h][0]+1, ci->total))
     711  1299586136 :                         break;
     712 10103746287 :         return h;
     713             : }
     714             : 
     715             : /* Return the position in ci->index that contains the address of
     716             :  * an inequality that is equal to the k'th inequality of "bmap"
     717             :  * up to the constant term, provided it does not point to the very
     718             :  * same inequality.
     719             :  * If there is no such inequality, then return the position where
     720             :  * such an inequality should be inserted.
     721             :  */
     722 10103746287 : static int hash_index(struct isl_constraint_index *ci,
     723             :         __isl_keep isl_basic_map *bmap, int k)
     724             : {
     725 10103746287 :         return hash_index_ineq(ci, &bmap->ineq[k]);
     726             : }
     727             : 
     728           0 : static int set_hash_index(struct isl_constraint_index *ci,
     729             :         __isl_keep isl_basic_set *bset, int k)
     730             : {
     731           0 :         return hash_index(ci, bset, k);
     732             : }
     733             : 
     734             : /* Fill in the "ci" data structure with the inequalities of "bset".
     735             :  */
     736           0 : static isl_stat setup_constraint_index(struct isl_constraint_index *ci,
     737             :         __isl_keep isl_basic_set *bset)
     738             : {
     739             :         int k, h;
     740             : 
     741           0 :         if (create_constraint_index(ci, bset) < 0)
     742           0 :                 return isl_stat_error;
     743             : 
     744           0 :         for (k = 0; k < bset->n_ineq; ++k) {
     745           0 :                 h = set_hash_index(ci, bset, k);
     746           0 :                 ci->index[h] = &bset->ineq[k];
     747             :         }
     748             : 
     749           0 :         return isl_stat_ok;
     750             : }
     751             : 
     752             : /* Is the inequality ineq (obviously) redundant with respect
     753             :  * to the constraints in "ci"?
     754             :  *
     755             :  * Look for an inequality in "ci" with the same coefficients and then
     756             :  * check if the contant term of "ineq" is greater than or equal
     757             :  * to the constant term of that inequality.  If so, "ineq" is clearly
     758             :  * redundant.
     759             :  *
     760             :  * Note that hash_index_ineq ignores a stored constraint if it has
     761             :  * the same address as the passed inequality.  It is ok to pass
     762             :  * the address of a local variable here since it will never be
     763             :  * the same as the address of a constraint in "ci".
     764             :  */
     765           0 : static isl_bool constraint_index_is_redundant(struct isl_constraint_index *ci,
     766             :         isl_int *ineq)
     767             : {
     768             :         int h;
     769             : 
     770           0 :         h = hash_index_ineq(ci, &ineq);
     771           0 :         if (!ci->index[h])
     772           0 :                 return isl_bool_false;
     773           0 :         return isl_int_ge(ineq[0], (*ci->index[h])[0]);
     774             : }
     775             : 
     776             : /* If we can eliminate more than one div, then we need to make
     777             :  * sure we do it from last div to first div, in order not to
     778             :  * change the position of the other divs that still need to
     779             :  * be removed.
     780             :  */
     781 16214254343 : static __isl_give isl_basic_map *remove_duplicate_divs(
     782             :         __isl_take isl_basic_map *bmap, int *progress)
     783             : {
     784             :         unsigned int size;
     785             :         int *index;
     786             :         int *elim_for;
     787             :         int k, l, h;
     788             :         int bits;
     789             :         struct isl_blk eq;
     790             :         unsigned total_var;
     791             :         unsigned total;
     792             :         struct isl_ctx *ctx;
     793             : 
     794 16214254343 :         bmap = isl_basic_map_order_divs(bmap);
     795 16214254343 :         if (!bmap || bmap->n_div <= 1)
     796 16214254343 :                 return bmap;
     797             : 
     798           0 :         total_var = isl_space_dim(bmap->dim, isl_dim_all);
     799           0 :         total = total_var + bmap->n_div;
     800             : 
     801           0 :         ctx = bmap->ctx;
     802           0 :         for (k = bmap->n_div - 1; k >= 0; --k)
     803           0 :                 if (!isl_int_is_zero(bmap->div[k][0]))
     804             :                         break;
     805           0 :         if (k <= 0)
     806           0 :                 return bmap;
     807             : 
     808           0 :         size = round_up(4 * bmap->n_div / 3 - 1);
     809           0 :         if (size == 0)
     810           0 :                 return bmap;
     811           0 :         elim_for = isl_calloc_array(ctx, int, bmap->n_div);
     812           0 :         bits = ffs(size) - 1;
     813           0 :         index = isl_calloc_array(ctx, int, size);
     814           0 :         if (!elim_for || !index)
     815             :                 goto out;
     816           0 :         eq = isl_blk_alloc(ctx, 1+total);
     817           0 :         if (isl_blk_is_error(eq))
     818           0 :                 goto out;
     819             : 
     820           0 :         isl_seq_clr(eq.data, 1+total);
     821           0 :         index[isl_seq_get_hash_bits(bmap->div[k], 2+total, bits)] = k + 1;
     822           0 :         for (--k; k >= 0; --k) {
     823             :                 uint32_t hash;
     824             : 
     825           0 :                 if (isl_int_is_zero(bmap->div[k][0]))
     826           0 :                         continue;
     827             : 
     828           0 :                 hash = isl_seq_get_hash_bits(bmap->div[k], 2+total, bits);
     829           0 :                 for (h = hash; index[h]; h = (h+1) % size)
     830           0 :                         if (isl_seq_eq(bmap->div[k],
     831           0 :                                        bmap->div[index[h]-1], 2+total))
     832           0 :                                 break;
     833           0 :                 if (index[h]) {
     834           0 :                         *progress = 1;
     835           0 :                         l = index[h] - 1;
     836           0 :                         elim_for[l] = k + 1;
     837             :                 }
     838           0 :                 index[h] = k+1;
     839             :         }
     840           0 :         for (l = bmap->n_div - 1; l >= 0; --l) {
     841           0 :                 if (!elim_for[l])
     842           0 :                         continue;
     843           0 :                 k = elim_for[l] - 1;
     844           0 :                 isl_int_set_si(eq.data[1+total_var+k], -1);
     845           0 :                 isl_int_set_si(eq.data[1+total_var+l], 1);
     846           0 :                 bmap = eliminate_div(bmap, eq.data, l, 1);
     847           0 :                 if (!bmap)
     848           0 :                         break;
     849           0 :                 isl_int_set_si(eq.data[1+total_var+k], 0);
     850           0 :                 isl_int_set_si(eq.data[1+total_var+l], 0);
     851             :         }
     852             : 
     853           0 :         isl_blk_free(ctx, eq);
     854             : out:
     855           0 :         free(index);
     856           0 :         free(elim_for);
     857           0 :         return bmap;
     858             : }
     859             : 
     860           0 : static int n_pure_div_eq(struct isl_basic_map *bmap)
     861             : {
     862             :         int i, j;
     863             :         unsigned total;
     864             : 
     865           0 :         total = isl_space_dim(bmap->dim, isl_dim_all);
     866           0 :         for (i = 0, j = bmap->n_div-1; i < bmap->n_eq; ++i) {
     867           0 :                 while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
     868           0 :                         --j;
     869           0 :                 if (j < 0)
     870           0 :                         break;
     871           0 :                 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, j) != -1)
     872           0 :                         return 0;
     873             :         }
     874           0 :         return i;
     875             : }
     876             : 
     877             : /* Normalize divs that appear in equalities.
     878             :  *
     879             :  * In particular, we assume that bmap contains some equalities
     880             :  * of the form
     881             :  *
     882             :  *      a x = m * e_i
     883             :  *
     884             :  * and we want to replace the set of e_i by a minimal set and
     885             :  * such that the new e_i have a canonical representation in terms
     886             :  * of the vector x.
     887             :  * If any of the equalities involves more than one divs, then
     888             :  * we currently simply bail out.
     889             :  *
     890             :  * Let us first additionally assume that all equalities involve
     891             :  * a div.  The equalities then express modulo constraints on the
     892             :  * remaining variables and we can use "parameter compression"
     893             :  * to find a minimal set of constraints.  The result is a transformation
     894             :  *
     895             :  *      x = T(x') = x_0 + G x'
     896             :  *
     897             :  * with G a lower-triangular matrix with all elements below the diagonal
     898             :  * non-negative and smaller than the diagonal element on the same row.
     899             :  * We first normalize x_0 by making the same property hold in the affine
     900             :  * T matrix.
     901             :  * The rows i of G with a 1 on the diagonal do not impose any modulo
     902             :  * constraint and simply express x_i = x'_i.
     903             :  * For each of the remaining rows i, we introduce a div and a corresponding
     904             :  * equality.  In particular
     905             :  *
     906             :  *      g_ii e_j = x_i - g_i(x')
     907             :  *
     908             :  * where each x'_k is replaced either by x_k (if g_kk = 1) or the
     909             :  * corresponding div (if g_kk != 1).
     910             :  *
     911             :  * If there are any equalities not involving any div, then we
     912             :  * first apply a variable compression on the variables x:
     913             :  *
     914             :  *      x = C x''       x'' = C_2 x
     915             :  *
     916             :  * and perform the above parameter compression on A C instead of on A.
     917             :  * The resulting compression is then of the form
     918             :  *
     919             :  *      x'' = T(x') = x_0 + G x'
     920             :  *
     921             :  * and in constructing the new divs and the corresponding equalities,
     922             :  * we have to replace each x'', i.e., the x'_k with (g_kk = 1),
     923             :  * by the corresponding row from C_2.
     924             :  */
     925 16214254343 : static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap,
     926             :         int *progress)
     927             : {
     928             :         int i, j, k;
     929             :         int total;
     930             :         int div_eq;
     931             :         struct isl_mat *B;
     932             :         struct isl_vec *d;
     933 16214254343 :         struct isl_mat *T = NULL;
     934 16214254343 :         struct isl_mat *C = NULL;
     935 16214254343 :         struct isl_mat *C2 = NULL;
     936             :         isl_int v;
     937 16214254343 :         int *pos = NULL;
     938             :         int dropped, needed;
     939             : 
     940 16214254343 :         if (!bmap)
     941           0 :                 return NULL;
     942             : 
     943 16214254343 :         if (bmap->n_div == 0)
     944 16214254343 :                 return bmap;
     945             : 
     946           0 :         if (bmap->n_eq == 0)
     947           0 :                 return bmap;
     948             : 
     949           0 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS))
     950           0 :                 return bmap;
     951             : 
     952           0 :         total = isl_space_dim(bmap->dim, isl_dim_all);
     953           0 :         div_eq = n_pure_div_eq(bmap);
     954           0 :         if (div_eq == 0)
     955           0 :                 return bmap;
     956             : 
     957           0 :         if (div_eq < bmap->n_eq) {
     958           0 :                 B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, div_eq,
     959           0 :                                         bmap->n_eq - div_eq, 0, 1 + total);
     960           0 :                 C = isl_mat_variable_compression(B, &C2);
     961           0 :                 if (!C || !C2)
     962             :                         goto error;
     963           0 :                 if (C->n_col == 0) {
     964           0 :                         bmap = isl_basic_map_set_to_empty(bmap);
     965           0 :                         isl_mat_free(C);
     966           0 :                         isl_mat_free(C2);
     967           0 :                         goto done;
     968             :                 }
     969             :         }
     970             : 
     971           0 :         d = isl_vec_alloc(bmap->ctx, div_eq);
     972           0 :         if (!d)
     973           0 :                 goto error;
     974           0 :         for (i = 0, j = bmap->n_div-1; i < div_eq; ++i) {
     975           0 :                 while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
     976           0 :                         --j;
     977           0 :                 isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j]);
     978             :         }
     979           0 :         B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total);
     980             : 
     981           0 :         if (C) {
     982           0 :                 B = isl_mat_product(B, C);
     983           0 :                 C = NULL;
     984             :         }
     985             : 
     986           0 :         T = isl_mat_parameter_compression(B, d);
     987           0 :         if (!T)
     988           0 :                 goto error;
     989           0 :         if (T->n_col == 0) {
     990           0 :                 bmap = isl_basic_map_set_to_empty(bmap);
     991           0 :                 isl_mat_free(C2);
     992           0 :                 isl_mat_free(T);
     993           0 :                 goto done;
     994             :         }
     995           0 :         isl_int_init(v);
     996           0 :         for (i = 0; i < T->n_row - 1; ++i) {
     997           0 :                 isl_int_fdiv_q(v, T->row[1 + i][0], T->row[1 + i][1 + i]);
     998           0 :                 if (isl_int_is_zero(v))
     999           0 :                         continue;
    1000           0 :                 isl_mat_col_submul(T, 0, v, 1 + i);
    1001             :         }
    1002           0 :         isl_int_clear(v);
    1003           0 :         pos = isl_alloc_array(bmap->ctx, int, T->n_row);
    1004           0 :         if (!pos)
    1005           0 :                 goto error;
    1006             :         /* We have to be careful because dropping equalities may reorder them */
    1007           0 :         dropped = 0;
    1008           0 :         for (j = bmap->n_div - 1; j >= 0; --j) {
    1009           0 :                 for (i = 0; i < bmap->n_eq; ++i)
    1010           0 :                         if (!isl_int_is_zero(bmap->eq[i][1 + total + j]))
    1011             :                                 break;
    1012           0 :                 if (i < bmap->n_eq) {
    1013           0 :                         bmap = isl_basic_map_drop_div(bmap, j);
    1014           0 :                         isl_basic_map_drop_equality(bmap, i);
    1015           0 :                         ++dropped;
    1016             :                 }
    1017             :         }
    1018           0 :         pos[0] = 0;
    1019           0 :         needed = 0;
    1020           0 :         for (i = 1; i < T->n_row; ++i) {
    1021           0 :                 if (isl_int_is_one(T->row[i][i]))
    1022           0 :                         pos[i] = i;
    1023             :                 else
    1024           0 :                         needed++;
    1025             :         }
    1026           0 :         if (needed > dropped) {
    1027           0 :                 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
    1028             :                                 needed, needed, 0);
    1029           0 :                 if (!bmap)
    1030           0 :                         goto error;
    1031             :         }
    1032           0 :         for (i = 1; i < T->n_row; ++i) {
    1033           0 :                 if (isl_int_is_one(T->row[i][i]))
    1034           0 :                         continue;
    1035           0 :                 k = isl_basic_map_alloc_div(bmap);
    1036           0 :                 pos[i] = 1 + total + k;
    1037           0 :                 isl_seq_clr(bmap->div[k] + 1, 1 + total + bmap->n_div);
    1038           0 :                 isl_int_set(bmap->div[k][0], T->row[i][i]);
    1039           0 :                 if (C2)
    1040           0 :                         isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + total);
    1041             :                 else
    1042           0 :                         isl_int_set_si(bmap->div[k][1 + i], 1);
    1043           0 :                 for (j = 0; j < i; ++j) {
    1044           0 :                         if (isl_int_is_zero(T->row[i][j]))
    1045           0 :                                 continue;
    1046           0 :                         if (pos[j] < T->n_row && C2)
    1047           0 :                                 isl_seq_submul(bmap->div[k] + 1, T->row[i][j],
    1048           0 :                                                 C2->row[pos[j]], 1 + total);
    1049             :                         else
    1050           0 :                                 isl_int_neg(bmap->div[k][1 + pos[j]],
    1051             :                                                                 T->row[i][j]);
    1052             :                 }
    1053           0 :                 j = isl_basic_map_alloc_equality(bmap);
    1054           0 :                 isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+total+bmap->n_div);
    1055           0 :                 isl_int_set(bmap->eq[j][pos[i]], bmap->div[k][0]);
    1056             :         }
    1057           0 :         free(pos);
    1058           0 :         isl_mat_free(C2);
    1059           0 :         isl_mat_free(T);
    1060             : 
    1061           0 :         if (progress)
    1062           0 :                 *progress = 1;
    1063             : done:
    1064           0 :         ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
    1065             : 
    1066           0 :         return bmap;
    1067             : error:
    1068           0 :         free(pos);
    1069           0 :         isl_mat_free(C);
    1070           0 :         isl_mat_free(C2);
    1071           0 :         isl_mat_free(T);
    1072           0 :         return bmap;
    1073             : }
    1074             : 
    1075           0 : static __isl_give isl_basic_map *set_div_from_lower_bound(
    1076             :         __isl_take isl_basic_map *bmap, int div, int ineq)
    1077             : {
    1078           0 :         unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
    1079             : 
    1080           0 :         isl_seq_neg(bmap->div[div] + 1, bmap->ineq[ineq], total + bmap->n_div);
    1081           0 :         isl_int_set(bmap->div[div][0], bmap->ineq[ineq][total + div]);
    1082           0 :         isl_int_add(bmap->div[div][1], bmap->div[div][1], bmap->div[div][0]);
    1083           0 :         isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
    1084           0 :         isl_int_set_si(bmap->div[div][1 + total + div], 0);
    1085             : 
    1086           0 :         return bmap;
    1087             : }
    1088             : 
    1089             : /* Check whether it is ok to define a div based on an inequality.
    1090             :  * To avoid the introduction of circular definitions of divs, we
    1091             :  * do not allow such a definition if the resulting expression would refer to
    1092             :  * any other undefined divs or if any known div is defined in
    1093             :  * terms of the unknown div.
    1094             :  */
    1095           0 : static isl_bool ok_to_set_div_from_bound(__isl_keep isl_basic_map *bmap,
    1096             :         int div, int ineq)
    1097             : {
    1098             :         int j;
    1099           0 :         unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
    1100             : 
    1101             :         /* Not defined in terms of unknown divs */
    1102           0 :         for (j = 0; j < bmap->n_div; ++j) {
    1103           0 :                 if (div == j)
    1104           0 :                         continue;
    1105           0 :                 if (isl_int_is_zero(bmap->ineq[ineq][total + j]))
    1106           0 :                         continue;
    1107           0 :                 if (isl_int_is_zero(bmap->div[j][0]))
    1108           0 :                         return isl_bool_false;
    1109             :         }
    1110             : 
    1111             :         /* No other div defined in terms of this one => avoid loops */
    1112           0 :         for (j = 0; j < bmap->n_div; ++j) {
    1113           0 :                 if (div == j)
    1114           0 :                         continue;
    1115           0 :                 if (isl_int_is_zero(bmap->div[j][0]))
    1116           0 :                         continue;
    1117           0 :                 if (!isl_int_is_zero(bmap->div[j][1 + total + div]))
    1118           0 :                         return isl_bool_false;
    1119             :         }
    1120             : 
    1121           0 :         return isl_bool_true;
    1122             : }
    1123             : 
    1124             : /* Would an expression for div "div" based on inequality "ineq" of "bmap"
    1125             :  * be a better expression than the current one?
    1126             :  *
    1127             :  * If we do not have any expression yet, then any expression would be better.
    1128             :  * Otherwise we check if the last variable involved in the inequality
    1129             :  * (disregarding the div that it would define) is in an earlier position
    1130             :  * than the last variable involved in the current div expression.
    1131             :  */
    1132           0 : static isl_bool better_div_constraint(__isl_keep isl_basic_map *bmap,
    1133             :         int div, int ineq)
    1134             : {
    1135           0 :         unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
    1136             :         int last_div;
    1137             :         int last_ineq;
    1138             : 
    1139           0 :         if (isl_int_is_zero(bmap->div[div][0]))
    1140           0 :                 return isl_bool_true;
    1141             : 
    1142           0 :         if (isl_seq_last_non_zero(bmap->ineq[ineq] + total + div + 1,
    1143           0 :                                   bmap->n_div - (div + 1)) >= 0)
    1144           0 :                 return isl_bool_false;
    1145             : 
    1146           0 :         last_ineq = isl_seq_last_non_zero(bmap->ineq[ineq], total + div);
    1147           0 :         last_div = isl_seq_last_non_zero(bmap->div[div] + 1,
    1148           0 :                                          total + bmap->n_div);
    1149             : 
    1150           0 :         return last_ineq < last_div;
    1151             : }
    1152             : 
    1153             : /* Given two constraints "k" and "l" that are opposite to each other,
    1154             :  * except for the constant term, check if we can use them
    1155             :  * to obtain an expression for one of the hitherto unknown divs or
    1156             :  * a "better" expression for a div for which we already have an expression.
    1157             :  * "sum" is the sum of the constant terms of the constraints.
    1158             :  * If this sum is strictly smaller than the coefficient of one
    1159             :  * of the divs, then this pair can be used define the div.
    1160             :  * To avoid the introduction of circular definitions of divs, we
    1161             :  * do not use the pair if the resulting expression would refer to
    1162             :  * any other undefined divs or if any known div is defined in
    1163             :  * terms of the unknown div.
    1164             :  */
    1165  1012353148 : static __isl_give isl_basic_map *check_for_div_constraints(
    1166             :         __isl_take isl_basic_map *bmap, int k, int l, isl_int sum,
    1167             :         int *progress)
    1168             : {
    1169             :         int i;
    1170  1012353148 :         unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
    1171             : 
    1172  1012353148 :         for (i = 0; i < bmap->n_div; ++i) {
    1173             :                 isl_bool set_div;
    1174             : 
    1175           0 :                 if (isl_int_is_zero(bmap->ineq[k][total + i]))
    1176           0 :                         continue;
    1177           0 :                 if (isl_int_abs_ge(sum, bmap->ineq[k][total + i]))
    1178           0 :                         continue;
    1179           0 :                 set_div = better_div_constraint(bmap, i, k);
    1180           0 :                 if (set_div >= 0 && set_div)
    1181           0 :                         set_div = ok_to_set_div_from_bound(bmap, i, k);
    1182           0 :                 if (set_div < 0)
    1183           0 :                         return isl_basic_map_free(bmap);
    1184           0 :                 if (!set_div)
    1185           0 :                         break;
    1186           0 :                 if (isl_int_is_pos(bmap->ineq[k][total + i]))
    1187           0 :                         bmap = set_div_from_lower_bound(bmap, i, k);
    1188             :                 else
    1189           0 :                         bmap = set_div_from_lower_bound(bmap, i, l);
    1190           0 :                 if (progress)
    1191           0 :                         *progress = 1;
    1192           0 :                 break;
    1193             :         }
    1194  1012353148 :         return bmap;
    1195             : }
    1196             : 
    1197 16214282001 : __isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
    1198             :         __isl_take isl_basic_map *bmap, int *progress, int detect_divs)
    1199             : {
    1200             :         struct isl_constraint_index ci;
    1201             :         int k, l, h;
    1202 16214282001 :         unsigned total = isl_basic_map_total_dim(bmap);
    1203             :         isl_int sum;
    1204             : 
    1205 16214282001 :         if (!bmap || bmap->n_ineq <= 1)
    1206 14221862380 :                 return bmap;
    1207             : 
    1208  1992419621 :         if (create_constraint_index(&ci, bmap) < 0)
    1209           0 :                 return bmap;
    1210             : 
    1211  1992419621 :         h = isl_seq_get_hash_bits(bmap->ineq[0] + 1, total, ci.bits);
    1212  1992419621 :         ci.index[h] = &bmap->ineq[0];
    1213  7456164042 :         for (k = 1; k < bmap->n_ineq; ++k) {
    1214  5463744421 :                 h = hash_index(&ci, bmap, k);
    1215  5463744421 :                 if (!ci.index[h]) {
    1216  5258891874 :                         ci.index[h] = &bmap->ineq[k];
    1217  5258891874 :                         continue;
    1218             :                 }
    1219   204852547 :                 if (progress)
    1220   204852547 :                         *progress = 1;
    1221   204852547 :                 l = ci.index[h] - &bmap->ineq[0];
    1222   204852547 :                 if (isl_int_lt(bmap->ineq[k][0], bmap->ineq[l][0]))
    1223    30940916 :                         swap_inequality(bmap, k, l);
    1224   204852547 :                 isl_basic_map_drop_inequality(bmap, k);
    1225   204852547 :                 --k;
    1226             :         }
    1227  1992419621 :         isl_int_init(sum);
    1228  6550137802 :         for (k = 0; k < bmap->n_ineq-1; ++k) {
    1229  4640001866 :                 isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
    1230  4640001866 :                 h = hash_index(&ci, bmap, k);
    1231  4640001866 :                 isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
    1232  4640001866 :                 if (!ci.index[h])
    1233  3545268277 :                         continue;
    1234  1094733589 :                 l = ci.index[h] - &bmap->ineq[0];
    1235  1094733589 :                 isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0]);
    1236  1094733589 :                 if (isl_int_is_pos(sum)) {
    1237  1012449904 :                         if (detect_divs)
    1238  1012353148 :                                 bmap = check_for_div_constraints(bmap, k, l,
    1239             :                                                                  sum, progress);
    1240  1012449904 :                         continue;
    1241             :                 }
    1242    82283685 :                 if (isl_int_is_zero(sum)) {
    1243             :                         /* We need to break out of the loop after these
    1244             :                          * changes since the contents of the hash
    1245             :                          * will no longer be valid.
    1246             :                          * Plus, we probably we want to regauss first.
    1247             :                          */
    1248    37971387 :                         if (progress)
    1249    37971387 :                                 *progress = 1;
    1250    37971387 :                         isl_basic_map_drop_inequality(bmap, l);
    1251    37971387 :                         isl_basic_map_inequality_to_equality(bmap, k);
    1252             :                 } else
    1253    44312298 :                         bmap = isl_basic_map_set_to_empty(bmap);
    1254    82283685 :                 break;
    1255             :         }
    1256  1992419621 :         isl_int_clear(sum);
    1257             : 
    1258  1992419621 :         constraint_index_free(&ci);
    1259  1992419621 :         return bmap;
    1260             : }
    1261             : 
    1262             : /* Detect all pairs of inequalities that form an equality.
    1263             :  *
    1264             :  * isl_basic_map_remove_duplicate_constraints detects at most one such pair.
    1265             :  * Call it repeatedly while it is making progress.
    1266             :  */
    1267       27658 : __isl_give isl_basic_map *isl_basic_map_detect_inequality_pairs(
    1268             :         __isl_take isl_basic_map *bmap, int *progress)
    1269             : {
    1270             :         int duplicate;
    1271             : 
    1272             :         do {
    1273       27658 :                 duplicate = 0;
    1274       27658 :                 bmap = isl_basic_map_remove_duplicate_constraints(bmap,
    1275             :                                                                 &duplicate, 0);
    1276       27658 :                 if (progress && duplicate)
    1277         221 :                         *progress = 1;
    1278       27658 :         } while (duplicate);
    1279             : 
    1280       16142 :         return bmap;
    1281             : }
    1282             : 
    1283             : /* Eliminate knowns divs from constraints where they appear with
    1284             :  * a (positive or negative) unit coefficient.
    1285             :  *
    1286             :  * That is, replace
    1287             :  *
    1288             :  *      floor(e/m) + f >= 0
    1289             :  *
    1290             :  * by
    1291             :  *
    1292             :  *      e + m f >= 0
    1293             :  *
    1294             :  * and
    1295             :  *
    1296             :  *      -floor(e/m) + f >= 0
    1297             :  *
    1298             :  * by
    1299             :  *
    1300             :  *      -e + m f + m - 1 >= 0
    1301             :  *
    1302             :  * The first conversion is valid because floor(e/m) >= -f is equivalent
    1303             :  * to e/m >= -f because -f is an integral expression.
    1304             :  * The second conversion follows from the fact that
    1305             :  *
    1306             :  *      -floor(e/m) = ceil(-e/m) = floor((-e + m - 1)/m)
    1307             :  *
    1308             :  *
    1309             :  * Note that one of the div constraints may have been eliminated
    1310             :  * due to being redundant with respect to the constraint that is
    1311             :  * being modified by this function.  The modified constraint may
    1312             :  * no longer imply this div constraint, so we add it back to make
    1313             :  * sure we do not lose any information.
    1314             :  *
    1315             :  * We skip integral divs, i.e., those with denominator 1, as we would
    1316             :  * risk eliminating the div from the div constraints.  We do not need
    1317             :  * to handle those divs here anyway since the div constraints will turn
    1318             :  * out to form an equality and this equality can then be used to eliminate
    1319             :  * the div from all constraints.
    1320             :  */
    1321 16214254343 : static __isl_give isl_basic_map *eliminate_unit_divs(
    1322             :         __isl_take isl_basic_map *bmap, int *progress)
    1323             : {
    1324             :         int i, j;
    1325             :         isl_ctx *ctx;
    1326             :         unsigned total;
    1327             : 
    1328 16214254343 :         if (!bmap)
    1329           0 :                 return NULL;
    1330             : 
    1331 16214254343 :         ctx = isl_basic_map_get_ctx(bmap);
    1332 16214254343 :         total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
    1333             : 
    1334 16214254343 :         for (i = 0; i < bmap->n_div; ++i) {
    1335           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
    1336           0 :                         continue;
    1337           0 :                 if (isl_int_is_one(bmap->div[i][0]))
    1338           0 :                         continue;
    1339           0 :                 for (j = 0; j < bmap->n_ineq; ++j) {
    1340             :                         int s;
    1341             : 
    1342           0 :                         if (!isl_int_is_one(bmap->ineq[j][total + i]) &&
    1343           0 :                             !isl_int_is_negone(bmap->ineq[j][total + i]))
    1344           0 :                                 continue;
    1345             : 
    1346           0 :                         *progress = 1;
    1347             : 
    1348           0 :                         s = isl_int_sgn(bmap->ineq[j][total + i]);
    1349           0 :                         isl_int_set_si(bmap->ineq[j][total + i], 0);
    1350           0 :                         if (s < 0)
    1351           0 :                                 isl_seq_combine(bmap->ineq[j],
    1352           0 :                                         ctx->negone, bmap->div[i] + 1,
    1353           0 :                                         bmap->div[i][0], bmap->ineq[j],
    1354           0 :                                         total + bmap->n_div);
    1355             :                         else
    1356           0 :                                 isl_seq_combine(bmap->ineq[j],
    1357           0 :                                         ctx->one, bmap->div[i] + 1,
    1358           0 :                                         bmap->div[i][0], bmap->ineq[j],
    1359           0 :                                         total + bmap->n_div);
    1360           0 :                         if (s < 0) {
    1361           0 :                                 isl_int_add(bmap->ineq[j][0],
    1362             :                                         bmap->ineq[j][0], bmap->div[i][0]);
    1363           0 :                                 isl_int_sub_ui(bmap->ineq[j][0],
    1364             :                                         bmap->ineq[j][0], 1);
    1365             :                         }
    1366             : 
    1367           0 :                         bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
    1368           0 :                         if (isl_basic_map_add_div_constraint(bmap, i, s) < 0)
    1369           0 :                                 return isl_basic_map_free(bmap);
    1370             :                 }
    1371             :         }
    1372             : 
    1373 16214254343 :         return bmap;
    1374             : }
    1375             : 
    1376 12231209136 : __isl_give isl_basic_map *isl_basic_map_simplify(__isl_take isl_basic_map *bmap)
    1377             : {
    1378 12231209136 :         int progress = 1;
    1379 12231209136 :         if (!bmap)
    1380           0 :                 return NULL;
    1381 40676672615 :         while (progress) {
    1382             :                 isl_bool empty;
    1383             : 
    1384 17041287968 :                 progress = 0;
    1385 17041287968 :                 empty = isl_basic_map_plain_is_empty(bmap);
    1386 17041287968 :                 if (empty < 0)
    1387           0 :                         return isl_basic_map_free(bmap);
    1388 17041287968 :                 if (empty)
    1389   827033625 :                         break;
    1390 16214254343 :                 bmap = isl_basic_map_normalize_constraints(bmap);
    1391 16214254343 :                 bmap = reduce_div_coefficients(bmap);
    1392 16214254343 :                 bmap = normalize_div_expressions(bmap);
    1393 16214254343 :                 bmap = remove_duplicate_divs(bmap, &progress);
    1394 16214254343 :                 bmap = eliminate_unit_divs(bmap, &progress);
    1395 16214254343 :                 bmap = eliminate_divs_eq(bmap, &progress);
    1396 16214254343 :                 bmap = eliminate_divs_ineq(bmap, &progress);
    1397 16214254343 :                 bmap = isl_basic_map_gauss(bmap, &progress);
    1398             :                 /* requires equalities in normal form */
    1399 16214254343 :                 bmap = normalize_divs(bmap, &progress);
    1400 16214254343 :                 bmap = isl_basic_map_remove_duplicate_constraints(bmap,
    1401             :                                                                 &progress, 1);
    1402 16214254343 :                 if (bmap && progress)
    1403  4810078832 :                         ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
    1404             :         }
    1405 12231209136 :         return bmap;
    1406             : }
    1407             : 
    1408 11421529127 : struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset)
    1409             : {
    1410 11421529127 :         return bset_from_bmap(isl_basic_map_simplify(bset_to_bmap(bset)));
    1411             : }
    1412             : 
    1413             : 
    1414           0 : isl_bool isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap,
    1415             :         isl_int *constraint, unsigned div)
    1416             : {
    1417             :         unsigned pos;
    1418             : 
    1419           0 :         if (!bmap)
    1420           0 :                 return isl_bool_error;
    1421             : 
    1422           0 :         pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
    1423             : 
    1424           0 :         if (isl_int_eq(constraint[pos], bmap->div[div][0])) {
    1425             :                 int neg;
    1426           0 :                 isl_int_sub(bmap->div[div][1],
    1427             :                                 bmap->div[div][1], bmap->div[div][0]);
    1428           0 :                 isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1);
    1429           0 :                 neg = isl_seq_is_neg(constraint, bmap->div[div]+1, pos);
    1430           0 :                 isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
    1431           0 :                 isl_int_add(bmap->div[div][1],
    1432             :                                 bmap->div[div][1], bmap->div[div][0]);
    1433           0 :                 if (!neg)
    1434           0 :                         return isl_bool_false;
    1435           0 :                 if (isl_seq_first_non_zero(constraint+pos+1,
    1436           0 :                                             bmap->n_div-div-1) != -1)
    1437           0 :                         return isl_bool_false;
    1438           0 :         } else if (isl_int_abs_eq(constraint[pos], bmap->div[div][0])) {
    1439           0 :                 if (!isl_seq_eq(constraint, bmap->div[div]+1, pos))
    1440           0 :                         return isl_bool_false;
    1441           0 :                 if (isl_seq_first_non_zero(constraint+pos+1,
    1442           0 :                                             bmap->n_div-div-1) != -1)
    1443           0 :                         return isl_bool_false;
    1444             :         } else
    1445           0 :                 return isl_bool_false;
    1446             : 
    1447           0 :         return isl_bool_true;
    1448             : }
    1449             : 
    1450           0 : isl_bool isl_basic_set_is_div_constraint(__isl_keep isl_basic_set *bset,
    1451             :         isl_int *constraint, unsigned div)
    1452             : {
    1453           0 :         return isl_basic_map_is_div_constraint(bset, constraint, div);
    1454             : }
    1455             : 
    1456             : 
    1457             : /* If the only constraints a div d=floor(f/m)
    1458             :  * appears in are its two defining constraints
    1459             :  *
    1460             :  *      f - m d >=0
    1461             :  *      -(f - (m - 1)) + m d >= 0
    1462             :  *
    1463             :  * then it can safely be removed.
    1464             :  */
    1465           0 : static isl_bool div_is_redundant(__isl_keep isl_basic_map *bmap, int div)
    1466             : {
    1467             :         int i;
    1468           0 :         unsigned pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
    1469             : 
    1470           0 :         for (i = 0; i < bmap->n_eq; ++i)
    1471           0 :                 if (!isl_int_is_zero(bmap->eq[i][pos]))
    1472           0 :                         return isl_bool_false;
    1473             : 
    1474           0 :         for (i = 0; i < bmap->n_ineq; ++i) {
    1475             :                 isl_bool red;
    1476             : 
    1477           0 :                 if (isl_int_is_zero(bmap->ineq[i][pos]))
    1478           0 :                         continue;
    1479           0 :                 red = isl_basic_map_is_div_constraint(bmap, bmap->ineq[i], div);
    1480           0 :                 if (red < 0 || !red)
    1481           0 :                         return red;
    1482             :         }
    1483             : 
    1484           0 :         for (i = 0; i < bmap->n_div; ++i) {
    1485           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
    1486           0 :                         continue;
    1487           0 :                 if (!isl_int_is_zero(bmap->div[i][1+pos]))
    1488           0 :                         return isl_bool_false;
    1489             :         }
    1490             : 
    1491           0 :         return isl_bool_true;
    1492             : }
    1493             : 
    1494             : /*
    1495             :  * Remove divs that don't occur in any of the constraints or other divs.
    1496             :  * These can arise when dropping constraints from a basic map or
    1497             :  * when the divs of a basic map have been temporarily aligned
    1498             :  * with the divs of another basic map.
    1499             :  */
    1500 25838543167 : static __isl_give isl_basic_map *remove_redundant_divs(
    1501             :         __isl_take isl_basic_map *bmap)
    1502             : {
    1503             :         int i;
    1504             : 
    1505 25838543167 :         if (!bmap)
    1506           0 :                 return NULL;
    1507             : 
    1508 25838543167 :         for (i = bmap->n_div-1; i >= 0; --i) {
    1509             :                 isl_bool redundant;
    1510             : 
    1511           0 :                 redundant = div_is_redundant(bmap, i);
    1512           0 :                 if (redundant < 0)
    1513           0 :                         return isl_basic_map_free(bmap);
    1514           0 :                 if (!redundant)
    1515           0 :                         continue;
    1516           0 :                 bmap = isl_basic_map_drop_div(bmap, i);
    1517             :         }
    1518 25838543167 :         return bmap;
    1519             : }
    1520             : 
    1521             : /* Mark "bmap" as final, without checking for obviously redundant
    1522             :  * integer divisions.  This function should be used when "bmap"
    1523             :  * is known not to involve any such integer divisions.
    1524             :  */
    1525 25838543167 : __isl_give isl_basic_map *isl_basic_map_mark_final(
    1526             :         __isl_take isl_basic_map *bmap)
    1527             : {
    1528 25838543167 :         if (!bmap)
    1529           0 :                 return NULL;
    1530 25838543167 :         ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
    1531 25838543167 :         return bmap;
    1532             : }
    1533             : 
    1534             : /* Mark "bmap" as final, after removing obviously redundant integer divisions.
    1535             :  */
    1536 25838543167 : __isl_give isl_basic_map *isl_basic_map_finalize(__isl_take isl_basic_map *bmap)
    1537             : {
    1538 25838543167 :         bmap = remove_redundant_divs(bmap);
    1539 25838543167 :         bmap = isl_basic_map_mark_final(bmap);
    1540 25838543167 :         return bmap;
    1541             : }
    1542             : 
    1543 10625867154 : struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset)
    1544             : {
    1545 10625867154 :         return bset_from_bmap(isl_basic_map_finalize(bset_to_bmap(bset)));
    1546             : }
    1547             : 
    1548             : /* Remove definition of any div that is defined in terms of the given variable.
    1549             :  * The div itself is not removed.  Functions such as
    1550             :  * eliminate_divs_ineq depend on the other divs remaining in place.
    1551             :  */
    1552     1275257 : static __isl_give isl_basic_map *remove_dependent_vars(
    1553             :         __isl_take isl_basic_map *bmap, int pos)
    1554             : {
    1555             :         int i;
    1556             : 
    1557     1275257 :         if (!bmap)
    1558           0 :                 return NULL;
    1559             : 
    1560     1275257 :         for (i = 0; i < bmap->n_div; ++i) {
    1561           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
    1562           0 :                         continue;
    1563           0 :                 if (isl_int_is_zero(bmap->div[i][1+1+pos]))
    1564           0 :                         continue;
    1565           0 :                 bmap = isl_basic_map_mark_div_unknown(bmap, i);
    1566           0 :                 if (!bmap)
    1567           0 :                         return NULL;
    1568             :         }
    1569     1275257 :         return bmap;
    1570             : }
    1571             : 
    1572             : /* Eliminate the specified variables from the constraints using
    1573             :  * Fourier-Motzkin.  The variables themselves are not removed.
    1574             :  */
    1575      752725 : __isl_give isl_basic_map *isl_basic_map_eliminate_vars(
    1576             :         __isl_take isl_basic_map *bmap, unsigned pos, unsigned n)
    1577             : {
    1578             :         int d;
    1579             :         int i, j, k;
    1580             :         unsigned total;
    1581      752725 :         int need_gauss = 0;
    1582             : 
    1583      752725 :         if (n == 0)
    1584           0 :                 return bmap;
    1585      752725 :         if (!bmap)
    1586           0 :                 return NULL;
    1587      752725 :         total = isl_basic_map_total_dim(bmap);
    1588             : 
    1589      752725 :         bmap = isl_basic_map_cow(bmap);
    1590     2027982 :         for (d = pos + n - 1; d >= 0 && d >= pos; --d)
    1591     1275257 :                 bmap = remove_dependent_vars(bmap, d);
    1592      752725 :         if (!bmap)
    1593           0 :                 return NULL;
    1594             : 
    1595     1505450 :         for (d = pos + n - 1;
    1596      752725 :              d >= 0 && d >= total - bmap->n_div && d >= pos; --d)
    1597           0 :                 isl_seq_clr(bmap->div[d-(total-bmap->n_div)], 2+total);
    1598     2027982 :         for (d = pos + n - 1; d >= 0 && d >= pos; --d) {
    1599             :                 int n_lower, n_upper;
    1600     1275257 :                 if (!bmap)
    1601           0 :                         return NULL;
    1602     2922202 :                 for (i = 0; i < bmap->n_eq; ++i) {
    1603     1461101 :                         if (isl_int_is_zero(bmap->eq[i][1+d]))
    1604      185844 :                                 continue;
    1605     1275257 :                         eliminate_var_using_equality(bmap, d, bmap->eq[i], 0, NULL);
    1606     1275257 :                         isl_basic_map_drop_equality(bmap, i);
    1607     1275257 :                         need_gauss = 1;
    1608     1275257 :                         break;
    1609             :                 }
    1610     1275257 :                 if (i < bmap->n_eq)
    1611      384265 :                         continue;
    1612      890992 :                 n_lower = 0;
    1613      890992 :                 n_upper = 0;
    1614     4166777 :                 for (i = 0; i < bmap->n_ineq; ++i) {
    1615     3275785 :                         if (isl_int_is_pos(bmap->ineq[i][1+d]))
    1616           0 :                                 n_lower++;
    1617     3275785 :                         else if (isl_int_is_neg(bmap->ineq[i][1+d]))
    1618           0 :                                 n_upper++;
    1619             :                 }
    1620      890992 :                 bmap = isl_basic_map_extend_constraints(bmap,
    1621      890992 :                                 0, n_lower * n_upper);
    1622      890992 :                 if (!bmap)
    1623           0 :                         goto error;
    1624     4166777 :                 for (i = bmap->n_ineq - 1; i >= 0; --i) {
    1625             :                         int last;
    1626     3275785 :                         if (isl_int_is_zero(bmap->ineq[i][1+d]))
    1627     3275785 :                                 continue;
    1628           0 :                         last = -1;
    1629           0 :                         for (j = 0; j < i; ++j) {
    1630           0 :                                 if (isl_int_is_zero(bmap->ineq[j][1+d]))
    1631           0 :                                         continue;
    1632           0 :                                 last = j;
    1633           0 :                                 if (isl_int_sgn(bmap->ineq[i][1+d]) ==
    1634           0 :                                     isl_int_sgn(bmap->ineq[j][1+d]))
    1635           0 :                                         continue;
    1636           0 :                                 k = isl_basic_map_alloc_inequality(bmap);
    1637           0 :                                 if (k < 0)
    1638           0 :                                         goto error;
    1639           0 :                                 isl_seq_cpy(bmap->ineq[k], bmap->ineq[i],
    1640             :                                                 1+total);
    1641           0 :                                 isl_seq_elim(bmap->ineq[k], bmap->ineq[j],
    1642           0 :                                                 1+d, 1+total, NULL);
    1643             :                         }
    1644           0 :                         isl_basic_map_drop_inequality(bmap, i);
    1645           0 :                         i = last + 1;
    1646             :                 }
    1647      890992 :                 if (n_lower > 0 && n_upper > 0) {
    1648           0 :                         bmap = isl_basic_map_normalize_constraints(bmap);
    1649           0 :                         bmap = isl_basic_map_remove_duplicate_constraints(bmap,
    1650             :                                                                     NULL, 0);
    1651           0 :                         bmap = isl_basic_map_gauss(bmap, NULL);
    1652           0 :                         bmap = isl_basic_map_remove_redundancies(bmap);
    1653           0 :                         need_gauss = 0;
    1654           0 :                         if (!bmap)
    1655           0 :                                 goto error;
    1656           0 :                         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
    1657           0 :                                 break;
    1658             :                 }
    1659             :         }
    1660      752725 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    1661      752725 :         if (need_gauss)
    1662      752725 :                 bmap = isl_basic_map_gauss(bmap, NULL);
    1663      752725 :         return bmap;
    1664             : error:
    1665           0 :         isl_basic_map_free(bmap);
    1666           0 :         return NULL;
    1667             : }
    1668             : 
    1669           0 : struct isl_basic_set *isl_basic_set_eliminate_vars(
    1670             :         struct isl_basic_set *bset, unsigned pos, unsigned n)
    1671             : {
    1672           0 :         return bset_from_bmap(isl_basic_map_eliminate_vars(bset_to_bmap(bset),
    1673             :                                                                 pos, n));
    1674             : }
    1675             : 
    1676             : /* Eliminate the specified n dimensions starting at first from the
    1677             :  * constraints, without removing the dimensions from the space.
    1678             :  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
    1679             :  * Otherwise, they are projected out and the original space is restored.
    1680             :  */
    1681           0 : __isl_give isl_basic_map *isl_basic_map_eliminate(
    1682             :         __isl_take isl_basic_map *bmap,
    1683             :         enum isl_dim_type type, unsigned first, unsigned n)
    1684             : {
    1685             :         isl_space *space;
    1686             : 
    1687           0 :         if (!bmap)
    1688           0 :                 return NULL;
    1689           0 :         if (n == 0)
    1690           0 :                 return bmap;
    1691             : 
    1692           0 :         if (first + n > isl_basic_map_dim(bmap, type) || first + n < first)
    1693           0 :                 isl_die(bmap->ctx, isl_error_invalid,
    1694             :                         "index out of bounds", goto error);
    1695             : 
    1696           0 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
    1697           0 :                 first += isl_basic_map_offset(bmap, type) - 1;
    1698           0 :                 bmap = isl_basic_map_eliminate_vars(bmap, first, n);
    1699           0 :                 return isl_basic_map_finalize(bmap);
    1700             :         }
    1701             : 
    1702           0 :         space = isl_basic_map_get_space(bmap);
    1703           0 :         bmap = isl_basic_map_project_out(bmap, type, first, n);
    1704           0 :         bmap = isl_basic_map_insert_dims(bmap, type, first, n);
    1705           0 :         bmap = isl_basic_map_reset_space(bmap, space);
    1706           0 :         return bmap;
    1707             : error:
    1708           0 :         isl_basic_map_free(bmap);
    1709           0 :         return NULL;
    1710             : }
    1711             : 
    1712           0 : __isl_give isl_basic_set *isl_basic_set_eliminate(
    1713             :         __isl_take isl_basic_set *bset,
    1714             :         enum isl_dim_type type, unsigned first, unsigned n)
    1715             : {
    1716           0 :         return isl_basic_map_eliminate(bset, type, first, n);
    1717             : }
    1718             : 
    1719             : /* Remove all constraints from "bmap" that reference any unknown local
    1720             :  * variables (directly or indirectly).
    1721             :  *
    1722             :  * Dropping all constraints on a local variable will make it redundant,
    1723             :  * so it will get removed implicitly by
    1724             :  * isl_basic_map_drop_constraints_involving_dims.  Some other local
    1725             :  * variables may also end up becoming redundant if they only appear
    1726             :  * in constraints together with the unknown local variable.
    1727             :  * Therefore, start over after calling
    1728             :  * isl_basic_map_drop_constraints_involving_dims.
    1729             :  */
    1730           0 : __isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs(
    1731             :         __isl_take isl_basic_map *bmap)
    1732             : {
    1733             :         isl_bool known;
    1734             :         int i, n_div, o_div;
    1735             : 
    1736           0 :         known = isl_basic_map_divs_known(bmap);
    1737           0 :         if (known < 0)
    1738           0 :                 return isl_basic_map_free(bmap);
    1739           0 :         if (known)
    1740           0 :                 return bmap;
    1741             : 
    1742           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    1743           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div) - 1;
    1744             : 
    1745           0 :         for (i = 0; i < n_div; ++i) {
    1746           0 :                 known = isl_basic_map_div_is_known(bmap, i);
    1747           0 :                 if (known < 0)
    1748           0 :                         return isl_basic_map_free(bmap);
    1749           0 :                 if (known)
    1750           0 :                         continue;
    1751           0 :                 bmap = remove_dependent_vars(bmap, o_div + i);
    1752           0 :                 bmap = isl_basic_map_drop_constraints_involving_dims(bmap,
    1753             :                                                             isl_dim_div, i, 1);
    1754           0 :                 if (!bmap)
    1755           0 :                         return NULL;
    1756           0 :                 n_div = isl_basic_map_dim(bmap, isl_dim_div);
    1757           0 :                 i = -1;
    1758             :         }
    1759             : 
    1760           0 :         return bmap;
    1761             : }
    1762             : 
    1763             : /* Remove all constraints from "map" that reference any unknown local
    1764             :  * variables (directly or indirectly).
    1765             :  *
    1766             :  * Since constraints may get dropped from the basic maps,
    1767             :  * they may no longer be disjoint from each other.
    1768             :  */
    1769           0 : __isl_give isl_map *isl_map_drop_constraint_involving_unknown_divs(
    1770             :         __isl_take isl_map *map)
    1771             : {
    1772             :         int i;
    1773             :         isl_bool known;
    1774             : 
    1775           0 :         known = isl_map_divs_known(map);
    1776           0 :         if (known < 0)
    1777           0 :                 return isl_map_free(map);
    1778           0 :         if (known)
    1779           0 :                 return map;
    1780             : 
    1781           0 :         map = isl_map_cow(map);
    1782           0 :         if (!map)
    1783           0 :                 return NULL;
    1784             : 
    1785           0 :         for (i = 0; i < map->n; ++i) {
    1786           0 :                 map->p[i] =
    1787           0 :                     isl_basic_map_drop_constraint_involving_unknown_divs(
    1788           0 :                                                                     map->p[i]);
    1789           0 :                 if (!map->p[i])
    1790           0 :                         return isl_map_free(map);
    1791             :         }
    1792             : 
    1793           0 :         if (map->n > 1)
    1794           0 :                 ISL_F_CLR(map, ISL_MAP_DISJOINT);
    1795             : 
    1796           0 :         return map;
    1797             : }
    1798             : 
    1799             : /* Don't assume equalities are in order, because align_divs
    1800             :  * may have changed the order of the divs.
    1801             :  */
    1802     6822802 : static void compute_elimination_index(__isl_keep isl_basic_map *bmap, int *elim)
    1803             : {
    1804             :         int d, i;
    1805             :         unsigned total;
    1806             : 
    1807     6822802 :         total = isl_space_dim(bmap->dim, isl_dim_all);
    1808    51047165 :         for (d = 0; d < total; ++d)
    1809    44224363 :                 elim[d] = -1;
    1810    19107308 :         for (i = 0; i < bmap->n_eq; ++i) {
    1811    90438436 :                 for (d = total - 1; d >= 0; --d) {
    1812    45219218 :                         if (isl_int_is_zero(bmap->eq[i][1+d]))
    1813    32934712 :                                 continue;
    1814    12284506 :                         elim[d] = i;
    1815    12284506 :                         break;
    1816             :                 }
    1817             :         }
    1818     6822802 : }
    1819             : 
    1820           0 : static void set_compute_elimination_index(__isl_keep isl_basic_set *bset,
    1821             :         int *elim)
    1822             : {
    1823           0 :         compute_elimination_index(bset_to_bmap(bset), elim);
    1824           0 : }
    1825             : 
    1826    51711391 : static int reduced_using_equalities(isl_int *dst, isl_int *src,
    1827             :         __isl_keep isl_basic_map *bmap, int *elim)
    1828             : {
    1829             :         int d;
    1830    51711391 :         int copied = 0;
    1831             :         unsigned total;
    1832             : 
    1833    51711391 :         total = isl_space_dim(bmap->dim, isl_dim_all);
    1834   393221630 :         for (d = total - 1; d >= 0; --d) {
    1835   341510239 :                 if (isl_int_is_zero(src[1+d]))
    1836   204316367 :                         continue;
    1837   137193872 :                 if (elim[d] == -1)
    1838   123152337 :                         continue;
    1839    14041535 :                 if (!copied) {
    1840    11620235 :                         isl_seq_cpy(dst, src, 1 + total);
    1841    11620235 :                         copied = 1;
    1842             :                 }
    1843    14041535 :                 isl_seq_elim(dst, bmap->eq[elim[d]], 1 + d, 1 + total, NULL);
    1844             :         }
    1845    51711391 :         return copied;
    1846             : }
    1847             : 
    1848           0 : static int set_reduced_using_equalities(isl_int *dst, isl_int *src,
    1849             :         __isl_keep isl_basic_set *bset, int *elim)
    1850             : {
    1851           0 :         return reduced_using_equalities(dst, src,
    1852             :                                         bset_to_bmap(bset), elim);
    1853             : }
    1854             : 
    1855           0 : static __isl_give isl_basic_set *isl_basic_set_reduce_using_equalities(
    1856             :         __isl_take isl_basic_set *bset, __isl_take isl_basic_set *context)
    1857             : {
    1858             :         int i;
    1859             :         int *elim;
    1860             : 
    1861           0 :         if (!bset || !context)
    1862             :                 goto error;
    1863             : 
    1864           0 :         if (context->n_eq == 0) {
    1865           0 :                 isl_basic_set_free(context);
    1866           0 :                 return bset;
    1867             :         }
    1868             : 
    1869           0 :         bset = isl_basic_set_cow(bset);
    1870           0 :         if (!bset)
    1871           0 :                 goto error;
    1872             : 
    1873           0 :         elim = isl_alloc_array(bset->ctx, int, isl_basic_set_n_dim(bset));
    1874           0 :         if (!elim)
    1875           0 :                 goto error;
    1876           0 :         set_compute_elimination_index(context, elim);
    1877           0 :         for (i = 0; i < bset->n_eq; ++i)
    1878           0 :                 set_reduced_using_equalities(bset->eq[i], bset->eq[i],
    1879             :                                                         context, elim);
    1880           0 :         for (i = 0; i < bset->n_ineq; ++i)
    1881           0 :                 set_reduced_using_equalities(bset->ineq[i], bset->ineq[i],
    1882             :                                                         context, elim);
    1883           0 :         isl_basic_set_free(context);
    1884           0 :         free(elim);
    1885           0 :         bset = isl_basic_set_simplify(bset);
    1886           0 :         bset = isl_basic_set_finalize(bset);
    1887           0 :         return bset;
    1888             : error:
    1889           0 :         isl_basic_set_free(bset);
    1890           0 :         isl_basic_set_free(context);
    1891           0 :         return NULL;
    1892             : }
    1893             : 
    1894             : /* For each inequality in "ineq" that is a shifted (more relaxed)
    1895             :  * copy of an inequality in "context", mark the corresponding entry
    1896             :  * in "row" with -1.
    1897             :  * If an inequality only has a non-negative constant term, then
    1898             :  * mark it as well.
    1899             :  */
    1900           0 : static isl_stat mark_shifted_constraints(__isl_keep isl_mat *ineq,
    1901             :         __isl_keep isl_basic_set *context, int *row)
    1902             : {
    1903             :         struct isl_constraint_index ci;
    1904             :         int n_ineq;
    1905             :         unsigned total;
    1906             :         int k;
    1907             : 
    1908           0 :         if (!ineq || !context)
    1909           0 :                 return isl_stat_error;
    1910           0 :         if (context->n_ineq == 0)
    1911           0 :                 return isl_stat_ok;
    1912           0 :         if (setup_constraint_index(&ci, context) < 0)
    1913           0 :                 return isl_stat_error;
    1914             : 
    1915           0 :         n_ineq = isl_mat_rows(ineq);
    1916           0 :         total = isl_mat_cols(ineq) - 1;
    1917           0 :         for (k = 0; k < n_ineq; ++k) {
    1918             :                 int l;
    1919             :                 isl_bool redundant;
    1920             : 
    1921           0 :                 l = isl_seq_first_non_zero(ineq->row[k] + 1, total);
    1922           0 :                 if (l < 0 && isl_int_is_nonneg(ineq->row[k][0])) {
    1923           0 :                         row[k] = -1;
    1924           0 :                         continue;
    1925             :                 }
    1926           0 :                 redundant = constraint_index_is_redundant(&ci, ineq->row[k]);
    1927           0 :                 if (redundant < 0)
    1928           0 :                         goto error;
    1929           0 :                 if (!redundant)
    1930           0 :                         continue;
    1931           0 :                 row[k] = -1;
    1932             :         }
    1933           0 :         constraint_index_free(&ci);
    1934           0 :         return isl_stat_ok;
    1935             : error:
    1936           0 :         constraint_index_free(&ci);
    1937           0 :         return isl_stat_error;
    1938             : }
    1939             : 
    1940           0 : static __isl_give isl_basic_set *remove_shifted_constraints(
    1941             :         __isl_take isl_basic_set *bset, __isl_keep isl_basic_set *context)
    1942             : {
    1943             :         struct isl_constraint_index ci;
    1944             :         int k;
    1945             : 
    1946           0 :         if (!bset || !context)
    1947           0 :                 return bset;
    1948             : 
    1949           0 :         if (context->n_ineq == 0)
    1950           0 :                 return bset;
    1951           0 :         if (setup_constraint_index(&ci, context) < 0)
    1952           0 :                 return bset;
    1953             : 
    1954           0 :         for (k = 0; k < bset->n_ineq; ++k) {
    1955             :                 isl_bool redundant;
    1956             : 
    1957           0 :                 redundant = constraint_index_is_redundant(&ci, bset->ineq[k]);
    1958           0 :                 if (redundant < 0)
    1959           0 :                         goto error;
    1960           0 :                 if (!redundant)
    1961           0 :                         continue;
    1962           0 :                 bset = isl_basic_set_cow(bset);
    1963           0 :                 if (!bset)
    1964           0 :                         goto error;
    1965           0 :                 isl_basic_set_drop_inequality(bset, k);
    1966           0 :                 --k;
    1967             :         }
    1968           0 :         constraint_index_free(&ci);
    1969           0 :         return bset;
    1970             : error:
    1971           0 :         constraint_index_free(&ci);
    1972           0 :         return bset;
    1973             : }
    1974             : 
    1975             : /* Remove constraints from "bmap" that are identical to constraints
    1976             :  * in "context" or that are more relaxed (greater constant term).
    1977             :  *
    1978             :  * We perform the test for shifted copies on the pure constraints
    1979             :  * in remove_shifted_constraints.
    1980             :  */
    1981           0 : static __isl_give isl_basic_map *isl_basic_map_remove_shifted_constraints(
    1982             :         __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context)
    1983             : {
    1984             :         isl_basic_set *bset, *bset_context;
    1985             : 
    1986           0 :         if (!bmap || !context)
    1987             :                 goto error;
    1988             : 
    1989           0 :         if (bmap->n_ineq == 0 || context->n_ineq == 0) {
    1990           0 :                 isl_basic_map_free(context);
    1991           0 :                 return bmap;
    1992             :         }
    1993             : 
    1994           0 :         context = isl_basic_map_align_divs(context, bmap);
    1995           0 :         bmap = isl_basic_map_align_divs(bmap, context);
    1996             : 
    1997           0 :         bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
    1998           0 :         bset_context = isl_basic_map_underlying_set(context);
    1999           0 :         bset = remove_shifted_constraints(bset, bset_context);
    2000           0 :         isl_basic_set_free(bset_context);
    2001             : 
    2002           0 :         bmap = isl_basic_map_overlying_set(bset, bmap);
    2003             : 
    2004           0 :         return bmap;
    2005             : error:
    2006           0 :         isl_basic_map_free(bmap);
    2007           0 :         isl_basic_map_free(context);
    2008           0 :         return NULL;
    2009             : }
    2010             : 
    2011             : /* Does the (linear part of a) constraint "c" involve any of the "len"
    2012             :  * "relevant" dimensions?
    2013             :  */
    2014           0 : static int is_related(isl_int *c, int len, int *relevant)
    2015             : {
    2016             :         int i;
    2017             : 
    2018           0 :         for (i = 0; i < len; ++i) {
    2019           0 :                 if (!relevant[i])
    2020           0 :                         continue;
    2021           0 :                 if (!isl_int_is_zero(c[i]))
    2022           0 :                         return 1;
    2023             :         }
    2024             : 
    2025           0 :         return 0;
    2026             : }
    2027             : 
    2028             : /* Drop constraints from "bmap" that do not involve any of
    2029             :  * the dimensions marked "relevant".
    2030             :  */
    2031           0 : static __isl_give isl_basic_map *drop_unrelated_constraints(
    2032             :         __isl_take isl_basic_map *bmap, int *relevant)
    2033             : {
    2034             :         int i, dim;
    2035             : 
    2036           0 :         dim = isl_basic_map_dim(bmap, isl_dim_all);
    2037           0 :         for (i = 0; i < dim; ++i)
    2038           0 :                 if (!relevant[i])
    2039           0 :                         break;
    2040           0 :         if (i >= dim)
    2041           0 :                 return bmap;
    2042             : 
    2043           0 :         for (i = bmap->n_eq - 1; i >= 0; --i)
    2044           0 :                 if (!is_related(bmap->eq[i] + 1, dim, relevant)) {
    2045           0 :                         bmap = isl_basic_map_cow(bmap);
    2046           0 :                         if (isl_basic_map_drop_equality(bmap, i) < 0)
    2047           0 :                                 return isl_basic_map_free(bmap);
    2048             :                 }
    2049             : 
    2050           0 :         for (i = bmap->n_ineq - 1; i >= 0; --i)
    2051           0 :                 if (!is_related(bmap->ineq[i] + 1, dim, relevant)) {
    2052           0 :                         bmap = isl_basic_map_cow(bmap);
    2053           0 :                         if (isl_basic_map_drop_inequality(bmap, i) < 0)
    2054           0 :                                 return isl_basic_map_free(bmap);
    2055             :                 }
    2056             : 
    2057           0 :         return bmap;
    2058             : }
    2059             : 
    2060             : /* Update the groups in "group" based on the (linear part of a) constraint "c".
    2061             :  *
    2062             :  * In particular, for any variable involved in the constraint,
    2063             :  * find the actual group id from before and replace the group
    2064             :  * of the corresponding variable by the minimal group of all
    2065             :  * the variables involved in the constraint considered so far
    2066             :  * (if this minimum is smaller) or replace the minimum by this group
    2067             :  * (if the minimum is larger).
    2068             :  *
    2069             :  * At the end, all the variables in "c" will (indirectly) point
    2070             :  * to the minimal of the groups that they referred to originally.
    2071             :  */
    2072           0 : static void update_groups(int dim, int *group, isl_int *c)
    2073             : {
    2074             :         int j;
    2075           0 :         int min = dim;
    2076             : 
    2077           0 :         for (j = 0; j < dim; ++j) {
    2078           0 :                 if (isl_int_is_zero(c[j]))
    2079           0 :                         continue;
    2080           0 :                 while (group[j] >= 0 && group[group[j]] != group[j])
    2081           0 :                         group[j] = group[group[j]];
    2082           0 :                 if (group[j] == min)
    2083           0 :                         continue;
    2084           0 :                 if (group[j] < min) {
    2085           0 :                         if (min >= 0 && min < dim)
    2086           0 :                                 group[min] = group[j];
    2087           0 :                         min = group[j];
    2088             :                 } else
    2089           0 :                         group[group[j]] = min;
    2090             :         }
    2091           0 : }
    2092             : 
    2093             : /* Allocate an array of groups of variables, one for each variable
    2094             :  * in "context", initialized to zero.
    2095             :  */
    2096           0 : static int *alloc_groups(__isl_keep isl_basic_set *context)
    2097             : {
    2098             :         isl_ctx *ctx;
    2099             :         int dim;
    2100             : 
    2101           0 :         dim = isl_basic_set_dim(context, isl_dim_set);
    2102           0 :         ctx = isl_basic_set_get_ctx(context);
    2103           0 :         return isl_calloc_array(ctx, int, dim);
    2104             : }
    2105             : 
    2106             : /* Drop constraints from "bmap" that only involve variables that are
    2107             :  * not related to any of the variables marked with a "-1" in "group".
    2108             :  *
    2109             :  * We construct groups of variables that collect variables that
    2110             :  * (indirectly) appear in some common constraint of "bmap".
    2111             :  * Each group is identified by the first variable in the group,
    2112             :  * except for the special group of variables that was already identified
    2113             :  * in the input as -1 (or are related to those variables).
    2114             :  * If group[i] is equal to i (or -1), then the group of i is i (or -1),
    2115             :  * otherwise the group of i is the group of group[i].
    2116             :  *
    2117             :  * We first initialize groups for the remaining variables.
    2118             :  * Then we iterate over the constraints of "bmap" and update the
    2119             :  * group of the variables in the constraint by the smallest group.
    2120             :  * Finally, we resolve indirect references to groups by running over
    2121             :  * the variables.
    2122             :  *
    2123             :  * After computing the groups, we drop constraints that do not involve
    2124             :  * any variables in the -1 group.
    2125             :  */
    2126           0 : __isl_give isl_basic_map *isl_basic_map_drop_unrelated_constraints(
    2127             :         __isl_take isl_basic_map *bmap, __isl_take int *group)
    2128             : {
    2129             :         int dim;
    2130             :         int i;
    2131             :         int last;
    2132             : 
    2133           0 :         if (!bmap)
    2134           0 :                 return NULL;
    2135             : 
    2136           0 :         dim = isl_basic_map_dim(bmap, isl_dim_all);
    2137             : 
    2138           0 :         last = -1;
    2139           0 :         for (i = 0; i < dim; ++i)
    2140           0 :                 if (group[i] >= 0)
    2141           0 :                         last = group[i] = i;
    2142           0 :         if (last < 0) {
    2143           0 :                 free(group);
    2144           0 :                 return bmap;
    2145             :         }
    2146             : 
    2147           0 :         for (i = 0; i < bmap->n_eq; ++i)
    2148           0 :                 update_groups(dim, group, bmap->eq[i] + 1);
    2149           0 :         for (i = 0; i < bmap->n_ineq; ++i)
    2150           0 :                 update_groups(dim, group, bmap->ineq[i] + 1);
    2151             : 
    2152           0 :         for (i = 0; i < dim; ++i)
    2153           0 :                 if (group[i] >= 0)
    2154           0 :                         group[i] = group[group[i]];
    2155             : 
    2156           0 :         for (i = 0; i < dim; ++i)
    2157           0 :                 group[i] = group[i] == -1;
    2158             : 
    2159           0 :         bmap = drop_unrelated_constraints(bmap, group);
    2160             : 
    2161           0 :         free(group);
    2162           0 :         return bmap;
    2163             : }
    2164             : 
    2165             : /* Drop constraints from "context" that are irrelevant for computing
    2166             :  * the gist of "bset".
    2167             :  *
    2168             :  * In particular, drop constraints in variables that are not related
    2169             :  * to any of the variables involved in the constraints of "bset"
    2170             :  * in the sense that there is no sequence of constraints that connects them.
    2171             :  *
    2172             :  * We first mark all variables that appear in "bset" as belonging
    2173             :  * to a "-1" group and then continue with group_and_drop_irrelevant_constraints.
    2174             :  */
    2175           0 : static __isl_give isl_basic_set *drop_irrelevant_constraints(
    2176             :         __isl_take isl_basic_set *context, __isl_keep isl_basic_set *bset)
    2177             : {
    2178             :         int *group;
    2179             :         int dim;
    2180             :         int i, j;
    2181             : 
    2182           0 :         if (!context || !bset)
    2183           0 :                 return isl_basic_set_free(context);
    2184             : 
    2185           0 :         group = alloc_groups(context);
    2186             : 
    2187           0 :         if (!group)
    2188           0 :                 return isl_basic_set_free(context);
    2189             : 
    2190           0 :         dim = isl_basic_set_dim(bset, isl_dim_set);
    2191           0 :         for (i = 0; i < dim; ++i) {
    2192           0 :                 for (j = 0; j < bset->n_eq; ++j)
    2193           0 :                         if (!isl_int_is_zero(bset->eq[j][1 + i]))
    2194             :                                 break;
    2195           0 :                 if (j < bset->n_eq) {
    2196           0 :                         group[i] = -1;
    2197           0 :                         continue;
    2198             :                 }
    2199           0 :                 for (j = 0; j < bset->n_ineq; ++j)
    2200           0 :                         if (!isl_int_is_zero(bset->ineq[j][1 + i]))
    2201             :                                 break;
    2202           0 :                 if (j < bset->n_ineq)
    2203           0 :                         group[i] = -1;
    2204             :         }
    2205             : 
    2206           0 :         return isl_basic_map_drop_unrelated_constraints(context, group);
    2207             : }
    2208             : 
    2209             : /* Drop constraints from "context" that are irrelevant for computing
    2210             :  * the gist of the inequalities "ineq".
    2211             :  * Inequalities in "ineq" for which the corresponding element of row
    2212             :  * is set to -1 have already been marked for removal and should be ignored.
    2213             :  *
    2214             :  * In particular, drop constraints in variables that are not related
    2215             :  * to any of the variables involved in "ineq"
    2216             :  * in the sense that there is no sequence of constraints that connects them.
    2217             :  *
    2218             :  * We first mark all variables that appear in "bset" as belonging
    2219             :  * to a "-1" group and then continue with group_and_drop_irrelevant_constraints.
    2220             :  */
    2221           0 : static __isl_give isl_basic_set *drop_irrelevant_constraints_marked(
    2222             :         __isl_take isl_basic_set *context, __isl_keep isl_mat *ineq, int *row)
    2223             : {
    2224             :         int *group;
    2225             :         int dim;
    2226             :         int i, j, n;
    2227             : 
    2228           0 :         if (!context || !ineq)
    2229           0 :                 return isl_basic_set_free(context);
    2230             : 
    2231           0 :         group = alloc_groups(context);
    2232             : 
    2233           0 :         if (!group)
    2234           0 :                 return isl_basic_set_free(context);
    2235             : 
    2236           0 :         dim = isl_basic_set_dim(context, isl_dim_set);
    2237           0 :         n = isl_mat_rows(ineq);
    2238           0 :         for (i = 0; i < dim; ++i) {
    2239           0 :                 for (j = 0; j < n; ++j) {
    2240           0 :                         if (row[j] < 0)
    2241           0 :                                 continue;
    2242           0 :                         if (!isl_int_is_zero(ineq->row[j][1 + i]))
    2243             :                                 break;
    2244             :                 }
    2245           0 :                 if (j < n)
    2246           0 :                         group[i] = -1;
    2247             :         }
    2248             : 
    2249           0 :         return isl_basic_map_drop_unrelated_constraints(context, group);
    2250             : }
    2251             : 
    2252             : /* Do all "n" entries of "row" contain a negative value?
    2253             :  */
    2254           0 : static int all_neg(int *row, int n)
    2255             : {
    2256             :         int i;
    2257             : 
    2258           0 :         for (i = 0; i < n; ++i)
    2259           0 :                 if (row[i] >= 0)
    2260           0 :                         return 0;
    2261             : 
    2262           0 :         return 1;
    2263             : }
    2264             : 
    2265             : /* Update the inequalities in "bset" based on the information in "row"
    2266             :  * and "tab".
    2267             :  *
    2268             :  * In particular, the array "row" contains either -1, meaning that
    2269             :  * the corresponding inequality of "bset" is redundant, or the index
    2270             :  * of an inequality in "tab".
    2271             :  *
    2272             :  * If the row entry is -1, then drop the inequality.
    2273             :  * Otherwise, if the constraint is marked redundant in the tableau,
    2274             :  * then drop the inequality.  Similarly, if it is marked as an equality
    2275             :  * in the tableau, then turn the inequality into an equality and
    2276             :  * perform Gaussian elimination.
    2277             :  */
    2278           0 : static __isl_give isl_basic_set *update_ineq(__isl_take isl_basic_set *bset,
    2279             :         __isl_keep int *row, struct isl_tab *tab)
    2280             : {
    2281             :         int i;
    2282             :         unsigned n_ineq;
    2283             :         unsigned n_eq;
    2284           0 :         int found_equality = 0;
    2285             : 
    2286           0 :         if (!bset)
    2287           0 :                 return NULL;
    2288           0 :         if (tab && tab->empty)
    2289           0 :                 return isl_basic_set_set_to_empty(bset);
    2290             : 
    2291           0 :         n_ineq = bset->n_ineq;
    2292           0 :         for (i = n_ineq - 1; i >= 0; --i) {
    2293           0 :                 if (row[i] < 0) {
    2294           0 :                         if (isl_basic_set_drop_inequality(bset, i) < 0)
    2295           0 :                                 return isl_basic_set_free(bset);
    2296           0 :                         continue;
    2297             :                 }
    2298           0 :                 if (!tab)
    2299           0 :                         continue;
    2300           0 :                 n_eq = tab->n_eq;
    2301           0 :                 if (isl_tab_is_equality(tab, n_eq + row[i])) {
    2302           0 :                         isl_basic_map_inequality_to_equality(bset, i);
    2303           0 :                         found_equality = 1;
    2304           0 :                 } else if (isl_tab_is_redundant(tab, n_eq + row[i])) {
    2305           0 :                         if (isl_basic_set_drop_inequality(bset, i) < 0)
    2306           0 :                                 return isl_basic_set_free(bset);
    2307             :                 }
    2308             :         }
    2309             : 
    2310           0 :         if (found_equality)
    2311           0 :                 bset = isl_basic_set_gauss(bset, NULL);
    2312           0 :         bset = isl_basic_set_finalize(bset);
    2313           0 :         return bset;
    2314             : }
    2315             : 
    2316             : /* Update the inequalities in "bset" based on the information in "row"
    2317             :  * and "tab" and free all arguments (other than "bset").
    2318             :  */
    2319           0 : static __isl_give isl_basic_set *update_ineq_free(
    2320             :         __isl_take isl_basic_set *bset, __isl_take isl_mat *ineq,
    2321             :         __isl_take isl_basic_set *context, __isl_take int *row,
    2322             :         struct isl_tab *tab)
    2323             : {
    2324           0 :         isl_mat_free(ineq);
    2325           0 :         isl_basic_set_free(context);
    2326             : 
    2327           0 :         bset = update_ineq(bset, row, tab);
    2328             : 
    2329           0 :         free(row);
    2330           0 :         isl_tab_free(tab);
    2331           0 :         return bset;
    2332             : }
    2333             : 
    2334             : /* Remove all information from bset that is redundant in the context
    2335             :  * of context.
    2336             :  * "ineq" contains the (possibly transformed) inequalities of "bset",
    2337             :  * in the same order.
    2338             :  * The (explicit) equalities of "bset" are assumed to have been taken
    2339             :  * into account by the transformation such that only the inequalities
    2340             :  * are relevant.
    2341             :  * "context" is assumed not to be empty.
    2342             :  *
    2343             :  * "row" keeps track of the constraint index of a "bset" inequality in "tab".
    2344             :  * A value of -1 means that the inequality is obviously redundant and may
    2345             :  * not even appear in  "tab".
    2346             :  *
    2347             :  * We first mark the inequalities of "bset"
    2348             :  * that are obviously redundant with respect to some inequality in "context".
    2349             :  * Then we remove those constraints from "context" that have become
    2350             :  * irrelevant for computing the gist of "bset".
    2351             :  * Note that this removal of constraints cannot be replaced by
    2352             :  * a factorization because factors in "bset" may still be connected
    2353             :  * to each other through constraints in "context".
    2354             :  *
    2355             :  * If there are any inequalities left, we construct a tableau for
    2356             :  * the context and then add the inequalities of "bset".
    2357             :  * Before adding these inequalities, we freeze all constraints such that
    2358             :  * they won't be considered redundant in terms of the constraints of "bset".
    2359             :  * Then we detect all redundant constraints (among the
    2360             :  * constraints that weren't frozen), first by checking for redundancy in the
    2361             :  * the tableau and then by checking if replacing a constraint by its negation
    2362             :  * would lead to an empty set.  This last step is fairly expensive
    2363             :  * and could be optimized by more reuse of the tableau.
    2364             :  * Finally, we update bset according to the results.
    2365             :  */
    2366           0 : static __isl_give isl_basic_set *uset_gist_full(__isl_take isl_basic_set *bset,
    2367             :         __isl_take isl_mat *ineq, __isl_take isl_basic_set *context)
    2368             : {
    2369             :         int i, r;
    2370           0 :         int *row = NULL;
    2371             :         isl_ctx *ctx;
    2372           0 :         isl_basic_set *combined = NULL;
    2373           0 :         struct isl_tab *tab = NULL;
    2374             :         unsigned n_eq, context_ineq;
    2375             : 
    2376           0 :         if (!bset || !ineq || !context)
    2377             :                 goto error;
    2378             : 
    2379           0 :         if (bset->n_ineq == 0 || isl_basic_set_plain_is_universe(context)) {
    2380           0 :                 isl_basic_set_free(context);
    2381           0 :                 isl_mat_free(ineq);
    2382           0 :                 return bset;
    2383             :         }
    2384             : 
    2385           0 :         ctx = isl_basic_set_get_ctx(context);
    2386           0 :         row = isl_calloc_array(ctx, int, bset->n_ineq);
    2387           0 :         if (!row)
    2388           0 :                 goto error;
    2389             : 
    2390           0 :         if (mark_shifted_constraints(ineq, context, row) < 0)
    2391           0 :                 goto error;
    2392           0 :         if (all_neg(row, bset->n_ineq))
    2393           0 :                 return update_ineq_free(bset, ineq, context, row, NULL);
    2394             : 
    2395           0 :         context = drop_irrelevant_constraints_marked(context, ineq, row);
    2396           0 :         if (!context)
    2397           0 :                 goto error;
    2398           0 :         if (isl_basic_set_plain_is_universe(context))
    2399           0 :                 return update_ineq_free(bset, ineq, context, row, NULL);
    2400             : 
    2401           0 :         n_eq = context->n_eq;
    2402           0 :         context_ineq = context->n_ineq;
    2403           0 :         combined = isl_basic_set_cow(isl_basic_set_copy(context));
    2404           0 :         combined = isl_basic_set_extend_constraints(combined, 0, bset->n_ineq);
    2405           0 :         tab = isl_tab_from_basic_set(combined, 0);
    2406           0 :         for (i = 0; i < context_ineq; ++i)
    2407           0 :                 if (isl_tab_freeze_constraint(tab, n_eq + i) < 0)
    2408           0 :                         goto error;
    2409           0 :         if (isl_tab_extend_cons(tab, bset->n_ineq) < 0)
    2410           0 :                 goto error;
    2411           0 :         r = context_ineq;
    2412           0 :         for (i = 0; i < bset->n_ineq; ++i) {
    2413           0 :                 if (row[i] < 0)
    2414           0 :                         continue;
    2415           0 :                 combined = isl_basic_set_add_ineq(combined, ineq->row[i]);
    2416           0 :                 if (isl_tab_add_ineq(tab, ineq->row[i]) < 0)
    2417           0 :                         goto error;
    2418           0 :                 row[i] = r++;
    2419             :         }
    2420           0 :         if (isl_tab_detect_implicit_equalities(tab) < 0)
    2421           0 :                 goto error;
    2422           0 :         if (isl_tab_detect_redundant(tab) < 0)
    2423           0 :                 goto error;
    2424           0 :         for (i = bset->n_ineq - 1; i >= 0; --i) {
    2425             :                 isl_basic_set *test;
    2426             :                 int is_empty;
    2427             : 
    2428           0 :                 if (row[i] < 0)
    2429           0 :                         continue;
    2430           0 :                 r = row[i];
    2431           0 :                 if (tab->con[n_eq + r].is_redundant)
    2432           0 :                         continue;
    2433           0 :                 test = isl_basic_set_dup(combined);
    2434           0 :                 if (isl_inequality_negate(test, r) < 0)
    2435           0 :                         test = isl_basic_set_free(test);
    2436           0 :                 test = isl_basic_set_update_from_tab(test, tab);
    2437           0 :                 is_empty = isl_basic_set_is_empty(test);
    2438           0 :                 isl_basic_set_free(test);
    2439           0 :                 if (is_empty < 0)
    2440           0 :                         goto error;
    2441           0 :                 if (is_empty)
    2442           0 :                         tab->con[n_eq + r].is_redundant = 1;
    2443             :         }
    2444           0 :         bset = update_ineq_free(bset, ineq, context, row, tab);
    2445           0 :         if (bset) {
    2446           0 :                 ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT);
    2447           0 :                 ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT);
    2448             :         }
    2449             : 
    2450           0 :         isl_basic_set_free(combined);
    2451           0 :         return bset;
    2452             : error:
    2453           0 :         free(row);
    2454           0 :         isl_mat_free(ineq);
    2455           0 :         isl_tab_free(tab);
    2456           0 :         isl_basic_set_free(combined);
    2457           0 :         isl_basic_set_free(context);
    2458           0 :         isl_basic_set_free(bset);
    2459           0 :         return NULL;
    2460             : }
    2461             : 
    2462             : /* Extract the inequalities of "bset" as an isl_mat.
    2463             :  */
    2464           0 : static __isl_give isl_mat *extract_ineq(__isl_keep isl_basic_set *bset)
    2465             : {
    2466             :         unsigned total;
    2467             :         isl_ctx *ctx;
    2468             :         isl_mat *ineq;
    2469             : 
    2470           0 :         if (!bset)
    2471           0 :                 return NULL;
    2472             : 
    2473           0 :         ctx = isl_basic_set_get_ctx(bset);
    2474           0 :         total = isl_basic_set_total_dim(bset);
    2475           0 :         ineq = isl_mat_sub_alloc6(ctx, bset->ineq, 0, bset->n_ineq,
    2476             :                                     0, 1 + total);
    2477             : 
    2478           0 :         return ineq;
    2479             : }
    2480             : 
    2481             : /* Remove all information from "bset" that is redundant in the context
    2482             :  * of "context", for the case where both "bset" and "context" are
    2483             :  * full-dimensional.
    2484             :  */
    2485           0 : static __isl_give isl_basic_set *uset_gist_uncompressed(
    2486             :         __isl_take isl_basic_set *bset, __isl_take isl_basic_set *context)
    2487             : {
    2488             :         isl_mat *ineq;
    2489             : 
    2490           0 :         ineq = extract_ineq(bset);
    2491           0 :         return uset_gist_full(bset, ineq, context);
    2492             : }
    2493             : 
    2494             : /* Remove all information from "bset" that is redundant in the context
    2495             :  * of "context", for the case where the combined equalities of
    2496             :  * "bset" and "context" allow for a compression that can be obtained
    2497             :  * by preapplication of "T".
    2498             :  *
    2499             :  * "bset" itself is not transformed by "T".  Instead, the inequalities
    2500             :  * are extracted from "bset" and those are transformed by "T".
    2501             :  * uset_gist_full then determines which of the transformed inequalities
    2502             :  * are redundant with respect to the transformed "context" and removes
    2503             :  * the corresponding inequalities from "bset".
    2504             :  *
    2505             :  * After preapplying "T" to the inequalities, any common factor is
    2506             :  * removed from the coefficients.  If this results in a tightening
    2507             :  * of the constant term, then the same tightening is applied to
    2508             :  * the corresponding untransformed inequality in "bset".
    2509             :  * That is, if after plugging in T, a constraint f(x) >= 0 is of the form
    2510             :  *
    2511             :  *      g f'(x) + r >= 0
    2512             :  *
    2513             :  * with 0 <= r < g, then it is equivalent to
    2514             :  *
    2515             :  *      f'(x) >= 0
    2516             :  *
    2517             :  * This means that f(x) >= 0 is equivalent to f(x) - r >= 0 in the affine
    2518             :  * subspace compressed by T since the latter would be transformed to
    2519             :  *
    2520             :  *      g f'(x) >= 0
    2521             :  */
    2522           0 : static __isl_give isl_basic_set *uset_gist_compressed(
    2523             :         __isl_take isl_basic_set *bset, __isl_take isl_basic_set *context,
    2524             :         __isl_take isl_mat *T)
    2525             : {
    2526             :         isl_ctx *ctx;
    2527             :         isl_mat *ineq;
    2528             :         int i, n_row, n_col;
    2529             :         isl_int rem;
    2530             : 
    2531           0 :         ineq = extract_ineq(bset);
    2532           0 :         ineq = isl_mat_product(ineq, isl_mat_copy(T));
    2533           0 :         context = isl_basic_set_preimage(context, T);
    2534             : 
    2535           0 :         if (!ineq || !context)
    2536             :                 goto error;
    2537           0 :         if (isl_basic_set_plain_is_empty(context)) {
    2538           0 :                 isl_mat_free(ineq);
    2539           0 :                 isl_basic_set_free(context);
    2540           0 :                 return isl_basic_set_set_to_empty(bset);
    2541             :         }
    2542             : 
    2543           0 :         ctx = isl_mat_get_ctx(ineq);
    2544           0 :         n_row = isl_mat_rows(ineq);
    2545           0 :         n_col = isl_mat_cols(ineq);
    2546           0 :         isl_int_init(rem);
    2547           0 :         for (i = 0; i < n_row; ++i) {
    2548           0 :                 isl_seq_gcd(ineq->row[i] + 1, n_col - 1, &ctx->normalize_gcd);
    2549           0 :                 if (isl_int_is_zero(ctx->normalize_gcd))
    2550           0 :                         continue;
    2551           0 :                 if (isl_int_is_one(ctx->normalize_gcd))
    2552           0 :                         continue;
    2553           0 :                 isl_seq_scale_down(ineq->row[i] + 1, ineq->row[i] + 1,
    2554           0 :                                     ctx->normalize_gcd, n_col - 1);
    2555           0 :                 isl_int_fdiv_r(rem, ineq->row[i][0], ctx->normalize_gcd);
    2556           0 :                 isl_int_fdiv_q(ineq->row[i][0],
    2557             :                                 ineq->row[i][0], ctx->normalize_gcd);
    2558           0 :                 if (isl_int_is_zero(rem))
    2559           0 :                         continue;
    2560           0 :                 bset = isl_basic_set_cow(bset);
    2561           0 :                 if (!bset)
    2562           0 :                         break;
    2563           0 :                 isl_int_sub(bset->ineq[i][0], bset->ineq[i][0], rem);
    2564             :         }
    2565           0 :         isl_int_clear(rem);
    2566             : 
    2567           0 :         return uset_gist_full(bset, ineq, context);
    2568             : error:
    2569           0 :         isl_mat_free(ineq);
    2570           0 :         isl_basic_set_free(context);
    2571           0 :         isl_basic_set_free(bset);
    2572           0 :         return NULL;
    2573             : }
    2574             : 
    2575             : /* Project "bset" onto the variables that are involved in "template".
    2576             :  */
    2577           0 : static __isl_give isl_basic_set *project_onto_involved(
    2578             :         __isl_take isl_basic_set *bset, __isl_keep isl_basic_set *template)
    2579             : {
    2580             :         int i, n;
    2581             : 
    2582           0 :         if (!bset || !template)
    2583           0 :                 return isl_basic_set_free(bset);
    2584             : 
    2585           0 :         n = isl_basic_set_dim(template, isl_dim_set);
    2586             : 
    2587           0 :         for (i = 0; i < n; ++i) {
    2588             :                 isl_bool involved;
    2589             : 
    2590           0 :                 involved = isl_basic_set_involves_dims(template,
    2591             :                                                         isl_dim_set, i, 1);
    2592           0 :                 if (involved < 0)
    2593           0 :                         return isl_basic_set_free(bset);
    2594           0 :                 if (involved)
    2595           0 :                         continue;
    2596           0 :                 bset = isl_basic_set_eliminate_vars(bset, i, 1);
    2597             :         }
    2598             : 
    2599           0 :         return bset;
    2600             : }
    2601             : 
    2602             : /* Remove all information from bset that is redundant in the context
    2603             :  * of context.  In particular, equalities that are linear combinations
    2604             :  * of those in context are removed.  Then the inequalities that are
    2605             :  * redundant in the context of the equalities and inequalities of
    2606             :  * context are removed.
    2607             :  *
    2608             :  * First of all, we drop those constraints from "context"
    2609             :  * that are irrelevant for computing the gist of "bset".
    2610             :  * Alternatively, we could factorize the intersection of "context" and "bset".
    2611             :  *
    2612             :  * We first compute the intersection of the integer affine hulls
    2613             :  * of "bset" and "context",
    2614             :  * compute the gist inside this intersection and then reduce
    2615             :  * the constraints with respect to the equalities of the context
    2616             :  * that only involve variables already involved in the input.
    2617             :  *
    2618             :  * If two constraints are mutually redundant, then uset_gist_full
    2619             :  * will remove the second of those constraints.  We therefore first
    2620             :  * sort the constraints so that constraints not involving existentially
    2621             :  * quantified variables are given precedence over those that do.
    2622             :  * We have to perform this sorting before the variable compression,
    2623             :  * because that may effect the order of the variables.
    2624             :  */
    2625           0 : static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset,
    2626             :         __isl_take isl_basic_set *context)
    2627             : {
    2628             :         isl_mat *eq;
    2629             :         isl_mat *T;
    2630             :         isl_basic_set *aff;
    2631             :         isl_basic_set *aff_context;
    2632             :         unsigned total;
    2633             : 
    2634           0 :         if (!bset || !context)
    2635             :                 goto error;
    2636             : 
    2637           0 :         context = drop_irrelevant_constraints(context, bset);
    2638             : 
    2639           0 :         bset = isl_basic_set_detect_equalities(bset);
    2640           0 :         aff = isl_basic_set_copy(bset);
    2641           0 :         aff = isl_basic_set_plain_affine_hull(aff);
    2642           0 :         context = isl_basic_set_detect_equalities(context);
    2643           0 :         aff_context = isl_basic_set_copy(context);
    2644           0 :         aff_context = isl_basic_set_plain_affine_hull(aff_context);
    2645           0 :         aff = isl_basic_set_intersect(aff, aff_context);
    2646           0 :         if (!aff)
    2647           0 :                 goto error;
    2648           0 :         if (isl_basic_set_plain_is_empty(aff)) {
    2649           0 :                 isl_basic_set_free(bset);
    2650           0 :                 isl_basic_set_free(context);
    2651           0 :                 return aff;
    2652             :         }
    2653           0 :         bset = isl_basic_set_sort_constraints(bset);
    2654           0 :         if (aff->n_eq == 0) {
    2655           0 :                 isl_basic_set_free(aff);
    2656           0 :                 return uset_gist_uncompressed(bset, context);
    2657             :         }
    2658           0 :         total = isl_basic_set_total_dim(bset);
    2659           0 :         eq = isl_mat_sub_alloc6(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total);
    2660           0 :         eq = isl_mat_cow(eq);
    2661           0 :         T = isl_mat_variable_compression(eq, NULL);
    2662           0 :         isl_basic_set_free(aff);
    2663           0 :         if (T && T->n_col == 0) {
    2664           0 :                 isl_mat_free(T);
    2665           0 :                 isl_basic_set_free(context);
    2666           0 :                 return isl_basic_set_set_to_empty(bset);
    2667             :         }
    2668             : 
    2669           0 :         aff_context = isl_basic_set_affine_hull(isl_basic_set_copy(context));
    2670           0 :         aff_context = project_onto_involved(aff_context, bset);
    2671             : 
    2672           0 :         bset = uset_gist_compressed(bset, context, T);
    2673           0 :         bset = isl_basic_set_reduce_using_equalities(bset, aff_context);
    2674             : 
    2675           0 :         if (bset) {
    2676           0 :                 ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT);
    2677           0 :                 ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT);
    2678             :         }
    2679             : 
    2680           0 :         return bset;
    2681             : error:
    2682           0 :         isl_basic_set_free(bset);
    2683           0 :         isl_basic_set_free(context);
    2684           0 :         return NULL;
    2685             : }
    2686             : 
    2687             : /* Return the number of equality constraints in "bmap" that involve
    2688             :  * local variables.  This function assumes that Gaussian elimination
    2689             :  * has been applied to the equality constraints.
    2690             :  */
    2691           0 : static int n_div_eq(__isl_keep isl_basic_map *bmap)
    2692             : {
    2693             :         int i;
    2694             :         int total, n_div;
    2695             : 
    2696           0 :         if (!bmap)
    2697           0 :                 return -1;
    2698             : 
    2699           0 :         if (bmap->n_eq == 0)
    2700           0 :                 return 0;
    2701             : 
    2702           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    2703           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    2704           0 :         total -= n_div;
    2705             : 
    2706           0 :         for (i = 0; i < bmap->n_eq; ++i)
    2707           0 :                 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total,
    2708             :                                             n_div) == -1)
    2709           0 :                         return i;
    2710             : 
    2711           0 :         return bmap->n_eq;
    2712             : }
    2713             : 
    2714             : /* Construct a basic map in "space" defined by the equality constraints in "eq".
    2715             :  * The constraints are assumed not to involve any local variables.
    2716             :  */
    2717           0 : static __isl_give isl_basic_map *basic_map_from_equalities(
    2718             :         __isl_take isl_space *space, __isl_take isl_mat *eq)
    2719             : {
    2720             :         int i, k;
    2721           0 :         isl_basic_map *bmap = NULL;
    2722             : 
    2723           0 :         if (!space || !eq)
    2724             :                 goto error;
    2725             : 
    2726           0 :         if (1 + isl_space_dim(space, isl_dim_all) != eq->n_col)
    2727           0 :                 isl_die(isl_space_get_ctx(space), isl_error_internal,
    2728             :                         "unexpected number of columns", goto error);
    2729             : 
    2730           0 :         bmap = isl_basic_map_alloc_space(isl_space_copy(space),
    2731             :                                             0, eq->n_row, 0);
    2732           0 :         for (i = 0; i < eq->n_row; ++i) {
    2733           0 :                 k = isl_basic_map_alloc_equality(bmap);
    2734           0 :                 if (k < 0)
    2735           0 :                         goto error;
    2736           0 :                 isl_seq_cpy(bmap->eq[k], eq->row[i], eq->n_col);
    2737             :         }
    2738             : 
    2739           0 :         isl_space_free(space);
    2740           0 :         isl_mat_free(eq);
    2741           0 :         return bmap;
    2742             : error:
    2743           0 :         isl_space_free(space);
    2744           0 :         isl_mat_free(eq);
    2745           0 :         isl_basic_map_free(bmap);
    2746           0 :         return NULL;
    2747             : }
    2748             : 
    2749             : /* Construct and return a variable compression based on the equality
    2750             :  * constraints in "bmap1" and "bmap2" that do not involve the local variables.
    2751             :  * "n1" is the number of (initial) equality constraints in "bmap1"
    2752             :  * that do involve local variables.
    2753             :  * "n2" is the number of (initial) equality constraints in "bmap2"
    2754             :  * that do involve local variables.
    2755             :  * "total" is the total number of other variables.
    2756             :  * This function assumes that Gaussian elimination
    2757             :  * has been applied to the equality constraints in both "bmap1" and "bmap2"
    2758             :  * such that the equality constraints not involving local variables
    2759             :  * are those that start at "n1" or "n2".
    2760             :  *
    2761             :  * If either of "bmap1" and "bmap2" does not have such equality constraints,
    2762             :  * then simply compute the compression based on the equality constraints
    2763             :  * in the other basic map.
    2764             :  * Otherwise, combine the equality constraints from both into a new
    2765             :  * basic map such that Gaussian elimination can be applied to this combination
    2766             :  * and then construct a variable compression from the resulting
    2767             :  * equality constraints.
    2768             :  */
    2769           0 : static __isl_give isl_mat *combined_variable_compression(
    2770             :         __isl_keep isl_basic_map *bmap1, int n1,
    2771             :         __isl_keep isl_basic_map *bmap2, int n2, int total)
    2772             : {
    2773             :         isl_ctx *ctx;
    2774             :         isl_mat *E1, *E2, *V;
    2775             :         isl_basic_map *bmap;
    2776             : 
    2777           0 :         ctx = isl_basic_map_get_ctx(bmap1);
    2778           0 :         if (bmap1->n_eq == n1) {
    2779           0 :                 E2 = isl_mat_sub_alloc6(ctx, bmap2->eq,
    2780           0 :                                         n2, bmap2->n_eq - n2, 0, 1 + total);
    2781           0 :                 return isl_mat_variable_compression(E2, NULL);
    2782             :         }
    2783           0 :         if (bmap2->n_eq == n2) {
    2784           0 :                 E1 = isl_mat_sub_alloc6(ctx, bmap1->eq,
    2785           0 :                                         n1, bmap1->n_eq - n1, 0, 1 + total);
    2786           0 :                 return isl_mat_variable_compression(E1, NULL);
    2787             :         }
    2788           0 :         E1 = isl_mat_sub_alloc6(ctx, bmap1->eq,
    2789           0 :                                 n1, bmap1->n_eq - n1, 0, 1 + total);
    2790           0 :         E2 = isl_mat_sub_alloc6(ctx, bmap2->eq,
    2791           0 :                                 n2, bmap2->n_eq - n2, 0, 1 + total);
    2792           0 :         E1 = isl_mat_concat(E1, E2);
    2793           0 :         bmap = basic_map_from_equalities(isl_basic_map_get_space(bmap1), E1);
    2794           0 :         bmap = isl_basic_map_gauss(bmap, NULL);
    2795           0 :         if (!bmap)
    2796           0 :                 return NULL;
    2797           0 :         E1 = isl_mat_sub_alloc6(ctx, bmap->eq, 0, bmap->n_eq, 0, 1 + total);
    2798           0 :         V = isl_mat_variable_compression(E1, NULL);
    2799           0 :         isl_basic_map_free(bmap);
    2800             : 
    2801           0 :         return V;
    2802             : }
    2803             : 
    2804             : /* Extract the stride constraints from "bmap", compressed
    2805             :  * with respect to both the stride constraints in "context" and
    2806             :  * the remaining equality constraints in both "bmap" and "context".
    2807             :  * "bmap_n_eq" is the number of (initial) stride constraints in "bmap".
    2808             :  * "context_n_eq" is the number of (initial) stride constraints in "context".
    2809             :  *
    2810             :  * Let x be all variables in "bmap" (and "context") other than the local
    2811             :  * variables.  First compute a variable compression
    2812             :  *
    2813             :  *      x = V x'
    2814             :  *
    2815             :  * based on the non-stride equality constraints in "bmap" and "context".
    2816             :  * Consider the stride constraints of "context",
    2817             :  *
    2818             :  *      A(x) + B(y) = 0
    2819             :  *
    2820             :  * with y the local variables and plug in the variable compression,
    2821             :  * resulting in
    2822             :  *
    2823             :  *      A(V x') + B(y) = 0
    2824             :  *
    2825             :  * Use these constraints to compute a parameter compression on x'
    2826             :  *
    2827             :  *      x' = T x''
    2828             :  *
    2829             :  * Now consider the stride constraints of "bmap"
    2830             :  *
    2831             :  *      C(x) + D(y) = 0
    2832             :  *
    2833             :  * and plug in x = V*T x''.
    2834             :  * That is, return A = [C*V*T D].
    2835             :  */
    2836           0 : static __isl_give isl_mat *extract_compressed_stride_constraints(
    2837             :         __isl_keep isl_basic_map *bmap, int bmap_n_eq,
    2838             :         __isl_keep isl_basic_map *context, int context_n_eq)
    2839             : {
    2840             :         int total, n_div;
    2841             :         isl_ctx *ctx;
    2842             :         isl_mat *A, *B, *T, *V;
    2843             : 
    2844           0 :         total = isl_basic_map_dim(context, isl_dim_all);
    2845           0 :         n_div = isl_basic_map_dim(context, isl_dim_div);
    2846           0 :         total -= n_div;
    2847             : 
    2848           0 :         ctx = isl_basic_map_get_ctx(bmap);
    2849             : 
    2850           0 :         V = combined_variable_compression(bmap, bmap_n_eq,
    2851             :                                                 context, context_n_eq, total);
    2852             : 
    2853           0 :         A = isl_mat_sub_alloc6(ctx, context->eq, 0, context_n_eq, 0, 1 + total);
    2854           0 :         B = isl_mat_sub_alloc6(ctx, context->eq,
    2855           0 :                                 0, context_n_eq, 1 + total, n_div);
    2856           0 :         A = isl_mat_product(A, isl_mat_copy(V));
    2857           0 :         T = isl_mat_parameter_compression_ext(A, B);
    2858           0 :         T = isl_mat_product(V, T);
    2859             : 
    2860           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    2861           0 :         T = isl_mat_diagonal(T, isl_mat_identity(ctx, n_div));
    2862             : 
    2863           0 :         A = isl_mat_sub_alloc6(ctx, bmap->eq,
    2864           0 :                                 0, bmap_n_eq, 0, 1 + total + n_div);
    2865           0 :         A = isl_mat_product(A, T);
    2866             : 
    2867           0 :         return A;
    2868             : }
    2869             : 
    2870             : /* Remove the prime factors from *g that have an exponent that
    2871             :  * is strictly smaller than the exponent in "c".
    2872             :  * All exponents in *g are known to be smaller than or equal
    2873             :  * to those in "c".
    2874             :  *
    2875             :  * That is, if *g is equal to
    2876             :  *
    2877             :  *      p_1^{e_1} p_2^{e_2} ... p_n^{e_n}
    2878             :  *
    2879             :  * and "c" is equal to
    2880             :  *
    2881             :  *      p_1^{f_1} p_2^{f_2} ... p_n^{f_n}
    2882             :  *
    2883             :  * then update *g to
    2884             :  *
    2885             :  *      p_1^{e_1 * (e_1 = f_1)} p_2^{e_2 * (e_2 = f_2)} ...
    2886             :  *              p_n^{e_n * (e_n = f_n)}
    2887             :  *
    2888             :  * If e_i = f_i, then c / *g does not have any p_i factors and therefore
    2889             :  * neither does the gcd of *g and c / *g.
    2890             :  * If e_i < f_i, then the gcd of *g and c / *g has a positive
    2891             :  * power min(e_i, s_i) of p_i with s_i = f_i - e_i among its factors.
    2892             :  * Dividing *g by this gcd therefore strictly reduces the exponent
    2893             :  * of the prime factors that need to be removed, while leaving the
    2894             :  * other prime factors untouched.
    2895             :  * Repeating this process until gcd(*g, c / *g) = 1 therefore
    2896             :  * removes all undesired factors, without removing any others.
    2897             :  */
    2898           0 : static void remove_incomplete_powers(isl_int *g, isl_int c)
    2899             : {
    2900             :         isl_int t;
    2901             : 
    2902           0 :         isl_int_init(t);
    2903             :         for (;;) {
    2904           0 :                 isl_int_divexact(t, c, *g);
    2905           0 :                 isl_int_gcd(t, t, *g);
    2906           0 :                 if (isl_int_is_one(t))
    2907           0 :                         break;
    2908           0 :                 isl_int_divexact(*g, *g, t);
    2909           0 :         }
    2910           0 :         isl_int_clear(t);
    2911           0 : }
    2912             : 
    2913             : /* Reduce the "n" stride constraints in "bmap" based on a copy "A"
    2914             :  * of the same stride constraints in a compressed space that exploits
    2915             :  * all equalities in the context and the other equalities in "bmap".
    2916             :  *
    2917             :  * If the stride constraints of "bmap" are of the form
    2918             :  *
    2919             :  *      C(x) + D(y) = 0
    2920             :  *
    2921             :  * then A is of the form
    2922             :  *
    2923             :  *      B(x') + D(y) = 0
    2924             :  *
    2925             :  * If any of these constraints involves only a single local variable y,
    2926             :  * then the constraint appears as
    2927             :  *
    2928             :  *      f(x) + m y_i = 0
    2929             :  *
    2930             :  * in "bmap" and as
    2931             :  *
    2932             :  *      h(x') + m y_i = 0
    2933             :  *
    2934             :  * in "A".
    2935             :  *
    2936             :  * Let g be the gcd of m and the coefficients of h.
    2937             :  * Then, in particular, g is a divisor of the coefficients of h and
    2938             :  *
    2939             :  *      f(x) = h(x')
    2940             :  *
    2941             :  * is known to be a multiple of g.
    2942             :  * If some prime factor in m appears with the same exponent in g,
    2943             :  * then it can be removed from m because f(x) is already known
    2944             :  * to be a multiple of g and therefore in particular of this power
    2945             :  * of the prime factors.
    2946             :  * Prime factors that appear with a smaller exponent in g cannot
    2947             :  * be removed from m.
    2948             :  * Let g' be the divisor of g containing all prime factors that
    2949             :  * appear with the same exponent in m and g, then
    2950             :  *
    2951             :  *      f(x) + m y_i = 0
    2952             :  *
    2953             :  * can be replaced by
    2954             :  *
    2955             :  *      f(x) + m/g' y_i' = 0
    2956             :  *
    2957             :  * Note that (if g' != 1) this changes the explicit representation
    2958             :  * of y_i to that of y_i', so the integer division at position i
    2959             :  * is marked unknown and later recomputed by a call to
    2960             :  * isl_basic_map_gauss.
    2961             :  */
    2962           0 : static __isl_give isl_basic_map *reduce_stride_constraints(
    2963             :         __isl_take isl_basic_map *bmap, int n, __isl_keep isl_mat *A)
    2964             : {
    2965             :         int i;
    2966             :         int total, n_div;
    2967           0 :         int any = 0;
    2968             :         isl_int gcd;
    2969             : 
    2970           0 :         if (!bmap || !A)
    2971           0 :                 return isl_basic_map_free(bmap);
    2972             : 
    2973           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    2974           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    2975           0 :         total -= n_div;
    2976             : 
    2977           0 :         isl_int_init(gcd);
    2978           0 :         for (i = 0; i < n; ++i) {
    2979             :                 int div;
    2980             : 
    2981           0 :                 div = isl_seq_first_non_zero(bmap->eq[i] + 1 + total, n_div);
    2982           0 :                 if (div < 0)
    2983           0 :                         isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
    2984             :                                 "equality constraints modified unexpectedly",
    2985             :                                 goto error);
    2986           0 :                 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total + div + 1,
    2987           0 :                                                 n_div - div - 1) != -1)
    2988           0 :                         continue;
    2989           0 :                 if (isl_mat_row_gcd(A, i, &gcd) < 0)
    2990           0 :                         goto error;
    2991           0 :                 if (isl_int_is_one(gcd))
    2992           0 :                         continue;
    2993           0 :                 remove_incomplete_powers(&gcd, bmap->eq[i][1 + total + div]);
    2994           0 :                 if (isl_int_is_one(gcd))
    2995           0 :                         continue;
    2996           0 :                 isl_int_divexact(bmap->eq[i][1 + total + div],
    2997             :                                 bmap->eq[i][1 + total + div], gcd);
    2998           0 :                 bmap = isl_basic_map_mark_div_unknown(bmap, div);
    2999           0 :                 if (!bmap)
    3000           0 :                         goto error;
    3001           0 :                 any = 1;
    3002             :         }
    3003           0 :         isl_int_clear(gcd);
    3004             : 
    3005           0 :         if (any)
    3006           0 :                 bmap = isl_basic_map_gauss(bmap, NULL);
    3007             : 
    3008           0 :         return bmap;
    3009             : error:
    3010           0 :         isl_int_clear(gcd);
    3011           0 :         isl_basic_map_free(bmap);
    3012           0 :         return NULL;
    3013             : }
    3014             : 
    3015             : /* Simplify the stride constraints in "bmap" based on
    3016             :  * the remaining equality constraints in "bmap" and all equality
    3017             :  * constraints in "context".
    3018             :  * Only do this if both "bmap" and "context" have stride constraints.
    3019             :  *
    3020             :  * First extract a copy of the stride constraints in "bmap" in a compressed
    3021             :  * space exploiting all the other equality constraints and then
    3022             :  * use this compressed copy to simplify the original stride constraints.
    3023             :  */
    3024           0 : static __isl_give isl_basic_map *gist_strides(__isl_take isl_basic_map *bmap,
    3025             :         __isl_keep isl_basic_map *context)
    3026             : {
    3027             :         int bmap_n_eq, context_n_eq;
    3028             :         isl_mat *A;
    3029             : 
    3030           0 :         if (!bmap || !context)
    3031           0 :                 return isl_basic_map_free(bmap);
    3032             : 
    3033           0 :         bmap_n_eq = n_div_eq(bmap);
    3034           0 :         context_n_eq = n_div_eq(context);
    3035             : 
    3036           0 :         if (bmap_n_eq < 0 || context_n_eq < 0)
    3037           0 :                 return isl_basic_map_free(bmap);
    3038           0 :         if (bmap_n_eq == 0 || context_n_eq == 0)
    3039           0 :                 return bmap;
    3040             : 
    3041           0 :         A = extract_compressed_stride_constraints(bmap, bmap_n_eq,
    3042             :                                                     context, context_n_eq);
    3043           0 :         bmap = reduce_stride_constraints(bmap, bmap_n_eq, A);
    3044             : 
    3045           0 :         isl_mat_free(A);
    3046             : 
    3047           0 :         return bmap;
    3048             : }
    3049             : 
    3050             : /* Return a basic map that has the same intersection with "context" as "bmap"
    3051             :  * and that is as "simple" as possible.
    3052             :  *
    3053             :  * The core computation is performed on the pure constraints.
    3054             :  * When we add back the meaning of the integer divisions, we need
    3055             :  * to (re)introduce the div constraints.  If we happen to have
    3056             :  * discovered that some of these integer divisions are equal to
    3057             :  * some affine combination of other variables, then these div
    3058             :  * constraints may end up getting simplified in terms of the equalities,
    3059             :  * resulting in extra inequalities on the other variables that
    3060             :  * may have been removed already or that may not even have been
    3061             :  * part of the input.  We try and remove those constraints of
    3062             :  * this form that are most obviously redundant with respect to
    3063             :  * the context.  We also remove those div constraints that are
    3064             :  * redundant with respect to the other constraints in the result.
    3065             :  *
    3066             :  * The stride constraints among the equality constraints in "bmap" are
    3067             :  * also simplified with respecting to the other equality constraints
    3068             :  * in "bmap" and with respect to all equality constraints in "context".
    3069             :  */
    3070           0 : __isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap,
    3071             :         __isl_take isl_basic_map *context)
    3072             : {
    3073             :         isl_basic_set *bset, *eq;
    3074             :         isl_basic_map *eq_bmap;
    3075             :         unsigned total, n_div, extra, n_eq, n_ineq;
    3076             : 
    3077           0 :         if (!bmap || !context)
    3078             :                 goto error;
    3079             : 
    3080           0 :         if (isl_basic_map_plain_is_universe(bmap)) {
    3081           0 :                 isl_basic_map_free(context);
    3082           0 :                 return bmap;
    3083             :         }
    3084           0 :         if (isl_basic_map_plain_is_empty(context)) {
    3085           0 :                 isl_space *space = isl_basic_map_get_space(bmap);
    3086           0 :                 isl_basic_map_free(bmap);
    3087           0 :                 isl_basic_map_free(context);
    3088           0 :                 return isl_basic_map_universe(space);
    3089             :         }
    3090           0 :         if (isl_basic_map_plain_is_empty(bmap)) {
    3091           0 :                 isl_basic_map_free(context);
    3092           0 :                 return bmap;
    3093             :         }
    3094             : 
    3095           0 :         bmap = isl_basic_map_remove_redundancies(bmap);
    3096           0 :         context = isl_basic_map_remove_redundancies(context);
    3097           0 :         context = isl_basic_map_align_divs(context, bmap);
    3098           0 :         if (!context)
    3099           0 :                 goto error;
    3100             : 
    3101           0 :         n_div = isl_basic_map_dim(context, isl_dim_div);
    3102           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    3103           0 :         extra = n_div - isl_basic_map_dim(bmap, isl_dim_div);
    3104             : 
    3105           0 :         bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
    3106           0 :         bset = isl_basic_set_add_dims(bset, isl_dim_set, extra);
    3107           0 :         bset = uset_gist(bset,
    3108             :                     isl_basic_map_underlying_set(isl_basic_map_copy(context)));
    3109           0 :         bset = isl_basic_set_project_out(bset, isl_dim_set, total, extra);
    3110             : 
    3111           0 :         if (!bset || bset->n_eq == 0 || n_div == 0 ||
    3112           0 :             isl_basic_set_plain_is_empty(bset)) {
    3113           0 :                 isl_basic_map_free(context);
    3114           0 :                 return isl_basic_map_overlying_set(bset, bmap);
    3115             :         }
    3116             : 
    3117           0 :         n_eq = bset->n_eq;
    3118           0 :         n_ineq = bset->n_ineq;
    3119           0 :         eq = isl_basic_set_copy(bset);
    3120           0 :         eq = isl_basic_set_cow(eq);
    3121           0 :         if (isl_basic_set_free_inequality(eq, n_ineq) < 0)
    3122           0 :                 eq = isl_basic_set_free(eq);
    3123           0 :         if (isl_basic_set_free_equality(bset, n_eq) < 0)
    3124           0 :                 bset = isl_basic_set_free(bset);
    3125             : 
    3126           0 :         eq_bmap = isl_basic_map_overlying_set(eq, isl_basic_map_copy(bmap));
    3127           0 :         eq_bmap = gist_strides(eq_bmap, context);
    3128           0 :         eq_bmap = isl_basic_map_remove_shifted_constraints(eq_bmap, context);
    3129           0 :         bmap = isl_basic_map_overlying_set(bset, bmap);
    3130           0 :         bmap = isl_basic_map_intersect(bmap, eq_bmap);
    3131           0 :         bmap = isl_basic_map_remove_redundancies(bmap);
    3132             : 
    3133           0 :         return bmap;
    3134             : error:
    3135           0 :         isl_basic_map_free(bmap);
    3136           0 :         isl_basic_map_free(context);
    3137           0 :         return NULL;
    3138             : }
    3139             : 
    3140             : /*
    3141             :  * Assumes context has no implicit divs.
    3142             :  */
    3143           0 : __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
    3144             :         __isl_take isl_basic_map *context)
    3145             : {
    3146             :         int i;
    3147             : 
    3148           0 :         if (!map || !context)
    3149             :                 goto error;
    3150             : 
    3151           0 :         if (isl_basic_map_plain_is_empty(context)) {
    3152           0 :                 isl_space *space = isl_map_get_space(map);
    3153           0 :                 isl_map_free(map);
    3154           0 :                 isl_basic_map_free(context);
    3155           0 :                 return isl_map_universe(space);
    3156             :         }
    3157             : 
    3158           0 :         context = isl_basic_map_remove_redundancies(context);
    3159           0 :         map = isl_map_cow(map);
    3160           0 :         if (!map || !context)
    3161             :                 goto error;
    3162           0 :         isl_assert(map->ctx, isl_space_is_equal(map->dim, context->dim), goto error);
    3163           0 :         map = isl_map_compute_divs(map);
    3164           0 :         if (!map)
    3165           0 :                 goto error;
    3166           0 :         for (i = map->n - 1; i >= 0; --i) {
    3167           0 :                 map->p[i] = isl_basic_map_gist(map->p[i],
    3168             :                                                 isl_basic_map_copy(context));
    3169           0 :                 if (!map->p[i])
    3170           0 :                         goto error;
    3171           0 :                 if (isl_basic_map_plain_is_empty(map->p[i])) {
    3172           0 :                         isl_basic_map_free(map->p[i]);
    3173           0 :                         if (i != map->n - 1)
    3174           0 :                                 map->p[i] = map->p[map->n - 1];
    3175           0 :                         map->n--;
    3176             :                 }
    3177             :         }
    3178           0 :         isl_basic_map_free(context);
    3179           0 :         ISL_F_CLR(map, ISL_MAP_NORMALIZED);
    3180           0 :         return map;
    3181             : error:
    3182           0 :         isl_map_free(map);
    3183           0 :         isl_basic_map_free(context);
    3184           0 :         return NULL;
    3185             : }
    3186             : 
    3187             : /* Drop all inequalities from "bmap" that also appear in "context".
    3188             :  * "context" is assumed to have only known local variables and
    3189             :  * the initial local variables of "bmap" are assumed to be the same
    3190             :  * as those of "context".
    3191             :  * The constraints of both "bmap" and "context" are assumed
    3192             :  * to have been sorted using isl_basic_map_sort_constraints.
    3193             :  *
    3194             :  * Run through the inequality constraints of "bmap" and "context"
    3195             :  * in sorted order.
    3196             :  * If a constraint of "bmap" involves variables not in "context",
    3197             :  * then it cannot appear in "context".
    3198             :  * If a matching constraint is found, it is removed from "bmap".
    3199             :  */
    3200           0 : static __isl_give isl_basic_map *drop_inequalities(
    3201             :         __isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context)
    3202             : {
    3203             :         int i1, i2;
    3204             :         unsigned total, extra;
    3205             : 
    3206           0 :         if (!bmap || !context)
    3207           0 :                 return isl_basic_map_free(bmap);
    3208             : 
    3209           0 :         total = isl_basic_map_total_dim(context);
    3210           0 :         extra = isl_basic_map_total_dim(bmap) - total;
    3211             : 
    3212           0 :         i1 = bmap->n_ineq - 1;
    3213           0 :         i2 = context->n_ineq - 1;
    3214           0 :         while (bmap && i1 >= 0 && i2 >= 0) {
    3215             :                 int cmp;
    3216             : 
    3217           0 :                 if (isl_seq_first_non_zero(bmap->ineq[i1] + 1 + total,
    3218             :                                             extra) != -1) {
    3219           0 :                         --i1;
    3220           0 :                         continue;
    3221             :                 }
    3222           0 :                 cmp = isl_basic_map_constraint_cmp(context, bmap->ineq[i1],
    3223           0 :                                                         context->ineq[i2]);
    3224           0 :                 if (cmp < 0) {
    3225           0 :                         --i2;
    3226           0 :                         continue;
    3227             :                 }
    3228           0 :                 if (cmp > 0) {
    3229           0 :                         --i1;
    3230           0 :                         continue;
    3231             :                 }
    3232           0 :                 if (isl_int_eq(bmap->ineq[i1][0], context->ineq[i2][0])) {
    3233           0 :                         bmap = isl_basic_map_cow(bmap);
    3234           0 :                         if (isl_basic_map_drop_inequality(bmap, i1) < 0)
    3235           0 :                                 bmap = isl_basic_map_free(bmap);
    3236             :                 }
    3237           0 :                 --i1;
    3238           0 :                 --i2;
    3239             :         }
    3240             : 
    3241           0 :         return bmap;
    3242             : }
    3243             : 
    3244             : /* Drop all equalities from "bmap" that also appear in "context".
    3245             :  * "context" is assumed to have only known local variables and
    3246             :  * the initial local variables of "bmap" are assumed to be the same
    3247             :  * as those of "context".
    3248             :  *
    3249             :  * Run through the equality constraints of "bmap" and "context"
    3250             :  * in sorted order.
    3251             :  * If a constraint of "bmap" involves variables not in "context",
    3252             :  * then it cannot appear in "context".
    3253             :  * If a matching constraint is found, it is removed from "bmap".
    3254             :  */
    3255           0 : static __isl_give isl_basic_map *drop_equalities(
    3256             :         __isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context)
    3257             : {
    3258             :         int i1, i2;
    3259             :         unsigned total, extra;
    3260             : 
    3261           0 :         if (!bmap || !context)
    3262           0 :                 return isl_basic_map_free(bmap);
    3263             : 
    3264           0 :         total = isl_basic_map_total_dim(context);
    3265           0 :         extra = isl_basic_map_total_dim(bmap) - total;
    3266             : 
    3267           0 :         i1 = bmap->n_eq - 1;
    3268           0 :         i2 = context->n_eq - 1;
    3269             : 
    3270           0 :         while (bmap && i1 >= 0 && i2 >= 0) {
    3271             :                 int last1, last2;
    3272             : 
    3273           0 :                 if (isl_seq_first_non_zero(bmap->eq[i1] + 1 + total,
    3274             :                                             extra) != -1)
    3275           0 :                         break;
    3276           0 :                 last1 = isl_seq_last_non_zero(bmap->eq[i1] + 1, total);
    3277           0 :                 last2 = isl_seq_last_non_zero(context->eq[i2] + 1, total);
    3278           0 :                 if (last1 > last2) {
    3279           0 :                         --i2;
    3280           0 :                         continue;
    3281             :                 }
    3282           0 :                 if (last1 < last2) {
    3283           0 :                         --i1;
    3284           0 :                         continue;
    3285             :                 }
    3286           0 :                 if (isl_seq_eq(bmap->eq[i1], context->eq[i2], 1 + total)) {
    3287           0 :                         bmap = isl_basic_map_cow(bmap);
    3288           0 :                         if (isl_basic_map_drop_equality(bmap, i1) < 0)
    3289           0 :                                 bmap = isl_basic_map_free(bmap);
    3290             :                 }
    3291           0 :                 --i1;
    3292           0 :                 --i2;
    3293             :         }
    3294             : 
    3295           0 :         return bmap;
    3296             : }
    3297             : 
    3298             : /* Remove the constraints in "context" from "bmap".
    3299             :  * "context" is assumed to have explicit representations
    3300             :  * for all local variables.
    3301             :  *
    3302             :  * First align the divs of "bmap" to those of "context" and
    3303             :  * sort the constraints.  Then drop all constraints from "bmap"
    3304             :  * that appear in "context".
    3305             :  */
    3306           0 : __isl_give isl_basic_map *isl_basic_map_plain_gist(
    3307             :         __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context)
    3308             : {
    3309             :         isl_bool done, known;
    3310             : 
    3311           0 :         done = isl_basic_map_plain_is_universe(context);
    3312           0 :         if (done == isl_bool_false)
    3313           0 :                 done = isl_basic_map_plain_is_universe(bmap);
    3314           0 :         if (done == isl_bool_false)
    3315           0 :                 done = isl_basic_map_plain_is_empty(context);
    3316           0 :         if (done == isl_bool_false)
    3317           0 :                 done = isl_basic_map_plain_is_empty(bmap);
    3318           0 :         if (done < 0)
    3319           0 :                 goto error;
    3320           0 :         if (done) {
    3321           0 :                 isl_basic_map_free(context);
    3322           0 :                 return bmap;
    3323             :         }
    3324           0 :         known = isl_basic_map_divs_known(context);
    3325           0 :         if (known < 0)
    3326           0 :                 goto error;
    3327           0 :         if (!known)
    3328           0 :                 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
    3329             :                         "context has unknown divs", goto error);
    3330             : 
    3331           0 :         bmap = isl_basic_map_align_divs(bmap, context);
    3332           0 :         bmap = isl_basic_map_gauss(bmap, NULL);
    3333           0 :         bmap = isl_basic_map_sort_constraints(bmap);
    3334           0 :         context = isl_basic_map_sort_constraints(context);
    3335             : 
    3336           0 :         bmap = drop_inequalities(bmap, context);
    3337           0 :         bmap = drop_equalities(bmap, context);
    3338             : 
    3339           0 :         isl_basic_map_free(context);
    3340           0 :         bmap = isl_basic_map_finalize(bmap);
    3341           0 :         return bmap;
    3342             : error:
    3343           0 :         isl_basic_map_free(bmap);
    3344           0 :         isl_basic_map_free(context);
    3345           0 :         return NULL;
    3346             : }
    3347             : 
    3348             : /* Replace "map" by the disjunct at position "pos" and free "context".
    3349             :  */
    3350           0 : static __isl_give isl_map *replace_by_disjunct(__isl_take isl_map *map,
    3351             :         int pos, __isl_take isl_basic_map *context)
    3352             : {
    3353             :         isl_basic_map *bmap;
    3354             : 
    3355           0 :         bmap = isl_basic_map_copy(map->p[pos]);
    3356           0 :         isl_map_free(map);
    3357           0 :         isl_basic_map_free(context);
    3358           0 :         return isl_map_from_basic_map(bmap);
    3359             : }
    3360             : 
    3361             : /* Remove the constraints in "context" from "map".
    3362             :  * If any of the disjuncts in the result turns out to be the universe,
    3363             :  * then return this universe.
    3364             :  * "context" is assumed to have explicit representations
    3365             :  * for all local variables.
    3366             :  */
    3367           0 : __isl_give isl_map *isl_map_plain_gist_basic_map(__isl_take isl_map *map,
    3368             :         __isl_take isl_basic_map *context)
    3369             : {
    3370             :         int i;
    3371             :         isl_bool univ, known;
    3372             : 
    3373           0 :         univ = isl_basic_map_plain_is_universe(context);
    3374           0 :         if (univ < 0)
    3375           0 :                 goto error;
    3376           0 :         if (univ) {
    3377           0 :                 isl_basic_map_free(context);
    3378           0 :                 return map;
    3379             :         }
    3380           0 :         known = isl_basic_map_divs_known(context);
    3381           0 :         if (known < 0)
    3382           0 :                 goto error;
    3383           0 :         if (!known)
    3384           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
    3385             :                         "context has unknown divs", goto error);
    3386             : 
    3387           0 :         map = isl_map_cow(map);
    3388           0 :         if (!map)
    3389           0 :                 goto error;
    3390           0 :         for (i = 0; i < map->n; ++i) {
    3391           0 :                 map->p[i] = isl_basic_map_plain_gist(map->p[i],
    3392             :                                                 isl_basic_map_copy(context));
    3393           0 :                 univ = isl_basic_map_plain_is_universe(map->p[i]);
    3394           0 :                 if (univ < 0)
    3395           0 :                         goto error;
    3396           0 :                 if (univ && map->n > 1)
    3397           0 :                         return replace_by_disjunct(map, i, context);
    3398             :         }
    3399             : 
    3400           0 :         isl_basic_map_free(context);
    3401           0 :         ISL_F_CLR(map, ISL_MAP_NORMALIZED);
    3402           0 :         if (map->n > 1)
    3403           0 :                 ISL_F_CLR(map, ISL_MAP_DISJOINT);
    3404           0 :         return map;
    3405             : error:
    3406           0 :         isl_map_free(map);
    3407           0 :         isl_basic_map_free(context);
    3408           0 :         return NULL;
    3409             : }
    3410             : 
    3411             : /* Remove the constraints in "context" from "set".
    3412             :  * If any of the disjuncts in the result turns out to be the universe,
    3413             :  * then return this universe.
    3414             :  * "context" is assumed to have explicit representations
    3415             :  * for all local variables.
    3416             :  */
    3417           0 : __isl_give isl_set *isl_set_plain_gist_basic_set(__isl_take isl_set *set,
    3418             :         __isl_take isl_basic_set *context)
    3419             : {
    3420           0 :         return set_from_map(isl_map_plain_gist_basic_map(set_to_map(set),
    3421             :                                                         bset_to_bmap(context)));
    3422             : }
    3423             : 
    3424             : /* Remove the constraints in "context" from "map".
    3425             :  * If any of the disjuncts in the result turns out to be the universe,
    3426             :  * then return this universe.
    3427             :  * "context" is assumed to consist of a single disjunct and
    3428             :  * to have explicit representations for all local variables.
    3429             :  */
    3430           0 : __isl_give isl_map *isl_map_plain_gist(__isl_take isl_map *map,
    3431             :         __isl_take isl_map *context)
    3432             : {
    3433             :         isl_basic_map *hull;
    3434             : 
    3435           0 :         hull = isl_map_unshifted_simple_hull(context);
    3436           0 :         return isl_map_plain_gist_basic_map(map, hull);
    3437             : }
    3438             : 
    3439             : /* Replace "map" by a universe map in the same space and free "drop".
    3440             :  */
    3441           0 : static __isl_give isl_map *replace_by_universe(__isl_take isl_map *map,
    3442             :         __isl_take isl_map *drop)
    3443             : {
    3444             :         isl_map *res;
    3445             : 
    3446           0 :         res = isl_map_universe(isl_map_get_space(map));
    3447           0 :         isl_map_free(map);
    3448           0 :         isl_map_free(drop);
    3449           0 :         return res;
    3450             : }
    3451             : 
    3452             : /* Return a map that has the same intersection with "context" as "map"
    3453             :  * and that is as "simple" as possible.
    3454             :  *
    3455             :  * If "map" is already the universe, then we cannot make it any simpler.
    3456             :  * Similarly, if "context" is the universe, then we cannot exploit it
    3457             :  * to simplify "map"
    3458             :  * If "map" and "context" are identical to each other, then we can
    3459             :  * return the corresponding universe.
    3460             :  *
    3461             :  * If either "map" or "context" consists of multiple disjuncts,
    3462             :  * then check if "context" happens to be a subset of "map",
    3463             :  * in which case all constraints can be removed.
    3464             :  * In case of multiple disjuncts, the standard procedure
    3465             :  * may not be able to detect that all constraints can be removed.
    3466             :  *
    3467             :  * If none of these cases apply, we have to work a bit harder.
    3468             :  * During this computation, we make use of a single disjunct context,
    3469             :  * so if the original context consists of more than one disjunct
    3470             :  * then we need to approximate the context by a single disjunct set.
    3471             :  * Simply taking the simple hull may drop constraints that are
    3472             :  * only implicitly available in each disjunct.  We therefore also
    3473             :  * look for constraints among those defining "map" that are valid
    3474             :  * for the context.  These can then be used to simplify away
    3475             :  * the corresponding constraints in "map".
    3476             :  */
    3477           0 : static __isl_give isl_map *map_gist(__isl_take isl_map *map,
    3478             :         __isl_take isl_map *context)
    3479             : {
    3480             :         int equal;
    3481             :         int is_universe;
    3482             :         int single_disjunct_map, single_disjunct_context;
    3483             :         isl_bool subset;
    3484             :         isl_basic_map *hull;
    3485             : 
    3486           0 :         is_universe = isl_map_plain_is_universe(map);
    3487           0 :         if (is_universe >= 0 && !is_universe)
    3488           0 :                 is_universe = isl_map_plain_is_universe(context);
    3489           0 :         if (is_universe < 0)
    3490           0 :                 goto error;
    3491           0 :         if (is_universe) {
    3492           0 :                 isl_map_free(context);
    3493           0 :                 return map;
    3494             :         }
    3495             : 
    3496           0 :         equal = isl_map_plain_is_equal(map, context);
    3497           0 :         if (equal < 0)
    3498           0 :                 goto error;
    3499           0 :         if (equal)
    3500           0 :                 return replace_by_universe(map, context);
    3501             : 
    3502           0 :         single_disjunct_map = isl_map_n_basic_map(map) == 1;
    3503           0 :         single_disjunct_context = isl_map_n_basic_map(context) == 1;
    3504           0 :         if (!single_disjunct_map || !single_disjunct_context) {
    3505           0 :                 subset = isl_map_is_subset(context, map);
    3506           0 :                 if (subset < 0)
    3507           0 :                         goto error;
    3508           0 :                 if (subset)
    3509           0 :                         return replace_by_universe(map, context);
    3510             :         }
    3511             : 
    3512           0 :         context = isl_map_compute_divs(context);
    3513           0 :         if (!context)
    3514           0 :                 goto error;
    3515           0 :         if (single_disjunct_context) {
    3516           0 :                 hull = isl_map_simple_hull(context);
    3517             :         } else {
    3518             :                 isl_ctx *ctx;
    3519             :                 isl_map_list *list;
    3520             : 
    3521           0 :                 ctx = isl_map_get_ctx(map);
    3522           0 :                 list = isl_map_list_alloc(ctx, 2);
    3523           0 :                 list = isl_map_list_add(list, isl_map_copy(context));
    3524           0 :                 list = isl_map_list_add(list, isl_map_copy(map));
    3525           0 :                 hull = isl_map_unshifted_simple_hull_from_map_list(context,
    3526             :                                                                     list);
    3527             :         }
    3528           0 :         return isl_map_gist_basic_map(map, hull);
    3529             : error:
    3530           0 :         isl_map_free(map);
    3531           0 :         isl_map_free(context);
    3532           0 :         return NULL;
    3533             : }
    3534             : 
    3535           0 : __isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
    3536             :         __isl_take isl_map *context)
    3537             : {
    3538           0 :         return isl_map_align_params_map_map_and(map, context, &map_gist);
    3539             : }
    3540             : 
    3541           0 : struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset,
    3542             :                                                 struct isl_basic_set *context)
    3543             : {
    3544           0 :         return bset_from_bmap(isl_basic_map_gist(bset_to_bmap(bset),
    3545             :                                                 bset_to_bmap(context)));
    3546             : }
    3547             : 
    3548           0 : __isl_give isl_set *isl_set_gist_basic_set(__isl_take isl_set *set,
    3549             :         __isl_take isl_basic_set *context)
    3550             : {
    3551           0 :         return set_from_map(isl_map_gist_basic_map(set_to_map(set),
    3552             :                                         bset_to_bmap(context)));
    3553             : }
    3554             : 
    3555           0 : __isl_give isl_set *isl_set_gist_params_basic_set(__isl_take isl_set *set,
    3556             :         __isl_take isl_basic_set *context)
    3557             : {
    3558           0 :         isl_space *space = isl_set_get_space(set);
    3559           0 :         isl_basic_set *dom_context = isl_basic_set_universe(space);
    3560           0 :         dom_context = isl_basic_set_intersect_params(dom_context, context);
    3561           0 :         return isl_set_gist_basic_set(set, dom_context);
    3562             : }
    3563             : 
    3564           0 : __isl_give isl_set *isl_set_gist(__isl_take isl_set *set,
    3565             :         __isl_take isl_set *context)
    3566             : {
    3567           0 :         return set_from_map(isl_map_gist(set_to_map(set), set_to_map(context)));
    3568             : }
    3569             : 
    3570             : /* Compute the gist of "bmap" with respect to the constraints "context"
    3571             :  * on the domain.
    3572             :  */
    3573           0 : __isl_give isl_basic_map *isl_basic_map_gist_domain(
    3574             :         __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *context)
    3575             : {
    3576           0 :         isl_space *space = isl_basic_map_get_space(bmap);
    3577           0 :         isl_basic_map *bmap_context = isl_basic_map_universe(space);
    3578             : 
    3579           0 :         bmap_context = isl_basic_map_intersect_domain(bmap_context, context);
    3580           0 :         return isl_basic_map_gist(bmap, bmap_context);
    3581             : }
    3582             : 
    3583           0 : __isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map,
    3584             :         __isl_take isl_set *context)
    3585             : {
    3586           0 :         isl_map *map_context = isl_map_universe(isl_map_get_space(map));
    3587           0 :         map_context = isl_map_intersect_domain(map_context, context);
    3588           0 :         return isl_map_gist(map, map_context);
    3589             : }
    3590             : 
    3591           0 : __isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map,
    3592             :         __isl_take isl_set *context)
    3593             : {
    3594           0 :         isl_map *map_context = isl_map_universe(isl_map_get_space(map));
    3595           0 :         map_context = isl_map_intersect_range(map_context, context);
    3596           0 :         return isl_map_gist(map, map_context);
    3597             : }
    3598             : 
    3599           0 : __isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map,
    3600             :         __isl_take isl_set *context)
    3601             : {
    3602           0 :         isl_map *map_context = isl_map_universe(isl_map_get_space(map));
    3603           0 :         map_context = isl_map_intersect_params(map_context, context);
    3604           0 :         return isl_map_gist(map, map_context);
    3605             : }
    3606             : 
    3607           0 : __isl_give isl_set *isl_set_gist_params(__isl_take isl_set *set,
    3608             :         __isl_take isl_set *context)
    3609             : {
    3610           0 :         return isl_map_gist_params(set, context);
    3611             : }
    3612             : 
    3613             : /* Quick check to see if two basic maps are disjoint.
    3614             :  * In particular, we reduce the equalities and inequalities of
    3615             :  * one basic map in the context of the equalities of the other
    3616             :  * basic map and check if we get a contradiction.
    3617             :  */
    3618     7182202 : isl_bool isl_basic_map_plain_is_disjoint(__isl_keep isl_basic_map *bmap1,
    3619             :         __isl_keep isl_basic_map *bmap2)
    3620             : {
    3621     7182202 :         struct isl_vec *v = NULL;
    3622     7182202 :         int *elim = NULL;
    3623             :         unsigned total;
    3624             :         int i;
    3625             : 
    3626     7182202 :         if (!bmap1 || !bmap2)
    3627           0 :                 return isl_bool_error;
    3628     7182202 :         isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
    3629             :                         return isl_bool_error);
    3630     7182202 :         if (bmap1->n_div || bmap2->n_div)
    3631           0 :                 return isl_bool_false;
    3632     7182202 :         if (!bmap1->n_eq && !bmap2->n_eq)
    3633     3502132 :                 return isl_bool_false;
    3634             : 
    3635     3680070 :         total = isl_space_dim(bmap1->dim, isl_dim_all);
    3636     3680070 :         if (total == 0)
    3637           0 :                 return isl_bool_false;
    3638     3680070 :         v = isl_vec_alloc(bmap1->ctx, 1 + total);
    3639     3680070 :         if (!v)
    3640           0 :                 goto error;
    3641     3680070 :         elim = isl_alloc_array(bmap1->ctx, int, total);
    3642     3680070 :         if (!elim)
    3643           0 :                 goto error;
    3644     3680070 :         compute_elimination_index(bmap1, elim);
    3645    12086956 :         for (i = 0; i < bmap2->n_eq; ++i) {
    3646             :                 int reduced;
    3647     8714484 :                 reduced = reduced_using_equalities(v->block.data, bmap2->eq[i],
    3648             :                                                         bmap1, elim);
    3649     9245802 :                 if (reduced && !isl_int_is_zero(v->block.data[0]) &&
    3650      531318 :                     isl_seq_first_non_zero(v->block.data + 1, total) == -1)
    3651      307598 :                         goto disjoint;
    3652             :         }
    3653    32151434 :         for (i = 0; i < bmap2->n_ineq; ++i) {
    3654             :                 int reduced;
    3655    29008702 :                 reduced = reduced_using_equalities(v->block.data,
    3656    29008702 :                                                 bmap2->ineq[i], bmap1, elim);
    3657    30278354 :                 if (reduced && isl_int_is_neg(v->block.data[0]) &&
    3658     1269652 :                     isl_seq_first_non_zero(v->block.data + 1, total) == -1)
    3659      229740 :                         goto disjoint;
    3660             :         }
    3661     3142732 :         compute_elimination_index(bmap2, elim);
    3662    15599315 :         for (i = 0; i < bmap1->n_ineq; ++i) {
    3663             :                 int reduced;
    3664    13988205 :                 reduced = reduced_using_equalities(v->block.data,
    3665    13988205 :                                                 bmap1->ineq[i], bmap2, elim);
    3666    16599944 :                 if (reduced && isl_int_is_neg(v->block.data[0]) &&
    3667     2611739 :                     isl_seq_first_non_zero(v->block.data + 1, total) == -1)
    3668     1531622 :                         goto disjoint;
    3669             :         }
    3670     1611110 :         isl_vec_free(v);
    3671     1611110 :         free(elim);
    3672     1611110 :         return isl_bool_false;
    3673             : disjoint:
    3674     2068960 :         isl_vec_free(v);
    3675     2068960 :         free(elim);
    3676     2068960 :         return isl_bool_true;
    3677             : error:
    3678           0 :         isl_vec_free(v);
    3679           0 :         free(elim);
    3680           0 :         return isl_bool_error;
    3681             : }
    3682             : 
    3683           0 : int isl_basic_set_plain_is_disjoint(__isl_keep isl_basic_set *bset1,
    3684             :         __isl_keep isl_basic_set *bset2)
    3685             : {
    3686           0 :         return isl_basic_map_plain_is_disjoint(bset_to_bmap(bset1),
    3687             :                                               bset_to_bmap(bset2));
    3688             : }
    3689             : 
    3690             : /* Does "test" hold for all pairs of basic maps in "map1" and "map2"?
    3691             :  */
    3692      328482 : static isl_bool all_pairs(__isl_keep isl_map *map1, __isl_keep isl_map *map2,
    3693             :         isl_bool (*test)(__isl_keep isl_basic_map *bmap1,
    3694             :                 __isl_keep isl_basic_map *bmap2))
    3695             : {
    3696             :         int i, j;
    3697             : 
    3698      328482 :         if (!map1 || !map2)
    3699           0 :                 return isl_bool_error;
    3700             : 
    3701     2974126 :         for (i = 0; i < map1->n; ++i) {
    3702     9827846 :                 for (j = 0; j < map2->n; ++j) {
    3703     7182202 :                         isl_bool d = test(map1->p[i], map2->p[j]);
    3704     7182202 :                         if (d != isl_bool_true)
    3705      240268 :                                 return d;
    3706             :                 }
    3707             :         }
    3708             : 
    3709       88214 :         return isl_bool_true;
    3710             : }
    3711             : 
    3712             : /* Are "map1" and "map2" obviously disjoint, based on information
    3713             :  * that can be derived without looking at the individual basic maps?
    3714             :  *
    3715             :  * In particular, if one of them is empty or if they live in different spaces
    3716             :  * (ignoring parameters), then they are clearly disjoint.
    3717             :  */
    3718     3023681 : static isl_bool isl_map_plain_is_disjoint_global(__isl_keep isl_map *map1,
    3719             :         __isl_keep isl_map *map2)
    3720             : {
    3721             :         isl_bool disjoint;
    3722             :         isl_bool match;
    3723             : 
    3724     3023681 :         if (!map1 || !map2)
    3725           0 :                 return isl_bool_error;
    3726             : 
    3727     3023681 :         disjoint = isl_map_plain_is_empty(map1);
    3728     3023681 :         if (disjoint < 0 || disjoint)
    3729       87582 :                 return disjoint;
    3730             : 
    3731     2936099 :         disjoint = isl_map_plain_is_empty(map2);
    3732     2936099 :         if (disjoint < 0 || disjoint)
    3733      656571 :                 return disjoint;
    3734             : 
    3735     2279528 :         match = isl_space_tuple_is_equal(map1->dim, isl_dim_in,
    3736             :                                 map2->dim, isl_dim_in);
    3737     2279528 :         if (match < 0 || !match)
    3738           0 :                 return match < 0 ? isl_bool_error : isl_bool_true;
    3739             : 
    3740     2279528 :         match = isl_space_tuple_is_equal(map1->dim, isl_dim_out,
    3741             :                                 map2->dim, isl_dim_out);
    3742     2279528 :         if (match < 0 || !match)
    3743           0 :                 return match < 0 ? isl_bool_error : isl_bool_true;
    3744             : 
    3745     2279528 :         return isl_bool_false;
    3746             : }
    3747             : 
    3748             : /* Are "map1" and "map2" obviously disjoint?
    3749             :  *
    3750             :  * If one of them is empty or if they live in different spaces (ignoring
    3751             :  * parameters), then they are clearly disjoint.
    3752             :  * This is checked by isl_map_plain_is_disjoint_global.
    3753             :  *
    3754             :  * If they have different parameters, then we skip any further tests.
    3755             :  *
    3756             :  * If they are obviously equal, but not obviously empty, then we will
    3757             :  * not be able to detect if they are disjoint.
    3758             :  *
    3759             :  * Otherwise we check if each basic map in "map1" is obviously disjoint
    3760             :  * from each basic map in "map2".
    3761             :  */
    3762           0 : isl_bool isl_map_plain_is_disjoint(__isl_keep isl_map *map1,
    3763             :         __isl_keep isl_map *map2)
    3764             : {
    3765             :         isl_bool disjoint;
    3766             :         isl_bool intersect;
    3767             :         isl_bool match;
    3768             : 
    3769           0 :         disjoint = isl_map_plain_is_disjoint_global(map1, map2);
    3770           0 :         if (disjoint < 0 || disjoint)
    3771           0 :                 return disjoint;
    3772             : 
    3773           0 :         match = isl_map_has_equal_params(map1, map2);
    3774           0 :         if (match < 0 || !match)
    3775           0 :                 return match < 0 ? isl_bool_error : isl_bool_false;
    3776             : 
    3777           0 :         intersect = isl_map_plain_is_equal(map1, map2);
    3778           0 :         if (intersect < 0 || intersect)
    3779           0 :                 return intersect < 0 ? isl_bool_error : isl_bool_false;
    3780             : 
    3781           0 :         return all_pairs(map1, map2, &isl_basic_map_plain_is_disjoint);
    3782             : }
    3783             : 
    3784             : /* Are "map1" and "map2" disjoint?
    3785             :  * The parameters are assumed to have been aligned.
    3786             :  *
    3787             :  * In particular, check whether all pairs of basic maps are disjoint.
    3788             :  */
    3789      328482 : static isl_bool isl_map_is_disjoint_aligned(__isl_keep isl_map *map1,
    3790             :         __isl_keep isl_map *map2)
    3791             : {
    3792      328482 :         return all_pairs(map1, map2, &isl_basic_map_is_disjoint);
    3793             : }
    3794             : 
    3795             : /* Are "map1" and "map2" disjoint?
    3796             :  *
    3797             :  * They are disjoint if they are "obviously disjoint" or if one of them
    3798             :  * is empty.  Otherwise, they are not disjoint if one of them is universal.
    3799             :  * If the two inputs are (obviously) equal and not empty, then they are
    3800             :  * not disjoint.
    3801             :  * If none of these cases apply, then check if all pairs of basic maps
    3802             :  * are disjoint after aligning the parameters.
    3803             :  */
    3804     3023681 : isl_bool isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
    3805             : {
    3806             :         isl_bool disjoint;
    3807             :         isl_bool intersect;
    3808             : 
    3809     3023681 :         disjoint = isl_map_plain_is_disjoint_global(map1, map2);
    3810     3023681 :         if (disjoint < 0 || disjoint)
    3811      744153 :                 return disjoint;
    3812             : 
    3813     2279528 :         disjoint = isl_map_is_empty(map1);
    3814     2279528 :         if (disjoint < 0 || disjoint)
    3815           0 :                 return disjoint;
    3816             : 
    3817     2279528 :         disjoint = isl_map_is_empty(map2);
    3818     2279528 :         if (disjoint < 0 || disjoint)
    3819           0 :                 return disjoint;
    3820             : 
    3821     2279528 :         intersect = isl_map_plain_is_universe(map1);
    3822     2279528 :         if (intersect < 0 || intersect)
    3823     1917279 :                 return intersect < 0 ? isl_bool_error : isl_bool_false;
    3824             : 
    3825      362249 :         intersect = isl_map_plain_is_universe(map2);
    3826      362249 :         if (intersect < 0 || intersect)
    3827       33767 :                 return intersect < 0 ? isl_bool_error : isl_bool_false;
    3828             : 
    3829      328482 :         intersect = isl_map_plain_is_equal(map1, map2);
    3830      328482 :         if (intersect < 0 || intersect)
    3831           0 :                 return isl_bool_not(intersect);
    3832             : 
    3833      328482 :         return isl_map_align_params_map_map_and_test(map1, map2,
    3834             :                                                 &isl_map_is_disjoint_aligned);
    3835             : }
    3836             : 
    3837             : /* Are "bmap1" and "bmap2" disjoint?
    3838             :  *
    3839             :  * They are disjoint if they are "obviously disjoint" or if one of them
    3840             :  * is empty.  Otherwise, they are not disjoint if one of them is universal.
    3841             :  * If none of these cases apply, we compute the intersection and see if
    3842             :  * the result is empty.
    3843             :  */
    3844     7182202 : isl_bool isl_basic_map_is_disjoint(__isl_keep isl_basic_map *bmap1,
    3845             :         __isl_keep isl_basic_map *bmap2)
    3846             : {
    3847             :         isl_bool disjoint;
    3848             :         isl_bool intersect;
    3849             :         isl_basic_map *test;
    3850             : 
    3851     7182202 :         disjoint = isl_basic_map_plain_is_disjoint(bmap1, bmap2);
    3852     7182202 :         if (disjoint < 0 || disjoint)
    3853     2068960 :                 return disjoint;
    3854             : 
    3855     5113242 :         disjoint = isl_basic_map_is_empty(bmap1);
    3856     5113242 :         if (disjoint < 0 || disjoint)
    3857           0 :                 return disjoint;
    3858             : 
    3859     5113242 :         disjoint = isl_basic_map_is_empty(bmap2);
    3860     5113242 :         if (disjoint < 0 || disjoint)
    3861           0 :                 return disjoint;
    3862             : 
    3863     5113242 :         intersect = isl_basic_map_plain_is_universe(bmap1);
    3864     5113242 :         if (intersect < 0 || intersect)
    3865           0 :                 return intersect < 0 ? isl_bool_error : isl_bool_false;
    3866             : 
    3867     5113242 :         intersect = isl_basic_map_plain_is_universe(bmap2);
    3868     5113242 :         if (intersect < 0 || intersect)
    3869           0 :                 return intersect < 0 ? isl_bool_error : isl_bool_false;
    3870             : 
    3871     5113242 :         test = isl_basic_map_intersect(isl_basic_map_copy(bmap1),
    3872             :                 isl_basic_map_copy(bmap2));
    3873     5113242 :         disjoint = isl_basic_map_is_empty(test);
    3874     5113242 :         isl_basic_map_free(test);
    3875             : 
    3876     5113242 :         return disjoint;
    3877             : }
    3878             : 
    3879             : /* Are "bset1" and "bset2" disjoint?
    3880             :  */
    3881           0 : isl_bool isl_basic_set_is_disjoint(__isl_keep isl_basic_set *bset1,
    3882             :         __isl_keep isl_basic_set *bset2)
    3883             : {
    3884           0 :         return isl_basic_map_is_disjoint(bset1, bset2);
    3885             : }
    3886             : 
    3887           0 : isl_bool isl_set_plain_is_disjoint(__isl_keep isl_set *set1,
    3888             :         __isl_keep isl_set *set2)
    3889             : {
    3890           0 :         return isl_map_plain_is_disjoint(set_to_map(set1), set_to_map(set2));
    3891             : }
    3892             : 
    3893             : /* Are "set1" and "set2" disjoint?
    3894             :  */
    3895           0 : isl_bool isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
    3896             : {
    3897           0 :         return isl_map_is_disjoint(set1, set2);
    3898             : }
    3899             : 
    3900             : /* Is "v" equal to 0, 1 or -1?
    3901             :  */
    3902           0 : static int is_zero_or_one(isl_int v)
    3903             : {
    3904           0 :         return isl_int_is_zero(v) || isl_int_is_one(v) || isl_int_is_negone(v);
    3905             : }
    3906             : 
    3907             : /* Check if we can combine a given div with lower bound l and upper
    3908             :  * bound u with some other div and if so return that other div.
    3909             :  * Otherwise return -1.
    3910             :  *
    3911             :  * We first check that
    3912             :  *      - the bounds are opposites of each other (except for the constant
    3913             :  *        term)
    3914             :  *      - the bounds do not reference any other div
    3915             :  *      - no div is defined in terms of this div
    3916             :  *
    3917             :  * Let m be the size of the range allowed on the div by the bounds.
    3918             :  * That is, the bounds are of the form
    3919             :  *
    3920             :  *      e <= a <= e + m - 1
    3921             :  *
    3922             :  * with e some expression in the other variables.
    3923             :  * We look for another div b such that no third div is defined in terms
    3924             :  * of this second div b and such that in any constraint that contains
    3925             :  * a (except for the given lower and upper bound), also contains b
    3926             :  * with a coefficient that is m times that of b.
    3927             :  * That is, all constraints (except for the lower and upper bound)
    3928             :  * are of the form
    3929             :  *
    3930             :  *      e + f (a + m b) >= 0
    3931             :  *
    3932             :  * Furthermore, in the constraints that only contain b, the coefficient
    3933             :  * of b should be equal to 1 or -1.
    3934             :  * If so, we return b so that "a + m b" can be replaced by
    3935             :  * a single div "c = a + m b".
    3936             :  */
    3937           0 : static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs,
    3938             :         unsigned div, unsigned l, unsigned u)
    3939             : {
    3940             :         int i, j;
    3941             :         unsigned dim;
    3942           0 :         int coalesce = -1;
    3943             : 
    3944           0 :         if (bmap->n_div <= 1)
    3945           0 :                 return -1;
    3946           0 :         dim = isl_space_dim(bmap->dim, isl_dim_all);
    3947           0 :         if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim, div) != -1)
    3948           0 :                 return -1;
    3949           0 :         if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim + div + 1,
    3950           0 :                                    bmap->n_div - div - 1) != -1)
    3951           0 :                 return -1;
    3952           0 :         if (!isl_seq_is_neg(bmap->ineq[l] + 1, bmap->ineq[u] + 1,
    3953           0 :                             dim + bmap->n_div))
    3954           0 :                 return -1;
    3955             : 
    3956           0 :         for (i = 0; i < bmap->n_div; ++i) {
    3957           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
    3958           0 :                         continue;
    3959           0 :                 if (!isl_int_is_zero(bmap->div[i][1 + 1 + dim + div]))
    3960           0 :                         return -1;
    3961             :         }
    3962             : 
    3963           0 :         isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
    3964           0 :         if (isl_int_is_neg(bmap->ineq[l][0])) {
    3965           0 :                 isl_int_sub(bmap->ineq[l][0],
    3966             :                             bmap->ineq[l][0], bmap->ineq[u][0]);
    3967           0 :                 bmap = isl_basic_map_copy(bmap);
    3968           0 :                 bmap = isl_basic_map_set_to_empty(bmap);
    3969           0 :                 isl_basic_map_free(bmap);
    3970           0 :                 return -1;
    3971             :         }
    3972           0 :         isl_int_add_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
    3973           0 :         for (i = 0; i < bmap->n_div; ++i) {
    3974           0 :                 if (i == div)
    3975           0 :                         continue;
    3976           0 :                 if (!pairs[i])
    3977           0 :                         continue;
    3978           0 :                 for (j = 0; j < bmap->n_div; ++j) {
    3979           0 :                         if (isl_int_is_zero(bmap->div[j][0]))
    3980           0 :                                 continue;
    3981           0 :                         if (!isl_int_is_zero(bmap->div[j][1 + 1 + dim + i]))
    3982             :                                 break;
    3983             :                 }
    3984           0 :                 if (j < bmap->n_div)
    3985           0 :                         continue;
    3986           0 :                 for (j = 0; j < bmap->n_ineq; ++j) {
    3987             :                         int valid;
    3988           0 :                         if (j == l || j == u)
    3989           0 :                                 continue;
    3990           0 :                         if (isl_int_is_zero(bmap->ineq[j][1 + dim + div])) {
    3991           0 :                                 if (is_zero_or_one(bmap->ineq[j][1 + dim + i]))
    3992           0 :                                         continue;
    3993           0 :                                 break;
    3994             :                         }
    3995           0 :                         if (isl_int_is_zero(bmap->ineq[j][1 + dim + i]))
    3996           0 :                                 break;
    3997           0 :                         isl_int_mul(bmap->ineq[j][1 + dim + div],
    3998             :                                     bmap->ineq[j][1 + dim + div],
    3999             :                                     bmap->ineq[l][0]);
    4000           0 :                         valid = isl_int_eq(bmap->ineq[j][1 + dim + div],
    4001             :                                            bmap->ineq[j][1 + dim + i]);
    4002           0 :                         isl_int_divexact(bmap->ineq[j][1 + dim + div],
    4003             :                                          bmap->ineq[j][1 + dim + div],
    4004             :                                          bmap->ineq[l][0]);
    4005           0 :                         if (!valid)
    4006           0 :                                 break;
    4007             :                 }
    4008           0 :                 if (j < bmap->n_ineq)
    4009           0 :                         continue;
    4010           0 :                 coalesce = i;
    4011           0 :                 break;
    4012             :         }
    4013           0 :         isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
    4014           0 :         isl_int_sub(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
    4015           0 :         return coalesce;
    4016             : }
    4017             : 
    4018             : /* Internal data structure used during the construction and/or evaluation of
    4019             :  * an inequality that ensures that a pair of bounds always allows
    4020             :  * for an integer value.
    4021             :  *
    4022             :  * "tab" is the tableau in which the inequality is evaluated.  It may
    4023             :  * be NULL until it is actually needed.
    4024             :  * "v" contains the inequality coefficients.
    4025             :  * "g", "fl" and "fu" are temporary scalars used during the construction and
    4026             :  * evaluation.
    4027             :  */
    4028             : struct test_ineq_data {
    4029             :         struct isl_tab *tab;
    4030             :         isl_vec *v;
    4031             :         isl_int g;
    4032             :         isl_int fl;
    4033             :         isl_int fu;
    4034             : };
    4035             : 
    4036             : /* Free all the memory allocated by the fields of "data".
    4037             :  */
    4038           0 : static void test_ineq_data_clear(struct test_ineq_data *data)
    4039             : {
    4040           0 :         isl_tab_free(data->tab);
    4041           0 :         isl_vec_free(data->v);
    4042           0 :         isl_int_clear(data->g);
    4043           0 :         isl_int_clear(data->fl);
    4044           0 :         isl_int_clear(data->fu);
    4045           0 : }
    4046             : 
    4047             : /* Is the inequality stored in data->v satisfied by "bmap"?
    4048             :  * That is, does it only attain non-negative values?
    4049             :  * data->tab is a tableau corresponding to "bmap".
    4050             :  */
    4051           0 : static isl_bool test_ineq_is_satisfied(__isl_keep isl_basic_map *bmap,
    4052             :         struct test_ineq_data *data)
    4053             : {
    4054             :         isl_ctx *ctx;
    4055             :         enum isl_lp_result res;
    4056             : 
    4057           0 :         ctx = isl_basic_map_get_ctx(bmap);
    4058           0 :         if (!data->tab)
    4059           0 :                 data->tab = isl_tab_from_basic_map(bmap, 0);
    4060           0 :         res = isl_tab_min(data->tab, data->v->el, ctx->one, &data->g, NULL, 0);
    4061           0 :         if (res == isl_lp_error)
    4062           0 :                 return isl_bool_error;
    4063           0 :         return res == isl_lp_ok && isl_int_is_nonneg(data->g);
    4064             : }
    4065             : 
    4066             : /* Given a lower and an upper bound on div i, do they always allow
    4067             :  * for an integer value of the given div?
    4068             :  * Determine this property by constructing an inequality
    4069             :  * such that the property is guaranteed when the inequality is nonnegative.
    4070             :  * The lower bound is inequality l, while the upper bound is inequality u.
    4071             :  * The constructed inequality is stored in data->v.
    4072             :  *
    4073             :  * Let the upper bound be
    4074             :  *
    4075             :  *      -n_u a + e_u >= 0
    4076             :  *
    4077             :  * and the lower bound
    4078             :  *
    4079             :  *      n_l a + e_l >= 0
    4080             :  *
    4081             :  * Let n_u = f_u g and n_l = f_l g, with g = gcd(n_u, n_l).
    4082             :  * We have
    4083             :  *
    4084             :  *      - f_u e_l <= f_u f_l g a <= f_l e_u
    4085             :  *
    4086             :  * Since all variables are integer valued, this is equivalent to
    4087             :  *
    4088             :  *      - f_u e_l - (f_u - 1) <= f_u f_l g a <= f_l e_u + (f_l - 1)
    4089             :  *
    4090             :  * If this interval is at least f_u f_l g, then it contains at least
    4091             :  * one integer value for a.
    4092             :  * That is, the test constraint is
    4093             :  *
    4094             :  *      f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 >= f_u f_l g
    4095             :  *
    4096             :  * or
    4097             :  *
    4098             :  *      f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 - f_u f_l g >= 0
    4099             :  *
    4100             :  * If the coefficients of f_l e_u + f_u e_l have a common divisor g',
    4101             :  * then the constraint can be scaled down by a factor g',
    4102             :  * with the constant term replaced by
    4103             :  * floor((f_l e_{u,0} + f_u e_{l,0} + f_l - 1 + f_u - 1 + 1 - f_u f_l g)/g').
    4104             :  * Note that the result of applying Fourier-Motzkin to this pair
    4105             :  * of constraints is
    4106             :  *
    4107             :  *      f_l e_u + f_u e_l >= 0
    4108             :  *
    4109             :  * If the constant term of the scaled down version of this constraint,
    4110             :  * i.e., floor((f_l e_{u,0} + f_u e_{l,0})/g') is equal to the constant
    4111             :  * term of the scaled down test constraint, then the test constraint
    4112             :  * is known to hold and no explicit evaluation is required.
    4113             :  * This is essentially the Omega test.
    4114             :  *
    4115             :  * If the test constraint consists of only a constant term, then
    4116             :  * it is sufficient to look at the sign of this constant term.
    4117             :  */
    4118           0 : static isl_bool int_between_bounds(__isl_keep isl_basic_map *bmap, int i,
    4119             :         int l, int u, struct test_ineq_data *data)
    4120             : {
    4121             :         unsigned offset, n_div;
    4122           0 :         offset = isl_basic_map_offset(bmap, isl_dim_div);
    4123           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    4124             : 
    4125           0 :         isl_int_gcd(data->g,
    4126             :                     bmap->ineq[l][offset + i], bmap->ineq[u][offset + i]);
    4127           0 :         isl_int_divexact(data->fl, bmap->ineq[l][offset + i], data->g);
    4128           0 :         isl_int_divexact(data->fu, bmap->ineq[u][offset + i], data->g);
    4129           0 :         isl_int_neg(data->fu, data->fu);
    4130           0 :         isl_seq_combine(data->v->el, data->fl, bmap->ineq[u],
    4131           0 :                         data->fu, bmap->ineq[l], offset + n_div);
    4132           0 :         isl_int_mul(data->g, data->g, data->fl);
    4133           0 :         isl_int_mul(data->g, data->g, data->fu);
    4134           0 :         isl_int_sub(data->g, data->g, data->fl);
    4135           0 :         isl_int_sub(data->g, data->g, data->fu);
    4136           0 :         isl_int_add_ui(data->g, data->g, 1);
    4137           0 :         isl_int_sub(data->fl, data->v->el[0], data->g);
    4138             : 
    4139           0 :         isl_seq_gcd(data->v->el + 1, offset - 1 + n_div, &data->g);
    4140           0 :         if (isl_int_is_zero(data->g))
    4141           0 :                 return isl_int_is_nonneg(data->fl);
    4142           0 :         if (isl_int_is_one(data->g)) {
    4143           0 :                 isl_int_set(data->v->el[0], data->fl);
    4144           0 :                 return test_ineq_is_satisfied(bmap, data);
    4145             :         }
    4146           0 :         isl_int_fdiv_q(data->fl, data->fl, data->g);
    4147           0 :         isl_int_fdiv_q(data->v->el[0], data->v->el[0], data->g);
    4148           0 :         if (isl_int_eq(data->fl, data->v->el[0]))
    4149           0 :                 return isl_bool_true;
    4150           0 :         isl_int_set(data->v->el[0], data->fl);
    4151           0 :         isl_seq_scale_down(data->v->el + 1, data->v->el + 1, data->g,
    4152           0 :                             offset - 1 + n_div);
    4153             : 
    4154           0 :         return test_ineq_is_satisfied(bmap, data);
    4155             : }
    4156             : 
    4157             : /* Remove more kinds of divs that are not strictly needed.
    4158             :  * In particular, if all pairs of lower and upper bounds on a div
    4159             :  * are such that they allow at least one integer value of the div,
    4160             :  * then we can eliminate the div using Fourier-Motzkin without
    4161             :  * introducing any spurious solutions.
    4162             :  *
    4163             :  * If at least one of the two constraints has a unit coefficient for the div,
    4164             :  * then the presence of such a value is guaranteed so there is no need to check.
    4165             :  * In particular, the value attained by the bound with unit coefficient
    4166             :  * can serve as this intermediate value.
    4167             :  */
    4168           0 : static __isl_give isl_basic_map *drop_more_redundant_divs(
    4169             :         __isl_take isl_basic_map *bmap, __isl_take int *pairs, int n)
    4170             : {
    4171             :         isl_ctx *ctx;
    4172           0 :         struct test_ineq_data data = { NULL, NULL };
    4173             :         unsigned off, n_div;
    4174           0 :         int remove = -1;
    4175             : 
    4176           0 :         isl_int_init(data.g);
    4177           0 :         isl_int_init(data.fl);
    4178           0 :         isl_int_init(data.fu);
    4179             : 
    4180           0 :         if (!bmap)
    4181           0 :                 goto error;
    4182             : 
    4183           0 :         ctx = isl_basic_map_get_ctx(bmap);
    4184           0 :         off = isl_basic_map_offset(bmap, isl_dim_div);
    4185           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    4186           0 :         data.v = isl_vec_alloc(ctx, off + n_div);
    4187           0 :         if (!data.v)
    4188           0 :                 goto error;
    4189             : 
    4190           0 :         while (n > 0) {
    4191             :                 int i, l, u;
    4192           0 :                 int best = -1;
    4193             :                 isl_bool has_int;
    4194             : 
    4195           0 :                 for (i = 0; i < n_div; ++i) {
    4196           0 :                         if (!pairs[i])
    4197           0 :                                 continue;
    4198           0 :                         if (best >= 0 && pairs[best] <= pairs[i])
    4199           0 :                                 continue;
    4200           0 :                         best = i;
    4201             :                 }
    4202             : 
    4203           0 :                 i = best;
    4204           0 :                 for (l = 0; l < bmap->n_ineq; ++l) {
    4205           0 :                         if (!isl_int_is_pos(bmap->ineq[l][off + i]))
    4206           0 :                                 continue;
    4207           0 :                         if (isl_int_is_one(bmap->ineq[l][off + i]))
    4208           0 :                                 continue;
    4209           0 :                         for (u = 0; u < bmap->n_ineq; ++u) {
    4210           0 :                                 if (!isl_int_is_neg(bmap->ineq[u][off + i]))
    4211           0 :                                         continue;
    4212           0 :                                 if (isl_int_is_negone(bmap->ineq[u][off + i]))
    4213           0 :                                         continue;
    4214           0 :                                 has_int = int_between_bounds(bmap, i, l, u,
    4215             :                                                                 &data);
    4216           0 :                                 if (has_int < 0)
    4217           0 :                                         goto error;
    4218           0 :                                 if (data.tab && data.tab->empty)
    4219           0 :                                         break;
    4220           0 :                                 if (!has_int)
    4221           0 :                                         break;
    4222             :                         }
    4223           0 :                         if (u < bmap->n_ineq)
    4224           0 :                                 break;
    4225             :                 }
    4226           0 :                 if (data.tab && data.tab->empty) {
    4227           0 :                         bmap = isl_basic_map_set_to_empty(bmap);
    4228           0 :                         break;
    4229             :                 }
    4230           0 :                 if (l == bmap->n_ineq) {
    4231           0 :                         remove = i;
    4232           0 :                         break;
    4233             :                 }
    4234           0 :                 pairs[i] = 0;
    4235           0 :                 --n;
    4236             :         }
    4237             : 
    4238           0 :         test_ineq_data_clear(&data);
    4239             : 
    4240           0 :         free(pairs);
    4241             : 
    4242           0 :         if (remove < 0)
    4243           0 :                 return bmap;
    4244             : 
    4245           0 :         bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, remove, 1);
    4246           0 :         return isl_basic_map_drop_redundant_divs(bmap);
    4247             : error:
    4248           0 :         free(pairs);
    4249           0 :         isl_basic_map_free(bmap);
    4250           0 :         test_ineq_data_clear(&data);
    4251           0 :         return NULL;
    4252             : }
    4253             : 
    4254             : /* Given a pair of divs div1 and div2 such that, except for the lower bound l
    4255             :  * and the upper bound u, div1 always occurs together with div2 in the form
    4256             :  * (div1 + m div2), where m is the constant range on the variable div1
    4257             :  * allowed by l and u, replace the pair div1 and div2 by a single
    4258             :  * div that is equal to div1 + m div2.
    4259             :  *
    4260             :  * The new div will appear in the location that contains div2.
    4261             :  * We need to modify all constraints that contain
    4262             :  * div2 = (div - div1) / m
    4263             :  * The coefficient of div2 is known to be equal to 1 or -1.
    4264             :  * (If a constraint does not contain div2, it will also not contain div1.)
    4265             :  * If the constraint also contains div1, then we know they appear
    4266             :  * as f (div1 + m div2) and we can simply replace (div1 + m div2) by div,
    4267             :  * i.e., the coefficient of div is f.
    4268             :  *
    4269             :  * Otherwise, we first need to introduce div1 into the constraint.
    4270             :  * Let l be
    4271             :  *
    4272             :  *      div1 + f >=0
    4273             :  *
    4274             :  * and u
    4275             :  *
    4276             :  *      -div1 + f' >= 0
    4277             :  *
    4278             :  * A lower bound on div2
    4279             :  *
    4280             :  *      div2 + t >= 0
    4281             :  *
    4282             :  * can be replaced by
    4283             :  *
    4284             :  *      m div2 + div1 + m t + f >= 0
    4285             :  *
    4286             :  * An upper bound
    4287             :  *
    4288             :  *      -div2 + t >= 0
    4289             :  *
    4290             :  * can be replaced by
    4291             :  *
    4292             :  *      -(m div2 + div1) + m t + f' >= 0
    4293             :  *
    4294             :  * These constraint are those that we would obtain from eliminating
    4295             :  * div1 using Fourier-Motzkin.
    4296             :  *
    4297             :  * After all constraints have been modified, we drop the lower and upper
    4298             :  * bound and then drop div1.
    4299             :  * Since the new div is only placed in the same location that used
    4300             :  * to store div2, but otherwise has a different meaning, any possible
    4301             :  * explicit representation of the original div2 is removed.
    4302             :  */
    4303           0 : static __isl_give isl_basic_map *coalesce_divs(__isl_take isl_basic_map *bmap,
    4304             :         unsigned div1, unsigned div2, unsigned l, unsigned u)
    4305             : {
    4306             :         isl_ctx *ctx;
    4307             :         isl_int m;
    4308             :         unsigned dim, total;
    4309             :         int i;
    4310             : 
    4311           0 :         ctx = isl_basic_map_get_ctx(bmap);
    4312             : 
    4313           0 :         dim = isl_space_dim(bmap->dim, isl_dim_all);
    4314           0 :         total = 1 + dim + bmap->n_div;
    4315             : 
    4316           0 :         isl_int_init(m);
    4317           0 :         isl_int_add(m, bmap->ineq[l][0], bmap->ineq[u][0]);
    4318           0 :         isl_int_add_ui(m, m, 1);
    4319             : 
    4320           0 :         for (i = 0; i < bmap->n_ineq; ++i) {
    4321           0 :                 if (i == l || i == u)
    4322           0 :                         continue;
    4323           0 :                 if (isl_int_is_zero(bmap->ineq[i][1 + dim + div2]))
    4324           0 :                         continue;
    4325           0 :                 if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1])) {
    4326           0 :                         if (isl_int_is_pos(bmap->ineq[i][1 + dim + div2]))
    4327           0 :                                 isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i],
    4328           0 :                                                 ctx->one, bmap->ineq[l], total);
    4329             :                         else
    4330           0 :                                 isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i],
    4331           0 :                                                 ctx->one, bmap->ineq[u], total);
    4332             :                 }
    4333           0 :                 isl_int_set(bmap->ineq[i][1 + dim + div2],
    4334             :                             bmap->ineq[i][1 + dim + div1]);
    4335           0 :                 isl_int_set_si(bmap->ineq[i][1 + dim + div1], 0);
    4336             :         }
    4337             : 
    4338           0 :         isl_int_clear(m);
    4339           0 :         if (l > u) {
    4340           0 :                 isl_basic_map_drop_inequality(bmap, l);
    4341           0 :                 isl_basic_map_drop_inequality(bmap, u);
    4342             :         } else {
    4343           0 :                 isl_basic_map_drop_inequality(bmap, u);
    4344           0 :                 isl_basic_map_drop_inequality(bmap, l);
    4345             :         }
    4346           0 :         bmap = isl_basic_map_mark_div_unknown(bmap, div2);
    4347           0 :         bmap = isl_basic_map_drop_div(bmap, div1);
    4348           0 :         return bmap;
    4349             : }
    4350             : 
    4351             : /* First check if we can coalesce any pair of divs and
    4352             :  * then continue with dropping more redundant divs.
    4353             :  *
    4354             :  * We loop over all pairs of lower and upper bounds on a div
    4355             :  * with coefficient 1 and -1, respectively, check if there
    4356             :  * is any other div "c" with which we can coalesce the div
    4357             :  * and if so, perform the coalescing.
    4358             :  */
    4359           0 : static __isl_give isl_basic_map *coalesce_or_drop_more_redundant_divs(
    4360             :         __isl_take isl_basic_map *bmap, int *pairs, int n)
    4361             : {
    4362             :         int i, l, u;
    4363             :         unsigned dim;
    4364             : 
    4365           0 :         dim = isl_space_dim(bmap->dim, isl_dim_all);
    4366             : 
    4367           0 :         for (i = 0; i < bmap->n_div; ++i) {
    4368           0 :                 if (!pairs[i])
    4369           0 :                         continue;
    4370           0 :                 for (l = 0; l < bmap->n_ineq; ++l) {
    4371           0 :                         if (!isl_int_is_one(bmap->ineq[l][1 + dim + i]))
    4372           0 :                                 continue;
    4373           0 :                         for (u = 0; u < bmap->n_ineq; ++u) {
    4374             :                                 int c;
    4375             : 
    4376           0 :                                 if (!isl_int_is_negone(bmap->ineq[u][1+dim+i]))
    4377           0 :                                         continue;
    4378           0 :                                 c = div_find_coalesce(bmap, pairs, i, l, u);
    4379           0 :                                 if (c < 0)
    4380           0 :                                         continue;
    4381           0 :                                 free(pairs);
    4382           0 :                                 bmap = coalesce_divs(bmap, i, c, l, u);
    4383           0 :                                 return isl_basic_map_drop_redundant_divs(bmap);
    4384             :                         }
    4385             :                 }
    4386             :         }
    4387             : 
    4388           0 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) {
    4389           0 :                 free(pairs);
    4390           0 :                 return bmap;
    4391             :         }
    4392             : 
    4393           0 :         return drop_more_redundant_divs(bmap, pairs, n);
    4394             : }
    4395             : 
    4396             : /* Are the "n" coefficients starting at "first" of inequality constraints
    4397             :  * "i" and "j" of "bmap" equal to each other?
    4398             :  */
    4399           0 : static int is_parallel_part(__isl_keep isl_basic_map *bmap, int i, int j,
    4400             :         int first, int n)
    4401             : {
    4402           0 :         return isl_seq_eq(bmap->ineq[i] + first, bmap->ineq[j] + first, n);
    4403             : }
    4404             : 
    4405             : /* Are the "n" coefficients starting at "first" of inequality constraints
    4406             :  * "i" and "j" of "bmap" opposite to each other?
    4407             :  */
    4408           0 : static int is_opposite_part(__isl_keep isl_basic_map *bmap, int i, int j,
    4409             :         int first, int n)
    4410             : {
    4411           0 :         return isl_seq_is_neg(bmap->ineq[i] + first, bmap->ineq[j] + first, n);
    4412             : }
    4413             : 
    4414             : /* Are inequality constraints "i" and "j" of "bmap" opposite to each other,
    4415             :  * apart from the constant term?
    4416             :  */
    4417           0 : static isl_bool is_opposite(__isl_keep isl_basic_map *bmap, int i, int j)
    4418             : {
    4419             :         unsigned total;
    4420             : 
    4421           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    4422           0 :         return is_opposite_part(bmap, i, j, 1, total);
    4423             : }
    4424             : 
    4425             : /* Are inequality constraints "i" and "j" of "bmap" equal to each other,
    4426             :  * apart from the constant term and the coefficient at position "pos"?
    4427             :  */
    4428           0 : static int is_parallel_except(__isl_keep isl_basic_map *bmap, int i, int j,
    4429             :         int pos)
    4430             : {
    4431             :         unsigned total;
    4432             : 
    4433           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    4434           0 :         return is_parallel_part(bmap, i, j, 1, pos - 1) &&
    4435           0 :                 is_parallel_part(bmap, i, j, pos + 1, total - pos);
    4436             : }
    4437             : 
    4438             : /* Are inequality constraints "i" and "j" of "bmap" opposite to each other,
    4439             :  * apart from the constant term and the coefficient at position "pos"?
    4440             :  */
    4441           0 : static int is_opposite_except(__isl_keep isl_basic_map *bmap, int i, int j,
    4442             :         int pos)
    4443             : {
    4444             :         unsigned total;
    4445             : 
    4446           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    4447           0 :         return is_opposite_part(bmap, i, j, 1, pos - 1) &&
    4448           0 :                 is_opposite_part(bmap, i, j, pos + 1, total - pos);
    4449             : }
    4450             : 
    4451             : /* Restart isl_basic_map_drop_redundant_divs after "bmap" has
    4452             :  * been modified, simplying it if "simplify" is set.
    4453             :  * Free the temporary data structure "pairs" that was associated
    4454             :  * to the old version of "bmap".
    4455             :  */
    4456           0 : static __isl_give isl_basic_map *drop_redundant_divs_again(
    4457             :         __isl_take isl_basic_map *bmap, __isl_take int *pairs, int simplify)
    4458             : {
    4459           0 :         if (simplify)
    4460           0 :                 bmap = isl_basic_map_simplify(bmap);
    4461           0 :         free(pairs);
    4462           0 :         return isl_basic_map_drop_redundant_divs(bmap);
    4463             : }
    4464             : 
    4465             : /* Is "div" the single unknown existentially quantified variable
    4466             :  * in inequality constraint "ineq" of "bmap"?
    4467             :  * "div" is known to have a non-zero coefficient in "ineq".
    4468             :  */
    4469           0 : static isl_bool single_unknown(__isl_keep isl_basic_map *bmap, int ineq,
    4470             :         int div)
    4471             : {
    4472             :         int i;
    4473             :         unsigned n_div, o_div;
    4474             :         isl_bool known;
    4475             : 
    4476           0 :         known = isl_basic_map_div_is_known(bmap, div);
    4477           0 :         if (known < 0 || known)
    4478           0 :                 return isl_bool_not(known);
    4479           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    4480           0 :         if (n_div == 1)
    4481           0 :                 return isl_bool_true;
    4482           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
    4483           0 :         for (i = 0; i < n_div; ++i) {
    4484             :                 isl_bool known;
    4485             : 
    4486           0 :                 if (i == div)
    4487           0 :                         continue;
    4488           0 :                 if (isl_int_is_zero(bmap->ineq[ineq][o_div + i]))
    4489           0 :                         continue;
    4490           0 :                 known = isl_basic_map_div_is_known(bmap, i);
    4491           0 :                 if (known < 0 || !known)
    4492           0 :                         return known;
    4493             :         }
    4494             : 
    4495           0 :         return isl_bool_true;
    4496             : }
    4497             : 
    4498             : /* Does integer division "div" have coefficient 1 in inequality constraint
    4499             :  * "ineq" of "map"?
    4500             :  */
    4501           0 : static isl_bool has_coef_one(__isl_keep isl_basic_map *bmap, int div, int ineq)
    4502             : {
    4503             :         unsigned o_div;
    4504             : 
    4505           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
    4506           0 :         if (isl_int_is_one(bmap->ineq[ineq][o_div + div]))
    4507           0 :                 return isl_bool_true;
    4508             : 
    4509           0 :         return isl_bool_false;
    4510             : }
    4511             : 
    4512             : /* Turn inequality constraint "ineq" of "bmap" into an equality and
    4513             :  * then try and drop redundant divs again,
    4514             :  * freeing the temporary data structure "pairs" that was associated
    4515             :  * to the old version of "bmap".
    4516             :  */
    4517           0 : static __isl_give isl_basic_map *set_eq_and_try_again(
    4518             :         __isl_take isl_basic_map *bmap, int ineq, __isl_take int *pairs)
    4519             : {
    4520           0 :         bmap = isl_basic_map_cow(bmap);
    4521           0 :         isl_basic_map_inequality_to_equality(bmap, ineq);
    4522           0 :         return drop_redundant_divs_again(bmap, pairs, 1);
    4523             : }
    4524             : 
    4525             : /* Drop the integer division at position "div", along with the two
    4526             :  * inequality constraints "ineq1" and "ineq2" in which it appears
    4527             :  * from "bmap" and then try and drop redundant divs again,
    4528             :  * freeing the temporary data structure "pairs" that was associated
    4529             :  * to the old version of "bmap".
    4530             :  */
    4531           0 : static __isl_give isl_basic_map *drop_div_and_try_again(
    4532             :         __isl_take isl_basic_map *bmap, int div, int ineq1, int ineq2,
    4533             :         __isl_take int *pairs)
    4534             : {
    4535           0 :         if (ineq1 > ineq2) {
    4536           0 :                 isl_basic_map_drop_inequality(bmap, ineq1);
    4537           0 :                 isl_basic_map_drop_inequality(bmap, ineq2);
    4538             :         } else {
    4539           0 :                 isl_basic_map_drop_inequality(bmap, ineq2);
    4540           0 :                 isl_basic_map_drop_inequality(bmap, ineq1);
    4541             :         }
    4542           0 :         bmap = isl_basic_map_drop_div(bmap, div);
    4543           0 :         return drop_redundant_divs_again(bmap, pairs, 0);
    4544             : }
    4545             : 
    4546             : /* Given two inequality constraints
    4547             :  *
    4548             :  *      f(x) + n d + c >= 0,         (ineq)
    4549             :  *
    4550             :  * with d the variable at position "pos", and
    4551             :  *
    4552             :  *      f(x) + c0 >= 0,                      (lower)
    4553             :  *
    4554             :  * compute the maximal value of the lower bound ceil((-f(x) - c)/n)
    4555             :  * determined by the first constraint.
    4556             :  * That is, store
    4557             :  *
    4558             :  *      ceil((c0 - c)/n)
    4559             :  *
    4560             :  * in *l.
    4561             :  */
    4562           0 : static void lower_bound_from_parallel(__isl_keep isl_basic_map *bmap,
    4563             :         int ineq, int lower, int pos, isl_int *l)
    4564             : {
    4565           0 :         isl_int_neg(*l, bmap->ineq[ineq][0]);
    4566           0 :         isl_int_add(*l, *l, bmap->ineq[lower][0]);
    4567           0 :         isl_int_cdiv_q(*l, *l, bmap->ineq[ineq][pos]);
    4568           0 : }
    4569             : 
    4570             : /* Given two inequality constraints
    4571             :  *
    4572             :  *      f(x) + n d + c >= 0,         (ineq)
    4573             :  *
    4574             :  * with d the variable at position "pos", and
    4575             :  *
    4576             :  *      -f(x) - c0 >= 0,             (upper)
    4577             :  *
    4578             :  * compute the minimal value of the lower bound ceil((-f(x) - c)/n)
    4579             :  * determined by the first constraint.
    4580             :  * That is, store
    4581             :  *
    4582             :  *      ceil((-c1 - c)/n)
    4583             :  *
    4584             :  * in *u.
    4585             :  */
    4586           0 : static void lower_bound_from_opposite(__isl_keep isl_basic_map *bmap,
    4587             :         int ineq, int upper, int pos, isl_int *u)
    4588             : {
    4589           0 :         isl_int_neg(*u, bmap->ineq[ineq][0]);
    4590           0 :         isl_int_sub(*u, *u, bmap->ineq[upper][0]);
    4591           0 :         isl_int_cdiv_q(*u, *u, bmap->ineq[ineq][pos]);
    4592           0 : }
    4593             : 
    4594             : /* Given a lower bound constraint "ineq" on "div" in "bmap",
    4595             :  * does the corresponding lower bound have a fixed value in "bmap"?
    4596             :  *
    4597             :  * In particular, "ineq" is of the form
    4598             :  *
    4599             :  *      f(x) + n d + c >= 0
    4600             :  *
    4601             :  * with n > 0, c the constant term and
    4602             :  * d the existentially quantified variable "div".
    4603             :  * That is, the lower bound is
    4604             :  *
    4605             :  *      ceil((-f(x) - c)/n)
    4606             :  *
    4607             :  * Look for a pair of constraints
    4608             :  *
    4609             :  *      f(x) + c0 >= 0
    4610             :  *      -f(x) + c1 >= 0
    4611             :  *
    4612             :  * i.e., -c1 <= -f(x) <= c0, that fix ceil((-f(x) - c)/n) to a constant value.
    4613             :  * That is, check that
    4614             :  *
    4615             :  *      ceil((-c1 - c)/n) = ceil((c0 - c)/n)
    4616             :  *
    4617             :  * If so, return the index of inequality f(x) + c0 >= 0.
    4618             :  * Otherwise, return -1.
    4619             :  */
    4620           0 : static int lower_bound_is_cst(__isl_keep isl_basic_map *bmap, int div, int ineq)
    4621             : {
    4622             :         int i;
    4623           0 :         int lower = -1, upper = -1;
    4624             :         unsigned o_div;
    4625             :         isl_int l, u;
    4626             :         int equal;
    4627             : 
    4628           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
    4629           0 :         for (i = 0; i < bmap->n_ineq && (lower < 0 || upper < 0); ++i) {
    4630           0 :                 if (i == ineq)
    4631           0 :                         continue;
    4632           0 :                 if (!isl_int_is_zero(bmap->ineq[i][o_div + div]))
    4633           0 :                         continue;
    4634           0 :                 if (lower < 0 &&
    4635           0 :                     is_parallel_except(bmap, ineq, i, o_div + div)) {
    4636           0 :                         lower = i;
    4637           0 :                         continue;
    4638             :                 }
    4639           0 :                 if (upper < 0 &&
    4640           0 :                     is_opposite_except(bmap, ineq, i, o_div + div)) {
    4641           0 :                         upper = i;
    4642             :                 }
    4643             :         }
    4644             : 
    4645           0 :         if (lower < 0 || upper < 0)
    4646           0 :                 return -1;
    4647             : 
    4648           0 :         isl_int_init(l);
    4649           0 :         isl_int_init(u);
    4650             : 
    4651           0 :         lower_bound_from_parallel(bmap, ineq, lower, o_div + div, &l);
    4652           0 :         lower_bound_from_opposite(bmap, ineq, upper, o_div + div, &u);
    4653             : 
    4654           0 :         equal = isl_int_eq(l, u);
    4655             : 
    4656           0 :         isl_int_clear(l);
    4657           0 :         isl_int_clear(u);
    4658             : 
    4659           0 :         return equal ? lower : -1;
    4660             : }
    4661             : 
    4662             : /* Given a lower bound constraint "ineq" on the existentially quantified
    4663             :  * variable "div", such that the corresponding lower bound has
    4664             :  * a fixed value in "bmap", assign this fixed value to the variable and
    4665             :  * then try and drop redundant divs again,
    4666             :  * freeing the temporary data structure "pairs" that was associated
    4667             :  * to the old version of "bmap".
    4668             :  * "lower" determines the constant value for the lower bound.
    4669             :  *
    4670             :  * In particular, "ineq" is of the form
    4671             :  *
    4672             :  *      f(x) + n d + c >= 0,
    4673             :  *
    4674             :  * while "lower" is of the form
    4675             :  *
    4676             :  *      f(x) + c0 >= 0
    4677             :  *
    4678             :  * The lower bound is ceil((-f(x) - c)/n) and its constant value
    4679             :  * is ceil((c0 - c)/n).
    4680             :  */
    4681           0 : static __isl_give isl_basic_map *fix_cst_lower(__isl_take isl_basic_map *bmap,
    4682             :         int div, int ineq, int lower, int *pairs)
    4683             : {
    4684             :         isl_int c;
    4685             :         unsigned o_div;
    4686             : 
    4687           0 :         isl_int_init(c);
    4688             : 
    4689           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
    4690           0 :         lower_bound_from_parallel(bmap, ineq, lower, o_div + div, &c);
    4691           0 :         bmap = isl_basic_map_fix(bmap, isl_dim_div, div, c);
    4692           0 :         free(pairs);
    4693             : 
    4694           0 :         isl_int_clear(c);
    4695             : 
    4696           0 :         return isl_basic_map_drop_redundant_divs(bmap);
    4697             : }
    4698             : 
    4699             : /* Remove divs that are not strictly needed based on the inequality
    4700             :  * constraints.
    4701             :  * In particular, if a div only occurs positively (or negatively)
    4702             :  * in constraints, then it can simply be dropped.
    4703             :  * Also, if a div occurs in only two constraints and if moreover
    4704             :  * those two constraints are opposite to each other, except for the constant
    4705             :  * term and if the sum of the constant terms is such that for any value
    4706             :  * of the other values, there is always at least one integer value of the
    4707             :  * div, i.e., if one plus this sum is greater than or equal to
    4708             :  * the (absolute value) of the coefficient of the div in the constraints,
    4709             :  * then we can also simply drop the div.
    4710             :  *
    4711             :  * If an existentially quantified variable does not have an explicit
    4712             :  * representation, appears in only a single lower bound that does not
    4713             :  * involve any other such existentially quantified variables and appears
    4714             :  * in this lower bound with coefficient 1,
    4715             :  * then fix the variable to the value of the lower bound.  That is,
    4716             :  * turn the inequality into an equality.
    4717             :  * If for any value of the other variables, there is any value
    4718             :  * for the existentially quantified variable satisfying the constraints,
    4719             :  * then this lower bound also satisfies the constraints.
    4720             :  * It is therefore safe to pick this lower bound.
    4721             :  *
    4722             :  * The same reasoning holds even if the coefficient is not one.
    4723             :  * However, fixing the variable to the value of the lower bound may
    4724             :  * in general introduce an extra integer division, in which case
    4725             :  * it may be better to pick another value.
    4726             :  * If this integer division has a known constant value, then plugging
    4727             :  * in this constant value removes the existentially quantified variable
    4728             :  * completely.  In particular, if the lower bound is of the form
    4729             :  * ceil((-f(x) - c)/n) and there are two constraints, f(x) + c0 >= 0 and
    4730             :  * -f(x) + c1 >= 0 such that ceil((-c1 - c)/n) = ceil((c0 - c)/n),
    4731             :  * then the existentially quantified variable can be assigned this
    4732             :  * shared value.
    4733             :  *
    4734             :  * We skip divs that appear in equalities or in the definition of other divs.
    4735             :  * Divs that appear in the definition of other divs usually occur in at least
    4736             :  * 4 constraints, but the constraints may have been simplified.
    4737             :  *
    4738             :  * If any divs are left after these simple checks then we move on
    4739             :  * to more complicated cases in drop_more_redundant_divs.
    4740             :  */
    4741           0 : static __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs_ineq(
    4742             :         __isl_take isl_basic_map *bmap)
    4743             : {
    4744             :         int i, j;
    4745             :         unsigned off;
    4746           0 :         int *pairs = NULL;
    4747           0 :         int n = 0;
    4748             : 
    4749           0 :         if (!bmap)
    4750           0 :                 goto error;
    4751           0 :         if (bmap->n_div == 0)
    4752           0 :                 return bmap;
    4753             : 
    4754           0 :         off = isl_space_dim(bmap->dim, isl_dim_all);
    4755           0 :         pairs = isl_calloc_array(bmap->ctx, int, bmap->n_div);
    4756           0 :         if (!pairs)
    4757           0 :                 goto error;
    4758             : 
    4759           0 :         for (i = 0; i < bmap->n_div; ++i) {
    4760             :                 int pos, neg;
    4761             :                 int last_pos, last_neg;
    4762             :                 int redundant;
    4763             :                 int defined;
    4764             :                 isl_bool opp, set_div;
    4765             : 
    4766           0 :                 defined = !isl_int_is_zero(bmap->div[i][0]);
    4767           0 :                 for (j = i; j < bmap->n_div; ++j)
    4768           0 :                         if (!isl_int_is_zero(bmap->div[j][1 + 1 + off + i]))
    4769             :                                 break;
    4770           0 :                 if (j < bmap->n_div)
    4771           0 :                         continue;
    4772           0 :                 for (j = 0; j < bmap->n_eq; ++j)
    4773           0 :                         if (!isl_int_is_zero(bmap->eq[j][1 + off + i]))
    4774             :                                 break;
    4775           0 :                 if (j < bmap->n_eq)
    4776           0 :                         continue;
    4777           0 :                 ++n;
    4778           0 :                 pos = neg = 0;
    4779           0 :                 for (j = 0; j < bmap->n_ineq; ++j) {
    4780           0 :                         if (isl_int_is_pos(bmap->ineq[j][1 + off + i])) {
    4781           0 :                                 last_pos = j;
    4782           0 :                                 ++pos;
    4783             :                         }
    4784           0 :                         if (isl_int_is_neg(bmap->ineq[j][1 + off + i])) {
    4785           0 :                                 last_neg = j;
    4786           0 :                                 ++neg;
    4787             :                         }
    4788             :                 }
    4789           0 :                 pairs[i] = pos * neg;
    4790           0 :                 if (pairs[i] == 0) {
    4791           0 :                         for (j = bmap->n_ineq - 1; j >= 0; --j)
    4792           0 :                                 if (!isl_int_is_zero(bmap->ineq[j][1+off+i]))
    4793           0 :                                         isl_basic_map_drop_inequality(bmap, j);
    4794           0 :                         bmap = isl_basic_map_drop_div(bmap, i);
    4795           0 :                         return drop_redundant_divs_again(bmap, pairs, 0);
    4796             :                 }
    4797           0 :                 if (pairs[i] != 1)
    4798           0 :                         opp = isl_bool_false;
    4799             :                 else
    4800           0 :                         opp = is_opposite(bmap, last_pos, last_neg);
    4801           0 :                 if (opp < 0)
    4802           0 :                         goto error;
    4803           0 :                 if (!opp) {
    4804             :                         int lower;
    4805             :                         isl_bool single, one;
    4806             : 
    4807           0 :                         if (pos != 1)
    4808           0 :                                 continue;
    4809           0 :                         single = single_unknown(bmap, last_pos, i);
    4810           0 :                         if (single < 0)
    4811           0 :                                 goto error;
    4812           0 :                         if (!single)
    4813           0 :                                 continue;
    4814           0 :                         one = has_coef_one(bmap, i, last_pos);
    4815           0 :                         if (one < 0)
    4816           0 :                                 goto error;
    4817           0 :                         if (one)
    4818           0 :                                 return set_eq_and_try_again(bmap, last_pos,
    4819             :                                                             pairs);
    4820           0 :                         lower = lower_bound_is_cst(bmap, i, last_pos);
    4821           0 :                         if (lower >= 0)
    4822           0 :                                 return fix_cst_lower(bmap, i, last_pos, lower,
    4823             :                                                 pairs);
    4824           0 :                         continue;
    4825             :                 }
    4826             : 
    4827           0 :                 isl_int_add(bmap->ineq[last_pos][0],
    4828             :                             bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]);
    4829           0 :                 isl_int_add_ui(bmap->ineq[last_pos][0],
    4830             :                                bmap->ineq[last_pos][0], 1);
    4831           0 :                 redundant = isl_int_ge(bmap->ineq[last_pos][0],
    4832             :                                 bmap->ineq[last_pos][1+off+i]);
    4833           0 :                 isl_int_sub_ui(bmap->ineq[last_pos][0],
    4834             :                                bmap->ineq[last_pos][0], 1);
    4835           0 :                 isl_int_sub(bmap->ineq[last_pos][0],
    4836             :                             bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]);
    4837           0 :                 if (redundant)
    4838           0 :                         return drop_div_and_try_again(bmap, i,
    4839             :                                                     last_pos, last_neg, pairs);
    4840           0 :                 if (defined)
    4841           0 :                         set_div = isl_bool_false;
    4842             :                 else
    4843           0 :                         set_div = ok_to_set_div_from_bound(bmap, i, last_pos);
    4844           0 :                 if (set_div < 0)
    4845           0 :                         return isl_basic_map_free(bmap);
    4846           0 :                 if (set_div) {
    4847           0 :                         bmap = set_div_from_lower_bound(bmap, i, last_pos);
    4848           0 :                         return drop_redundant_divs_again(bmap, pairs, 1);
    4849             :                 }
    4850           0 :                 pairs[i] = 0;
    4851           0 :                 --n;
    4852             :         }
    4853             : 
    4854           0 :         if (n > 0)
    4855           0 :                 return coalesce_or_drop_more_redundant_divs(bmap, pairs, n);
    4856             : 
    4857           0 :         free(pairs);
    4858           0 :         return bmap;
    4859             : error:
    4860           0 :         free(pairs);
    4861           0 :         isl_basic_map_free(bmap);
    4862           0 :         return NULL;
    4863             : }
    4864             : 
    4865             : /* Consider the coefficients at "c" as a row vector and replace
    4866             :  * them with their product with "T".  "T" is assumed to be a square matrix.
    4867             :  */
    4868           0 : static isl_stat preimage(isl_int *c, __isl_keep isl_mat *T)
    4869             : {
    4870             :         int n;
    4871             :         isl_ctx *ctx;
    4872             :         isl_vec *v;
    4873             : 
    4874           0 :         if (!T)
    4875           0 :                 return isl_stat_error;
    4876           0 :         n = isl_mat_rows(T);
    4877           0 :         if (isl_seq_first_non_zero(c, n) == -1)
    4878           0 :                 return isl_stat_ok;
    4879           0 :         ctx = isl_mat_get_ctx(T);
    4880           0 :         v = isl_vec_alloc(ctx, n);
    4881           0 :         if (!v)
    4882           0 :                 return isl_stat_error;
    4883           0 :         isl_seq_swp_or_cpy(v->el, c, n);
    4884           0 :         v = isl_vec_mat_product(v, isl_mat_copy(T));
    4885           0 :         if (!v)
    4886           0 :                 return isl_stat_error;
    4887           0 :         isl_seq_swp_or_cpy(c, v->el, n);
    4888           0 :         isl_vec_free(v);
    4889             : 
    4890           0 :         return isl_stat_ok;
    4891             : }
    4892             : 
    4893             : /* Plug in T for the variables in "bmap" starting at "pos".
    4894             :  * T is a linear unimodular matrix, i.e., without constant term.
    4895             :  */
    4896           0 : static __isl_give isl_basic_map *isl_basic_map_preimage_vars(
    4897             :         __isl_take isl_basic_map *bmap, unsigned pos, __isl_take isl_mat *T)
    4898             : {
    4899             :         int i;
    4900             :         unsigned n, total;
    4901             : 
    4902           0 :         bmap = isl_basic_map_cow(bmap);
    4903           0 :         if (!bmap || !T)
    4904             :                 goto error;
    4905             : 
    4906           0 :         n = isl_mat_cols(T);
    4907           0 :         if (n != isl_mat_rows(T))
    4908           0 :                 isl_die(isl_mat_get_ctx(T), isl_error_invalid,
    4909             :                         "expecting square matrix", goto error);
    4910             : 
    4911           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    4912           0 :         if (pos + n > total || pos + n < pos)
    4913           0 :                 isl_die(isl_mat_get_ctx(T), isl_error_invalid,
    4914             :                         "invalid range", goto error);
    4915             : 
    4916           0 :         for (i = 0; i < bmap->n_eq; ++i)
    4917           0 :                 if (preimage(bmap->eq[i] + 1 + pos, T) < 0)
    4918           0 :                         goto error;
    4919           0 :         for (i = 0; i < bmap->n_ineq; ++i)
    4920           0 :                 if (preimage(bmap->ineq[i] + 1 + pos, T) < 0)
    4921           0 :                         goto error;
    4922           0 :         for (i = 0; i < bmap->n_div; ++i) {
    4923           0 :                 if (isl_basic_map_div_is_marked_unknown(bmap, i))
    4924           0 :                         continue;
    4925           0 :                 if (preimage(bmap->div[i] + 1 + 1 + pos, T) < 0)
    4926           0 :                         goto error;
    4927             :         }
    4928             : 
    4929           0 :         isl_mat_free(T);
    4930           0 :         return bmap;
    4931             : error:
    4932           0 :         isl_basic_map_free(bmap);
    4933           0 :         isl_mat_free(T);
    4934           0 :         return NULL;
    4935             : }
    4936             : 
    4937             : /* Remove divs that are not strictly needed.
    4938             :  *
    4939             :  * First look for an equality constraint involving two or more
    4940             :  * existentially quantified variables without an explicit
    4941             :  * representation.  Replace the combination that appears
    4942             :  * in the equality constraint by a single existentially quantified
    4943             :  * variable such that the equality can be used to derive
    4944             :  * an explicit representation for the variable.
    4945             :  * If there are no more such equality constraints, then continue
    4946             :  * with isl_basic_map_drop_redundant_divs_ineq.
    4947             :  *
    4948             :  * In particular, if the equality constraint is of the form
    4949             :  *
    4950             :  *      f(x) + \sum_i c_i a_i = 0
    4951             :  *
    4952             :  * with a_i existentially quantified variable without explicit
    4953             :  * representation, then apply a transformation on the existentially
    4954             :  * quantified variables to turn the constraint into
    4955             :  *
    4956             :  *      f(x) + g a_1' = 0
    4957             :  *
    4958             :  * with g the gcd of the c_i.
    4959             :  * In order to easily identify which existentially quantified variables
    4960             :  * have a complete explicit representation, i.e., without being defined
    4961             :  * in terms of other existentially quantified variables without
    4962             :  * an explicit representation, the existentially quantified variables
    4963             :  * are first sorted.
    4964             :  *
    4965             :  * The variable transformation is computed by extending the row
    4966             :  * [c_1/g ... c_n/g] to a unimodular matrix, obtaining the transformation
    4967             :  *
    4968             :  *      [a_1']   [c_1/g ... c_n/g]   [ a_1 ]
    4969             :  *      [a_2']                       [ a_2 ]
    4970             :  *       ...   =         U             ....
    4971             :  *      [a_n']                       [ a_n ]
    4972             :  *
    4973             :  * with [c_1/g ... c_n/g] representing the first row of U.
    4974             :  * The inverse of U is then plugged into the original constraints.
    4975             :  * The call to isl_basic_map_simplify makes sure the explicit
    4976             :  * representation for a_1' is extracted from the equality constraint.
    4977             :  */
    4978           0 : __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs(
    4979             :         __isl_take isl_basic_map *bmap)
    4980             : {
    4981             :         int first;
    4982             :         int i;
    4983             :         unsigned o_div, n_div;
    4984             :         int l;
    4985             :         isl_ctx *ctx;
    4986             :         isl_mat *T;
    4987             : 
    4988           0 :         if (!bmap)
    4989           0 :                 return NULL;
    4990           0 :         if (isl_basic_map_divs_known(bmap))
    4991           0 :                 return isl_basic_map_drop_redundant_divs_ineq(bmap);
    4992           0 :         if (bmap->n_eq == 0)
    4993           0 :                 return isl_basic_map_drop_redundant_divs_ineq(bmap);
    4994           0 :         bmap = isl_basic_map_sort_divs(bmap);
    4995           0 :         if (!bmap)
    4996           0 :                 return NULL;
    4997             : 
    4998           0 :         first = isl_basic_map_first_unknown_div(bmap);
    4999           0 :         if (first < 0)
    5000           0 :                 return isl_basic_map_free(bmap);
    5001             : 
    5002           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
    5003           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    5004             : 
    5005           0 :         for (i = 0; i < bmap->n_eq; ++i) {
    5006           0 :                 l = isl_seq_first_non_zero(bmap->eq[i] + o_div + first,
    5007             :                                             n_div - (first));
    5008           0 :                 if (l < 0)
    5009           0 :                         continue;
    5010           0 :                 l += first;
    5011           0 :                 if (isl_seq_first_non_zero(bmap->eq[i] + o_div + l + 1,
    5012           0 :                                             n_div - (l + 1)) == -1)
    5013           0 :                         continue;
    5014           0 :                 break;
    5015             :         }
    5016           0 :         if (i >= bmap->n_eq)
    5017           0 :                 return isl_basic_map_drop_redundant_divs_ineq(bmap);
    5018             : 
    5019           0 :         ctx = isl_basic_map_get_ctx(bmap);
    5020           0 :         T = isl_mat_alloc(ctx, n_div - l, n_div - l);
    5021           0 :         if (!T)
    5022           0 :                 return isl_basic_map_free(bmap);
    5023           0 :         isl_seq_cpy(T->row[0], bmap->eq[i] + o_div + l, n_div - l);
    5024           0 :         T = isl_mat_normalize_row(T, 0);
    5025           0 :         T = isl_mat_unimodular_complete(T, 1);
    5026           0 :         T = isl_mat_right_inverse(T);
    5027             : 
    5028           0 :         for (i = l; i < n_div; ++i)
    5029           0 :                 bmap = isl_basic_map_mark_div_unknown(bmap, i);
    5030           0 :         bmap = isl_basic_map_preimage_vars(bmap, o_div - 1 + l, T);
    5031           0 :         bmap = isl_basic_map_simplify(bmap);
    5032             : 
    5033           0 :         return isl_basic_map_drop_redundant_divs(bmap);
    5034             : }
    5035             : 
    5036             : /* Does "bmap" satisfy any equality that involves more than 2 variables
    5037             :  * and/or has coefficients different from -1 and 1?
    5038             :  */
    5039     1129738 : static int has_multiple_var_equality(__isl_keep isl_basic_map *bmap)
    5040             : {
    5041             :         int i;
    5042             :         unsigned total;
    5043             : 
    5044     1129738 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    5045             : 
    5046     6238794 :         for (i = 0; i < bmap->n_eq; ++i) {
    5047             :                 int j, k;
    5048             : 
    5049     5128768 :                 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
    5050     5128768 :                 if (j < 0)
    5051           0 :                         continue;
    5052     5149001 :                 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
    5053       20233 :                     !isl_int_is_negone(bmap->eq[i][1 + j]))
    5054       15549 :                         return 1;
    5055             : 
    5056     5113219 :                 j += 1;
    5057     5113219 :                 k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j);
    5058     5113219 :                 if (k < 0)
    5059     5104383 :                         continue;
    5060        8836 :                 j += k;
    5061       12426 :                 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
    5062        3590 :                     !isl_int_is_negone(bmap->eq[i][1 + j]))
    5063        2904 :                         return 1;
    5064             : 
    5065        5932 :                 j += 1;
    5066        5932 :                 k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j);
    5067        5932 :                 if (k >= 0)
    5068        1259 :                         return 1;
    5069             :         }
    5070             : 
    5071     1110026 :         return 0;
    5072             : }
    5073             : 
    5074             : /* Remove any common factor g from the constraint coefficients in "v".
    5075             :  * The constant term is stored in the first position and is replaced
    5076             :  * by floor(c/g).  If any common factor is removed and if this results
    5077             :  * in a tightening of the constraint, then set *tightened.
    5078             :  */
    5079       95064 : static __isl_give isl_vec *normalize_constraint(__isl_take isl_vec *v,
    5080             :         int *tightened)
    5081             : {
    5082             :         isl_ctx *ctx;
    5083             : 
    5084       95064 :         if (!v)
    5085           0 :                 return NULL;
    5086       95064 :         ctx = isl_vec_get_ctx(v);
    5087       95064 :         isl_seq_gcd(v->el + 1, v->size - 1, &ctx->normalize_gcd);
    5088       95064 :         if (isl_int_is_zero(ctx->normalize_gcd))
    5089           0 :                 return v;
    5090       95064 :         if (isl_int_is_one(ctx->normalize_gcd))
    5091       54592 :                 return v;
    5092       40472 :         v = isl_vec_cow(v);
    5093       40472 :         if (!v)
    5094           0 :                 return NULL;
    5095       40472 :         if (tightened && !isl_int_is_divisible_by(v->el[0], ctx->normalize_gcd))
    5096        8766 :                 *tightened = 1;
    5097       40472 :         isl_int_fdiv_q(v->el[0], v->el[0], ctx->normalize_gcd);
    5098       40472 :         isl_seq_scale_down(v->el + 1, v->el + 1, ctx->normalize_gcd,
    5099       40472 :                                 v->size - 1);
    5100       40472 :         return v;
    5101             : }
    5102             : 
    5103             : /* If "bmap" is an integer set that satisfies any equality involving
    5104             :  * more than 2 variables and/or has coefficients different from -1 and 1,
    5105             :  * then use variable compression to reduce the coefficients by removing
    5106             :  * any (hidden) common factor.
    5107             :  * In particular, apply the variable compression to each constraint,
    5108             :  * factor out any common factor in the non-constant coefficients and
    5109             :  * then apply the inverse of the compression.
    5110             :  * At the end, we mark the basic map as having reduced constants.
    5111             :  * If this flag is still set on the next invocation of this function,
    5112             :  * then we skip the computation.
    5113             :  *
    5114             :  * Removing a common factor may result in a tightening of some of
    5115             :  * the constraints.  If this happens, then we may end up with two
    5116             :  * opposite inequalities that can be replaced by an equality.
    5117             :  * We therefore call isl_basic_map_detect_inequality_pairs,
    5118             :  * which checks for such pairs of inequalities as well as eliminate_divs_eq
    5119             :  * and isl_basic_map_gauss if such a pair was found.
    5120             :  *
    5121             :  * Tightening may also result in some other constraints becoming
    5122             :  * (rationally) redundant with respect to the tightened constraint
    5123             :  * (in combination with other constraints).  The basic map may
    5124             :  * therefore no longer be assumed to have no redundant constraints.
    5125             :  *
    5126             :  * Note that this function may leave the result in an inconsistent state.
    5127             :  * In particular, the constraints may not be gaussed.
    5128             :  * Unfortunately, isl_map_coalesce actually depends on this inconsistent state
    5129             :  * for some of the test cases to pass successfully.
    5130             :  * Any potential modification of the representation is therefore only
    5131             :  * performed on a single copy of the basic map.
    5132             :  */
    5133  2898920016 : __isl_give isl_basic_map *isl_basic_map_reduce_coefficients(
    5134             :         __isl_take isl_basic_map *bmap)
    5135             : {
    5136             :         unsigned total;
    5137             :         isl_ctx *ctx;
    5138             :         isl_vec *v;
    5139             :         isl_mat *eq, *T, *T2;
    5140             :         int i;
    5141             :         int tightened;
    5142             : 
    5143  2898920016 :         if (!bmap)
    5144           0 :                 return NULL;
    5145  2898920016 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS))
    5146         209 :                 return bmap;
    5147  2898919807 :         if (isl_basic_map_is_rational(bmap))
    5148  2897679204 :                 return bmap;
    5149     1240603 :         if (bmap->n_eq == 0)
    5150      110865 :                 return bmap;
    5151     1129738 :         if (!has_multiple_var_equality(bmap))
    5152     1110026 :                 return bmap;
    5153             : 
    5154       19712 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    5155       19712 :         ctx = isl_basic_map_get_ctx(bmap);
    5156       19712 :         v = isl_vec_alloc(ctx, 1 + total);
    5157       19712 :         if (!v)
    5158           0 :                 return isl_basic_map_free(bmap);
    5159             : 
    5160       19712 :         eq = isl_mat_sub_alloc6(ctx, bmap->eq, 0, bmap->n_eq, 0, 1 + total);
    5161       19712 :         T = isl_mat_variable_compression(eq, &T2);
    5162       19712 :         if (!T || !T2)
    5163             :                 goto error;
    5164       19712 :         if (T->n_col == 0) {
    5165           0 :                 isl_mat_free(T);
    5166           0 :                 isl_mat_free(T2);
    5167           0 :                 isl_vec_free(v);
    5168           0 :                 return isl_basic_map_set_to_empty(bmap);
    5169             :         }
    5170             : 
    5171       19712 :         bmap = isl_basic_map_cow(bmap);
    5172       19712 :         if (!bmap)
    5173           0 :                 goto error;
    5174             : 
    5175       19712 :         tightened = 0;
    5176      114776 :         for (i = 0; i < bmap->n_ineq; ++i) {
    5177       95064 :                 isl_seq_cpy(v->el, bmap->ineq[i], 1 + total);
    5178       95064 :                 v = isl_vec_mat_product(v, isl_mat_copy(T));
    5179       95064 :                 v = normalize_constraint(v, &tightened);
    5180       95064 :                 v = isl_vec_mat_product(v, isl_mat_copy(T2));
    5181       95064 :                 if (!v)
    5182           0 :                         goto error;
    5183       95064 :                 isl_seq_cpy(bmap->ineq[i], v->el, 1 + total);
    5184             :         }
    5185             : 
    5186       19712 :         isl_mat_free(T);
    5187       19712 :         isl_mat_free(T2);
    5188       19712 :         isl_vec_free(v);
    5189             : 
    5190       19712 :         ISL_F_SET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
    5191             : 
    5192       19712 :         if (tightened) {
    5193        7523 :                 int progress = 0;
    5194             : 
    5195        7523 :                 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
    5196        7523 :                 bmap = isl_basic_map_detect_inequality_pairs(bmap, &progress);
    5197        7523 :                 if (progress) {
    5198         218 :                         bmap = eliminate_divs_eq(bmap, &progress);
    5199         218 :                         bmap = isl_basic_map_gauss(bmap, NULL);
    5200             :                 }
    5201             :         }
    5202             : 
    5203       19712 :         return bmap;
    5204             : error:
    5205           0 :         isl_mat_free(T);
    5206           0 :         isl_mat_free(T2);
    5207           0 :         isl_vec_free(v);
    5208           0 :         return isl_basic_map_free(bmap);
    5209             : }
    5210             : 
    5211             : /* Shift the integer division at position "div" of "bmap"
    5212             :  * by "shift" times the variable at position "pos".
    5213             :  * "pos" is as determined by isl_basic_map_offset, i.e., pos == 0
    5214             :  * corresponds to the constant term.
    5215             :  *
    5216             :  * That is, if the integer division has the form
    5217             :  *
    5218             :  *      floor(f(x)/d)
    5219             :  *
    5220             :  * then replace it by
    5221             :  *
    5222             :  *      floor((f(x) + shift * d * x_pos)/d) - shift * x_pos
    5223             :  */
    5224           0 : __isl_give isl_basic_map *isl_basic_map_shift_div(
    5225             :         __isl_take isl_basic_map *bmap, int div, int pos, isl_int shift)
    5226             : {
    5227             :         int i;
    5228             :         unsigned total;
    5229             : 
    5230           0 :         if (isl_int_is_zero(shift))
    5231           0 :                 return bmap;
    5232           0 :         if (!bmap)
    5233           0 :                 return NULL;
    5234             : 
    5235           0 :         total = isl_basic_map_dim(bmap, isl_dim_all);
    5236           0 :         total -= isl_basic_map_dim(bmap, isl_dim_div);
    5237             : 
    5238           0 :         isl_int_addmul(bmap->div[div][1 + pos], shift, bmap->div[div][0]);
    5239             : 
    5240           0 :         for (i = 0; i < bmap->n_eq; ++i) {
    5241           0 :                 if (isl_int_is_zero(bmap->eq[i][1 + total + div]))
    5242           0 :                         continue;
    5243           0 :                 isl_int_submul(bmap->eq[i][pos],
    5244             :                                 shift, bmap->eq[i][1 + total + div]);
    5245             :         }
    5246           0 :         for (i = 0; i < bmap->n_ineq; ++i) {
    5247           0 :                 if (isl_int_is_zero(bmap->ineq[i][1 + total + div]))
    5248           0 :                         continue;
    5249           0 :                 isl_int_submul(bmap->ineq[i][pos],
    5250             :                                 shift, bmap->ineq[i][1 + total + div]);
    5251             :         }
    5252           0 :         for (i = 0; i < bmap->n_div; ++i) {
    5253           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
    5254           0 :                         continue;
    5255           0 :                 if (isl_int_is_zero(bmap->div[i][1 + 1 + total + div]))
    5256           0 :                         continue;
    5257           0 :                 isl_int_submul(bmap->div[i][1 + pos],
    5258             :                                 shift, bmap->div[i][1 + 1 + total + div]);
    5259             :         }
    5260             : 
    5261           0 :         return bmap;
    5262             : }

Generated by: LCOV version 1.12