LCOV - code coverage report
Current view: top level - metalib_isl - isl_map.c (source / functions) Hit Total Coverage
Test: 2018-10-31_point_maint_greina16.lcov Lines: 1117 6643 16.8 %
Date: 2018-11-01 11:27:00 Functions: 159 753 21.1 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008-2009 Katholieke Universiteit Leuven
       3             :  * Copyright 2010      INRIA Saclay
       4             :  * Copyright 2012-2014 Ecole Normale Superieure
       5             :  * Copyright 2014      INRIA Rocquencourt
       6             :  * Copyright 2016      INRIA Paris
       7             :  * Copyright 2016      Sven Verdoolaege
       8             :  *
       9             :  * Use of this software is governed by the MIT license
      10             :  *
      11             :  * Written by Sven Verdoolaege, K.U.Leuven, Departement
      12             :  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
      13             :  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
      14             :  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
      15             :  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
      16             :  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
      17             :  * B.P. 105 - 78153 Le Chesnay, France
      18             :  * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
      19             :  * CS 42112, 75589 Paris Cedex 12, France
      20             :  */
      21             : 
      22             : #include <string.h>
      23             : #include <isl_ctx_private.h>
      24             : #include <isl_map_private.h>
      25             : #include <isl_blk.h>
      26             : #include <isl/id.h>
      27             : #include <isl/constraint.h>
      28             : #include "isl_space_private.h"
      29             : #include "isl_equalities.h"
      30             : #include <isl_lp_private.h>
      31             : #include <isl_seq.h>
      32             : #include <isl/set.h>
      33             : #include <isl/map.h>
      34             : #include <isl_reordering.h>
      35             : #include "isl_sample.h"
      36             : #include <isl_sort.h>
      37             : #include "isl_tab.h"
      38             : #include <isl/vec.h>
      39             : #include <isl_mat_private.h>
      40             : #include <isl_vec_private.h>
      41             : #include <isl_dim_map.h>
      42             : #include <isl_local_space_private.h>
      43             : #include <isl_aff_private.h>
      44             : #include <isl_options_private.h>
      45             : #include <isl_morph.h>
      46             : #include <isl_val_private.h>
      47             : 
      48             : #include <bset_to_bmap.c>
      49             : #include <bset_from_bmap.c>
      50             : #include <set_to_map.c>
      51             : #include <set_from_map.c>
      52             : 
      53             : #undef TYPE
      54             : #define TYPE    isl_basic_map
      55             : #include "has_single_reference_templ.c"
      56             : 
      57  7006220366 : static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
      58             : {
      59  7006220366 :         switch (type) {
      60      112944 :         case isl_dim_param:     return dim->nparam;
      61           0 :         case isl_dim_in:        return dim->n_in;
      62  7006107422 :         case isl_dim_out:       return dim->n_out;
      63           0 :         case isl_dim_all:       return dim->nparam + dim->n_in + dim->n_out;
      64           0 :         default:                return 0;
      65             :         }
      66             : }
      67             : 
      68           0 : static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
      69             : {
      70           0 :         switch (type) {
      71           0 :         case isl_dim_param:     return 1;
      72           0 :         case isl_dim_in:        return 1 + dim->nparam;
      73           0 :         case isl_dim_out:       return 1 + dim->nparam + dim->n_in;
      74           0 :         default:                return 0;
      75             :         }
      76             : }
      77             : 
      78 >13075*10^7 : unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
      79             :                                 enum isl_dim_type type)
      80             : {
      81 >13075*10^7 :         if (!bmap)
      82           0 :                 return 0;
      83 >13075*10^7 :         switch (type) {
      84           0 :         case isl_dim_cst:       return 1;
      85             :         case isl_dim_param:
      86             :         case isl_dim_in:
      87 >12320*10^7 :         case isl_dim_out:       return isl_space_dim(bmap->dim, type);
      88  7547212309 :         case isl_dim_div:       return bmap->n_div;
      89     1149450 :         case isl_dim_all:       return isl_basic_map_total_dim(bmap);
      90           0 :         default:                return 0;
      91             :         }
      92             : }
      93             : 
      94             : /* Return the space of "map".
      95             :  */
      96   115239480 : __isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
      97             : {
      98   115239480 :         return map ? map->dim : NULL;
      99             : }
     100             : 
     101           0 : unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
     102             : {
     103           0 :         return map ? n(map->dim, type) : 0;
     104             : }
     105             : 
     106  7006220366 : unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
     107             : {
     108  7006220366 :         return set ? n(set->dim, type) : 0;
     109             : }
     110             : 
     111    18906741 : unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
     112             :                                         enum isl_dim_type type)
     113             : {
     114             :         isl_space *space;
     115             : 
     116    18906741 :         if (!bmap)
     117           0 :                 return 0;
     118             : 
     119    18906741 :         space = bmap->dim;
     120    18906741 :         switch (type) {
     121           0 :         case isl_dim_cst:       return 0;
     122           0 :         case isl_dim_param:     return 1;
     123           0 :         case isl_dim_in:        return 1 + space->nparam;
     124    17789123 :         case isl_dim_out:       return 1 + space->nparam + space->n_in;
     125     2235236 :         case isl_dim_div:       return 1 + space->nparam + space->n_in +
     126     1117618 :                                                                 space->n_out;
     127           0 :         default:                return 0;
     128             :         }
     129             : }
     130             : 
     131           0 : unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
     132             :                                         enum isl_dim_type type)
     133             : {
     134           0 :         return isl_basic_map_offset(bset, type);
     135             : }
     136             : 
     137           0 : static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
     138             : {
     139           0 :         return pos(map->dim, type);
     140             : }
     141             : 
     142 12550787499 : unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
     143             :                                 enum isl_dim_type type)
     144             : {
     145 12550787499 :         return isl_basic_map_dim(bset, type);
     146             : }
     147             : 
     148  7078525128 : unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
     149             : {
     150  7078525128 :         return isl_basic_set_dim(bset, isl_dim_set);
     151             : }
     152             : 
     153  5382797331 : unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
     154             : {
     155  5382797331 :         return isl_basic_set_dim(bset, isl_dim_param);
     156             : }
     157             : 
     158  2204713082 : unsigned isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
     159             : {
     160  2204713082 :         if (!bset)
     161           0 :                 return 0;
     162  2204713082 :         return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
     163             : }
     164             : 
     165  7005994478 : unsigned isl_set_n_dim(__isl_keep isl_set *set)
     166             : {
     167  7005994478 :         return isl_set_dim(set, isl_dim_set);
     168             : }
     169             : 
     170           0 : unsigned isl_set_n_param(__isl_keep isl_set *set)
     171             : {
     172           0 :         return isl_set_dim(set, isl_dim_param);
     173             : }
     174             : 
     175           0 : unsigned isl_basic_map_n_in(__isl_keep const isl_basic_map *bmap)
     176             : {
     177           0 :         return bmap ? bmap->dim->n_in : 0;
     178             : }
     179             : 
     180           0 : unsigned isl_basic_map_n_out(__isl_keep const isl_basic_map *bmap)
     181             : {
     182           0 :         return bmap ? bmap->dim->n_out : 0;
     183             : }
     184             : 
     185           0 : unsigned isl_basic_map_n_param(__isl_keep const isl_basic_map *bmap)
     186             : {
     187           0 :         return bmap ? bmap->dim->nparam : 0;
     188             : }
     189             : 
     190           0 : unsigned isl_basic_map_n_div(__isl_keep const isl_basic_map *bmap)
     191             : {
     192           0 :         return bmap ? bmap->n_div : 0;
     193             : }
     194             : 
     195 >26899*10^7 : unsigned isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
     196             : {
     197 >26899*10^7 :         return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
     198             : }
     199             : 
     200           0 : unsigned isl_map_n_in(__isl_keep const isl_map *map)
     201             : {
     202           0 :         return map ? map->dim->n_in : 0;
     203             : }
     204             : 
     205           0 : unsigned isl_map_n_out(__isl_keep const isl_map *map)
     206             : {
     207           0 :         return map ? map->dim->n_out : 0;
     208             : }
     209             : 
     210           0 : unsigned isl_map_n_param(__isl_keep const isl_map *map)
     211             : {
     212           0 :         return map ? map->dim->nparam : 0;
     213             : }
     214             : 
     215             : /* Return the number of equality constraints in the description of "bmap".
     216             :  * Return -1 on error.
     217             :  */
     218  8206588573 : int isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
     219             : {
     220  8206588573 :         if (!bmap)
     221           0 :                 return -1;
     222  8206588573 :         return bmap->n_eq;
     223             : }
     224             : 
     225             : /* Return the number of equality constraints in the description of "bset".
     226             :  * Return -1 on error.
     227             :  */
     228  1211723574 : int isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
     229             : {
     230  1211723574 :         return isl_basic_map_n_equality(bset_to_bmap(bset));
     231             : }
     232             : 
     233             : /* Return the number of inequality constraints in the description of "bmap".
     234             :  * Return -1 on error.
     235             :  */
     236  9350011720 : int isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
     237             : {
     238  9350011720 :         if (!bmap)
     239           0 :                 return -1;
     240  9350011720 :         return bmap->n_ineq;
     241             : }
     242             : 
     243             : /* Return the number of inequality constraints in the description of "bset".
     244             :  * Return -1 on error.
     245             :  */
     246           0 : int isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
     247             : {
     248           0 :         return isl_basic_map_n_inequality(bset_to_bmap(bset));
     249             : }
     250             : 
     251             : /* Do "bmap1" and "bmap2" have the same parameters?
     252             :  */
     253   110183997 : static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
     254             :         __isl_keep isl_basic_map *bmap2)
     255             : {
     256             :         isl_space *space1, *space2;
     257             : 
     258   110183997 :         space1 = isl_basic_map_peek_space(bmap1);
     259   110183997 :         space2 = isl_basic_map_peek_space(bmap2);
     260   110183997 :         return isl_space_has_equal_params(space1, space2);
     261             : }
     262             : 
     263             : /* Do "map1" and "map2" have the same parameters?
     264             :  */
     265    55124743 : isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
     266             :         __isl_keep isl_map *map2)
     267             : {
     268             :         isl_space *space1, *space2;
     269             : 
     270    55124743 :         space1 = isl_map_peek_space(map1);
     271    55124743 :         space2 = isl_map_peek_space(map2);
     272    55124743 :         return isl_space_has_equal_params(space1, space2);
     273             : }
     274             : 
     275             : /* Do "map" and "set" have the same parameters?
     276             :  */
     277           0 : static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
     278             :         __isl_keep isl_set *set)
     279             : {
     280           0 :         return isl_map_has_equal_params(map, set_to_map(set));
     281             : }
     282             : 
     283           0 : isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
     284             :         __isl_keep isl_set *set)
     285             : {
     286             :         isl_bool m;
     287           0 :         if (!map || !set)
     288           0 :                 return isl_bool_error;
     289           0 :         m = isl_map_has_equal_params(map, set_to_map(set));
     290           0 :         if (m < 0 || !m)
     291           0 :                 return m;
     292           0 :         return isl_space_tuple_is_equal(map->dim, isl_dim_in,
     293             :                                         set->dim, isl_dim_set);
     294             : }
     295             : 
     296           0 : isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
     297             :         __isl_keep isl_basic_set *bset)
     298             : {
     299             :         isl_bool m;
     300           0 :         if (!bmap || !bset)
     301           0 :                 return isl_bool_error;
     302           0 :         m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
     303           0 :         if (m < 0 || !m)
     304           0 :                 return m;
     305           0 :         return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
     306             :                                         bset->dim, isl_dim_set);
     307             : }
     308             : 
     309           0 : isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
     310             :         __isl_keep isl_set *set)
     311             : {
     312             :         isl_bool m;
     313           0 :         if (!map || !set)
     314           0 :                 return isl_bool_error;
     315           0 :         m = isl_map_has_equal_params(map, set_to_map(set));
     316           0 :         if (m < 0 || !m)
     317           0 :                 return m;
     318           0 :         return isl_space_tuple_is_equal(map->dim, isl_dim_out,
     319             :                                         set->dim, isl_dim_set);
     320             : }
     321             : 
     322           0 : isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
     323             :         __isl_keep isl_basic_set *bset)
     324             : {
     325             :         isl_bool m;
     326           0 :         if (!bmap || !bset)
     327           0 :                 return isl_bool_error;
     328           0 :         m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
     329           0 :         if (m < 0 || !m)
     330           0 :                 return m;
     331           0 :         return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
     332             :                                         bset->dim, isl_dim_set);
     333             : }
     334             : 
     335 18208849539 : isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
     336             : {
     337 18208849539 :         return bmap ? bmap->ctx : NULL;
     338             : }
     339             : 
     340    43381213 : isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
     341             : {
     342    43381213 :         return bset ? bset->ctx : NULL;
     343             : }
     344             : 
     345  1208338725 : isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
     346             : {
     347  1208338725 :         return map ? map->ctx : NULL;
     348             : }
     349             : 
     350      225888 : isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
     351             : {
     352      225888 :         return set ? set->ctx : NULL;
     353             : }
     354             : 
     355             : /* Return the space of "bmap".
     356             :  */
     357  2994676980 : __isl_keep isl_space *isl_basic_map_peek_space(
     358             :         __isl_keep const isl_basic_map *bmap)
     359             : {
     360  2994676980 :         return bmap ? bmap->dim : NULL;
     361             : }
     362             : 
     363             : /* Return the space of "bset".
     364             :  */
     365           0 : __isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
     366             : {
     367           0 :         return isl_basic_map_peek_space(bset_to_bmap(bset));
     368             : }
     369             : 
     370   662155962 : __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
     371             : {
     372   662155962 :         return isl_space_copy(isl_basic_map_peek_space(bmap));
     373             : }
     374             : 
     375     7938506 : __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
     376             : {
     377     7938506 :         return isl_basic_map_get_space(bset_to_bmap(bset));
     378             : }
     379             : 
     380             : /* Extract the divs in "bmap" as a matrix.
     381             :  */
     382     1117618 : __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
     383             : {
     384             :         int i;
     385             :         isl_ctx *ctx;
     386             :         isl_mat *div;
     387             :         unsigned total;
     388             :         unsigned cols;
     389             : 
     390     1117618 :         if (!bmap)
     391           0 :                 return NULL;
     392             : 
     393     1117618 :         ctx = isl_basic_map_get_ctx(bmap);
     394     1117618 :         total = isl_space_dim(bmap->dim, isl_dim_all);
     395     1117618 :         cols = 1 + 1 + total + bmap->n_div;
     396     1117618 :         div = isl_mat_alloc(ctx, bmap->n_div, cols);
     397     1117618 :         if (!div)
     398           0 :                 return NULL;
     399             : 
     400     1117618 :         for (i = 0; i < bmap->n_div; ++i)
     401           0 :                 isl_seq_cpy(div->row[i], bmap->div[i], cols);
     402             : 
     403     1117618 :         return div;
     404             : }
     405             : 
     406             : /* Extract the divs in "bset" as a matrix.
     407             :  */
     408           0 : __isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
     409             : {
     410           0 :         return isl_basic_map_get_divs(bset);
     411             : }
     412             : 
     413           0 : __isl_give isl_local_space *isl_basic_map_get_local_space(
     414             :         __isl_keep isl_basic_map *bmap)
     415             : {
     416             :         isl_mat *div;
     417             : 
     418           0 :         if (!bmap)
     419           0 :                 return NULL;
     420             : 
     421           0 :         div = isl_basic_map_get_divs(bmap);
     422           0 :         return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
     423             : }
     424             : 
     425           0 : __isl_give isl_local_space *isl_basic_set_get_local_space(
     426             :         __isl_keep isl_basic_set *bset)
     427             : {
     428           0 :         return isl_basic_map_get_local_space(bset);
     429             : }
     430             : 
     431             : /* For each known div d = floor(f/m), add the constraints
     432             :  *
     433             :  *              f - m d >= 0
     434             :  *              -(f-(m-1)) + m d >= 0
     435             :  *
     436             :  * Do not finalize the result.
     437             :  */
     438           0 : static __isl_give isl_basic_map *add_known_div_constraints(
     439             :         __isl_take isl_basic_map *bmap)
     440             : {
     441             :         int i;
     442             :         unsigned n_div;
     443             : 
     444           0 :         if (!bmap)
     445           0 :                 return NULL;
     446           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
     447           0 :         if (n_div == 0)
     448           0 :                 return bmap;
     449           0 :         bmap = isl_basic_map_cow(bmap);
     450           0 :         bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
     451           0 :         if (!bmap)
     452           0 :                 return NULL;
     453           0 :         for (i = 0; i < n_div; ++i) {
     454           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
     455           0 :                         continue;
     456           0 :                 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
     457           0 :                         return isl_basic_map_free(bmap);
     458             :         }
     459             : 
     460           0 :         return bmap;
     461             : }
     462             : 
     463           0 : __isl_give isl_basic_map *isl_basic_map_from_local_space(
     464             :         __isl_take isl_local_space *ls)
     465             : {
     466             :         int i;
     467             :         int n_div;
     468             :         isl_basic_map *bmap;
     469             : 
     470           0 :         if (!ls)
     471           0 :                 return NULL;
     472             : 
     473           0 :         n_div = isl_local_space_dim(ls, isl_dim_div);
     474           0 :         bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
     475           0 :                                         n_div, 0, 2 * n_div);
     476             : 
     477           0 :         for (i = 0; i < n_div; ++i)
     478           0 :                 if (isl_basic_map_alloc_div(bmap) < 0)
     479           0 :                         goto error;
     480             : 
     481           0 :         for (i = 0; i < n_div; ++i)
     482           0 :                 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
     483           0 :         bmap = add_known_div_constraints(bmap);
     484             :                                         
     485           0 :         isl_local_space_free(ls);
     486           0 :         return bmap;
     487             : error:
     488           0 :         isl_local_space_free(ls);
     489           0 :         isl_basic_map_free(bmap);
     490           0 :         return NULL;
     491             : }
     492             : 
     493           0 : __isl_give isl_basic_set *isl_basic_set_from_local_space(
     494             :         __isl_take isl_local_space *ls)
     495             : {
     496           0 :         return isl_basic_map_from_local_space(ls);
     497             : }
     498             : 
     499     4989994 : __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
     500             : {
     501     4989994 :         return isl_space_copy(isl_map_peek_space(map));
     502             : }
     503             : 
     504           0 : __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
     505             : {
     506           0 :         if (!set)
     507           0 :                 return NULL;
     508           0 :         return isl_space_copy(set->dim);
     509             : }
     510             : 
     511           0 : __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
     512             :         __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
     513             : {
     514           0 :         bmap = isl_basic_map_cow(bmap);
     515           0 :         if (!bmap)
     516           0 :                 return NULL;
     517           0 :         bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
     518           0 :         if (!bmap->dim)
     519           0 :                 goto error;
     520           0 :         bmap = isl_basic_map_finalize(bmap);
     521           0 :         return bmap;
     522             : error:
     523           0 :         isl_basic_map_free(bmap);
     524           0 :         return NULL;
     525             : }
     526             : 
     527           0 : __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
     528             :         __isl_take isl_basic_set *bset, const char *s)
     529             : {
     530           0 :         return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
     531             : }
     532             : 
     533           0 : const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
     534             :         enum isl_dim_type type)
     535             : {
     536           0 :         return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
     537             : }
     538             : 
     539           0 : __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
     540             :         enum isl_dim_type type, const char *s)
     541             : {
     542             :         int i;
     543             : 
     544           0 :         map = isl_map_cow(map);
     545           0 :         if (!map)
     546           0 :                 return NULL;
     547             : 
     548           0 :         map->dim = isl_space_set_tuple_name(map->dim, type, s);
     549           0 :         if (!map->dim)
     550           0 :                 goto error;
     551             : 
     552           0 :         for (i = 0; i < map->n; ++i) {
     553           0 :                 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
     554           0 :                 if (!map->p[i])
     555           0 :                         goto error;
     556             :         }
     557             : 
     558           0 :         return map;
     559             : error:
     560           0 :         isl_map_free(map);
     561           0 :         return NULL;
     562             : }
     563             : 
     564             : /* Replace the identifier of the tuple of type "type" by "id".
     565             :  */
     566           0 : __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
     567             :         __isl_take isl_basic_map *bmap,
     568             :         enum isl_dim_type type, __isl_take isl_id *id)
     569             : {
     570           0 :         bmap = isl_basic_map_cow(bmap);
     571           0 :         if (!bmap)
     572           0 :                 goto error;
     573           0 :         bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
     574           0 :         if (!bmap->dim)
     575           0 :                 return isl_basic_map_free(bmap);
     576           0 :         bmap = isl_basic_map_finalize(bmap);
     577           0 :         return bmap;
     578             : error:
     579           0 :         isl_id_free(id);
     580           0 :         return NULL;
     581             : }
     582             : 
     583             : /* Replace the identifier of the tuple by "id".
     584             :  */
     585           0 : __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
     586             :         __isl_take isl_basic_set *bset, __isl_take isl_id *id)
     587             : {
     588           0 :         return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
     589             : }
     590             : 
     591             : /* Does the input or output tuple have a name?
     592             :  */
     593           0 : isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
     594             : {
     595           0 :         return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
     596             : }
     597             : 
     598           0 : const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
     599             :         enum isl_dim_type type)
     600             : {
     601           0 :         return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
     602             : }
     603             : 
     604           0 : __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
     605             :         const char *s)
     606             : {
     607           0 :         return set_from_map(isl_map_set_tuple_name(set_to_map(set),
     608             :                                                 isl_dim_set, s));
     609             : }
     610             : 
     611           0 : __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
     612             :         enum isl_dim_type type, __isl_take isl_id *id)
     613             : {
     614           0 :         map = isl_map_cow(map);
     615           0 :         if (!map)
     616           0 :                 goto error;
     617             : 
     618           0 :         map->dim = isl_space_set_tuple_id(map->dim, type, id);
     619             : 
     620           0 :         return isl_map_reset_space(map, isl_space_copy(map->dim));
     621             : error:
     622           0 :         isl_id_free(id);
     623           0 :         return NULL;
     624             : }
     625             : 
     626           0 : __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
     627             :         __isl_take isl_id *id)
     628             : {
     629           0 :         return isl_map_set_tuple_id(set, isl_dim_set, id);
     630             : }
     631             : 
     632           0 : __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
     633             :         enum isl_dim_type type)
     634             : {
     635           0 :         map = isl_map_cow(map);
     636           0 :         if (!map)
     637           0 :                 return NULL;
     638             : 
     639           0 :         map->dim = isl_space_reset_tuple_id(map->dim, type);
     640             : 
     641           0 :         return isl_map_reset_space(map, isl_space_copy(map->dim));
     642             : }
     643             : 
     644           0 : __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
     645             : {
     646           0 :         return isl_map_reset_tuple_id(set, isl_dim_set);
     647             : }
     648             : 
     649           0 : isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
     650             : {
     651           0 :         return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
     652             : }
     653             : 
     654           0 : __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
     655             :         enum isl_dim_type type)
     656             : {
     657           0 :         return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
     658             : }
     659             : 
     660           0 : isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
     661             : {
     662           0 :         return isl_map_has_tuple_id(set, isl_dim_set);
     663             : }
     664             : 
     665           0 : __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
     666             : {
     667           0 :         return isl_map_get_tuple_id(set, isl_dim_set);
     668             : }
     669             : 
     670             : /* Does the set tuple have a name?
     671             :  */
     672           0 : isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
     673             : {
     674           0 :         if (!set)
     675           0 :                 return isl_bool_error;
     676           0 :         return isl_space_has_tuple_name(set->dim, isl_dim_set);
     677             : }
     678             : 
     679             : 
     680           0 : const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
     681             : {
     682           0 :         return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
     683             : }
     684             : 
     685           0 : const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
     686             : {
     687           0 :         return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
     688             : }
     689             : 
     690           0 : const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
     691             :         enum isl_dim_type type, unsigned pos)
     692             : {
     693           0 :         return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
     694             : }
     695             : 
     696           0 : const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
     697             :         enum isl_dim_type type, unsigned pos)
     698             : {
     699           0 :         return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
     700             : }
     701             : 
     702             : /* Does the given dimension have a name?
     703             :  */
     704           0 : isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
     705             :         enum isl_dim_type type, unsigned pos)
     706             : {
     707           0 :         if (!map)
     708           0 :                 return isl_bool_error;
     709           0 :         return isl_space_has_dim_name(map->dim, type, pos);
     710             : }
     711             : 
     712           0 : const char *isl_map_get_dim_name(__isl_keep isl_map *map,
     713             :         enum isl_dim_type type, unsigned pos)
     714             : {
     715           0 :         return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
     716             : }
     717             : 
     718           0 : const char *isl_set_get_dim_name(__isl_keep isl_set *set,
     719             :         enum isl_dim_type type, unsigned pos)
     720             : {
     721           0 :         return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
     722             : }
     723             : 
     724             : /* Does the given dimension have a name?
     725             :  */
     726           0 : isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
     727             :         enum isl_dim_type type, unsigned pos)
     728             : {
     729           0 :         if (!set)
     730           0 :                 return isl_bool_error;
     731           0 :         return isl_space_has_dim_name(set->dim, type, pos);
     732             : }
     733             : 
     734           0 : __isl_give isl_basic_map *isl_basic_map_set_dim_name(
     735             :         __isl_take isl_basic_map *bmap,
     736             :         enum isl_dim_type type, unsigned pos, const char *s)
     737             : {
     738           0 :         bmap = isl_basic_map_cow(bmap);
     739           0 :         if (!bmap)
     740           0 :                 return NULL;
     741           0 :         bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
     742           0 :         if (!bmap->dim)
     743           0 :                 goto error;
     744           0 :         return isl_basic_map_finalize(bmap);
     745             : error:
     746           0 :         isl_basic_map_free(bmap);
     747           0 :         return NULL;
     748             : }
     749             : 
     750           0 : __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
     751             :         enum isl_dim_type type, unsigned pos, const char *s)
     752             : {
     753             :         int i;
     754             : 
     755           0 :         map = isl_map_cow(map);
     756           0 :         if (!map)
     757           0 :                 return NULL;
     758             : 
     759           0 :         map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
     760           0 :         if (!map->dim)
     761           0 :                 goto error;
     762             : 
     763           0 :         for (i = 0; i < map->n; ++i) {
     764           0 :                 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
     765           0 :                 if (!map->p[i])
     766           0 :                         goto error;
     767             :         }
     768             : 
     769           0 :         return map;
     770             : error:
     771           0 :         isl_map_free(map);
     772           0 :         return NULL;
     773             : }
     774             : 
     775           0 : __isl_give isl_basic_set *isl_basic_set_set_dim_name(
     776             :         __isl_take isl_basic_set *bset,
     777             :         enum isl_dim_type type, unsigned pos, const char *s)
     778             : {
     779           0 :         return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
     780             :                                                         type, pos, s));
     781             : }
     782             : 
     783           0 : __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
     784             :         enum isl_dim_type type, unsigned pos, const char *s)
     785             : {
     786           0 :         return set_from_map(isl_map_set_dim_name(set_to_map(set),
     787             :                                                         type, pos, s));
     788             : }
     789             : 
     790           0 : isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
     791             :         enum isl_dim_type type, unsigned pos)
     792             : {
     793           0 :         if (!bmap)
     794           0 :                 return isl_bool_error;
     795           0 :         return isl_space_has_dim_id(bmap->dim, type, pos);
     796             : }
     797             : 
     798           0 : __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
     799             :         enum isl_dim_type type, unsigned pos)
     800             : {
     801           0 :         return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
     802             : }
     803             : 
     804           0 : isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
     805             :         enum isl_dim_type type, unsigned pos)
     806             : {
     807           0 :         return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
     808             : }
     809             : 
     810           0 : __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
     811             :         enum isl_dim_type type, unsigned pos)
     812             : {
     813           0 :         return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
     814             : }
     815             : 
     816           0 : isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
     817             :         enum isl_dim_type type, unsigned pos)
     818             : {
     819           0 :         return isl_map_has_dim_id(set, type, pos);
     820             : }
     821             : 
     822           0 : __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
     823             :         enum isl_dim_type type, unsigned pos)
     824             : {
     825           0 :         return isl_map_get_dim_id(set, type, pos);
     826             : }
     827             : 
     828           0 : __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
     829             :         enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
     830             : {
     831           0 :         map = isl_map_cow(map);
     832           0 :         if (!map)
     833           0 :                 goto error;
     834             : 
     835           0 :         map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
     836             : 
     837           0 :         return isl_map_reset_space(map, isl_space_copy(map->dim));
     838             : error:
     839           0 :         isl_id_free(id);
     840           0 :         return NULL;
     841             : }
     842             : 
     843           0 : __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
     844             :         enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
     845             : {
     846           0 :         return isl_map_set_dim_id(set, type, pos, id);
     847             : }
     848             : 
     849           0 : int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
     850             :         __isl_keep isl_id *id)
     851             : {
     852           0 :         if (!map)
     853           0 :                 return -1;
     854           0 :         return isl_space_find_dim_by_id(map->dim, type, id);
     855             : }
     856             : 
     857           0 : int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
     858             :         __isl_keep isl_id *id)
     859             : {
     860           0 :         return isl_map_find_dim_by_id(set, type, id);
     861             : }
     862             : 
     863             : /* Return the position of the dimension of the given type and name
     864             :  * in "bmap".
     865             :  * Return -1 if no such dimension can be found.
     866             :  */
     867           0 : int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
     868             :         enum isl_dim_type type, const char *name)
     869             : {
     870           0 :         if (!bmap)
     871           0 :                 return -1;
     872           0 :         return isl_space_find_dim_by_name(bmap->dim, type, name);
     873             : }
     874             : 
     875           0 : int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
     876             :         const char *name)
     877             : {
     878           0 :         if (!map)
     879           0 :                 return -1;
     880           0 :         return isl_space_find_dim_by_name(map->dim, type, name);
     881             : }
     882             : 
     883           0 : int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
     884             :         const char *name)
     885             : {
     886           0 :         return isl_map_find_dim_by_name(set, type, name);
     887             : }
     888             : 
     889             : /* Check whether equality i of bset is a pure stride constraint
     890             :  * on a single dimension, i.e., of the form
     891             :  *
     892             :  *      v = k e
     893             :  *
     894             :  * with k a constant and e an existentially quantified variable.
     895             :  */
     896           0 : isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
     897             : {
     898             :         unsigned nparam;
     899             :         unsigned d;
     900             :         unsigned n_div;
     901             :         int pos1;
     902             :         int pos2;
     903             : 
     904           0 :         if (!bset)
     905           0 :                 return isl_bool_error;
     906             : 
     907           0 :         if (!isl_int_is_zero(bset->eq[i][0]))
     908           0 :                 return isl_bool_false;
     909             : 
     910           0 :         nparam = isl_basic_set_dim(bset, isl_dim_param);
     911           0 :         d = isl_basic_set_dim(bset, isl_dim_set);
     912           0 :         n_div = isl_basic_set_dim(bset, isl_dim_div);
     913             : 
     914           0 :         if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
     915           0 :                 return isl_bool_false;
     916           0 :         pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
     917           0 :         if (pos1 == -1)
     918           0 :                 return isl_bool_false;
     919           0 :         if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
     920           0 :                                         d - pos1 - 1) != -1)
     921           0 :                 return isl_bool_false;
     922             : 
     923           0 :         pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
     924           0 :         if (pos2 == -1)
     925           0 :                 return isl_bool_false;
     926           0 :         if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d  + pos2 + 1,
     927           0 :                                    n_div - pos2 - 1) != -1)
     928           0 :                 return isl_bool_false;
     929           0 :         if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
     930           0 :             !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
     931           0 :                 return isl_bool_false;
     932             : 
     933           0 :         return isl_bool_true;
     934             : }
     935             : 
     936             : /* Reset the user pointer on all identifiers of parameters and tuples
     937             :  * of the space of "map".
     938             :  */
     939           0 : __isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
     940             : {
     941             :         isl_space *space;
     942             : 
     943           0 :         space = isl_map_get_space(map);
     944           0 :         space = isl_space_reset_user(space);
     945           0 :         map = isl_map_reset_space(map, space);
     946             : 
     947           0 :         return map;
     948             : }
     949             : 
     950             : /* Reset the user pointer on all identifiers of parameters and tuples
     951             :  * of the space of "set".
     952             :  */
     953           0 : __isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
     954             : {
     955           0 :         return isl_map_reset_user(set);
     956             : }
     957             : 
     958  2909068323 : isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
     959             : {
     960  2909068323 :         if (!bmap)
     961           0 :                 return isl_bool_error;
     962  2909068323 :         return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
     963             : }
     964             : 
     965             : /* Has "map" been marked as a rational map?
     966             :  * In particular, have all basic maps in "map" been marked this way?
     967             :  * An empty map is not considered to be rational.
     968             :  * Maps where only some of the basic maps are marked rational
     969             :  * are not allowed.
     970             :  */
     971           0 : isl_bool isl_map_is_rational(__isl_keep isl_map *map)
     972             : {
     973             :         int i;
     974             :         isl_bool rational;
     975             : 
     976           0 :         if (!map)
     977           0 :                 return isl_bool_error;
     978           0 :         if (map->n == 0)
     979           0 :                 return isl_bool_false;
     980           0 :         rational = isl_basic_map_is_rational(map->p[0]);
     981           0 :         if (rational < 0)
     982           0 :                 return rational;
     983           0 :         for (i = 1; i < map->n; ++i) {
     984             :                 isl_bool rational_i;
     985             : 
     986           0 :                 rational_i = isl_basic_map_is_rational(map->p[i]);
     987           0 :                 if (rational_i < 0)
     988           0 :                         return rational_i;
     989           0 :                 if (rational != rational_i)
     990           0 :                         isl_die(isl_map_get_ctx(map), isl_error_unsupported,
     991             :                                 "mixed rational and integer basic maps "
     992             :                                 "not supported", return isl_bool_error);
     993             :         }
     994             : 
     995           0 :         return rational;
     996             : }
     997             : 
     998             : /* Has "set" been marked as a rational set?
     999             :  * In particular, have all basic set in "set" been marked this way?
    1000             :  * An empty set is not considered to be rational.
    1001             :  * Sets where only some of the basic sets are marked rational
    1002             :  * are not allowed.
    1003             :  */
    1004           0 : isl_bool isl_set_is_rational(__isl_keep isl_set *set)
    1005             : {
    1006           0 :         return isl_map_is_rational(set);
    1007             : }
    1008             : 
    1009      129106 : int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
    1010             : {
    1011      129106 :         return isl_basic_map_is_rational(bset);
    1012             : }
    1013             : 
    1014             : /* Does "bmap" contain any rational points?
    1015             :  *
    1016             :  * If "bmap" has an equality for each dimension, equating the dimension
    1017             :  * to an integer constant, then it has no rational points, even if it
    1018             :  * is marked as rational.
    1019             :  */
    1020    10019410 : isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
    1021             : {
    1022    10019410 :         isl_bool has_rational = isl_bool_true;
    1023             :         unsigned total;
    1024             : 
    1025    10019410 :         if (!bmap)
    1026           0 :                 return isl_bool_error;
    1027    10019410 :         if (isl_basic_map_plain_is_empty(bmap))
    1028           0 :                 return isl_bool_false;
    1029    10019410 :         if (!isl_basic_map_is_rational(bmap))
    1030    10019410 :                 return isl_bool_false;
    1031           0 :         bmap = isl_basic_map_copy(bmap);
    1032           0 :         bmap = isl_basic_map_implicit_equalities(bmap);
    1033           0 :         if (!bmap)
    1034           0 :                 return isl_bool_error;
    1035           0 :         total = isl_basic_map_total_dim(bmap);
    1036           0 :         if (bmap->n_eq == total) {
    1037             :                 int i, j;
    1038           0 :                 for (i = 0; i < bmap->n_eq; ++i) {
    1039           0 :                         j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
    1040           0 :                         if (j < 0)
    1041           0 :                                 break;
    1042           0 :                         if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
    1043           0 :                             !isl_int_is_negone(bmap->eq[i][1 + j]))
    1044           0 :                                 break;
    1045           0 :                         j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
    1046           0 :                                                     total - j - 1);
    1047           0 :                         if (j >= 0)
    1048           0 :                                 break;
    1049             :                 }
    1050           0 :                 if (i == bmap->n_eq)
    1051           0 :                         has_rational = isl_bool_false;
    1052             :         }
    1053           0 :         isl_basic_map_free(bmap);
    1054             : 
    1055           0 :         return has_rational;
    1056             : }
    1057             : 
    1058             : /* Does "map" contain any rational points?
    1059             :  */
    1060      406980 : isl_bool isl_map_has_rational(__isl_keep isl_map *map)
    1061             : {
    1062             :         int i;
    1063             :         isl_bool has_rational;
    1064             : 
    1065      406980 :         if (!map)
    1066           0 :                 return isl_bool_error;
    1067    10426390 :         for (i = 0; i < map->n; ++i) {
    1068    10019410 :                 has_rational = isl_basic_map_has_rational(map->p[i]);
    1069    10019410 :                 if (has_rational < 0 || has_rational)
    1070           0 :                         return has_rational;
    1071             :         }
    1072      406980 :         return isl_bool_false;
    1073             : }
    1074             : 
    1075             : /* Does "set" contain any rational points?
    1076             :  */
    1077           0 : isl_bool isl_set_has_rational(__isl_keep isl_set *set)
    1078             : {
    1079           0 :         return isl_map_has_rational(set);
    1080             : }
    1081             : 
    1082             : /* Is this basic set a parameter domain?
    1083             :  */
    1084           0 : isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
    1085             : {
    1086           0 :         if (!bset)
    1087           0 :                 return isl_bool_error;
    1088           0 :         return isl_space_is_params(bset->dim);
    1089             : }
    1090             : 
    1091             : /* Is this set a parameter domain?
    1092             :  */
    1093           0 : isl_bool isl_set_is_params(__isl_keep isl_set *set)
    1094             : {
    1095           0 :         if (!set)
    1096           0 :                 return isl_bool_error;
    1097           0 :         return isl_space_is_params(set->dim);
    1098             : }
    1099             : 
    1100             : /* Is this map actually a parameter domain?
    1101             :  * Users should never call this function.  Outside of isl,
    1102             :  * a map can never be a parameter domain.
    1103             :  */
    1104           0 : isl_bool isl_map_is_params(__isl_keep isl_map *map)
    1105             : {
    1106           0 :         if (!map)
    1107           0 :                 return isl_bool_error;
    1108           0 :         return isl_space_is_params(map->dim);
    1109             : }
    1110             : 
    1111 26025648161 : static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
    1112             :                 struct isl_basic_map *bmap, unsigned extra,
    1113             :                 unsigned n_eq, unsigned n_ineq)
    1114             : {
    1115             :         int i;
    1116 26025648161 :         size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
    1117             : 
    1118 26025648161 :         bmap->ctx = ctx;
    1119 26025648161 :         isl_ctx_ref(ctx);
    1120             : 
    1121 26025648161 :         bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
    1122 26025648161 :         if (isl_blk_is_error(bmap->block))
    1123           0 :                 goto error;
    1124             : 
    1125 26025648161 :         bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
    1126 26025648161 :         if ((n_ineq + n_eq) && !bmap->ineq)
    1127           0 :                 goto error;
    1128             : 
    1129 26025648161 :         if (extra == 0) {
    1130 26025648161 :                 bmap->block2 = isl_blk_empty();
    1131 26025648161 :                 bmap->div = NULL;
    1132             :         } else {
    1133           0 :                 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
    1134           0 :                 if (isl_blk_is_error(bmap->block2))
    1135           0 :                         goto error;
    1136             : 
    1137           0 :                 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
    1138           0 :                 if (!bmap->div)
    1139           0 :                         goto error;
    1140             :         }
    1141             : 
    1142 >11666*10^7 :         for (i = 0; i < n_ineq + n_eq; ++i)
    1143 90642263631 :                 bmap->ineq[i] = bmap->block.data + i * row_size;
    1144             : 
    1145 26025648161 :         for (i = 0; i < extra; ++i)
    1146           0 :                 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
    1147             : 
    1148 26025648161 :         bmap->ref = 1;
    1149 26025648161 :         bmap->flags = 0;
    1150 26025648161 :         bmap->c_size = n_eq + n_ineq;
    1151 26025648161 :         bmap->eq = bmap->ineq + n_ineq;
    1152 26025648161 :         bmap->extra = extra;
    1153 26025648161 :         bmap->n_eq = 0;
    1154 26025648161 :         bmap->n_ineq = 0;
    1155 26025648161 :         bmap->n_div = 0;
    1156 26025648161 :         bmap->sample = NULL;
    1157             : 
    1158 26025648161 :         return bmap;
    1159             : error:
    1160           0 :         isl_basic_map_free(bmap);
    1161           0 :         return NULL;
    1162             : }
    1163             : 
    1164  1971025537 : struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
    1165             :                 unsigned nparam, unsigned dim, unsigned extra,
    1166             :                 unsigned n_eq, unsigned n_ineq)
    1167             : {
    1168             :         struct isl_basic_map *bmap;
    1169             :         isl_space *space;
    1170             : 
    1171  1971025537 :         space = isl_space_set_alloc(ctx, nparam, dim);
    1172  1971025537 :         if (!space)
    1173           0 :                 return NULL;
    1174             : 
    1175  1971025537 :         bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
    1176  1971025537 :         return bset_from_bmap(bmap);
    1177             : }
    1178             : 
    1179   421428521 : __isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
    1180             :                 unsigned extra, unsigned n_eq, unsigned n_ineq)
    1181             : {
    1182             :         struct isl_basic_map *bmap;
    1183   421428521 :         if (!dim)
    1184           0 :                 return NULL;
    1185   421428521 :         isl_assert(dim->ctx, dim->n_in == 0, goto error);
    1186   421428521 :         bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
    1187   421428521 :         return bset_from_bmap(bmap);
    1188             : error:
    1189           0 :         isl_space_free(dim);
    1190           0 :         return NULL;
    1191             : }
    1192             : 
    1193 26025648161 : struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
    1194             :                 unsigned extra, unsigned n_eq, unsigned n_ineq)
    1195             : {
    1196             :         struct isl_basic_map *bmap;
    1197             : 
    1198 26025648161 :         if (!dim)
    1199           0 :                 return NULL;
    1200 26025648161 :         bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
    1201 26025648161 :         if (!bmap)
    1202           0 :                 goto error;
    1203 26025648161 :         bmap->dim = dim;
    1204             : 
    1205 26025648161 :         return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
    1206             : error:
    1207           0 :         isl_space_free(dim);
    1208           0 :         return NULL;
    1209             : }
    1210             : 
    1211           0 : struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
    1212             :                 unsigned nparam, unsigned in, unsigned out, unsigned extra,
    1213             :                 unsigned n_eq, unsigned n_ineq)
    1214             : {
    1215             :         struct isl_basic_map *bmap;
    1216             :         isl_space *dim;
    1217             : 
    1218           0 :         dim = isl_space_alloc(ctx, nparam, in, out);
    1219           0 :         if (!dim)
    1220           0 :                 return NULL;
    1221             : 
    1222           0 :         bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
    1223           0 :         return bmap;
    1224             : }
    1225             : 
    1226 17551941943 : static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
    1227             :         __isl_keep isl_basic_map *src)
    1228             : {
    1229             :         int i;
    1230 17551941943 :         unsigned total = isl_basic_map_total_dim(src);
    1231             : 
    1232 17551941943 :         if (!dst)
    1233           0 :                 return NULL;
    1234             : 
    1235 57372485222 :         for (i = 0; i < src->n_eq; ++i) {
    1236 39820543279 :                 int j = isl_basic_map_alloc_equality(dst);
    1237 39820543279 :                 if (j < 0)
    1238           0 :                         return isl_basic_map_free(dst);
    1239 39820543279 :                 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
    1240             :         }
    1241             : 
    1242 24880468187 :         for (i = 0; i < src->n_ineq; ++i) {
    1243  7328526244 :                 int j = isl_basic_map_alloc_inequality(dst);
    1244  7328526244 :                 if (j < 0)
    1245           0 :                         return isl_basic_map_free(dst);
    1246  7328526244 :                 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
    1247             :         }
    1248             : 
    1249 17551941943 :         for (i = 0; i < src->n_div; ++i) {
    1250           0 :                 int j = isl_basic_map_alloc_div(dst);
    1251           0 :                 if (j < 0)
    1252           0 :                         return isl_basic_map_free(dst);
    1253           0 :                 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
    1254             :         }
    1255 17551941943 :         ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
    1256 17551941943 :         return dst;
    1257             : }
    1258             : 
    1259 17551941943 : __isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
    1260             : {
    1261             :         struct isl_basic_map *dup;
    1262             : 
    1263 17551941943 :         if (!bmap)
    1264           0 :                 return NULL;
    1265 17551941943 :         dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
    1266             :                         bmap->n_div, bmap->n_eq, bmap->n_ineq);
    1267 17551941943 :         dup = dup_constraints(dup, bmap);
    1268 17551941943 :         if (!dup)
    1269           0 :                 return NULL;
    1270 17551941943 :         dup->flags = bmap->flags;
    1271 17551941943 :         dup->sample = isl_vec_copy(bmap->sample);
    1272 17551941943 :         return dup;
    1273             : }
    1274             : 
    1275   850267412 : struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
    1276             : {
    1277             :         struct isl_basic_map *dup;
    1278             : 
    1279   850267412 :         dup = isl_basic_map_dup(bset_to_bmap(bset));
    1280   850267412 :         return bset_from_bmap(dup);
    1281             : }
    1282             : 
    1283  1990293972 : __isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
    1284             : {
    1285  1990293972 :         if (!bset)
    1286           0 :                 return NULL;
    1287             : 
    1288  1990293972 :         if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
    1289  1140026560 :                 bset->ref++;
    1290  1140026560 :                 return bset;
    1291             :         }
    1292   850267412 :         return isl_basic_set_dup(bset);
    1293             : }
    1294             : 
    1295  3013848416 : __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
    1296             : {
    1297  3013848416 :         if (!set)
    1298           0 :                 return NULL;
    1299             : 
    1300  3013848416 :         set->ref++;
    1301  3013848416 :         return set;
    1302             : }
    1303             : 
    1304 26979508049 : __isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
    1305             : {
    1306 26979508049 :         if (!bmap)
    1307           0 :                 return NULL;
    1308             : 
    1309 26979508049 :         if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
    1310 24749313886 :                 bmap->ref++;
    1311 24749313886 :                 return bmap;
    1312             :         }
    1313  2230194163 :         bmap = isl_basic_map_dup(bmap);
    1314  2230194163 :         if (bmap)
    1315  2230194163 :                 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
    1316  2230194163 :         return bmap;
    1317             : }
    1318             : 
    1319    39254002 : __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
    1320             : {
    1321    39254002 :         if (!map)
    1322           0 :                 return NULL;
    1323             : 
    1324    39254002 :         map->ref++;
    1325    39254002 :         return map;
    1326             : }
    1327             : 
    1328 66791347963 : __isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
    1329             : {
    1330 66791347963 :         if (!bmap)
    1331 29347839724 :                 return NULL;
    1332             : 
    1333 37443508239 :         if (--bmap->ref > 0)
    1334 11417860078 :                 return NULL;
    1335             : 
    1336 26025648161 :         isl_ctx_deref(bmap->ctx);
    1337 26025648161 :         free(bmap->div);
    1338 26025648161 :         isl_blk_free(bmap->ctx, bmap->block2);
    1339 26025648161 :         free(bmap->ineq);
    1340 26025648161 :         isl_blk_free(bmap->ctx, bmap->block);
    1341 26025648161 :         isl_vec_free(bmap->sample);
    1342 26025648161 :         isl_space_free(bmap->dim);
    1343 26025648161 :         free(bmap);
    1344             : 
    1345 26025648161 :         return NULL;
    1346             : }
    1347             : 
    1348  4978110151 : __isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
    1349             : {
    1350  4978110151 :         return isl_basic_map_free(bset_to_bmap(bset));
    1351             : }
    1352             : 
    1353 71228679587 : static int room_for_con(struct isl_basic_map *bmap, unsigned n)
    1354             : {
    1355 71228679587 :         return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
    1356             : }
    1357             : 
    1358             : /* Check that "map" has only named parameters, reporting an error
    1359             :  * if it does not.
    1360             :  */
    1361           0 : isl_stat isl_map_check_named_params(__isl_keep isl_map *map)
    1362             : {
    1363           0 :         return isl_space_check_named_params(isl_map_peek_space(map));
    1364             : }
    1365             : 
    1366             : /* Check that "bmap" has only named parameters, reporting an error
    1367             :  * if it does not.
    1368             :  */
    1369           0 : static isl_stat isl_basic_map_check_named_params(__isl_keep isl_basic_map *bmap)
    1370             : {
    1371           0 :         return isl_space_check_named_params(isl_basic_map_peek_space(bmap));
    1372             : }
    1373             : 
    1374             : /* Check that "bmap1" and "bmap2" have the same parameters,
    1375             :  * reporting an error if they do not.
    1376             :  */
    1377   110183997 : static isl_stat isl_basic_map_check_equal_params(
    1378             :         __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
    1379             : {
    1380             :         isl_bool match;
    1381             : 
    1382   110183997 :         match = isl_basic_map_has_equal_params(bmap1, bmap2);
    1383   110183997 :         if (match < 0)
    1384           0 :                 return isl_stat_error;
    1385   110183997 :         if (!match)
    1386           0 :                 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
    1387             :                         "parameters don't match", return isl_stat_error);
    1388   110183997 :         return isl_stat_ok;
    1389             : }
    1390             : 
    1391    54491026 : __isl_give isl_map *isl_map_align_params_map_map_and(
    1392             :         __isl_take isl_map *map1, __isl_take isl_map *map2,
    1393             :         __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
    1394             :                                     __isl_take isl_map *map2))
    1395             : {
    1396    54491026 :         if (!map1 || !map2)
    1397             :                 goto error;
    1398    54491026 :         if (isl_map_has_equal_params(map1, map2))
    1399    54491026 :                 return fn(map1, map2);
    1400           0 :         if (isl_map_check_named_params(map1) < 0)
    1401           0 :                 goto error;
    1402           0 :         if (isl_map_check_named_params(map2) < 0)
    1403           0 :                 goto error;
    1404           0 :         map1 = isl_map_align_params(map1, isl_map_get_space(map2));
    1405           0 :         map2 = isl_map_align_params(map2, isl_map_get_space(map1));
    1406           0 :         return fn(map1, map2);
    1407             : error:
    1408           0 :         isl_map_free(map1);
    1409           0 :         isl_map_free(map2);
    1410           0 :         return NULL;
    1411             : }
    1412             : 
    1413      633717 : isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
    1414             :         __isl_keep isl_map *map2,
    1415             :         isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
    1416             : {
    1417             :         isl_bool r;
    1418             : 
    1419      633717 :         if (!map1 || !map2)
    1420           0 :                 return isl_bool_error;
    1421      633717 :         if (isl_map_has_equal_params(map1, map2))
    1422      633717 :                 return fn(map1, map2);
    1423           0 :         if (isl_map_check_named_params(map1) < 0)
    1424           0 :                 return isl_bool_error;
    1425           0 :         if (isl_map_check_named_params(map2) < 0)
    1426           0 :                 return isl_bool_error;
    1427           0 :         map1 = isl_map_copy(map1);
    1428           0 :         map2 = isl_map_copy(map2);
    1429           0 :         map1 = isl_map_align_params(map1, isl_map_get_space(map2));
    1430           0 :         map2 = isl_map_align_params(map2, isl_map_get_space(map1));
    1431           0 :         r = fn(map1, map2);
    1432           0 :         isl_map_free(map1);
    1433           0 :         isl_map_free(map2);
    1434           0 :         return r;
    1435             : }
    1436             : 
    1437 61460575396 : int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
    1438             : {
    1439             :         struct isl_ctx *ctx;
    1440 61460575396 :         if (!bmap)
    1441           0 :                 return -1;
    1442 61460575396 :         ctx = bmap->ctx;
    1443 61460575396 :         isl_assert(ctx, room_for_con(bmap, 1), return -1);
    1444 61460575396 :         isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
    1445             :                         return -1);
    1446 61460575396 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    1447 61460575396 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
    1448 61460575396 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
    1449 61460575396 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
    1450 61460575396 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
    1451 61460575396 :         if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
    1452             :                 isl_int *t;
    1453    51661544 :                 int j = isl_basic_map_alloc_inequality(bmap);
    1454    51661544 :                 if (j < 0)
    1455           0 :                         return -1;
    1456    51661544 :                 t = bmap->ineq[j];
    1457    51661544 :                 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
    1458    51661544 :                 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
    1459    51661544 :                 bmap->eq[-1] = t;
    1460    51661544 :                 bmap->n_eq++;
    1461    51661544 :                 bmap->n_ineq--;
    1462    51661544 :                 bmap->eq--;
    1463    51661544 :                 return 0;
    1464             :         }
    1465 61408913852 :         isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
    1466 61408913852 :                       bmap->extra - bmap->n_div);
    1467 61408913852 :         return bmap->n_eq++;
    1468             : }
    1469             : 
    1470 15874318875 : int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
    1471             : {
    1472 15874318875 :         return isl_basic_map_alloc_equality(bset_to_bmap(bset));
    1473             : }
    1474             : 
    1475  5847702420 : int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
    1476             : {
    1477  5847702420 :         if (!bmap)
    1478           0 :                 return -1;
    1479  5847702420 :         isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
    1480  5847702420 :         bmap->n_eq -= n;
    1481  5847702420 :         return 0;
    1482             : }
    1483             : 
    1484           0 : int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
    1485             : {
    1486           0 :         return isl_basic_map_free_equality(bset_to_bmap(bset), n);
    1487             : }
    1488             : 
    1489  1103466289 : int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
    1490             : {
    1491             :         isl_int *t;
    1492  1103466289 :         if (!bmap)
    1493           0 :                 return -1;
    1494  1103466289 :         isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
    1495             : 
    1496  1103466289 :         if (pos != bmap->n_eq - 1) {
    1497   661936717 :                 t = bmap->eq[pos];
    1498   661936717 :                 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
    1499   661936717 :                 bmap->eq[bmap->n_eq - 1] = t;
    1500             :         }
    1501  1103466289 :         bmap->n_eq--;
    1502  1103466289 :         return 0;
    1503             : }
    1504             : 
    1505             : /* Turn inequality "pos" of "bmap" into an equality.
    1506             :  *
    1507             :  * In particular, we move the inequality in front of the equalities
    1508             :  * and move the last inequality in the position of the moved inequality.
    1509             :  * Note that isl_tab_make_equalities_explicit depends on this particular
    1510             :  * change in the ordering of the constraints.
    1511             :  */
    1512   621411189 : void isl_basic_map_inequality_to_equality(
    1513             :                 struct isl_basic_map *bmap, unsigned pos)
    1514             : {
    1515             :         isl_int *t;
    1516             : 
    1517   621411189 :         t = bmap->ineq[pos];
    1518   621411189 :         bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
    1519   621411189 :         bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
    1520   621411189 :         bmap->eq[-1] = t;
    1521   621411189 :         bmap->n_eq++;
    1522   621411189 :         bmap->n_ineq--;
    1523   621411189 :         bmap->eq--;
    1524   621411189 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
    1525   621411189 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    1526   621411189 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
    1527   621411189 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
    1528   621411189 : }
    1529             : 
    1530 35826352771 : static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
    1531             : {
    1532 35826352771 :         return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
    1533             : }
    1534             : 
    1535 30918441926 : int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
    1536             : {
    1537             :         struct isl_ctx *ctx;
    1538 30918441926 :         if (!bmap)
    1539           0 :                 return -1;
    1540 30918441926 :         ctx = bmap->ctx;
    1541 30918441926 :         isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
    1542 30918441926 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
    1543 30918441926 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
    1544 30918441926 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    1545 30918441926 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
    1546 61836883852 :         isl_seq_clr(bmap->ineq[bmap->n_ineq] +
    1547 30918441926 :                       1 + isl_basic_map_total_dim(bmap),
    1548 30918441926 :                       bmap->extra - bmap->n_div);
    1549 30918441926 :         return bmap->n_ineq++;
    1550             : }
    1551             : 
    1552  6978651350 : int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
    1553             : {
    1554  6978651350 :         return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
    1555             : }
    1556             : 
    1557 12840401547 : int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
    1558             : {
    1559 12840401547 :         if (!bmap)
    1560           0 :                 return -1;
    1561 12840401547 :         isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
    1562 12840401547 :         bmap->n_ineq -= n;
    1563 12840401547 :         return 0;
    1564             : }
    1565             : 
    1566           0 : int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
    1567             : {
    1568           0 :         return isl_basic_map_free_inequality(bset_to_bmap(bset), n);
    1569             : }
    1570             : 
    1571  1868725399 : int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
    1572             : {
    1573             :         isl_int *t;
    1574  1868725399 :         if (!bmap)
    1575           0 :                 return -1;
    1576  1868725399 :         isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
    1577             : 
    1578  1868725399 :         if (pos != bmap->n_ineq - 1) {
    1579   863271881 :                 t = bmap->ineq[pos];
    1580   863271881 :                 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
    1581   863271881 :                 bmap->ineq[bmap->n_ineq - 1] = t;
    1582   863271881 :                 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    1583             :         }
    1584  1868725399 :         bmap->n_ineq--;
    1585  1868725399 :         return 0;
    1586             : }
    1587             : 
    1588           0 : int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
    1589             : {
    1590           0 :         return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
    1591             : }
    1592             : 
    1593           0 : __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
    1594             :         isl_int *eq)
    1595             : {
    1596             :         int k;
    1597             : 
    1598           0 :         bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
    1599           0 :         if (!bmap)
    1600           0 :                 return NULL;
    1601           0 :         k = isl_basic_map_alloc_equality(bmap);
    1602           0 :         if (k < 0)
    1603           0 :                 goto error;
    1604           0 :         isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
    1605           0 :         return bmap;
    1606             : error:
    1607           0 :         isl_basic_map_free(bmap);
    1608           0 :         return NULL;
    1609             : }
    1610             : 
    1611           0 : __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
    1612             :         isl_int *eq)
    1613             : {
    1614           0 :         return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
    1615             : }
    1616             : 
    1617  3825163776 : __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
    1618             :         isl_int *ineq)
    1619             : {
    1620             :         int k;
    1621             : 
    1622  3825163776 :         bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
    1623  3825163776 :         if (!bmap)
    1624           0 :                 return NULL;
    1625  3825163776 :         k = isl_basic_map_alloc_inequality(bmap);
    1626  3825163776 :         if (k < 0)
    1627           0 :                 goto error;
    1628  3825163776 :         isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
    1629  3825163776 :         return bmap;
    1630             : error:
    1631           0 :         isl_basic_map_free(bmap);
    1632           0 :         return NULL;
    1633             : }
    1634             : 
    1635           0 : __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
    1636             :         isl_int *ineq)
    1637             : {
    1638           0 :         return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
    1639             : }
    1640             : 
    1641           0 : int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
    1642             : {
    1643           0 :         if (!bmap)
    1644           0 :                 return -1;
    1645           0 :         isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
    1646           0 :         isl_seq_clr(bmap->div[bmap->n_div] +
    1647           0 :                       1 + 1 + isl_basic_map_total_dim(bmap),
    1648           0 :                       bmap->extra - bmap->n_div);
    1649           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
    1650           0 :         return bmap->n_div++;
    1651             : }
    1652             : 
    1653           0 : int isl_basic_set_alloc_div(struct isl_basic_set *bset)
    1654             : {
    1655           0 :         return isl_basic_map_alloc_div(bset_to_bmap(bset));
    1656             : }
    1657             : 
    1658             : /* Check that there are "n" dimensions of type "type" starting at "first"
    1659             :  * in "bmap".
    1660             :  */
    1661     7702949 : static isl_stat isl_basic_map_check_range(__isl_keep isl_basic_map *bmap,
    1662             :         enum isl_dim_type type, unsigned first, unsigned n)
    1663             : {
    1664             :         unsigned dim;
    1665             : 
    1666     7702949 :         if (!bmap)
    1667           0 :                 return isl_stat_error;
    1668     7702949 :         dim = isl_basic_map_dim(bmap, type);
    1669     7702949 :         if (first + n > dim || first + n < first)
    1670           0 :                 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
    1671             :                         "position or range out of bounds",
    1672             :                         return isl_stat_error);
    1673     7702949 :         return isl_stat_ok;
    1674             : }
    1675             : 
    1676             : /* Insert an extra integer division, prescribed by "div", to "bmap"
    1677             :  * at (integer division) position "pos".
    1678             :  *
    1679             :  * The integer division is first added at the end and then moved
    1680             :  * into the right position.
    1681             :  */
    1682           0 : __isl_give isl_basic_map *isl_basic_map_insert_div(
    1683             :         __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
    1684             : {
    1685             :         int i, k;
    1686             : 
    1687           0 :         bmap = isl_basic_map_cow(bmap);
    1688           0 :         if (!bmap || !div)
    1689           0 :                 return isl_basic_map_free(bmap);
    1690             : 
    1691           0 :         if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
    1692           0 :                 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
    1693             :                         "unexpected size", return isl_basic_map_free(bmap));
    1694           0 :         if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
    1695           0 :                 return isl_basic_map_free(bmap);
    1696             : 
    1697           0 :         bmap = isl_basic_map_extend_space(bmap,
    1698             :                                         isl_basic_map_get_space(bmap), 1, 0, 2);
    1699           0 :         k = isl_basic_map_alloc_div(bmap);
    1700           0 :         if (k < 0)
    1701           0 :                 return isl_basic_map_free(bmap);
    1702           0 :         isl_seq_cpy(bmap->div[k], div->el, div->size);
    1703           0 :         isl_int_set_si(bmap->div[k][div->size], 0);
    1704             : 
    1705           0 :         for (i = k; i > pos; --i)
    1706           0 :                 isl_basic_map_swap_div(bmap, i, i - 1);
    1707             : 
    1708           0 :         return bmap;
    1709             : }
    1710             : 
    1711  2845818736 : isl_stat isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
    1712             : {
    1713  2845818736 :         if (!bmap)
    1714           0 :                 return isl_stat_error;
    1715  2845818736 :         isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
    1716  2845818736 :         bmap->n_div -= n;
    1717  2845818736 :         return isl_stat_ok;
    1718             : }
    1719             : 
    1720             : /* Copy constraint from src to dst, putting the vars of src at offset
    1721             :  * dim_off in dst and the divs of src at offset div_off in dst.
    1722             :  * If both sets are actually map, then dim_off applies to the input
    1723             :  * variables.
    1724             :  */
    1725 18445940278 : static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
    1726             :                             struct isl_basic_map *src_map, isl_int *src,
    1727             :                             unsigned in_off, unsigned out_off, unsigned div_off)
    1728             : {
    1729 18445940278 :         unsigned src_nparam = isl_basic_map_dim(src_map, isl_dim_param);
    1730 18445940278 :         unsigned dst_nparam = isl_basic_map_dim(dst_map, isl_dim_param);
    1731 18445940278 :         unsigned src_in = isl_basic_map_dim(src_map, isl_dim_in);
    1732 18445940278 :         unsigned dst_in = isl_basic_map_dim(dst_map, isl_dim_in);
    1733 18445940278 :         unsigned src_out = isl_basic_map_dim(src_map, isl_dim_out);
    1734 18445940278 :         unsigned dst_out = isl_basic_map_dim(dst_map, isl_dim_out);
    1735 18445940278 :         isl_int_set(dst[0], src[0]);
    1736 18445940278 :         isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
    1737 18445940278 :         if (dst_nparam > src_nparam)
    1738           0 :                 isl_seq_clr(dst+1+src_nparam,
    1739             :                                 dst_nparam - src_nparam);
    1740 18445940278 :         isl_seq_clr(dst+1+dst_nparam, in_off);
    1741 36891880556 :         isl_seq_cpy(dst+1+dst_nparam+in_off,
    1742 18445940278 :                     src+1+src_nparam,
    1743 18445940278 :                     isl_min(dst_in-in_off, src_in));
    1744 18445940278 :         if (dst_in-in_off > src_in)
    1745           0 :                 isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
    1746           0 :                                 dst_in - in_off - src_in);
    1747 18445940278 :         isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
    1748 36891880556 :         isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
    1749 18445940278 :                     src+1+src_nparam+src_in,
    1750 18445940278 :                     isl_min(dst_out-out_off, src_out));
    1751 18445940278 :         if (dst_out-out_off > src_out)
    1752  2919590919 :                 isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
    1753  2919590919 :                                 dst_out - out_off - src_out);
    1754 18445940278 :         isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
    1755 36891880556 :         isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
    1756 18445940278 :                     src+1+src_nparam+src_in+src_out,
    1757 18445940278 :                     isl_min(dst_map->extra-div_off, src_map->n_div));
    1758 18445940278 :         if (dst_map->n_div-div_off > src_map->n_div)
    1759           0 :                 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
    1760           0 :                                 div_off+src_map->n_div,
    1761           0 :                                 dst_map->n_div - div_off - src_map->n_div);
    1762 18445940278 : }
    1763             : 
    1764           0 : static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
    1765             :                      struct isl_basic_map *src_map, isl_int *src,
    1766             :                      unsigned in_off, unsigned out_off, unsigned div_off)
    1767             : {
    1768           0 :         isl_int_set(dst[0], src[0]);
    1769           0 :         copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
    1770           0 : }
    1771             : 
    1772  6188865966 : static __isl_give isl_basic_map *add_constraints(
    1773             :         __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
    1774             :         unsigned i_pos, unsigned o_pos)
    1775             : {
    1776             :         int i;
    1777             :         unsigned div_off;
    1778             : 
    1779  6188865966 :         if (!bmap1 || !bmap2)
    1780             :                 goto error;
    1781             : 
    1782  6188865966 :         div_off = bmap1->n_div;
    1783             : 
    1784 11901085198 :         for (i = 0; i < bmap2->n_eq; ++i) {
    1785  5712219232 :                 int i1 = isl_basic_map_alloc_equality(bmap1);
    1786  5712219232 :                 if (i1 < 0)
    1787           0 :                         goto error;
    1788  5712219232 :                 copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
    1789             :                                 i_pos, o_pos, div_off);
    1790             :         }
    1791             : 
    1792 18922587012 :         for (i = 0; i < bmap2->n_ineq; ++i) {
    1793 12733721046 :                 int i1 = isl_basic_map_alloc_inequality(bmap1);
    1794 12733721046 :                 if (i1 < 0)
    1795           0 :                         goto error;
    1796 12733721046 :                 copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
    1797             :                                 i_pos, o_pos, div_off);
    1798             :         }
    1799             : 
    1800  6188865966 :         for (i = 0; i < bmap2->n_div; ++i) {
    1801           0 :                 int i1 = isl_basic_map_alloc_div(bmap1);
    1802           0 :                 if (i1 < 0)
    1803           0 :                         goto error;
    1804           0 :                 copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
    1805             :                          i_pos, o_pos, div_off);
    1806             :         }
    1807             : 
    1808  6188865966 :         isl_basic_map_free(bmap2);
    1809             : 
    1810  6188865966 :         return bmap1;
    1811             : 
    1812             : error:
    1813           0 :         isl_basic_map_free(bmap1);
    1814           0 :         isl_basic_map_free(bmap2);
    1815           0 :         return NULL;
    1816             : }
    1817             : 
    1818           0 : struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
    1819             :                 struct isl_basic_set *bset2, unsigned pos)
    1820             : {
    1821           0 :         return bset_from_bmap(add_constraints(bset_to_bmap(bset1),
    1822             :                                                 bset_to_bmap(bset2), 0, pos));
    1823             : }
    1824             : 
    1825 10986592814 : __isl_give isl_basic_map *isl_basic_map_extend_space(
    1826             :         __isl_take isl_basic_map *base, __isl_take isl_space *dim,
    1827             :         unsigned extra, unsigned n_eq, unsigned n_ineq)
    1828             : {
    1829             :         struct isl_basic_map *ext;
    1830             :         unsigned flags;
    1831             :         int dims_ok;
    1832             : 
    1833 10986592814 :         if (!dim)
    1834           0 :                 goto error;
    1835             : 
    1836 10986592814 :         if (!base)
    1837           0 :                 goto error;
    1838             : 
    1839 20754697005 :         dims_ok = isl_space_is_equal(base->dim, dim) &&
    1840  9768104191 :                   base->extra >= base->n_div + extra;
    1841             : 
    1842 15894503659 :         if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
    1843  4907910845 :                        room_for_ineq(base, n_ineq)) {
    1844  4907910845 :                 isl_space_free(dim);
    1845  4907910845 :                 return base;
    1846             :         }
    1847             : 
    1848  6078681969 :         isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
    1849  6078681969 :         isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
    1850  6078681969 :         isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
    1851  6078681969 :         extra += base->extra;
    1852  6078681969 :         n_eq += base->n_eq;
    1853  6078681969 :         n_ineq += base->n_ineq;
    1854             : 
    1855  6078681969 :         ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
    1856  6078681969 :         dim = NULL;
    1857  6078681969 :         if (!ext)
    1858           0 :                 goto error;
    1859             : 
    1860  6078681969 :         if (dims_ok)
    1861  4860193346 :                 ext->sample = isl_vec_copy(base->sample);
    1862  6078681969 :         flags = base->flags;
    1863  6078681969 :         ext = add_constraints(ext, base, 0, 0);
    1864  6078681969 :         if (ext) {
    1865  6078681969 :                 ext->flags = flags;
    1866  6078681969 :                 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
    1867             :         }
    1868             : 
    1869  6078681969 :         return ext;
    1870             : 
    1871             : error:
    1872           0 :         isl_space_free(dim);
    1873           0 :         isl_basic_map_free(base);
    1874           0 :         return NULL;
    1875             : }
    1876             : 
    1877  1218270283 : __isl_give isl_basic_set *isl_basic_set_extend_space(
    1878             :         __isl_take isl_basic_set *base,
    1879             :                 __isl_take isl_space *dim, unsigned extra,
    1880             :                 unsigned n_eq, unsigned n_ineq)
    1881             : {
    1882  1218270283 :         return bset_from_bmap(isl_basic_map_extend_space(bset_to_bmap(base),
    1883             :                                                     dim, extra, n_eq, n_ineq));
    1884             : }
    1885             : 
    1886  3826054768 : struct isl_basic_map *isl_basic_map_extend_constraints(
    1887             :                 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
    1888             : {
    1889  3826054768 :         if (!base)
    1890           0 :                 return NULL;
    1891  3826054768 :         return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
    1892             :                                         0, n_eq, n_ineq);
    1893             : }
    1894             : 
    1895  5831859936 : struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
    1896             :                 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
    1897             :                 unsigned n_eq, unsigned n_ineq)
    1898             : {
    1899             :         struct isl_basic_map *bmap;
    1900             :         isl_space *dim;
    1901             : 
    1902  5831859936 :         if (!base)
    1903           0 :                 return NULL;
    1904  5831859936 :         dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
    1905  5831859936 :         if (!dim)
    1906           0 :                 goto error;
    1907             : 
    1908  5831859936 :         bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
    1909  5831859936 :         return bmap;
    1910             : error:
    1911           0 :         isl_basic_map_free(base);
    1912           0 :         return NULL;
    1913             : }
    1914             : 
    1915  5831859936 : struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
    1916             :                 unsigned nparam, unsigned dim, unsigned extra,
    1917             :                 unsigned n_eq, unsigned n_ineq)
    1918             : {
    1919  5831859936 :         return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
    1920             :                                         nparam, 0, dim, extra, n_eq, n_ineq));
    1921             : }
    1922             : 
    1923           0 : struct isl_basic_set *isl_basic_set_extend_constraints(
    1924             :                 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
    1925             : {
    1926           0 :         isl_basic_map *bmap = bset_to_bmap(base);
    1927           0 :         bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
    1928           0 :         return bset_from_bmap(bmap);
    1929             : }
    1930             : 
    1931 15253739189 : __isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
    1932             : {
    1933 15253739189 :         return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
    1934             : }
    1935             : 
    1936 24157891949 : __isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
    1937             : {
    1938 24157891949 :         if (!bmap)
    1939           0 :                 return NULL;
    1940             : 
    1941 24157891949 :         if (bmap->ref > 1) {
    1942 14471480368 :                 bmap->ref--;
    1943 14471480368 :                 bmap = isl_basic_map_dup(bmap);
    1944             :         }
    1945 24157891949 :         if (bmap) {
    1946 24157891949 :                 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
    1947 24157891949 :                 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
    1948             :         }
    1949 24157891949 :         return bmap;
    1950             : }
    1951             : 
    1952             : /* Clear all cached information in "map", either because it is about
    1953             :  * to be modified or because it is being freed.
    1954             :  * Always return the same pointer that is passed in.
    1955             :  * This is needed for the use in isl_map_free.
    1956             :  */
    1957 10528261078 : static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
    1958             : {
    1959 10528261078 :         isl_basic_map_free(map->cached_simple_hull[0]);
    1960 10528261078 :         isl_basic_map_free(map->cached_simple_hull[1]);
    1961 10528261078 :         map->cached_simple_hull[0] = NULL;
    1962 10528261078 :         map->cached_simple_hull[1] = NULL;
    1963 10528261078 :         return map;
    1964             : }
    1965             : 
    1966  3638559013 : __isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
    1967             : {
    1968  3638559013 :         return isl_map_cow(set);
    1969             : }
    1970             : 
    1971             : /* Return an isl_map that is equal to "map" and that has only
    1972             :  * a single reference.
    1973             :  *
    1974             :  * If the original input already has only one reference, then
    1975             :  * simply return it, but clear all cached information, since
    1976             :  * it may be rendered invalid by the operations that will be
    1977             :  * performed on the result.
    1978             :  *
    1979             :  * Otherwise, create a duplicate (without any cached information).
    1980             :  */
    1981 10435146687 : __isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
    1982             : {
    1983 10435146687 :         if (!map)
    1984           0 :                 return NULL;
    1985             : 
    1986 10435146687 :         if (map->ref == 1)
    1987  7430417647 :                 return clear_caches(map);
    1988  3004729040 :         map->ref--;
    1989  3004729040 :         return isl_map_dup(map);
    1990             : }
    1991             : 
    1992           0 : static void swap_vars(struct isl_blk blk, isl_int *a,
    1993             :                         unsigned a_len, unsigned b_len)
    1994             : {
    1995           0 :         isl_seq_cpy(blk.data, a+a_len, b_len);
    1996           0 :         isl_seq_cpy(blk.data+b_len, a, a_len);
    1997           0 :         isl_seq_cpy(a, blk.data, b_len+a_len);
    1998           0 : }
    1999             : 
    2000           0 : static __isl_give isl_basic_map *isl_basic_map_swap_vars(
    2001             :         __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
    2002             : {
    2003             :         int i;
    2004             :         struct isl_blk blk;
    2005             : 
    2006           0 :         if (!bmap)
    2007           0 :                 goto error;
    2008             : 
    2009           0 :         isl_assert(bmap->ctx,
    2010             :                 pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
    2011             : 
    2012           0 :         if (n1 == 0 || n2 == 0)
    2013           0 :                 return bmap;
    2014             : 
    2015           0 :         bmap = isl_basic_map_cow(bmap);
    2016           0 :         if (!bmap)
    2017           0 :                 return NULL;
    2018             : 
    2019           0 :         blk = isl_blk_alloc(bmap->ctx, n1 + n2);
    2020           0 :         if (isl_blk_is_error(blk))
    2021           0 :                 goto error;
    2022             : 
    2023           0 :         for (i = 0; i < bmap->n_eq; ++i)
    2024           0 :                 swap_vars(blk,
    2025           0 :                           bmap->eq[i] + pos, n1, n2);
    2026             : 
    2027           0 :         for (i = 0; i < bmap->n_ineq; ++i)
    2028           0 :                 swap_vars(blk,
    2029           0 :                           bmap->ineq[i] + pos, n1, n2);
    2030             : 
    2031           0 :         for (i = 0; i < bmap->n_div; ++i)
    2032           0 :                 swap_vars(blk,
    2033           0 :                           bmap->div[i]+1 + pos, n1, n2);
    2034             : 
    2035           0 :         isl_blk_free(bmap->ctx, blk);
    2036             : 
    2037           0 :         ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
    2038           0 :         bmap = isl_basic_map_gauss(bmap, NULL);
    2039           0 :         return isl_basic_map_finalize(bmap);
    2040             : error:
    2041           0 :         isl_basic_map_free(bmap);
    2042           0 :         return NULL;
    2043             : }
    2044             : 
    2045  2845818736 : __isl_give isl_basic_map *isl_basic_map_set_to_empty(
    2046             :         __isl_take isl_basic_map *bmap)
    2047             : {
    2048  2845818736 :         int i = 0;
    2049             :         unsigned total;
    2050  2845818736 :         if (!bmap)
    2051           0 :                 goto error;
    2052  2845818736 :         total = isl_basic_map_total_dim(bmap);
    2053  2845818736 :         if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
    2054           0 :                 return isl_basic_map_free(bmap);
    2055  2845818736 :         isl_basic_map_free_inequality(bmap, bmap->n_ineq);
    2056  2845818736 :         if (bmap->n_eq > 0)
    2057  2792646113 :                 isl_basic_map_free_equality(bmap, bmap->n_eq-1);
    2058             :         else {
    2059    53172623 :                 i = isl_basic_map_alloc_equality(bmap);
    2060    53172623 :                 if (i < 0)
    2061           0 :                         goto error;
    2062             :         }
    2063  2845818736 :         isl_int_set_si(bmap->eq[i][0], 1);
    2064  2845818736 :         isl_seq_clr(bmap->eq[i]+1, total);
    2065  2845818736 :         ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
    2066  2845818736 :         isl_vec_free(bmap->sample);
    2067  2845818736 :         bmap->sample = NULL;
    2068  2845818736 :         return isl_basic_map_finalize(bmap);
    2069             : error:
    2070           0 :         isl_basic_map_free(bmap);
    2071           0 :         return NULL;
    2072             : }
    2073             : 
    2074     1419589 : __isl_give isl_basic_set *isl_basic_set_set_to_empty(
    2075             :         __isl_take isl_basic_set *bset)
    2076             : {
    2077     1419589 :         return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
    2078             : }
    2079             : 
    2080 10423960158 : __isl_give isl_basic_map *isl_basic_map_set_rational(
    2081             :         __isl_take isl_basic_map *bmap)
    2082             : {
    2083 10423960158 :         if (!bmap)
    2084           0 :                 return NULL;
    2085             : 
    2086 10423960158 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
    2087  8085459516 :                 return bmap;
    2088             : 
    2089  2338500642 :         bmap = isl_basic_map_cow(bmap);
    2090  2338500642 :         if (!bmap)
    2091           0 :                 return NULL;
    2092             : 
    2093  2338500642 :         ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
    2094             : 
    2095  2338500642 :         return isl_basic_map_finalize(bmap);
    2096             : }
    2097             : 
    2098  2336980258 : __isl_give isl_basic_set *isl_basic_set_set_rational(
    2099             :         __isl_take isl_basic_set *bset)
    2100             : {
    2101  2336980258 :         return isl_basic_map_set_rational(bset);
    2102             : }
    2103             : 
    2104           0 : __isl_give isl_basic_set *isl_basic_set_set_integral(
    2105             :         __isl_take isl_basic_set *bset)
    2106             : {
    2107           0 :         if (!bset)
    2108           0 :                 return NULL;
    2109             : 
    2110           0 :         if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
    2111           0 :                 return bset;
    2112             : 
    2113           0 :         bset = isl_basic_set_cow(bset);
    2114           0 :         if (!bset)
    2115           0 :                 return NULL;
    2116             : 
    2117           0 :         ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
    2118             : 
    2119           0 :         return isl_basic_set_finalize(bset);
    2120             : }
    2121             : 
    2122  2347048276 : __isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
    2123             : {
    2124             :         int i;
    2125             : 
    2126  2347048276 :         map = isl_map_cow(map);
    2127  2347048276 :         if (!map)
    2128           0 :                 return NULL;
    2129 10434028176 :         for (i = 0; i < map->n; ++i) {
    2130  8086979900 :                 map->p[i] = isl_basic_map_set_rational(map->p[i]);
    2131  8086979900 :                 if (!map->p[i])
    2132           0 :                         goto error;
    2133             :         }
    2134  2347048276 :         return map;
    2135             : error:
    2136           0 :         isl_map_free(map);
    2137           0 :         return NULL;
    2138             : }
    2139             : 
    2140  2347048276 : __isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
    2141             : {
    2142  2347048276 :         return isl_map_set_rational(set);
    2143             : }
    2144             : 
    2145             : /* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
    2146             :  * of "bmap").
    2147             :  */
    2148           0 : static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
    2149             : {
    2150           0 :         isl_int *t = bmap->div[a];
    2151           0 :         bmap->div[a] = bmap->div[b];
    2152           0 :         bmap->div[b] = t;
    2153           0 : }
    2154             : 
    2155             : /* Swap divs "a" and "b" in "bmap" and adjust the constraints and
    2156             :  * div definitions accordingly.
    2157             :  */
    2158           0 : void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
    2159             : {
    2160             :         int i;
    2161           0 :         unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
    2162             : 
    2163           0 :         swap_div(bmap, a, b);
    2164             : 
    2165           0 :         for (i = 0; i < bmap->n_eq; ++i)
    2166           0 :                 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
    2167             : 
    2168           0 :         for (i = 0; i < bmap->n_ineq; ++i)
    2169           0 :                 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
    2170             : 
    2171           0 :         for (i = 0; i < bmap->n_div; ++i)
    2172           0 :                 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
    2173           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    2174           0 : }
    2175             : 
    2176             : /* Swap divs "a" and "b" in "bset" and adjust the constraints and
    2177             :  * div definitions accordingly.
    2178             :  */
    2179           0 : void isl_basic_set_swap_div(__isl_keep isl_basic_set *bset, int a, int b)
    2180             : {
    2181           0 :         isl_basic_map_swap_div(bset, a, b);
    2182           0 : }
    2183             : 
    2184    36691185 : static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
    2185             : {
    2186    36691185 :         isl_seq_cpy(c, c + n, rem);
    2187    36691185 :         isl_seq_clr(c + rem, n);
    2188    36691185 : }
    2189             : 
    2190             : /* Drop n dimensions starting at first.
    2191             :  *
    2192             :  * In principle, this frees up some extra variables as the number
    2193             :  * of columns remains constant, but we would have to extend
    2194             :  * the div array too as the number of rows in this array is assumed
    2195             :  * to be equal to extra.
    2196             :  */
    2197    16043818 : __isl_give isl_basic_set *isl_basic_set_drop_dims(
    2198             :         __isl_take isl_basic_set *bset, unsigned first, unsigned n)
    2199             : {
    2200    16043818 :         return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
    2201             : }
    2202             : 
    2203             : /* Move "n" divs starting at "first" to the end of the list of divs.
    2204             :  */
    2205           0 : static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
    2206             :         unsigned first, unsigned n)
    2207             : {
    2208             :         isl_int **div;
    2209             :         int i;
    2210             : 
    2211           0 :         if (first + n == bmap->n_div)
    2212           0 :                 return bmap;
    2213             : 
    2214           0 :         div = isl_alloc_array(bmap->ctx, isl_int *, n);
    2215           0 :         if (!div)
    2216           0 :                 goto error;
    2217           0 :         for (i = 0; i < n; ++i)
    2218           0 :                 div[i] = bmap->div[first + i];
    2219           0 :         for (i = 0; i < bmap->n_div - first - n; ++i)
    2220           0 :                 bmap->div[first + i] = bmap->div[first + n + i];
    2221           0 :         for (i = 0; i < n; ++i)
    2222           0 :                 bmap->div[bmap->n_div - n + i] = div[i];
    2223           0 :         free(div);
    2224           0 :         return bmap;
    2225             : error:
    2226           0 :         isl_basic_map_free(bmap);
    2227           0 :         return NULL;
    2228             : }
    2229             : 
    2230             : /* Check that there are "n" dimensions of type "type" starting at "first"
    2231             :  * in "map".
    2232             :  */
    2233           0 : static isl_stat isl_map_check_range(__isl_keep isl_map *map,
    2234             :         enum isl_dim_type type, unsigned first, unsigned n)
    2235             : {
    2236           0 :         if (!map)
    2237           0 :                 return isl_stat_error;
    2238           0 :         if (first + n > isl_map_dim(map, type) || first + n < first)
    2239           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
    2240             :                         "position or range out of bounds",
    2241             :                         return isl_stat_error);
    2242           0 :         return isl_stat_ok;
    2243             : }
    2244             : 
    2245             : /* Drop "n" dimensions of type "type" starting at "first".
    2246             :  *
    2247             :  * In principle, this frees up some extra variables as the number
    2248             :  * of columns remains constant, but we would have to extend
    2249             :  * the div array too as the number of rows in this array is assumed
    2250             :  * to be equal to extra.
    2251             :  */
    2252    17273171 : __isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
    2253             :         enum isl_dim_type type, unsigned first, unsigned n)
    2254             : {
    2255             :         int i;
    2256             :         unsigned dim;
    2257             :         unsigned offset;
    2258             :         unsigned left;
    2259             : 
    2260    17273171 :         if (!bmap)
    2261           0 :                 goto error;
    2262             : 
    2263    17273171 :         dim = isl_basic_map_dim(bmap, type);
    2264    17273171 :         isl_assert(bmap->ctx, first + n <= dim, goto error);
    2265             : 
    2266    17273171 :         if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
    2267      236773 :                 return bmap;
    2268             : 
    2269    17036398 :         bmap = isl_basic_map_cow(bmap);
    2270    17036398 :         if (!bmap)
    2271           0 :                 return NULL;
    2272             : 
    2273    17036398 :         offset = isl_basic_map_offset(bmap, type) + first;
    2274    17036398 :         left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
    2275    17036556 :         for (i = 0; i < bmap->n_eq; ++i)
    2276         158 :                 constraint_drop_vars(bmap->eq[i]+offset, n, left);
    2277             : 
    2278    53727425 :         for (i = 0; i < bmap->n_ineq; ++i)
    2279    36691027 :                 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
    2280             : 
    2281    17036398 :         for (i = 0; i < bmap->n_div; ++i)
    2282           0 :                 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
    2283             : 
    2284    17036398 :         if (type == isl_dim_div) {
    2285           0 :                 bmap = move_divs_last(bmap, first, n);
    2286           0 :                 if (!bmap)
    2287           0 :                         goto error;
    2288           0 :                 if (isl_basic_map_free_div(bmap, n) < 0)
    2289           0 :                         return isl_basic_map_free(bmap);
    2290             :         } else
    2291    17036398 :                 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
    2292    17036398 :         if (!bmap->dim)
    2293           0 :                 goto error;
    2294             : 
    2295    17036398 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    2296    17036398 :         bmap = isl_basic_map_simplify(bmap);
    2297    17036398 :         return isl_basic_map_finalize(bmap);
    2298             : error:
    2299           0 :         isl_basic_map_free(bmap);
    2300           0 :         return NULL;
    2301             : }
    2302             : 
    2303      476628 : __isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
    2304             :         enum isl_dim_type type, unsigned first, unsigned n)
    2305             : {
    2306      476628 :         return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
    2307             :                                                         type, first, n));
    2308             : }
    2309             : 
    2310             : /* No longer consider "map" to be normalized.
    2311             :  */
    2312 14162872024 : static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
    2313             : {
    2314 14162872024 :         if (!map)
    2315           0 :                 return NULL;
    2316 14162872024 :         ISL_F_CLR(map, ISL_MAP_NORMALIZED);
    2317 14162872024 :         return map;
    2318             : }
    2319             : 
    2320           0 : __isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
    2321             :         enum isl_dim_type type, unsigned first, unsigned n)
    2322             : {
    2323             :         int i;
    2324             : 
    2325           0 :         if (isl_map_check_range(map, type, first, n) < 0)
    2326           0 :                 return isl_map_free(map);
    2327             : 
    2328           0 :         if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
    2329           0 :                 return map;
    2330           0 :         map = isl_map_cow(map);
    2331           0 :         if (!map)
    2332           0 :                 goto error;
    2333           0 :         map->dim = isl_space_drop_dims(map->dim, type, first, n);
    2334           0 :         if (!map->dim)
    2335           0 :                 goto error;
    2336             : 
    2337           0 :         for (i = 0; i < map->n; ++i) {
    2338           0 :                 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
    2339           0 :                 if (!map->p[i])
    2340           0 :                         goto error;
    2341             :         }
    2342           0 :         map = isl_map_unmark_normalized(map);
    2343             : 
    2344           0 :         return map;
    2345             : error:
    2346           0 :         isl_map_free(map);
    2347           0 :         return NULL;
    2348             : }
    2349             : 
    2350           0 : __isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
    2351             :         enum isl_dim_type type, unsigned first, unsigned n)
    2352             : {
    2353           0 :         return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
    2354             : }
    2355             : 
    2356             : /*
    2357             :  * We don't cow, as the div is assumed to be redundant.
    2358             :  */
    2359           0 : __isl_give isl_basic_map *isl_basic_map_drop_div(
    2360             :         __isl_take isl_basic_map *bmap, unsigned div)
    2361             : {
    2362             :         int i;
    2363             :         unsigned pos;
    2364             : 
    2365           0 :         if (!bmap)
    2366           0 :                 goto error;
    2367             : 
    2368           0 :         pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
    2369             : 
    2370           0 :         isl_assert(bmap->ctx, div < bmap->n_div, goto error);
    2371             : 
    2372           0 :         for (i = 0; i < bmap->n_eq; ++i)
    2373           0 :                 constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
    2374             : 
    2375           0 :         for (i = 0; i < bmap->n_ineq; ++i) {
    2376           0 :                 if (!isl_int_is_zero(bmap->ineq[i][pos])) {
    2377           0 :                         isl_basic_map_drop_inequality(bmap, i);
    2378           0 :                         --i;
    2379           0 :                         continue;
    2380             :                 }
    2381           0 :                 constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
    2382             :         }
    2383             : 
    2384           0 :         for (i = 0; i < bmap->n_div; ++i)
    2385           0 :                 constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
    2386             : 
    2387           0 :         if (div != bmap->n_div - 1) {
    2388             :                 int j;
    2389           0 :                 isl_int *t = bmap->div[div];
    2390             : 
    2391           0 :                 for (j = div; j < bmap->n_div - 1; ++j)
    2392           0 :                         bmap->div[j] = bmap->div[j+1];
    2393             : 
    2394           0 :                 bmap->div[bmap->n_div - 1] = t;
    2395             :         }
    2396           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    2397           0 :         if (isl_basic_map_free_div(bmap, 1) < 0)
    2398           0 :                 return isl_basic_map_free(bmap);
    2399             : 
    2400           0 :         return bmap;
    2401             : error:
    2402           0 :         isl_basic_map_free(bmap);
    2403           0 :         return NULL;
    2404             : }
    2405             : 
    2406             : /* Eliminate the specified n dimensions starting at first from the
    2407             :  * constraints, without removing the dimensions from the space.
    2408             :  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
    2409             :  */
    2410           0 : __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
    2411             :         enum isl_dim_type type, unsigned first, unsigned n)
    2412             : {
    2413             :         int i;
    2414             : 
    2415           0 :         if (n == 0)
    2416           0 :                 return map;
    2417             : 
    2418           0 :         if (isl_map_check_range(map, type, first, n) < 0)
    2419           0 :                 return isl_map_free(map);
    2420             : 
    2421           0 :         map = isl_map_cow(map);
    2422           0 :         if (!map)
    2423           0 :                 return NULL;
    2424             : 
    2425           0 :         for (i = 0; i < map->n; ++i) {
    2426           0 :                 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
    2427           0 :                 if (!map->p[i])
    2428           0 :                         goto error;
    2429             :         }
    2430           0 :         return map;
    2431             : error:
    2432           0 :         isl_map_free(map);
    2433           0 :         return NULL;
    2434             : }
    2435             : 
    2436             : /* Eliminate the specified n dimensions starting at first from the
    2437             :  * constraints, without removing the dimensions from the space.
    2438             :  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
    2439             :  */
    2440           0 : __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
    2441             :         enum isl_dim_type type, unsigned first, unsigned n)
    2442             : {
    2443           0 :         return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
    2444             : }
    2445             : 
    2446             : /* Eliminate the specified n dimensions starting at first from the
    2447             :  * constraints, without removing the dimensions from the space.
    2448             :  * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
    2449             :  */
    2450           0 : __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
    2451             :         unsigned first, unsigned n)
    2452             : {
    2453           0 :         return isl_set_eliminate(set, isl_dim_set, first, n);
    2454             : }
    2455             : 
    2456           0 : __isl_give isl_basic_map *isl_basic_map_remove_divs(
    2457             :         __isl_take isl_basic_map *bmap)
    2458             : {
    2459           0 :         if (!bmap)
    2460           0 :                 return NULL;
    2461           0 :         bmap = isl_basic_map_eliminate_vars(bmap,
    2462             :                             isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
    2463           0 :         if (!bmap)
    2464           0 :                 return NULL;
    2465           0 :         bmap->n_div = 0;
    2466           0 :         return isl_basic_map_finalize(bmap);
    2467             : }
    2468             : 
    2469           0 : __isl_give isl_basic_set *isl_basic_set_remove_divs(
    2470             :         __isl_take isl_basic_set *bset)
    2471             : {
    2472           0 :         return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
    2473             : }
    2474             : 
    2475           0 : __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
    2476             : {
    2477             :         int i;
    2478             : 
    2479           0 :         if (!map)
    2480           0 :                 return NULL;
    2481           0 :         if (map->n == 0)
    2482           0 :                 return map;
    2483             : 
    2484           0 :         map = isl_map_cow(map);
    2485           0 :         if (!map)
    2486           0 :                 return NULL;
    2487             :         
    2488           0 :         for (i = 0; i < map->n; ++i) {
    2489           0 :                 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
    2490           0 :                 if (!map->p[i])
    2491           0 :                         goto error;
    2492             :         }
    2493           0 :         return map;
    2494             : error:
    2495           0 :         isl_map_free(map);
    2496           0 :         return NULL;
    2497             : }
    2498             : 
    2499           0 : __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
    2500             : {
    2501           0 :         return isl_map_remove_divs(set);
    2502             : }
    2503             : 
    2504     7702949 : __isl_give isl_basic_map *isl_basic_map_remove_dims(
    2505             :         __isl_take isl_basic_map *bmap, enum isl_dim_type type,
    2506             :         unsigned first, unsigned n)
    2507             : {
    2508     7702949 :         if (isl_basic_map_check_range(bmap, type, first, n) < 0)
    2509           0 :                 return isl_basic_map_free(bmap);
    2510     7702949 :         if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
    2511     6950224 :                 return bmap;
    2512      752725 :         bmap = isl_basic_map_eliminate_vars(bmap,
    2513      752725 :                         isl_basic_map_offset(bmap, type) - 1 + first, n);
    2514      752725 :         if (!bmap)
    2515           0 :                 return bmap;
    2516      752725 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
    2517           0 :                 return bmap;
    2518      752725 :         bmap = isl_basic_map_drop(bmap, type, first, n);
    2519      752725 :         return bmap;
    2520             : }
    2521             : 
    2522             : /* Return true if the definition of the given div (recursively) involves
    2523             :  * any of the given variables.
    2524             :  */
    2525           0 : static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
    2526             :         unsigned first, unsigned n)
    2527             : {
    2528             :         int i;
    2529           0 :         unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
    2530             : 
    2531           0 :         if (isl_int_is_zero(bmap->div[div][0]))
    2532           0 :                 return isl_bool_false;
    2533           0 :         if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
    2534           0 :                 return isl_bool_true;
    2535             : 
    2536           0 :         for (i = bmap->n_div - 1; i >= 0; --i) {
    2537             :                 isl_bool involves;
    2538             : 
    2539           0 :                 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
    2540           0 :                         continue;
    2541           0 :                 involves = div_involves_vars(bmap, i, first, n);
    2542           0 :                 if (involves < 0 || involves)
    2543           0 :                         return involves;
    2544             :         }
    2545             : 
    2546           0 :         return isl_bool_false;
    2547             : }
    2548             : 
    2549             : /* Try and add a lower and/or upper bound on "div" to "bmap"
    2550             :  * based on inequality "i".
    2551             :  * "total" is the total number of variables (excluding the divs).
    2552             :  * "v" is a temporary object that can be used during the calculations.
    2553             :  * If "lb" is set, then a lower bound should be constructed.
    2554             :  * If "ub" is set, then an upper bound should be constructed.
    2555             :  *
    2556             :  * The calling function has already checked that the inequality does not
    2557             :  * reference "div", but we still need to check that the inequality is
    2558             :  * of the right form.  We'll consider the case where we want to construct
    2559             :  * a lower bound.  The construction of upper bounds is similar.
    2560             :  *
    2561             :  * Let "div" be of the form
    2562             :  *
    2563             :  *      q = floor((a + f(x))/d)
    2564             :  *
    2565             :  * We essentially check if constraint "i" is of the form
    2566             :  *
    2567             :  *      b + f(x) >= 0
    2568             :  *
    2569             :  * so that we can use it to derive a lower bound on "div".
    2570             :  * However, we allow a slightly more general form
    2571             :  *
    2572             :  *      b + g(x) >= 0
    2573             :  *
    2574             :  * with the condition that the coefficients of g(x) - f(x) are all
    2575             :  * divisible by d.
    2576             :  * Rewriting this constraint as
    2577             :  *
    2578             :  *      0 >= -b - g(x)
    2579             :  *
    2580             :  * adding a + f(x) to both sides and dividing by d, we obtain
    2581             :  *
    2582             :  *      (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
    2583             :  *
    2584             :  * Taking the floor on both sides, we obtain
    2585             :  *
    2586             :  *      q >= floor((a-b)/d) + (f(x)-g(x))/d
    2587             :  *
    2588             :  * or
    2589             :  *
    2590             :  *      (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
    2591             :  *
    2592             :  * In the case of an upper bound, we construct the constraint
    2593             :  *
    2594             :  *      (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
    2595             :  *
    2596             :  */
    2597           0 : static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
    2598             :         __isl_take isl_basic_map *bmap, int div, int i,
    2599             :         unsigned total, isl_int v, int lb, int ub)
    2600             : {
    2601             :         int j;
    2602             : 
    2603           0 :         for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
    2604           0 :                 if (lb) {
    2605           0 :                         isl_int_sub(v, bmap->ineq[i][1 + j],
    2606             :                                         bmap->div[div][1 + 1 + j]);
    2607           0 :                         lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
    2608             :                 }
    2609           0 :                 if (ub) {
    2610           0 :                         isl_int_add(v, bmap->ineq[i][1 + j],
    2611             :                                         bmap->div[div][1 + 1 + j]);
    2612           0 :                         ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
    2613             :                 }
    2614             :         }
    2615           0 :         if (!lb && !ub)
    2616           0 :                 return bmap;
    2617             : 
    2618           0 :         bmap = isl_basic_map_cow(bmap);
    2619           0 :         bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
    2620           0 :         if (lb) {
    2621           0 :                 int k = isl_basic_map_alloc_inequality(bmap);
    2622           0 :                 if (k < 0)
    2623           0 :                         goto error;
    2624           0 :                 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
    2625           0 :                         isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
    2626             :                                         bmap->div[div][1 + j]);
    2627           0 :                         isl_int_cdiv_q(bmap->ineq[k][j],
    2628             :                                         bmap->ineq[k][j], bmap->div[div][0]);
    2629             :                 }
    2630           0 :                 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
    2631             :         }
    2632           0 :         if (ub) {
    2633           0 :                 int k = isl_basic_map_alloc_inequality(bmap);
    2634           0 :                 if (k < 0)
    2635           0 :                         goto error;
    2636           0 :                 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
    2637           0 :                         isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
    2638             :                                         bmap->div[div][1 + j]);
    2639           0 :                         isl_int_fdiv_q(bmap->ineq[k][j],
    2640             :                                         bmap->ineq[k][j], bmap->div[div][0]);
    2641             :                 }
    2642           0 :                 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
    2643             :         }
    2644             : 
    2645           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    2646           0 :         return bmap;
    2647             : error:
    2648           0 :         isl_basic_map_free(bmap);
    2649           0 :         return NULL;
    2650             : }
    2651             : 
    2652             : /* This function is called right before "div" is eliminated from "bmap"
    2653             :  * using Fourier-Motzkin.
    2654             :  * Look through the constraints of "bmap" for constraints on the argument
    2655             :  * of the integer division and use them to construct constraints on the
    2656             :  * integer division itself.  These constraints can then be combined
    2657             :  * during the Fourier-Motzkin elimination.
    2658             :  * Note that it is only useful to introduce lower bounds on "div"
    2659             :  * if "bmap" already contains upper bounds on "div" as the newly
    2660             :  * introduce lower bounds can then be combined with the pre-existing
    2661             :  * upper bounds.  Similarly for upper bounds.
    2662             :  * We therefore first check if "bmap" contains any lower and/or upper bounds
    2663             :  * on "div".
    2664             :  *
    2665             :  * It is interesting to note that the introduction of these constraints
    2666             :  * can indeed lead to more accurate results, even when compared to
    2667             :  * deriving constraints on the argument of "div" from constraints on "div".
    2668             :  * Consider, for example, the set
    2669             :  *
    2670             :  *      { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
    2671             :  *
    2672             :  * The second constraint can be rewritten as
    2673             :  *
    2674             :  *      2 * [(-i-2j+3)/4] + k >= 0
    2675             :  *
    2676             :  * from which we can derive
    2677             :  *
    2678             :  *      -i - 2j + 3 >= -2k
    2679             :  *
    2680             :  * or
    2681             :  *
    2682             :  *      i + 2j <= 3 + 2k
    2683             :  *
    2684             :  * Combined with the first constraint, we obtain
    2685             :  *
    2686             :  *      -3 <= 3 + 2k or      k >= -3
    2687             :  *
    2688             :  * If, on the other hand we derive a constraint on [(i+2j)/4] from
    2689             :  * the first constraint, we obtain
    2690             :  *
    2691             :  *      [(i + 2j)/4] >= [-3/4] = -1
    2692             :  *
    2693             :  * Combining this constraint with the second constraint, we obtain
    2694             :  *
    2695             :  *      k >= -2
    2696             :  */
    2697           0 : static __isl_give isl_basic_map *insert_bounds_on_div(
    2698             :         __isl_take isl_basic_map *bmap, int div)
    2699             : {
    2700             :         int i;
    2701             :         int check_lb, check_ub;
    2702             :         isl_int v;
    2703             :         unsigned total;
    2704             : 
    2705           0 :         if (!bmap)
    2706           0 :                 return NULL;
    2707             : 
    2708           0 :         if (isl_int_is_zero(bmap->div[div][0]))
    2709           0 :                 return bmap;
    2710             : 
    2711           0 :         total = isl_space_dim(bmap->dim, isl_dim_all);
    2712             : 
    2713           0 :         check_lb = 0;
    2714           0 :         check_ub = 0;
    2715           0 :         for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
    2716           0 :                 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
    2717           0 :                 if (s > 0)
    2718           0 :                         check_ub = 1;
    2719           0 :                 if (s < 0)
    2720           0 :                         check_lb = 1;
    2721             :         }
    2722             : 
    2723           0 :         if (!check_lb && !check_ub)
    2724           0 :                 return bmap;
    2725             : 
    2726           0 :         isl_int_init(v);
    2727             : 
    2728           0 :         for (i = 0; bmap && i < bmap->n_ineq; ++i) {
    2729           0 :                 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
    2730           0 :                         continue;
    2731             : 
    2732           0 :                 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
    2733             :                                                         check_lb, check_ub);
    2734             :         }
    2735             : 
    2736           0 :         isl_int_clear(v);
    2737             : 
    2738           0 :         return bmap;
    2739             : }
    2740             : 
    2741             : /* Remove all divs (recursively) involving any of the given dimensions
    2742             :  * in their definitions.
    2743             :  */
    2744           0 : __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
    2745             :         __isl_take isl_basic_map *bmap,
    2746             :         enum isl_dim_type type, unsigned first, unsigned n)
    2747             : {
    2748             :         int i;
    2749             : 
    2750           0 :         if (isl_basic_map_check_range(bmap, type, first, n) < 0)
    2751           0 :                 return isl_basic_map_free(bmap);
    2752           0 :         first += isl_basic_map_offset(bmap, type);
    2753             : 
    2754           0 :         for (i = bmap->n_div - 1; i >= 0; --i) {
    2755             :                 isl_bool involves;
    2756             : 
    2757           0 :                 involves = div_involves_vars(bmap, i, first, n);
    2758           0 :                 if (involves < 0)
    2759           0 :                         return isl_basic_map_free(bmap);
    2760           0 :                 if (!involves)
    2761           0 :                         continue;
    2762           0 :                 bmap = insert_bounds_on_div(bmap, i);
    2763           0 :                 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
    2764           0 :                 if (!bmap)
    2765           0 :                         return NULL;
    2766           0 :                 i = bmap->n_div;
    2767             :         }
    2768             : 
    2769           0 :         return bmap;
    2770             : }
    2771             : 
    2772           0 : __isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
    2773             :         __isl_take isl_basic_set *bset,
    2774             :         enum isl_dim_type type, unsigned first, unsigned n)
    2775             : {
    2776           0 :         return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
    2777             : }
    2778             : 
    2779           0 : __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
    2780             :         enum isl_dim_type type, unsigned first, unsigned n)
    2781             : {
    2782             :         int i;
    2783             : 
    2784           0 :         if (!map)
    2785           0 :                 return NULL;
    2786           0 :         if (map->n == 0)
    2787           0 :                 return map;
    2788             : 
    2789           0 :         map = isl_map_cow(map);
    2790           0 :         if (!map)
    2791           0 :                 return NULL;
    2792             : 
    2793           0 :         for (i = 0; i < map->n; ++i) {
    2794           0 :                 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
    2795             :                                                                 type, first, n);
    2796           0 :                 if (!map->p[i])
    2797           0 :                         goto error;
    2798             :         }
    2799           0 :         return map;
    2800             : error:
    2801           0 :         isl_map_free(map);
    2802           0 :         return NULL;
    2803             : }
    2804             : 
    2805           0 : __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
    2806             :         enum isl_dim_type type, unsigned first, unsigned n)
    2807             : {
    2808           0 :         return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
    2809             :                                                               type, first, n));
    2810             : }
    2811             : 
    2812             : /* Does the description of "bmap" depend on the specified dimensions?
    2813             :  * We also check whether the dimensions appear in any of the div definitions.
    2814             :  * In principle there is no need for this check.  If the dimensions appear
    2815             :  * in a div definition, they also appear in the defining constraints of that
    2816             :  * div.
    2817             :  */
    2818           0 : isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
    2819             :         enum isl_dim_type type, unsigned first, unsigned n)
    2820             : {
    2821             :         int i;
    2822             : 
    2823           0 :         if (isl_basic_map_check_range(bmap, type, first, n) < 0)
    2824           0 :                 return isl_bool_error;
    2825             : 
    2826           0 :         first += isl_basic_map_offset(bmap, type);
    2827           0 :         for (i = 0; i < bmap->n_eq; ++i)
    2828           0 :                 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
    2829           0 :                         return isl_bool_true;
    2830           0 :         for (i = 0; i < bmap->n_ineq; ++i)
    2831           0 :                 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
    2832           0 :                         return isl_bool_true;
    2833           0 :         for (i = 0; i < bmap->n_div; ++i) {
    2834           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
    2835           0 :                         continue;
    2836           0 :                 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
    2837           0 :                         return isl_bool_true;
    2838             :         }
    2839             : 
    2840           0 :         return isl_bool_false;
    2841             : }
    2842             : 
    2843           0 : isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
    2844             :         enum isl_dim_type type, unsigned first, unsigned n)
    2845             : {
    2846             :         int i;
    2847             : 
    2848           0 :         if (isl_map_check_range(map, type, first, n) < 0)
    2849           0 :                 return isl_bool_error;
    2850             : 
    2851           0 :         for (i = 0; i < map->n; ++i) {
    2852           0 :                 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
    2853             :                                                             type, first, n);
    2854           0 :                 if (involves < 0 || involves)
    2855           0 :                         return involves;
    2856             :         }
    2857             : 
    2858           0 :         return isl_bool_false;
    2859             : }
    2860             : 
    2861           0 : isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
    2862             :         enum isl_dim_type type, unsigned first, unsigned n)
    2863             : {
    2864           0 :         return isl_basic_map_involves_dims(bset, type, first, n);
    2865             : }
    2866             : 
    2867           0 : isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
    2868             :         enum isl_dim_type type, unsigned first, unsigned n)
    2869             : {
    2870           0 :         return isl_map_involves_dims(set, type, first, n);
    2871             : }
    2872             : 
    2873             : /* Drop all constraints in bmap that involve any of the dimensions
    2874             :  * first to first+n-1.
    2875             :  */
    2876    16520446 : static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
    2877             :         __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
    2878             : {
    2879             :         int i;
    2880             : 
    2881    16520446 :         if (n == 0)
    2882      236773 :                 return bmap;
    2883             : 
    2884    16283673 :         bmap = isl_basic_map_cow(bmap);
    2885             : 
    2886    16283673 :         if (!bmap)
    2887           0 :                 return NULL;
    2888             : 
    2889    16283831 :         for (i = bmap->n_eq - 1; i >= 0; --i) {
    2890         158 :                 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
    2891         158 :                         continue;
    2892           0 :                 isl_basic_map_drop_equality(bmap, i);
    2893             :         }
    2894             : 
    2895   127042799 :         for (i = bmap->n_ineq - 1; i >= 0; --i) {
    2896   110759126 :                 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
    2897    33790740 :                         continue;
    2898    76968386 :                 isl_basic_map_drop_inequality(bmap, i);
    2899             :         }
    2900             : 
    2901    16283673 :         bmap = isl_basic_map_add_known_div_constraints(bmap);
    2902    16283673 :         return bmap;
    2903             : }
    2904             : 
    2905             : /* Drop all constraints in bset that involve any of the dimensions
    2906             :  * first to first+n-1.
    2907             :  */
    2908    16520446 : __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
    2909             :         __isl_take isl_basic_set *bset, unsigned first, unsigned n)
    2910             : {
    2911    16520446 :         return isl_basic_map_drop_constraints_involving(bset, first, n);
    2912             : }
    2913             : 
    2914             : /* Drop all constraints in bmap that do not involve any of the dimensions
    2915             :  * first to first + n - 1 of the given type.
    2916             :  */
    2917           0 : __isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
    2918             :         __isl_take isl_basic_map *bmap,
    2919             :         enum isl_dim_type type, unsigned first, unsigned n)
    2920             : {
    2921             :         int i;
    2922             : 
    2923           0 :         if (n == 0) {
    2924           0 :                 isl_space *space = isl_basic_map_get_space(bmap);
    2925           0 :                 isl_basic_map_free(bmap);
    2926           0 :                 return isl_basic_map_universe(space);
    2927             :         }
    2928           0 :         bmap = isl_basic_map_cow(bmap);
    2929           0 :         if (!bmap)
    2930           0 :                 return NULL;
    2931             : 
    2932           0 :         if (isl_basic_map_check_range(bmap, type, first, n) < 0)
    2933           0 :                 return isl_basic_map_free(bmap);
    2934             : 
    2935           0 :         first += isl_basic_map_offset(bmap, type) - 1;
    2936             : 
    2937           0 :         for (i = bmap->n_eq - 1; i >= 0; --i) {
    2938           0 :                 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
    2939           0 :                         continue;
    2940           0 :                 isl_basic_map_drop_equality(bmap, i);
    2941             :         }
    2942             : 
    2943           0 :         for (i = bmap->n_ineq - 1; i >= 0; --i) {
    2944           0 :                 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
    2945           0 :                         continue;
    2946           0 :                 isl_basic_map_drop_inequality(bmap, i);
    2947             :         }
    2948             : 
    2949           0 :         bmap = isl_basic_map_add_known_div_constraints(bmap);
    2950           0 :         return bmap;
    2951             : }
    2952             : 
    2953             : /* Drop all constraints in bset that do not involve any of the dimensions
    2954             :  * first to first + n - 1 of the given type.
    2955             :  */
    2956           0 : __isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
    2957             :         __isl_take isl_basic_set *bset,
    2958             :         enum isl_dim_type type, unsigned first, unsigned n)
    2959             : {
    2960           0 :         return isl_basic_map_drop_constraints_not_involving_dims(bset,
    2961             :                                                             type, first, n);
    2962             : }
    2963             : 
    2964             : /* Drop all constraints in bmap that involve any of the dimensions
    2965             :  * first to first + n - 1 of the given type.
    2966             :  */
    2967  2898920016 : __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
    2968             :         __isl_take isl_basic_map *bmap,
    2969             :         enum isl_dim_type type, unsigned first, unsigned n)
    2970             : {
    2971  2898920016 :         if (!bmap)
    2972           0 :                 return NULL;
    2973  2898920016 :         if (n == 0)
    2974  2898920016 :                 return bmap;
    2975             : 
    2976           0 :         if (isl_basic_map_check_range(bmap, type, first, n) < 0)
    2977           0 :                 return isl_basic_map_free(bmap);
    2978             : 
    2979           0 :         bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
    2980           0 :         first += isl_basic_map_offset(bmap, type) - 1;
    2981           0 :         return isl_basic_map_drop_constraints_involving(bmap, first, n);
    2982             : }
    2983             : 
    2984             : /* Drop all constraints in bset that involve any of the dimensions
    2985             :  * first to first + n - 1 of the given type.
    2986             :  */
    2987           0 : __isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
    2988             :         __isl_take isl_basic_set *bset,
    2989             :         enum isl_dim_type type, unsigned first, unsigned n)
    2990             : {
    2991           0 :         return isl_basic_map_drop_constraints_involving_dims(bset,
    2992             :                                                             type, first, n);
    2993             : }
    2994             : 
    2995             : /* Drop constraints from "map" by applying "drop" to each basic map.
    2996             :  */
    2997           0 : static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
    2998             :         enum isl_dim_type type, unsigned first, unsigned n,
    2999             :         __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
    3000             :                 enum isl_dim_type type, unsigned first, unsigned n))
    3001             : {
    3002             :         int i;
    3003             : 
    3004           0 :         if (isl_map_check_range(map, type, first, n) < 0)
    3005           0 :                 return isl_map_free(map);
    3006             : 
    3007           0 :         map = isl_map_cow(map);
    3008           0 :         if (!map)
    3009           0 :                 return NULL;
    3010             : 
    3011           0 :         for (i = 0; i < map->n; ++i) {
    3012           0 :                 map->p[i] = drop(map->p[i], type, first, n);
    3013           0 :                 if (!map->p[i])
    3014           0 :                         return isl_map_free(map);
    3015             :         }
    3016             : 
    3017           0 :         if (map->n > 1)
    3018           0 :                 ISL_F_CLR(map, ISL_MAP_DISJOINT);
    3019             : 
    3020           0 :         return map;
    3021             : }
    3022             : 
    3023             : /* Drop all constraints in map that involve any of the dimensions
    3024             :  * first to first + n - 1 of the given type.
    3025             :  */
    3026           0 : __isl_give isl_map *isl_map_drop_constraints_involving_dims(
    3027             :         __isl_take isl_map *map,
    3028             :         enum isl_dim_type type, unsigned first, unsigned n)
    3029             : {
    3030           0 :         if (n == 0)
    3031           0 :                 return map;
    3032           0 :         return drop_constraints(map, type, first, n,
    3033             :                                 &isl_basic_map_drop_constraints_involving_dims);
    3034             : }
    3035             : 
    3036             : /* Drop all constraints in "map" that do not involve any of the dimensions
    3037             :  * first to first + n - 1 of the given type.
    3038             :  */
    3039           0 : __isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
    3040             :         __isl_take isl_map *map,
    3041             :         enum isl_dim_type type, unsigned first, unsigned n)
    3042             : {
    3043           0 :         if (n == 0) {
    3044           0 :                 isl_space *space = isl_map_get_space(map);
    3045           0 :                 isl_map_free(map);
    3046           0 :                 return isl_map_universe(space);
    3047             :         }
    3048           0 :         return drop_constraints(map, type, first, n,
    3049             :                             &isl_basic_map_drop_constraints_not_involving_dims);
    3050             : }
    3051             : 
    3052             : /* Drop all constraints in set that involve any of the dimensions
    3053             :  * first to first + n - 1 of the given type.
    3054             :  */
    3055           0 : __isl_give isl_set *isl_set_drop_constraints_involving_dims(
    3056             :         __isl_take isl_set *set,
    3057             :         enum isl_dim_type type, unsigned first, unsigned n)
    3058             : {
    3059           0 :         return isl_map_drop_constraints_involving_dims(set, type, first, n);
    3060             : }
    3061             : 
    3062             : /* Drop all constraints in "set" that do not involve any of the dimensions
    3063             :  * first to first + n - 1 of the given type.
    3064             :  */
    3065           0 : __isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
    3066             :         __isl_take isl_set *set,
    3067             :         enum isl_dim_type type, unsigned first, unsigned n)
    3068             : {
    3069           0 :         return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
    3070             : }
    3071             : 
    3072             : /* Does local variable "div" of "bmap" have a complete explicit representation?
    3073             :  * Having a complete explicit representation requires not only
    3074             :  * an explicit representation, but also that all local variables
    3075             :  * that appear in this explicit representation in turn have
    3076             :  * a complete explicit representation.
    3077             :  */
    3078           0 : isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
    3079             : {
    3080             :         int i;
    3081           0 :         unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
    3082             :         isl_bool marked;
    3083             : 
    3084           0 :         marked = isl_basic_map_div_is_marked_unknown(bmap, div);
    3085           0 :         if (marked < 0 || marked)
    3086           0 :                 return isl_bool_not(marked);
    3087             : 
    3088           0 :         for (i = bmap->n_div - 1; i >= 0; --i) {
    3089             :                 isl_bool known;
    3090             : 
    3091           0 :                 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
    3092           0 :                         continue;
    3093           0 :                 known = isl_basic_map_div_is_known(bmap, i);
    3094           0 :                 if (known < 0 || !known)
    3095           0 :                         return known;
    3096             :         }
    3097             : 
    3098           0 :         return isl_bool_true;
    3099             : }
    3100             : 
    3101             : /* Remove all divs that are unknown or defined in terms of unknown divs.
    3102             :  */
    3103  1188543038 : __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
    3104             :         __isl_take isl_basic_map *bmap)
    3105             : {
    3106             :         int i;
    3107             : 
    3108  1188543038 :         if (!bmap)
    3109           0 :                 return NULL;
    3110             : 
    3111  1188543038 :         for (i = bmap->n_div - 1; i >= 0; --i) {
    3112           0 :                 if (isl_basic_map_div_is_known(bmap, i))
    3113           0 :                         continue;
    3114           0 :                 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
    3115           0 :                 if (!bmap)
    3116           0 :                         return NULL;
    3117           0 :                 i = bmap->n_div;
    3118             :         }
    3119             : 
    3120  1188543038 :         return bmap;
    3121             : }
    3122             : 
    3123             : /* Remove all divs that are unknown or defined in terms of unknown divs.
    3124             :  */
    3125           0 : __isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
    3126             :         __isl_take isl_basic_set *bset)
    3127             : {
    3128           0 :         return isl_basic_map_remove_unknown_divs(bset);
    3129             : }
    3130             : 
    3131   645829553 : __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
    3132             : {
    3133             :         int i;
    3134             : 
    3135   645829553 :         if (!map)
    3136           0 :                 return NULL;
    3137   645829553 :         if (map->n == 0)
    3138           0 :                 return map;
    3139             : 
    3140   645829553 :         map = isl_map_cow(map);
    3141   645829553 :         if (!map)
    3142           0 :                 return NULL;
    3143             : 
    3144  1834372591 :         for (i = 0; i < map->n; ++i) {
    3145  1188543038 :                 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
    3146  1188543038 :                 if (!map->p[i])
    3147           0 :                         goto error;
    3148             :         }
    3149   645829553 :         return map;
    3150             : error:
    3151           0 :         isl_map_free(map);
    3152           0 :         return NULL;
    3153             : }
    3154             : 
    3155           0 : __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
    3156             : {
    3157           0 :         return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
    3158             : }
    3159             : 
    3160     7702949 : __isl_give isl_basic_set *isl_basic_set_remove_dims(
    3161             :         __isl_take isl_basic_set *bset,
    3162             :         enum isl_dim_type type, unsigned first, unsigned n)
    3163             : {
    3164     7702949 :         isl_basic_map *bmap = bset_to_bmap(bset);
    3165     7702949 :         bmap = isl_basic_map_remove_dims(bmap, type, first, n);
    3166     7702949 :         return bset_from_bmap(bmap);
    3167             : }
    3168             : 
    3169           0 : __isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
    3170             :         enum isl_dim_type type, unsigned first, unsigned n)
    3171             : {
    3172             :         int i;
    3173             : 
    3174           0 :         if (n == 0)
    3175           0 :                 return map;
    3176             : 
    3177           0 :         map = isl_map_cow(map);
    3178           0 :         if (isl_map_check_range(map, type, first, n) < 0)
    3179           0 :                 return isl_map_free(map);
    3180             :         
    3181           0 :         for (i = 0; i < map->n; ++i) {
    3182           0 :                 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
    3183           0 :                         isl_basic_map_offset(map->p[i], type) - 1 + first, n);
    3184           0 :                 if (!map->p[i])
    3185           0 :                         goto error;
    3186             :         }
    3187           0 :         map = isl_map_drop(map, type, first, n);
    3188           0 :         return map;
    3189             : error:
    3190           0 :         isl_map_free(map);
    3191           0 :         return NULL;
    3192             : }
    3193             : 
    3194           0 : __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
    3195             :         enum isl_dim_type type, unsigned first, unsigned n)
    3196             : {
    3197           0 :         return set_from_map(isl_map_remove_dims(set_to_map(bset),
    3198             :                                                 type, first, n));
    3199             : }
    3200             : 
    3201             : /* Project out n inputs starting at first using Fourier-Motzkin */
    3202           0 : struct isl_map *isl_map_remove_inputs(struct isl_map *map,
    3203             :         unsigned first, unsigned n)
    3204             : {
    3205           0 :         return isl_map_remove_dims(map, isl_dim_in, first, n);
    3206             : }
    3207             : 
    3208           0 : static void dump_term(struct isl_basic_map *bmap,
    3209             :                         isl_int c, int pos, FILE *out)
    3210             : {
    3211             :         const char *name;
    3212           0 :         unsigned in = isl_basic_map_dim(bmap, isl_dim_in);
    3213           0 :         unsigned dim = in + isl_basic_map_dim(bmap, isl_dim_out);
    3214           0 :         unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
    3215           0 :         if (!pos)
    3216           0 :                 isl_int_print(out, c, 0);
    3217             :         else {
    3218           0 :                 if (!isl_int_is_one(c))
    3219           0 :                         isl_int_print(out, c, 0);
    3220           0 :                 if (pos < 1 + nparam) {
    3221           0 :                         name = isl_space_get_dim_name(bmap->dim,
    3222           0 :                                                 isl_dim_param, pos - 1);
    3223           0 :                         if (name)
    3224           0 :                                 fprintf(out, "%s", name);
    3225             :                         else
    3226           0 :                                 fprintf(out, "p%d", pos - 1);
    3227           0 :                 } else if (pos < 1 + nparam + in)
    3228           0 :                         fprintf(out, "i%d", pos - 1 - nparam);
    3229           0 :                 else if (pos < 1 + nparam + dim)
    3230           0 :                         fprintf(out, "o%d", pos - 1 - nparam - in);
    3231             :                 else
    3232           0 :                         fprintf(out, "e%d", pos - 1 - nparam - dim);
    3233             :         }
    3234           0 : }
    3235             : 
    3236           0 : static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
    3237             :                                 int sign, FILE *out)
    3238             : {
    3239             :         int i;
    3240             :         int first;
    3241           0 :         unsigned len = 1 + isl_basic_map_total_dim(bmap);
    3242             :         isl_int v;
    3243             : 
    3244           0 :         isl_int_init(v);
    3245           0 :         for (i = 0, first = 1; i < len; ++i) {
    3246           0 :                 if (isl_int_sgn(c[i]) * sign <= 0)
    3247           0 :                         continue;
    3248           0 :                 if (!first)
    3249           0 :                         fprintf(out, " + ");
    3250           0 :                 first = 0;
    3251           0 :                 isl_int_abs(v, c[i]);
    3252           0 :                 dump_term(bmap, v, i, out);
    3253             :         }
    3254           0 :         isl_int_clear(v);
    3255           0 :         if (first)
    3256           0 :                 fprintf(out, "0");
    3257           0 : }
    3258             : 
    3259           0 : static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
    3260             :                                 const char *op, FILE *out, int indent)
    3261             : {
    3262             :         int i;
    3263             : 
    3264           0 :         fprintf(out, "%*s", indent, "");
    3265             : 
    3266           0 :         dump_constraint_sign(bmap, c, 1, out);
    3267           0 :         fprintf(out, " %s ", op);
    3268           0 :         dump_constraint_sign(bmap, c, -1, out);
    3269             : 
    3270           0 :         fprintf(out, "\n");
    3271             : 
    3272           0 :         for (i = bmap->n_div; i < bmap->extra; ++i) {
    3273           0 :                 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
    3274           0 :                         continue;
    3275           0 :                 fprintf(out, "%*s", indent, "");
    3276           0 :                 fprintf(out, "ERROR: unused div coefficient not zero\n");
    3277           0 :                 abort();
    3278             :         }
    3279           0 : }
    3280             : 
    3281           0 : static void dump_constraints(struct isl_basic_map *bmap,
    3282             :                                 isl_int **c, unsigned n,
    3283             :                                 const char *op, FILE *out, int indent)
    3284             : {
    3285             :         int i;
    3286             : 
    3287           0 :         for (i = 0; i < n; ++i)
    3288           0 :                 dump_constraint(bmap, c[i], op, out, indent);
    3289           0 : }
    3290             : 
    3291           0 : static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
    3292             : {
    3293             :         int j;
    3294           0 :         int first = 1;
    3295           0 :         unsigned total = isl_basic_map_total_dim(bmap);
    3296             : 
    3297           0 :         for (j = 0; j < 1 + total; ++j) {
    3298           0 :                 if (isl_int_is_zero(exp[j]))
    3299           0 :                         continue;
    3300           0 :                 if (!first && isl_int_is_pos(exp[j]))
    3301           0 :                         fprintf(out, "+");
    3302           0 :                 dump_term(bmap, exp[j], j, out);
    3303           0 :                 first = 0;
    3304             :         }
    3305           0 : }
    3306             : 
    3307           0 : static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
    3308             : {
    3309             :         int i;
    3310             : 
    3311           0 :         dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
    3312           0 :         dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
    3313             : 
    3314           0 :         for (i = 0; i < bmap->n_div; ++i) {
    3315           0 :                 fprintf(out, "%*s", indent, "");
    3316           0 :                 fprintf(out, "e%d = [(", i);
    3317           0 :                 dump_affine(bmap, bmap->div[i]+1, out);
    3318           0 :                 fprintf(out, ")/");
    3319           0 :                 isl_int_print(out, bmap->div[i][0], 0);
    3320           0 :                 fprintf(out, "]\n");
    3321             :         }
    3322           0 : }
    3323             : 
    3324           0 : void isl_basic_set_print_internal(struct isl_basic_set *bset,
    3325             :         FILE *out, int indent)
    3326             : {
    3327           0 :         if (!bset) {
    3328           0 :                 fprintf(out, "null basic set\n");
    3329           0 :                 return;
    3330             :         }
    3331             : 
    3332           0 :         fprintf(out, "%*s", indent, "");
    3333           0 :         fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
    3334           0 :                         bset->ref, bset->dim->nparam, bset->dim->n_out,
    3335             :                         bset->extra, bset->flags);
    3336           0 :         dump(bset_to_bmap(bset), out, indent);
    3337             : }
    3338             : 
    3339           0 : void isl_basic_map_print_internal(struct isl_basic_map *bmap,
    3340             :         FILE *out, int indent)
    3341             : {
    3342           0 :         if (!bmap) {
    3343           0 :                 fprintf(out, "null basic map\n");
    3344           0 :                 return;
    3345             :         }
    3346             : 
    3347           0 :         fprintf(out, "%*s", indent, "");
    3348           0 :         fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
    3349             :                         "flags: %x, n_name: %d\n",
    3350             :                 bmap->ref,
    3351           0 :                 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
    3352           0 :                 bmap->extra, bmap->flags, bmap->dim->n_id);
    3353           0 :         dump(bmap, out, indent);
    3354             : }
    3355             : 
    3356           0 : int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
    3357             : {
    3358             :         unsigned total;
    3359           0 :         if (!bmap)
    3360           0 :                 return -1;
    3361           0 :         total = isl_basic_map_total_dim(bmap);
    3362           0 :         isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
    3363           0 :         isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
    3364           0 :         isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
    3365           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    3366           0 :         return 0;
    3367             : }
    3368             : 
    3369      112944 : __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
    3370             :         unsigned flags)
    3371             : {
    3372      112944 :         if (!space)
    3373           0 :                 return NULL;
    3374      112944 :         if (isl_space_dim(space, isl_dim_in) != 0)
    3375           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    3376             :                         "set cannot have input dimensions", goto error);
    3377      112944 :         return isl_map_alloc_space(space, n, flags);
    3378             : error:
    3379           0 :         isl_space_free(space);
    3380           0 :         return NULL;
    3381             : }
    3382             : 
    3383             : /* Make sure "map" has room for at least "n" more basic maps.
    3384             :  */
    3385           0 : __isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
    3386             : {
    3387             :         int i;
    3388           0 :         struct isl_map *grown = NULL;
    3389             : 
    3390           0 :         if (!map)
    3391           0 :                 return NULL;
    3392           0 :         isl_assert(map->ctx, n >= 0, goto error);
    3393           0 :         if (map->n + n <= map->size)
    3394           0 :                 return map;
    3395           0 :         grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
    3396           0 :         if (!grown)
    3397           0 :                 goto error;
    3398           0 :         for (i = 0; i < map->n; ++i) {
    3399           0 :                 grown->p[i] = isl_basic_map_copy(map->p[i]);
    3400           0 :                 if (!grown->p[i])
    3401           0 :                         goto error;
    3402           0 :                 grown->n++;
    3403             :         }
    3404           0 :         isl_map_free(map);
    3405           0 :         return grown;
    3406             : error:
    3407           0 :         isl_map_free(grown);
    3408           0 :         isl_map_free(map);
    3409           0 :         return NULL;
    3410             : }
    3411             : 
    3412             : /* Make sure "set" has room for at least "n" more basic sets.
    3413             :  */
    3414           0 : struct isl_set *isl_set_grow(struct isl_set *set, int n)
    3415             : {
    3416           0 :         return set_from_map(isl_map_grow(set_to_map(set), n));
    3417             : }
    3418             : 
    3419     2571461 : __isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
    3420             : {
    3421     2571461 :         return isl_map_from_basic_map(bset);
    3422             : }
    3423             : 
    3424    40834706 : __isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
    3425             : {
    3426             :         struct isl_map *map;
    3427             : 
    3428    40834706 :         if (!bmap)
    3429           0 :                 return NULL;
    3430             : 
    3431    40834706 :         map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
    3432    40834706 :         return isl_map_add_basic_map(map, bmap);
    3433             : }
    3434             : 
    3435           0 : __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
    3436             :                                                 __isl_take isl_basic_set *bset)
    3437             : {
    3438           0 :         return set_from_map(isl_map_add_basic_map(set_to_map(set),
    3439             :                                                 bset_to_bmap(bset)));
    3440             : }
    3441             : 
    3442  3009682364 : __isl_null isl_set *isl_set_free(__isl_take isl_set *set)
    3443             : {
    3444  3009682364 :         return isl_map_free(set);
    3445             : }
    3446             : 
    3447           0 : void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
    3448             : {
    3449             :         int i;
    3450             : 
    3451           0 :         if (!set) {
    3452           0 :                 fprintf(out, "null set\n");
    3453           0 :                 return;
    3454             :         }
    3455             : 
    3456           0 :         fprintf(out, "%*s", indent, "");
    3457           0 :         fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
    3458           0 :                         set->ref, set->n, set->dim->nparam, set->dim->n_out,
    3459             :                         set->flags);
    3460           0 :         for (i = 0; i < set->n; ++i) {
    3461           0 :                 fprintf(out, "%*s", indent, "");
    3462           0 :                 fprintf(out, "basic set %d:\n", i);
    3463           0 :                 isl_basic_set_print_internal(set->p[i], out, indent+4);
    3464             :         }
    3465             : }
    3466             : 
    3467           0 : void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
    3468             : {
    3469             :         int i;
    3470             : 
    3471           0 :         if (!map) {
    3472           0 :                 fprintf(out, "null map\n");
    3473           0 :                 return;
    3474             :         }
    3475             : 
    3476           0 :         fprintf(out, "%*s", indent, "");
    3477           0 :         fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
    3478             :                      "flags: %x, n_name: %d\n",
    3479           0 :                         map->ref, map->n, map->dim->nparam, map->dim->n_in,
    3480           0 :                         map->dim->n_out, map->flags, map->dim->n_id);
    3481           0 :         for (i = 0; i < map->n; ++i) {
    3482           0 :                 fprintf(out, "%*s", indent, "");
    3483           0 :                 fprintf(out, "basic map %d:\n", i);
    3484           0 :                 isl_basic_map_print_internal(map->p[i], out, indent+4);
    3485             :         }
    3486             : }
    3487             : 
    3488           0 : __isl_give isl_basic_map *isl_basic_map_intersect_domain(
    3489             :         __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
    3490             : {
    3491             :         struct isl_basic_map *bmap_domain;
    3492             : 
    3493           0 :         if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
    3494           0 :                 goto error;
    3495             : 
    3496           0 :         if (isl_space_dim(bset->dim, isl_dim_set) != 0)
    3497           0 :                 isl_assert(bset->ctx,
    3498             :                     isl_basic_map_compatible_domain(bmap, bset), goto error);
    3499             : 
    3500           0 :         bmap = isl_basic_map_cow(bmap);
    3501           0 :         if (!bmap)
    3502           0 :                 goto error;
    3503           0 :         bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
    3504             :                         bset->n_div, bset->n_eq, bset->n_ineq);
    3505           0 :         bmap_domain = isl_basic_map_from_domain(bset);
    3506           0 :         bmap = add_constraints(bmap, bmap_domain, 0, 0);
    3507             : 
    3508           0 :         bmap = isl_basic_map_simplify(bmap);
    3509           0 :         return isl_basic_map_finalize(bmap);
    3510             : error:
    3511           0 :         isl_basic_map_free(bmap);
    3512           0 :         isl_basic_set_free(bset);
    3513           0 :         return NULL;
    3514             : }
    3515             : 
    3516             : /* Check that the space of "bset" is the same as that of the range of "bmap".
    3517             :  */
    3518           0 : static isl_stat isl_basic_map_check_compatible_range(
    3519             :         __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
    3520             : {
    3521             :         isl_bool ok;
    3522             : 
    3523           0 :         ok = isl_basic_map_compatible_range(bmap, bset);
    3524           0 :         if (ok < 0)
    3525           0 :                 return isl_stat_error;
    3526           0 :         if (!ok)
    3527           0 :                 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
    3528             :                         "incompatible spaces", return isl_stat_error);
    3529             : 
    3530           0 :         return isl_stat_ok;
    3531             : }
    3532             : 
    3533           0 : __isl_give isl_basic_map *isl_basic_map_intersect_range(
    3534             :         __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
    3535             : {
    3536             :         struct isl_basic_map *bmap_range;
    3537             : 
    3538           0 :         if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
    3539           0 :                 goto error;
    3540             : 
    3541           0 :         if (isl_space_dim(bset->dim, isl_dim_set) != 0 &&
    3542           0 :             isl_basic_map_check_compatible_range(bmap, bset) < 0)
    3543           0 :                 goto error;
    3544             : 
    3545           0 :         if (isl_basic_set_plain_is_universe(bset)) {
    3546           0 :                 isl_basic_set_free(bset);
    3547           0 :                 return bmap;
    3548             :         }
    3549             : 
    3550           0 :         bmap = isl_basic_map_cow(bmap);
    3551           0 :         if (!bmap)
    3552           0 :                 goto error;
    3553           0 :         bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
    3554             :                         bset->n_div, bset->n_eq, bset->n_ineq);
    3555           0 :         bmap_range = bset_to_bmap(bset);
    3556           0 :         bmap = add_constraints(bmap, bmap_range, 0, 0);
    3557             : 
    3558           0 :         bmap = isl_basic_map_simplify(bmap);
    3559           0 :         return isl_basic_map_finalize(bmap);
    3560             : error:
    3561           0 :         isl_basic_map_free(bmap);
    3562           0 :         isl_basic_set_free(bset);
    3563           0 :         return NULL;
    3564             : }
    3565             : 
    3566   406736124 : isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
    3567             :         __isl_keep isl_vec *vec)
    3568             : {
    3569             :         int i;
    3570             :         unsigned total;
    3571             :         isl_int s;
    3572             : 
    3573   406736124 :         if (!bmap || !vec)
    3574           0 :                 return isl_bool_error;
    3575             : 
    3576   406736124 :         total = 1 + isl_basic_map_total_dim(bmap);
    3577   406736124 :         if (total != vec->size)
    3578           0 :                 return isl_bool_false;
    3579             : 
    3580   406736124 :         isl_int_init(s);
    3581             : 
    3582   663412738 :         for (i = 0; i < bmap->n_eq; ++i) {
    3583   328637149 :                 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
    3584   328637149 :                 if (!isl_int_is_zero(s)) {
    3585    71960535 :                         isl_int_clear(s);
    3586    71960535 :                         return isl_bool_false;
    3587             :                 }
    3588             :         }
    3589             : 
    3590  2087255628 :         for (i = 0; i < bmap->n_ineq; ++i) {
    3591  1925713169 :                 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
    3592  1925713169 :                 if (isl_int_is_neg(s)) {
    3593   173233130 :                         isl_int_clear(s);
    3594   173233130 :                         return isl_bool_false;
    3595             :                 }
    3596             :         }
    3597             : 
    3598   161542459 :         isl_int_clear(s);
    3599             : 
    3600   161542459 :         return isl_bool_true;
    3601             : }
    3602             : 
    3603     3188338 : isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
    3604             :         __isl_keep isl_vec *vec)
    3605             : {
    3606     3188338 :         return isl_basic_map_contains(bset_to_bmap(bset), vec);
    3607             : }
    3608             : 
    3609   110183997 : __isl_give isl_basic_map *isl_basic_map_intersect(
    3610             :         __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
    3611             : {
    3612   110183997 :         struct isl_vec *sample = NULL;
    3613             : 
    3614   110183997 :         if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
    3615           0 :                 goto error;
    3616   220367994 :         if (isl_space_dim(bmap1->dim, isl_dim_all) ==
    3617   110183997 :                                 isl_space_dim(bmap1->dim, isl_dim_param) &&
    3618           0 :             isl_space_dim(bmap2->dim, isl_dim_all) !=
    3619           0 :                                 isl_space_dim(bmap2->dim, isl_dim_param))
    3620           0 :                 return isl_basic_map_intersect(bmap2, bmap1);
    3621             : 
    3622   220367994 :         if (isl_space_dim(bmap2->dim, isl_dim_all) !=
    3623   110183997 :                                         isl_space_dim(bmap2->dim, isl_dim_param))
    3624   110183997 :                 isl_assert(bmap1->ctx,
    3625             :                             isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
    3626             : 
    3627   110183997 :         if (isl_basic_map_plain_is_empty(bmap1)) {
    3628           0 :                 isl_basic_map_free(bmap2);
    3629           0 :                 return bmap1;
    3630             :         }
    3631   110183997 :         if (isl_basic_map_plain_is_empty(bmap2)) {
    3632           0 :                 isl_basic_map_free(bmap1);
    3633           0 :                 return bmap2;
    3634             :         }
    3635             : 
    3636   219984580 :         if (bmap1->sample &&
    3637   219564605 :             isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
    3638   109764022 :             isl_basic_map_contains(bmap2, bmap1->sample) > 0)
    3639     4965551 :                 sample = isl_vec_copy(bmap1->sample);
    3640   210227554 :         else if (bmap2->sample &&
    3641   106269363 :             isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
    3642     1260255 :             isl_basic_map_contains(bmap2, bmap2->sample) > 0)
    3643     1260013 :                 sample = isl_vec_copy(bmap2->sample);
    3644             : 
    3645   110183997 :         bmap1 = isl_basic_map_cow(bmap1);
    3646   110183997 :         if (!bmap1)
    3647           0 :                 goto error;
    3648   110183997 :         bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
    3649             :                         bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
    3650   110183997 :         bmap1 = add_constraints(bmap1, bmap2, 0, 0);
    3651             : 
    3652   110183997 :         if (!bmap1)
    3653           0 :                 isl_vec_free(sample);
    3654   110183997 :         else if (sample) {
    3655     6225564 :                 isl_vec_free(bmap1->sample);
    3656     6225564 :                 bmap1->sample = sample;
    3657             :         }
    3658             : 
    3659   110183997 :         bmap1 = isl_basic_map_simplify(bmap1);
    3660   110183997 :         return isl_basic_map_finalize(bmap1);
    3661             : error:
    3662           0 :         if (sample)
    3663           0 :                 isl_vec_free(sample);
    3664           0 :         isl_basic_map_free(bmap1);
    3665           0 :         isl_basic_map_free(bmap2);
    3666           0 :         return NULL;
    3667             : }
    3668             : 
    3669      200179 : struct isl_basic_set *isl_basic_set_intersect(
    3670             :                 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
    3671             : {
    3672      200179 :         return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
    3673             :                                                         bset_to_bmap(bset2)));
    3674             : }
    3675             : 
    3676           0 : __isl_give isl_basic_set *isl_basic_set_intersect_params(
    3677             :         __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
    3678             : {
    3679           0 :         return isl_basic_set_intersect(bset1, bset2);
    3680             : }
    3681             : 
    3682             : /* Special case of isl_map_intersect, where both map1 and map2
    3683             :  * are convex, without any divs and such that either map1 or map2
    3684             :  * contains a single constraint.  This constraint is then simply
    3685             :  * added to the other map.
    3686             :  */
    3687           0 : static __isl_give isl_map *map_intersect_add_constraint(
    3688             :         __isl_take isl_map *map1, __isl_take isl_map *map2)
    3689             : {
    3690           0 :         isl_assert(map1->ctx, map1->n == 1, goto error);
    3691           0 :         isl_assert(map2->ctx, map1->n == 1, goto error);
    3692           0 :         isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
    3693           0 :         isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
    3694             : 
    3695           0 :         if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
    3696           0 :                 return isl_map_intersect(map2, map1);
    3697             : 
    3698           0 :         map1 = isl_map_cow(map1);
    3699           0 :         if (!map1)
    3700           0 :                 goto error;
    3701           0 :         if (isl_map_plain_is_empty(map1)) {
    3702           0 :                 isl_map_free(map2);
    3703           0 :                 return map1;
    3704             :         }
    3705           0 :         map1->p[0] = isl_basic_map_cow(map1->p[0]);
    3706           0 :         if (map2->p[0]->n_eq == 1)
    3707           0 :                 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
    3708             :         else
    3709           0 :                 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
    3710           0 :                                                         map2->p[0]->ineq[0]);
    3711             : 
    3712           0 :         map1->p[0] = isl_basic_map_simplify(map1->p[0]);
    3713           0 :         map1->p[0] = isl_basic_map_finalize(map1->p[0]);
    3714           0 :         if (!map1->p[0])
    3715           0 :                 goto error;
    3716             : 
    3717           0 :         if (isl_basic_map_plain_is_empty(map1->p[0])) {
    3718           0 :                 isl_basic_map_free(map1->p[0]);
    3719           0 :                 map1->n = 0;
    3720             :         }
    3721             : 
    3722           0 :         isl_map_free(map2);
    3723             : 
    3724           0 :         map1 = isl_map_unmark_normalized(map1);
    3725           0 :         return map1;
    3726             : error:
    3727           0 :         isl_map_free(map1);
    3728           0 :         isl_map_free(map2);
    3729           0 :         return NULL;
    3730             : }
    3731             : 
    3732             : /* map2 may be either a parameter domain or a map living in the same
    3733             :  * space as map1.
    3734             :  */
    3735     2294503 : static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
    3736             :         __isl_take isl_map *map2)
    3737             : {
    3738     2294503 :         unsigned flags = 0;
    3739             :         isl_bool equal;
    3740             :         isl_map *result;
    3741             :         int i, j;
    3742             : 
    3743     2294503 :         if (!map1 || !map2)
    3744             :                 goto error;
    3745             : 
    3746     4095141 :         if ((isl_map_plain_is_empty(map1) ||
    3747     2323064 :              isl_map_plain_is_universe(map2)) &&
    3748      522426 :             isl_space_is_equal(map1->dim, map2->dim)) {
    3749      522426 :                 isl_map_free(map2);
    3750      522426 :                 return map1;
    3751             :         }
    3752     3257539 :         if ((isl_map_plain_is_empty(map2) ||
    3753     1840618 :              isl_map_plain_is_universe(map1)) &&
    3754      355156 :             isl_space_is_equal(map1->dim, map2->dim)) {
    3755      355156 :                 isl_map_free(map1);
    3756      355156 :                 return map2;
    3757             :         }
    3758             : 
    3759     2068400 :         if (map1->n == 1 && map2->n == 1 &&
    3760     1954437 :             map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
    3761     1302958 :             isl_space_is_equal(map1->dim, map2->dim) &&
    3762     1302958 :             (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
    3763      651479 :              map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
    3764           0 :                 return map_intersect_add_constraint(map1, map2);
    3765             : 
    3766     1416921 :         equal = isl_map_plain_is_equal(map1, map2);
    3767     1416921 :         if (equal < 0)
    3768           0 :                 goto error;
    3769     1416921 :         if (equal) {
    3770      113348 :                 isl_map_free(map2);
    3771      113348 :                 return map1;
    3772             :         }
    3773             : 
    3774     2607146 :         if (isl_space_dim(map2->dim, isl_dim_all) !=
    3775     1303573 :                                 isl_space_dim(map2->dim, isl_dim_param))
    3776     1303573 :                 isl_assert(map1->ctx,
    3777             :                             isl_space_is_equal(map1->dim, map2->dim), goto error);
    3778             : 
    3779     2306528 :         if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
    3780     1002955 :             ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
    3781      927384 :                 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
    3782             : 
    3783     1303573 :         result = isl_map_alloc_space(isl_space_copy(map1->dim),
    3784     1303573 :                                 map1->n * map2->n, flags);
    3785     1303573 :         if (!result)
    3786           0 :                 goto error;
    3787    10332144 :         for (i = 0; i < map1->n; ++i)
    3788   113899147 :                 for (j = 0; j < map2->n; ++j) {
    3789             :                         struct isl_basic_map *part;
    3790   209741152 :                         part = isl_basic_map_intersect(
    3791   104870576 :                                     isl_basic_map_copy(map1->p[i]),
    3792   104870576 :                                     isl_basic_map_copy(map2->p[j]));
    3793   104870576 :                         if (isl_basic_map_is_empty(part) < 0)
    3794           0 :                                 part = isl_basic_map_free(part);
    3795   104870576 :                         result = isl_map_add_basic_map(result, part);
    3796   104870576 :                         if (!result)
    3797           0 :                                 goto error;
    3798             :                 }
    3799     1303573 :         isl_map_free(map1);
    3800     1303573 :         isl_map_free(map2);
    3801     1303573 :         return result;
    3802             : error:
    3803           0 :         isl_map_free(map1);
    3804           0 :         isl_map_free(map2);
    3805           0 :         return NULL;
    3806             : }
    3807             : 
    3808     2294503 : static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
    3809             :         __isl_take isl_map *map2)
    3810             : {
    3811     2294503 :         if (!map1 || !map2)
    3812             :                 goto error;
    3813     2294503 :         if (!isl_space_is_equal(map1->dim, map2->dim))
    3814           0 :                 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
    3815             :                         "spaces don't match", goto error);
    3816     2294503 :         return map_intersect_internal(map1, map2);
    3817             : error:
    3818           0 :         isl_map_free(map1);
    3819           0 :         isl_map_free(map2);
    3820           0 :         return NULL;
    3821             : }
    3822             : 
    3823     2294503 : __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
    3824             :         __isl_take isl_map *map2)
    3825             : {
    3826     2294503 :         return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
    3827             : }
    3828             : 
    3829     2294503 : struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
    3830             : {
    3831     2294503 :         return set_from_map(isl_map_intersect(set_to_map(set1),
    3832             :                                               set_to_map(set2)));
    3833             : }
    3834             : 
    3835             : /* map_intersect_internal accepts intersections
    3836             :  * with parameter domains, so we can just call that function.
    3837             :  */
    3838           0 : static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
    3839             :                 __isl_take isl_set *params)
    3840             : {
    3841           0 :         return map_intersect_internal(map, params);
    3842             : }
    3843             : 
    3844           0 : __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
    3845             :         __isl_take isl_map *map2)
    3846             : {
    3847           0 :         return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
    3848             : }
    3849             : 
    3850           0 : __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
    3851             :                 __isl_take isl_set *params)
    3852             : {
    3853           0 :         return isl_map_intersect_params(set, params);
    3854             : }
    3855             : 
    3856           0 : __isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
    3857             : {
    3858             :         isl_space *space;
    3859             :         unsigned pos, n1, n2;
    3860             : 
    3861           0 :         if (!bmap)
    3862           0 :                 return NULL;
    3863           0 :         bmap = isl_basic_map_cow(bmap);
    3864           0 :         if (!bmap)
    3865           0 :                 return NULL;
    3866           0 :         space = isl_space_reverse(isl_space_copy(bmap->dim));
    3867           0 :         pos = isl_basic_map_offset(bmap, isl_dim_in);
    3868           0 :         n1 = isl_basic_map_dim(bmap, isl_dim_in);
    3869           0 :         n2 = isl_basic_map_dim(bmap, isl_dim_out);
    3870           0 :         bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
    3871           0 :         return isl_basic_map_reset_space(bmap, space);
    3872             : }
    3873             : 
    3874           0 : static __isl_give isl_basic_map *basic_map_space_reset(
    3875             :         __isl_take isl_basic_map *bmap, enum isl_dim_type type)
    3876             : {
    3877             :         isl_space *space;
    3878             : 
    3879           0 :         if (!bmap)
    3880           0 :                 return NULL;
    3881           0 :         if (!isl_space_is_named_or_nested(bmap->dim, type))
    3882           0 :                 return bmap;
    3883             : 
    3884           0 :         space = isl_basic_map_get_space(bmap);
    3885           0 :         space = isl_space_reset(space, type);
    3886           0 :         bmap = isl_basic_map_reset_space(bmap, space);
    3887           0 :         return bmap;
    3888             : }
    3889             : 
    3890           0 : __isl_give isl_basic_map *isl_basic_map_insert_dims(
    3891             :         __isl_take isl_basic_map *bmap, enum isl_dim_type type,
    3892             :         unsigned pos, unsigned n)
    3893             : {
    3894             :         isl_bool rational;
    3895             :         isl_space *res_space;
    3896             :         struct isl_basic_map *res;
    3897             :         struct isl_dim_map *dim_map;
    3898             :         unsigned total, off;
    3899             :         enum isl_dim_type t;
    3900             : 
    3901           0 :         if (n == 0)
    3902           0 :                 return basic_map_space_reset(bmap, type);
    3903             : 
    3904           0 :         res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
    3905             :                                         type, pos, n);
    3906           0 :         if (!res_space)
    3907           0 :                 return isl_basic_map_free(bmap);
    3908             : 
    3909           0 :         total = isl_basic_map_total_dim(bmap) + n;
    3910           0 :         dim_map = isl_dim_map_alloc(bmap->ctx, total);
    3911           0 :         off = 0;
    3912           0 :         for (t = isl_dim_param; t <= isl_dim_out; ++t) {
    3913           0 :                 if (t != type) {
    3914           0 :                         isl_dim_map_dim(dim_map, bmap->dim, t, off);
    3915             :                 } else {
    3916           0 :                         unsigned size = isl_basic_map_dim(bmap, t);
    3917           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    3918             :                                                 0, pos, off);
    3919           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    3920           0 :                                                 pos, size - pos, off + pos + n);
    3921             :                 }
    3922           0 :                 off += isl_space_dim(res_space, t);
    3923             :         }
    3924           0 :         isl_dim_map_div(dim_map, bmap, off);
    3925             : 
    3926           0 :         res = isl_basic_map_alloc_space(res_space,
    3927             :                         bmap->n_div, bmap->n_eq, bmap->n_ineq);
    3928           0 :         rational = isl_basic_map_is_rational(bmap);
    3929           0 :         if (rational < 0)
    3930           0 :                 res = isl_basic_map_free(res);
    3931           0 :         if (rational)
    3932           0 :                 res = isl_basic_map_set_rational(res);
    3933           0 :         if (isl_basic_map_plain_is_empty(bmap)) {
    3934           0 :                 isl_basic_map_free(bmap);
    3935           0 :                 free(dim_map);
    3936           0 :                 return isl_basic_map_set_to_empty(res);
    3937             :         }
    3938           0 :         res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
    3939           0 :         return isl_basic_map_finalize(res);
    3940             : }
    3941             : 
    3942           0 : __isl_give isl_basic_set *isl_basic_set_insert_dims(
    3943             :         __isl_take isl_basic_set *bset,
    3944             :         enum isl_dim_type type, unsigned pos, unsigned n)
    3945             : {
    3946           0 :         return isl_basic_map_insert_dims(bset, type, pos, n);
    3947             : }
    3948             : 
    3949           0 : __isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
    3950             :                 enum isl_dim_type type, unsigned n)
    3951             : {
    3952           0 :         if (!bmap)
    3953           0 :                 return NULL;
    3954           0 :         return isl_basic_map_insert_dims(bmap, type,
    3955             :                                         isl_basic_map_dim(bmap, type), n);
    3956             : }
    3957             : 
    3958           0 : __isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
    3959             :                 enum isl_dim_type type, unsigned n)
    3960             : {
    3961           0 :         if (!bset)
    3962           0 :                 return NULL;
    3963           0 :         isl_assert(bset->ctx, type != isl_dim_in, goto error);
    3964           0 :         return isl_basic_map_add_dims(bset, type, n);
    3965             : error:
    3966           0 :         isl_basic_set_free(bset);
    3967           0 :         return NULL;
    3968             : }
    3969             : 
    3970           0 : static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
    3971             :         enum isl_dim_type type)
    3972             : {
    3973             :         isl_space *space;
    3974             : 
    3975           0 :         if (!map || !isl_space_is_named_or_nested(map->dim, type))
    3976           0 :                 return map;
    3977             : 
    3978           0 :         space = isl_map_get_space(map);
    3979           0 :         space = isl_space_reset(space, type);
    3980           0 :         map = isl_map_reset_space(map, space);
    3981           0 :         return map;
    3982             : }
    3983             : 
    3984           0 : __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
    3985             :                 enum isl_dim_type type, unsigned pos, unsigned n)
    3986             : {
    3987             :         int i;
    3988             : 
    3989           0 :         if (n == 0)
    3990           0 :                 return map_space_reset(map, type);
    3991             : 
    3992           0 :         map = isl_map_cow(map);
    3993           0 :         if (!map)
    3994           0 :                 return NULL;
    3995             : 
    3996           0 :         map->dim = isl_space_insert_dims(map->dim, type, pos, n);
    3997           0 :         if (!map->dim)
    3998           0 :                 goto error;
    3999             : 
    4000           0 :         for (i = 0; i < map->n; ++i) {
    4001           0 :                 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
    4002           0 :                 if (!map->p[i])
    4003           0 :                         goto error;
    4004             :         }
    4005             : 
    4006           0 :         return map;
    4007             : error:
    4008           0 :         isl_map_free(map);
    4009           0 :         return NULL;
    4010             : }
    4011             : 
    4012           0 : __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
    4013             :                 enum isl_dim_type type, unsigned pos, unsigned n)
    4014             : {
    4015           0 :         return isl_map_insert_dims(set, type, pos, n);
    4016             : }
    4017             : 
    4018           0 : __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
    4019             :                 enum isl_dim_type type, unsigned n)
    4020             : {
    4021           0 :         if (!map)
    4022           0 :                 return NULL;
    4023           0 :         return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
    4024             : }
    4025             : 
    4026           0 : __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
    4027             :                 enum isl_dim_type type, unsigned n)
    4028             : {
    4029           0 :         if (!set)
    4030           0 :                 return NULL;
    4031           0 :         isl_assert(set->ctx, type != isl_dim_in, goto error);
    4032           0 :         return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
    4033             : error:
    4034           0 :         isl_set_free(set);
    4035           0 :         return NULL;
    4036             : }
    4037             : 
    4038           0 : __isl_give isl_basic_map *isl_basic_map_move_dims(
    4039             :         __isl_take isl_basic_map *bmap,
    4040             :         enum isl_dim_type dst_type, unsigned dst_pos,
    4041             :         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
    4042             : {
    4043             :         struct isl_dim_map *dim_map;
    4044             :         struct isl_basic_map *res;
    4045             :         enum isl_dim_type t;
    4046             :         unsigned total, off;
    4047             : 
    4048           0 :         if (!bmap)
    4049           0 :                 return NULL;
    4050           0 :         if (n == 0) {
    4051           0 :                 bmap = isl_basic_map_reset(bmap, src_type);
    4052           0 :                 bmap = isl_basic_map_reset(bmap, dst_type);
    4053           0 :                 return bmap;
    4054             :         }
    4055             : 
    4056           0 :         if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
    4057           0 :                 return isl_basic_map_free(bmap);
    4058             : 
    4059           0 :         if (dst_type == src_type && dst_pos == src_pos)
    4060           0 :                 return bmap;
    4061             : 
    4062           0 :         isl_assert(bmap->ctx, dst_type != src_type, goto error);
    4063             : 
    4064           0 :         if (pos(bmap->dim, dst_type) + dst_pos ==
    4065           0 :             pos(bmap->dim, src_type) + src_pos +
    4066           0 :                                             ((src_type < dst_type) ? n : 0)) {
    4067           0 :                 bmap = isl_basic_map_cow(bmap);
    4068           0 :                 if (!bmap)
    4069           0 :                         return NULL;
    4070             : 
    4071           0 :                 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
    4072             :                                                 src_type, src_pos, n);
    4073           0 :                 if (!bmap->dim)
    4074           0 :                         goto error;
    4075             : 
    4076           0 :                 bmap = isl_basic_map_finalize(bmap);
    4077             : 
    4078           0 :                 return bmap;
    4079             :         }
    4080             : 
    4081           0 :         total = isl_basic_map_total_dim(bmap);
    4082           0 :         dim_map = isl_dim_map_alloc(bmap->ctx, total);
    4083             : 
    4084           0 :         off = 0;
    4085           0 :         for (t = isl_dim_param; t <= isl_dim_out; ++t) {
    4086           0 :                 unsigned size = isl_space_dim(bmap->dim, t);
    4087           0 :                 if (t == dst_type) {
    4088           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    4089             :                                             0, dst_pos, off);
    4090           0 :                         off += dst_pos;
    4091           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
    4092             :                                             src_pos, n, off);
    4093           0 :                         off += n;
    4094           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    4095             :                                             dst_pos, size - dst_pos, off);
    4096           0 :                         off += size - dst_pos;
    4097           0 :                 } else if (t == src_type) {
    4098           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    4099             :                                             0, src_pos, off);
    4100           0 :                         off += src_pos;
    4101           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    4102           0 :                                         src_pos + n, size - src_pos - n, off);
    4103           0 :                         off += size - src_pos - n;
    4104             :                 } else {
    4105           0 :                         isl_dim_map_dim(dim_map, bmap->dim, t, off);
    4106           0 :                         off += size;
    4107             :                 }
    4108             :         }
    4109           0 :         isl_dim_map_div(dim_map, bmap, off);
    4110             : 
    4111           0 :         res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
    4112             :                         bmap->n_div, bmap->n_eq, bmap->n_ineq);
    4113           0 :         bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
    4114           0 :         if (!bmap)
    4115           0 :                 goto error;
    4116             : 
    4117           0 :         bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
    4118             :                                         src_type, src_pos, n);
    4119           0 :         if (!bmap->dim)
    4120           0 :                 goto error;
    4121             : 
    4122           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
    4123           0 :         bmap = isl_basic_map_gauss(bmap, NULL);
    4124           0 :         bmap = isl_basic_map_finalize(bmap);
    4125             : 
    4126           0 :         return bmap;
    4127             : error:
    4128           0 :         isl_basic_map_free(bmap);
    4129           0 :         return NULL;
    4130             : }
    4131             : 
    4132           0 : __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
    4133             :         enum isl_dim_type dst_type, unsigned dst_pos,
    4134             :         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
    4135             : {
    4136           0 :         isl_basic_map *bmap = bset_to_bmap(bset);
    4137           0 :         bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
    4138             :                                         src_type, src_pos, n);
    4139           0 :         return bset_from_bmap(bmap);
    4140             : }
    4141             : 
    4142           0 : __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
    4143             :         enum isl_dim_type dst_type, unsigned dst_pos,
    4144             :         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
    4145             : {
    4146           0 :         if (!set)
    4147           0 :                 return NULL;
    4148           0 :         isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
    4149           0 :         return set_from_map(isl_map_move_dims(set_to_map(set),
    4150             :                                     dst_type, dst_pos, src_type, src_pos, n));
    4151             : error:
    4152           0 :         isl_set_free(set);
    4153           0 :         return NULL;
    4154             : }
    4155             : 
    4156           0 : __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
    4157             :         enum isl_dim_type dst_type, unsigned dst_pos,
    4158             :         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
    4159             : {
    4160             :         int i;
    4161             : 
    4162           0 :         if (n == 0) {
    4163           0 :                 map = isl_map_reset(map, src_type);
    4164           0 :                 map = isl_map_reset(map, dst_type);
    4165           0 :                 return map;
    4166             :         }
    4167             : 
    4168           0 :         if (isl_map_check_range(map, src_type, src_pos, n))
    4169           0 :                 return isl_map_free(map);
    4170             : 
    4171           0 :         if (dst_type == src_type && dst_pos == src_pos)
    4172           0 :                 return map;
    4173             : 
    4174           0 :         isl_assert(map->ctx, dst_type != src_type, goto error);
    4175             : 
    4176           0 :         map = isl_map_cow(map);
    4177           0 :         if (!map)
    4178           0 :                 return NULL;
    4179             : 
    4180           0 :         map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
    4181           0 :         if (!map->dim)
    4182           0 :                 goto error;
    4183             : 
    4184           0 :         for (i = 0; i < map->n; ++i) {
    4185           0 :                 map->p[i] = isl_basic_map_move_dims(map->p[i],
    4186             :                                                 dst_type, dst_pos,
    4187             :                                                 src_type, src_pos, n);
    4188           0 :                 if (!map->p[i])
    4189           0 :                         goto error;
    4190             :         }
    4191             : 
    4192           0 :         return map;
    4193             : error:
    4194           0 :         isl_map_free(map);
    4195           0 :         return NULL;
    4196             : }
    4197             : 
    4198             : /* Move the specified dimensions to the last columns right before
    4199             :  * the divs.  Don't change the dimension specification of bmap.
    4200             :  * That's the responsibility of the caller.
    4201             :  */
    4202           0 : static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
    4203             :         enum isl_dim_type type, unsigned first, unsigned n)
    4204             : {
    4205             :         struct isl_dim_map *dim_map;
    4206             :         struct isl_basic_map *res;
    4207             :         enum isl_dim_type t;
    4208             :         unsigned total, off;
    4209             : 
    4210           0 :         if (!bmap)
    4211           0 :                 return NULL;
    4212           0 :         if (pos(bmap->dim, type) + first + n ==
    4213           0 :                                 1 + isl_space_dim(bmap->dim, isl_dim_all))
    4214           0 :                 return bmap;
    4215             : 
    4216           0 :         total = isl_basic_map_total_dim(bmap);
    4217           0 :         dim_map = isl_dim_map_alloc(bmap->ctx, total);
    4218             : 
    4219           0 :         off = 0;
    4220           0 :         for (t = isl_dim_param; t <= isl_dim_out; ++t) {
    4221           0 :                 unsigned size = isl_space_dim(bmap->dim, t);
    4222           0 :                 if (t == type) {
    4223           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    4224             :                                             0, first, off);
    4225           0 :                         off += first;
    4226           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    4227           0 :                                             first, n, total - bmap->n_div - n);
    4228           0 :                         isl_dim_map_dim_range(dim_map, bmap->dim, t,
    4229           0 :                                             first + n, size - (first + n), off);
    4230           0 :                         off += size - (first + n);
    4231             :                 } else {
    4232           0 :                         isl_dim_map_dim(dim_map, bmap->dim, t, off);
    4233           0 :                         off += size;
    4234             :                 }
    4235             :         }
    4236           0 :         isl_dim_map_div(dim_map, bmap, off + n);
    4237             : 
    4238           0 :         res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
    4239             :                         bmap->n_div, bmap->n_eq, bmap->n_ineq);
    4240           0 :         res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
    4241           0 :         return res;
    4242             : }
    4243             : 
    4244             : /* Insert "n" rows in the divs of "bmap".
    4245             :  *
    4246             :  * The number of columns is not changed, which means that the last
    4247             :  * dimensions of "bmap" are being reintepreted as the new divs.
    4248             :  * The space of "bmap" is not adjusted, however, which means
    4249             :  * that "bmap" is left in an inconsistent state.  Removing "n" dimensions
    4250             :  * from the space of "bmap" is the responsibility of the caller.
    4251             :  */
    4252           0 : static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
    4253             :         int n)
    4254             : {
    4255             :         int i;
    4256             :         size_t row_size;
    4257             :         isl_int **new_div;
    4258             :         isl_int *old;
    4259             : 
    4260           0 :         bmap = isl_basic_map_cow(bmap);
    4261           0 :         if (!bmap)
    4262           0 :                 return NULL;
    4263             : 
    4264           0 :         row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
    4265           0 :         old = bmap->block2.data;
    4266           0 :         bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
    4267           0 :                                         (bmap->extra + n) * (1 + row_size));
    4268           0 :         if (!bmap->block2.data)
    4269           0 :                 return isl_basic_map_free(bmap);
    4270           0 :         new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
    4271           0 :         if (!new_div)
    4272           0 :                 return isl_basic_map_free(bmap);
    4273           0 :         for (i = 0; i < n; ++i) {
    4274           0 :                 new_div[i] = bmap->block2.data +
    4275           0 :                                 (bmap->extra + i) * (1 + row_size);
    4276           0 :                 isl_seq_clr(new_div[i], 1 + row_size);
    4277             :         }
    4278           0 :         for (i = 0; i < bmap->extra; ++i)
    4279           0 :                 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
    4280           0 :         free(bmap->div);
    4281           0 :         bmap->div = new_div;
    4282           0 :         bmap->n_div += n;
    4283           0 :         bmap->extra += n;
    4284             : 
    4285           0 :         return bmap;
    4286             : }
    4287             : 
    4288             : /* Drop constraints from "bmap" that only involve the variables
    4289             :  * of "type" in the range [first, first + n] that are not related
    4290             :  * to any of the variables outside that interval.
    4291             :  * These constraints cannot influence the values for the variables
    4292             :  * outside the interval, except in case they cause "bmap" to be empty.
    4293             :  * Only drop the constraints if "bmap" is known to be non-empty.
    4294             :  */
    4295           0 : static __isl_give isl_basic_map *drop_irrelevant_constraints(
    4296             :         __isl_take isl_basic_map *bmap, enum isl_dim_type type,
    4297             :         unsigned first, unsigned n)
    4298             : {
    4299             :         int i;
    4300             :         int *groups;
    4301             :         unsigned dim, n_div;
    4302             :         isl_bool non_empty;
    4303             : 
    4304           0 :         non_empty = isl_basic_map_plain_is_non_empty(bmap);
    4305           0 :         if (non_empty < 0)
    4306           0 :                 return isl_basic_map_free(bmap);
    4307           0 :         if (!non_empty)
    4308           0 :                 return bmap;
    4309             : 
    4310           0 :         dim = isl_basic_map_dim(bmap, isl_dim_all);
    4311           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    4312           0 :         groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
    4313           0 :         if (!groups)
    4314           0 :                 return isl_basic_map_free(bmap);
    4315           0 :         first += isl_basic_map_offset(bmap, type) - 1;
    4316           0 :         for (i = 0; i < first; ++i)
    4317           0 :                 groups[i] = -1;
    4318           0 :         for (i = first + n; i < dim - n_div; ++i)
    4319           0 :                 groups[i] = -1;
    4320             : 
    4321           0 :         bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
    4322             : 
    4323           0 :         return bmap;
    4324             : }
    4325             : 
    4326             : /* Turn the n dimensions of type type, starting at first
    4327             :  * into existentially quantified variables.
    4328             :  *
    4329             :  * If a subset of the projected out variables are unrelated
    4330             :  * to any of the variables that remain, then the constraints
    4331             :  * involving this subset are simply dropped first.
    4332             :  */
    4333           0 : __isl_give isl_basic_map *isl_basic_map_project_out(
    4334             :                 __isl_take isl_basic_map *bmap,
    4335             :                 enum isl_dim_type type, unsigned first, unsigned n)
    4336             : {
    4337             :         isl_bool empty;
    4338             : 
    4339           0 :         if (n == 0)
    4340           0 :                 return basic_map_space_reset(bmap, type);
    4341           0 :         if (type == isl_dim_div)
    4342           0 :                 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
    4343             :                         "cannot project out existentially quantified variables",
    4344             :                         return isl_basic_map_free(bmap));
    4345             : 
    4346           0 :         empty = isl_basic_map_plain_is_empty(bmap);
    4347           0 :         if (empty < 0)
    4348           0 :                 return isl_basic_map_free(bmap);
    4349           0 :         if (empty)
    4350           0 :                 bmap = isl_basic_map_set_to_empty(bmap);
    4351             : 
    4352           0 :         bmap = drop_irrelevant_constraints(bmap, type, first, n);
    4353           0 :         if (!bmap)
    4354           0 :                 return NULL;
    4355             : 
    4356           0 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
    4357           0 :                 return isl_basic_map_remove_dims(bmap, type, first, n);
    4358             : 
    4359           0 :         if (isl_basic_map_check_range(bmap, type, first, n) < 0)
    4360           0 :                 return isl_basic_map_free(bmap);
    4361             : 
    4362           0 :         bmap = move_last(bmap, type, first, n);
    4363           0 :         bmap = isl_basic_map_cow(bmap);
    4364           0 :         bmap = insert_div_rows(bmap, n);
    4365           0 :         if (!bmap)
    4366           0 :                 return NULL;
    4367             : 
    4368           0 :         bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
    4369           0 :         if (!bmap->dim)
    4370           0 :                 goto error;
    4371           0 :         bmap = isl_basic_map_simplify(bmap);
    4372           0 :         bmap = isl_basic_map_drop_redundant_divs(bmap);
    4373           0 :         return isl_basic_map_finalize(bmap);
    4374             : error:
    4375           0 :         isl_basic_map_free(bmap);
    4376           0 :         return NULL;
    4377             : }
    4378             : 
    4379             : /* Turn the n dimensions of type type, starting at first
    4380             :  * into existentially quantified variables.
    4381             :  */
    4382           0 : struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
    4383             :                 enum isl_dim_type type, unsigned first, unsigned n)
    4384             : {
    4385           0 :         return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
    4386             :                                                         type, first, n));
    4387             : }
    4388             : 
    4389             : /* Turn the n dimensions of type type, starting at first
    4390             :  * into existentially quantified variables.
    4391             :  */
    4392           0 : __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
    4393             :                 enum isl_dim_type type, unsigned first, unsigned n)
    4394             : {
    4395             :         int i;
    4396             : 
    4397           0 :         if (n == 0)
    4398           0 :                 return map_space_reset(map, type);
    4399             : 
    4400           0 :         if (isl_map_check_range(map, type, first, n) < 0)
    4401           0 :                 return isl_map_free(map);
    4402             : 
    4403           0 :         map = isl_map_cow(map);
    4404           0 :         if (!map)
    4405           0 :                 return NULL;
    4406             : 
    4407           0 :         map->dim = isl_space_drop_dims(map->dim, type, first, n);
    4408           0 :         if (!map->dim)
    4409           0 :                 goto error;
    4410             : 
    4411           0 :         for (i = 0; i < map->n; ++i) {
    4412           0 :                 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
    4413           0 :                 if (!map->p[i])
    4414           0 :                         goto error;
    4415             :         }
    4416             : 
    4417           0 :         return map;
    4418             : error:
    4419           0 :         isl_map_free(map);
    4420           0 :         return NULL;
    4421             : }
    4422             : 
    4423             : /* Turn all the dimensions of type "type", except the "n" starting at "first"
    4424             :  * into existentially quantified variables.
    4425             :  */
    4426           0 : __isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
    4427             :         enum isl_dim_type type, unsigned first, unsigned n)
    4428             : {
    4429             :         unsigned dim;
    4430             : 
    4431           0 :         if (isl_map_check_range(map, type, first, n) < 0)
    4432           0 :                 return isl_map_free(map);
    4433           0 :         dim = isl_map_dim(map, type);
    4434           0 :         map = isl_map_project_out(map, type, first + n, dim - (first + n));
    4435           0 :         map = isl_map_project_out(map, type, 0, first);
    4436           0 :         return map;
    4437             : }
    4438             : 
    4439             : /* Turn the n dimensions of type type, starting at first
    4440             :  * into existentially quantified variables.
    4441             :  */
    4442           0 : __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
    4443             :                 enum isl_dim_type type, unsigned first, unsigned n)
    4444             : {
    4445           0 :         return set_from_map(isl_map_project_out(set_to_map(set),
    4446             :                                                 type, first, n));
    4447             : }
    4448             : 
    4449             : /* Return a map that projects the elements in "set" onto their
    4450             :  * "n" set dimensions starting at "first".
    4451             :  * "type" should be equal to isl_dim_set.
    4452             :  */
    4453           0 : __isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
    4454             :         enum isl_dim_type type, unsigned first, unsigned n)
    4455             : {
    4456             :         int i;
    4457             :         int dim;
    4458             :         isl_map *map;
    4459             : 
    4460           0 :         if (!set)
    4461           0 :                 return NULL;
    4462           0 :         if (type != isl_dim_set)
    4463           0 :                 isl_die(isl_set_get_ctx(set), isl_error_invalid,
    4464             :                         "only set dimensions can be projected out", goto error);
    4465           0 :         dim = isl_set_dim(set, isl_dim_set);
    4466           0 :         if (first + n > dim || first + n < first)
    4467           0 :                 isl_die(isl_set_get_ctx(set), isl_error_invalid,
    4468             :                         "index out of bounds", goto error);
    4469             : 
    4470           0 :         map = isl_map_from_domain(set);
    4471           0 :         map = isl_map_add_dims(map, isl_dim_out, n);
    4472           0 :         for (i = 0; i < n; ++i)
    4473           0 :                 map = isl_map_equate(map, isl_dim_in, first + i,
    4474             :                                         isl_dim_out, i);
    4475           0 :         return map;
    4476             : error:
    4477           0 :         isl_set_free(set);
    4478           0 :         return NULL;
    4479             : }
    4480             : 
    4481           0 : static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
    4482             : {
    4483             :         int i, j;
    4484             : 
    4485           0 :         for (i = 0; i < n; ++i) {
    4486           0 :                 j = isl_basic_map_alloc_div(bmap);
    4487           0 :                 if (j < 0)
    4488           0 :                         goto error;
    4489           0 :                 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
    4490             :         }
    4491           0 :         return bmap;
    4492             : error:
    4493           0 :         isl_basic_map_free(bmap);
    4494           0 :         return NULL;
    4495             : }
    4496             : 
    4497           0 : struct isl_basic_map *isl_basic_map_apply_range(
    4498             :                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
    4499             : {
    4500           0 :         isl_space *dim_result = NULL;
    4501             :         struct isl_basic_map *bmap;
    4502             :         unsigned n_in, n_out, n, nparam, total, pos;
    4503             :         struct isl_dim_map *dim_map1, *dim_map2;
    4504             : 
    4505           0 :         if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
    4506           0 :                 goto error;
    4507           0 :         if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
    4508             :                                     bmap2->dim, isl_dim_in))
    4509           0 :                 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
    4510             :                         "spaces don't match", goto error);
    4511             : 
    4512           0 :         dim_result = isl_space_join(isl_space_copy(bmap1->dim),
    4513             :                                   isl_space_copy(bmap2->dim));
    4514             : 
    4515           0 :         n_in = isl_basic_map_dim(bmap1, isl_dim_in);
    4516           0 :         n_out = isl_basic_map_dim(bmap2, isl_dim_out);
    4517           0 :         n = isl_basic_map_dim(bmap1, isl_dim_out);
    4518           0 :         nparam = isl_basic_map_dim(bmap1, isl_dim_param);
    4519             : 
    4520           0 :         total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
    4521           0 :         dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
    4522           0 :         dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
    4523           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
    4524           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
    4525           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
    4526           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
    4527           0 :         isl_dim_map_div(dim_map1, bmap1, pos += n_out);
    4528           0 :         isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
    4529           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
    4530           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
    4531             : 
    4532           0 :         bmap = isl_basic_map_alloc_space(dim_result,
    4533           0 :                         bmap1->n_div + bmap2->n_div + n,
    4534           0 :                         bmap1->n_eq + bmap2->n_eq,
    4535           0 :                         bmap1->n_ineq + bmap2->n_ineq);
    4536           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
    4537           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
    4538           0 :         bmap = add_divs(bmap, n);
    4539           0 :         bmap = isl_basic_map_simplify(bmap);
    4540           0 :         bmap = isl_basic_map_drop_redundant_divs(bmap);
    4541           0 :         return isl_basic_map_finalize(bmap);
    4542             : error:
    4543           0 :         isl_basic_map_free(bmap1);
    4544           0 :         isl_basic_map_free(bmap2);
    4545           0 :         return NULL;
    4546             : }
    4547             : 
    4548           0 : struct isl_basic_set *isl_basic_set_apply(
    4549             :                 struct isl_basic_set *bset, struct isl_basic_map *bmap)
    4550             : {
    4551           0 :         if (!bset || !bmap)
    4552             :                 goto error;
    4553             : 
    4554           0 :         isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
    4555             :                     goto error);
    4556             : 
    4557           0 :         return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
    4558             :                                                         bmap));
    4559             : error:
    4560           0 :         isl_basic_set_free(bset);
    4561           0 :         isl_basic_map_free(bmap);
    4562           0 :         return NULL;
    4563             : }
    4564             : 
    4565           0 : struct isl_basic_map *isl_basic_map_apply_domain(
    4566             :                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
    4567             : {
    4568           0 :         if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
    4569           0 :                 goto error;
    4570           0 :         if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
    4571             :                                         bmap2->dim, isl_dim_in))
    4572           0 :                 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
    4573             :                         "spaces don't match", goto error);
    4574             : 
    4575           0 :         bmap1 = isl_basic_map_reverse(bmap1);
    4576           0 :         bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
    4577           0 :         return isl_basic_map_reverse(bmap1);
    4578             : error:
    4579           0 :         isl_basic_map_free(bmap1);
    4580           0 :         isl_basic_map_free(bmap2);
    4581           0 :         return NULL;
    4582             : }
    4583             : 
    4584             : /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
    4585             :  * A \cap B -> f(A) + f(B)
    4586             :  */
    4587           0 : __isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
    4588             :         __isl_take isl_basic_map *bmap2)
    4589             : {
    4590             :         unsigned n_in, n_out, nparam, total, pos;
    4591           0 :         struct isl_basic_map *bmap = NULL;
    4592             :         struct isl_dim_map *dim_map1, *dim_map2;
    4593             :         int i;
    4594             : 
    4595           0 :         if (!bmap1 || !bmap2)
    4596             :                 goto error;
    4597             : 
    4598           0 :         isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
    4599             :                 goto error);
    4600             : 
    4601           0 :         nparam = isl_basic_map_dim(bmap1, isl_dim_param);
    4602           0 :         n_in = isl_basic_map_dim(bmap1, isl_dim_in);
    4603           0 :         n_out = isl_basic_map_dim(bmap1, isl_dim_out);
    4604             : 
    4605           0 :         total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
    4606           0 :         dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
    4607           0 :         dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
    4608           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
    4609           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
    4610           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
    4611           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
    4612           0 :         isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
    4613           0 :         isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
    4614           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
    4615           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
    4616             : 
    4617           0 :         bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
    4618           0 :                         bmap1->n_div + bmap2->n_div + 2 * n_out,
    4619           0 :                         bmap1->n_eq + bmap2->n_eq + n_out,
    4620           0 :                         bmap1->n_ineq + bmap2->n_ineq);
    4621           0 :         for (i = 0; i < n_out; ++i) {
    4622           0 :                 int j = isl_basic_map_alloc_equality(bmap);
    4623           0 :                 if (j < 0)
    4624           0 :                         goto error;
    4625           0 :                 isl_seq_clr(bmap->eq[j], 1+total);
    4626           0 :                 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
    4627           0 :                 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
    4628           0 :                 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
    4629             :         }
    4630           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
    4631           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
    4632           0 :         bmap = add_divs(bmap, 2 * n_out);
    4633             : 
    4634           0 :         bmap = isl_basic_map_simplify(bmap);
    4635           0 :         return isl_basic_map_finalize(bmap);
    4636             : error:
    4637           0 :         isl_basic_map_free(bmap);
    4638           0 :         isl_basic_map_free(bmap1);
    4639           0 :         isl_basic_map_free(bmap2);
    4640           0 :         return NULL;
    4641             : }
    4642             : 
    4643             : /* Given two maps A -> f(A) and B -> g(B), construct a map
    4644             :  * A \cap B -> f(A) + f(B)
    4645             :  */
    4646           0 : __isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
    4647             :         __isl_take isl_map *map2)
    4648             : {
    4649             :         struct isl_map *result;
    4650             :         int i, j;
    4651             : 
    4652           0 :         if (!map1 || !map2)
    4653             :                 goto error;
    4654             : 
    4655           0 :         isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
    4656             : 
    4657           0 :         result = isl_map_alloc_space(isl_space_copy(map1->dim),
    4658           0 :                                 map1->n * map2->n, 0);
    4659           0 :         if (!result)
    4660           0 :                 goto error;
    4661           0 :         for (i = 0; i < map1->n; ++i)
    4662           0 :                 for (j = 0; j < map2->n; ++j) {
    4663             :                         struct isl_basic_map *part;
    4664           0 :                         part = isl_basic_map_sum(
    4665           0 :                                     isl_basic_map_copy(map1->p[i]),
    4666           0 :                                     isl_basic_map_copy(map2->p[j]));
    4667           0 :                         if (isl_basic_map_is_empty(part))
    4668           0 :                                 isl_basic_map_free(part);
    4669             :                         else
    4670           0 :                                 result = isl_map_add_basic_map(result, part);
    4671           0 :                         if (!result)
    4672           0 :                                 goto error;
    4673             :                 }
    4674           0 :         isl_map_free(map1);
    4675           0 :         isl_map_free(map2);
    4676           0 :         return result;
    4677             : error:
    4678           0 :         isl_map_free(map1);
    4679           0 :         isl_map_free(map2);
    4680           0 :         return NULL;
    4681             : }
    4682             : 
    4683           0 : __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
    4684             :         __isl_take isl_set *set2)
    4685             : {
    4686           0 :         return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
    4687             : }
    4688             : 
    4689             : /* Given a basic map A -> f(A), construct A -> -f(A).
    4690             :  */
    4691           0 : __isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
    4692             : {
    4693             :         int i, j;
    4694             :         unsigned off, n;
    4695             : 
    4696           0 :         bmap = isl_basic_map_cow(bmap);
    4697           0 :         if (!bmap)
    4698           0 :                 return NULL;
    4699             : 
    4700           0 :         n = isl_basic_map_dim(bmap, isl_dim_out);
    4701           0 :         off = isl_basic_map_offset(bmap, isl_dim_out);
    4702           0 :         for (i = 0; i < bmap->n_eq; ++i)
    4703           0 :                 for (j = 0; j < n; ++j)
    4704           0 :                         isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
    4705           0 :         for (i = 0; i < bmap->n_ineq; ++i)
    4706           0 :                 for (j = 0; j < n; ++j)
    4707           0 :                         isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
    4708           0 :         for (i = 0; i < bmap->n_div; ++i)
    4709           0 :                 for (j = 0; j < n; ++j)
    4710           0 :                         isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
    4711           0 :         bmap = isl_basic_map_gauss(bmap, NULL);
    4712           0 :         return isl_basic_map_finalize(bmap);
    4713             : }
    4714             : 
    4715           0 : __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
    4716             : {
    4717           0 :         return isl_basic_map_neg(bset);
    4718             : }
    4719             : 
    4720             : /* Given a map A -> f(A), construct A -> -f(A).
    4721             :  */
    4722           0 : __isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
    4723             : {
    4724             :         int i;
    4725             : 
    4726           0 :         map = isl_map_cow(map);
    4727           0 :         if (!map)
    4728           0 :                 return NULL;
    4729             : 
    4730           0 :         for (i = 0; i < map->n; ++i) {
    4731           0 :                 map->p[i] = isl_basic_map_neg(map->p[i]);
    4732           0 :                 if (!map->p[i])
    4733           0 :                         goto error;
    4734             :         }
    4735             : 
    4736           0 :         return map;
    4737             : error:
    4738           0 :         isl_map_free(map);
    4739           0 :         return NULL;
    4740             : }
    4741             : 
    4742           0 : __isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
    4743             : {
    4744           0 :         return set_from_map(isl_map_neg(set_to_map(set)));
    4745             : }
    4746             : 
    4747             : /* Given a basic map A -> f(A) and an integer d, construct a basic map
    4748             :  * A -> floor(f(A)/d).
    4749             :  */
    4750           0 : __isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
    4751             :                 isl_int d)
    4752             : {
    4753             :         unsigned n_in, n_out, nparam, total, pos;
    4754           0 :         struct isl_basic_map *result = NULL;
    4755             :         struct isl_dim_map *dim_map;
    4756             :         int i;
    4757             : 
    4758           0 :         if (!bmap)
    4759           0 :                 return NULL;
    4760             : 
    4761           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    4762           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    4763           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
    4764             : 
    4765           0 :         total = nparam + n_in + n_out + bmap->n_div + n_out;
    4766           0 :         dim_map = isl_dim_map_alloc(bmap->ctx, total);
    4767           0 :         isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
    4768           0 :         isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
    4769           0 :         isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
    4770           0 :         isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
    4771             : 
    4772           0 :         result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
    4773           0 :                         bmap->n_div + n_out,
    4774           0 :                         bmap->n_eq, bmap->n_ineq + 2 * n_out);
    4775           0 :         result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
    4776           0 :         result = add_divs(result, n_out);
    4777           0 :         for (i = 0; i < n_out; ++i) {
    4778             :                 int j;
    4779           0 :                 j = isl_basic_map_alloc_inequality(result);
    4780           0 :                 if (j < 0)
    4781           0 :                         goto error;
    4782           0 :                 isl_seq_clr(result->ineq[j], 1+total);
    4783           0 :                 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
    4784           0 :                 isl_int_set_si(result->ineq[j][1+pos+i], 1);
    4785           0 :                 j = isl_basic_map_alloc_inequality(result);
    4786           0 :                 if (j < 0)
    4787           0 :                         goto error;
    4788           0 :                 isl_seq_clr(result->ineq[j], 1+total);
    4789           0 :                 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
    4790           0 :                 isl_int_set_si(result->ineq[j][1+pos+i], -1);
    4791           0 :                 isl_int_sub_ui(result->ineq[j][0], d, 1);
    4792             :         }
    4793             : 
    4794           0 :         result = isl_basic_map_simplify(result);
    4795           0 :         return isl_basic_map_finalize(result);
    4796             : error:
    4797           0 :         isl_basic_map_free(result);
    4798           0 :         return NULL;
    4799             : }
    4800             : 
    4801             : /* Given a map A -> f(A) and an integer d, construct a map
    4802             :  * A -> floor(f(A)/d).
    4803             :  */
    4804           0 : __isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
    4805             : {
    4806             :         int i;
    4807             : 
    4808           0 :         map = isl_map_cow(map);
    4809           0 :         if (!map)
    4810           0 :                 return NULL;
    4811             : 
    4812           0 :         ISL_F_CLR(map, ISL_MAP_DISJOINT);
    4813           0 :         for (i = 0; i < map->n; ++i) {
    4814           0 :                 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
    4815           0 :                 if (!map->p[i])
    4816           0 :                         goto error;
    4817             :         }
    4818           0 :         map = isl_map_unmark_normalized(map);
    4819             : 
    4820           0 :         return map;
    4821             : error:
    4822           0 :         isl_map_free(map);
    4823           0 :         return NULL;
    4824             : }
    4825             : 
    4826             : /* Given a map A -> f(A) and an integer d, construct a map
    4827             :  * A -> floor(f(A)/d).
    4828             :  */
    4829           0 : __isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
    4830             :         __isl_take isl_val *d)
    4831             : {
    4832           0 :         if (!map || !d)
    4833             :                 goto error;
    4834           0 :         if (!isl_val_is_int(d))
    4835           0 :                 isl_die(isl_val_get_ctx(d), isl_error_invalid,
    4836             :                         "expecting integer denominator", goto error);
    4837           0 :         map = isl_map_floordiv(map, d->n);
    4838           0 :         isl_val_free(d);
    4839           0 :         return map;
    4840             : error:
    4841           0 :         isl_map_free(map);
    4842           0 :         isl_val_free(d);
    4843           0 :         return NULL;
    4844             : }
    4845             : 
    4846           0 : static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
    4847             :         unsigned pos)
    4848             : {
    4849             :         int i;
    4850             :         unsigned nparam;
    4851             :         unsigned n_in;
    4852             : 
    4853           0 :         i = isl_basic_map_alloc_equality(bmap);
    4854           0 :         if (i < 0)
    4855           0 :                 goto error;
    4856           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    4857           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    4858           0 :         isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
    4859           0 :         isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
    4860           0 :         isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
    4861           0 :         return isl_basic_map_finalize(bmap);
    4862             : error:
    4863           0 :         isl_basic_map_free(bmap);
    4864           0 :         return NULL;
    4865             : }
    4866             : 
    4867             : /* Add a constraint to "bmap" expressing i_pos < o_pos
    4868             :  */
    4869           0 : static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
    4870             :         unsigned pos)
    4871             : {
    4872             :         int i;
    4873             :         unsigned nparam;
    4874             :         unsigned n_in;
    4875             : 
    4876           0 :         i = isl_basic_map_alloc_inequality(bmap);
    4877           0 :         if (i < 0)
    4878           0 :                 goto error;
    4879           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    4880           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    4881           0 :         isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
    4882           0 :         isl_int_set_si(bmap->ineq[i][0], -1);
    4883           0 :         isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
    4884           0 :         isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
    4885           0 :         return isl_basic_map_finalize(bmap);
    4886             : error:
    4887           0 :         isl_basic_map_free(bmap);
    4888           0 :         return NULL;
    4889             : }
    4890             : 
    4891             : /* Add a constraint to "bmap" expressing i_pos <= o_pos
    4892             :  */
    4893           0 : static __isl_give isl_basic_map *var_less_or_equal(
    4894             :         __isl_take isl_basic_map *bmap, unsigned pos)
    4895             : {
    4896             :         int i;
    4897             :         unsigned nparam;
    4898             :         unsigned n_in;
    4899             : 
    4900           0 :         i = isl_basic_map_alloc_inequality(bmap);
    4901           0 :         if (i < 0)
    4902           0 :                 goto error;
    4903           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    4904           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    4905           0 :         isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
    4906           0 :         isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
    4907           0 :         isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
    4908           0 :         return isl_basic_map_finalize(bmap);
    4909             : error:
    4910           0 :         isl_basic_map_free(bmap);
    4911           0 :         return NULL;
    4912             : }
    4913             : 
    4914             : /* Add a constraint to "bmap" expressing i_pos > o_pos
    4915             :  */
    4916           0 : static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
    4917             :         unsigned pos)
    4918             : {
    4919             :         int i;
    4920             :         unsigned nparam;
    4921             :         unsigned n_in;
    4922             : 
    4923           0 :         i = isl_basic_map_alloc_inequality(bmap);
    4924           0 :         if (i < 0)
    4925           0 :                 goto error;
    4926           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    4927           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    4928           0 :         isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
    4929           0 :         isl_int_set_si(bmap->ineq[i][0], -1);
    4930           0 :         isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
    4931           0 :         isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
    4932           0 :         return isl_basic_map_finalize(bmap);
    4933             : error:
    4934           0 :         isl_basic_map_free(bmap);
    4935           0 :         return NULL;
    4936             : }
    4937             : 
    4938             : /* Add a constraint to "bmap" expressing i_pos >= o_pos
    4939             :  */
    4940           0 : static __isl_give isl_basic_map *var_more_or_equal(
    4941             :         __isl_take isl_basic_map *bmap, unsigned pos)
    4942             : {
    4943             :         int i;
    4944             :         unsigned nparam;
    4945             :         unsigned n_in;
    4946             : 
    4947           0 :         i = isl_basic_map_alloc_inequality(bmap);
    4948           0 :         if (i < 0)
    4949           0 :                 goto error;
    4950           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    4951           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    4952           0 :         isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
    4953           0 :         isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
    4954           0 :         isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
    4955           0 :         return isl_basic_map_finalize(bmap);
    4956             : error:
    4957           0 :         isl_basic_map_free(bmap);
    4958           0 :         return NULL;
    4959             : }
    4960             : 
    4961           0 : __isl_give isl_basic_map *isl_basic_map_equal(
    4962             :         __isl_take isl_space *dim, unsigned n_equal)
    4963             : {
    4964             :         int i;
    4965             :         struct isl_basic_map *bmap;
    4966           0 :         bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
    4967           0 :         if (!bmap)
    4968           0 :                 return NULL;
    4969           0 :         for (i = 0; i < n_equal && bmap; ++i)
    4970           0 :                 bmap = var_equal(bmap, i);
    4971           0 :         return isl_basic_map_finalize(bmap);
    4972             : }
    4973             : 
    4974             : /* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
    4975             :  */
    4976           0 : __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
    4977             :         unsigned pos)
    4978             : {
    4979             :         int i;
    4980             :         struct isl_basic_map *bmap;
    4981           0 :         bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
    4982           0 :         if (!bmap)
    4983           0 :                 return NULL;
    4984           0 :         for (i = 0; i < pos && bmap; ++i)
    4985           0 :                 bmap = var_equal(bmap, i);
    4986           0 :         if (bmap)
    4987           0 :                 bmap = var_less(bmap, pos);
    4988           0 :         return isl_basic_map_finalize(bmap);
    4989             : }
    4990             : 
    4991             : /* Return a relation on "dim" expressing i_[0..pos] <<= o_[0..pos]
    4992             :  */
    4993           0 : __isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
    4994             :         __isl_take isl_space *dim, unsigned pos)
    4995             : {
    4996             :         int i;
    4997             :         isl_basic_map *bmap;
    4998             : 
    4999           0 :         bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
    5000           0 :         for (i = 0; i < pos; ++i)
    5001           0 :                 bmap = var_equal(bmap, i);
    5002           0 :         bmap = var_less_or_equal(bmap, pos);
    5003           0 :         return isl_basic_map_finalize(bmap);
    5004             : }
    5005             : 
    5006             : /* Return a relation on "dim" expressing i_pos > o_pos
    5007             :  */
    5008           0 : __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
    5009             :         unsigned pos)
    5010             : {
    5011             :         int i;
    5012             :         struct isl_basic_map *bmap;
    5013           0 :         bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
    5014           0 :         if (!bmap)
    5015           0 :                 return NULL;
    5016           0 :         for (i = 0; i < pos && bmap; ++i)
    5017           0 :                 bmap = var_equal(bmap, i);
    5018           0 :         if (bmap)
    5019           0 :                 bmap = var_more(bmap, pos);
    5020           0 :         return isl_basic_map_finalize(bmap);
    5021             : }
    5022             : 
    5023             : /* Return a relation on "dim" expressing i_[0..pos] >>= o_[0..pos]
    5024             :  */
    5025           0 : __isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
    5026             :         __isl_take isl_space *dim, unsigned pos)
    5027             : {
    5028             :         int i;
    5029             :         isl_basic_map *bmap;
    5030             : 
    5031           0 :         bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
    5032           0 :         for (i = 0; i < pos; ++i)
    5033           0 :                 bmap = var_equal(bmap, i);
    5034           0 :         bmap = var_more_or_equal(bmap, pos);
    5035           0 :         return isl_basic_map_finalize(bmap);
    5036             : }
    5037             : 
    5038           0 : static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
    5039             :         unsigned n, int equal)
    5040             : {
    5041             :         struct isl_map *map;
    5042             :         int i;
    5043             : 
    5044           0 :         if (n == 0 && equal)
    5045           0 :                 return isl_map_universe(dims);
    5046             : 
    5047           0 :         map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
    5048             : 
    5049           0 :         for (i = 0; i + 1 < n; ++i)
    5050           0 :                 map = isl_map_add_basic_map(map,
    5051             :                                   isl_basic_map_less_at(isl_space_copy(dims), i));
    5052           0 :         if (n > 0) {
    5053           0 :                 if (equal)
    5054           0 :                         map = isl_map_add_basic_map(map,
    5055             :                               isl_basic_map_less_or_equal_at(dims, n - 1));
    5056             :                 else
    5057           0 :                         map = isl_map_add_basic_map(map,
    5058             :                               isl_basic_map_less_at(dims, n - 1));
    5059             :         } else
    5060           0 :                 isl_space_free(dims);
    5061             : 
    5062           0 :         return map;
    5063             : }
    5064             : 
    5065           0 : static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
    5066             : {
    5067           0 :         if (!dims)
    5068           0 :                 return NULL;
    5069           0 :         return map_lex_lte_first(dims, dims->n_out, equal);
    5070             : }
    5071             : 
    5072           0 : __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
    5073             : {
    5074           0 :         return map_lex_lte_first(dim, n, 0);
    5075             : }
    5076             : 
    5077           0 : __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
    5078             : {
    5079           0 :         return map_lex_lte_first(dim, n, 1);
    5080             : }
    5081             : 
    5082           0 : __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
    5083             : {
    5084           0 :         return map_lex_lte(isl_space_map_from_set(set_dim), 0);
    5085             : }
    5086             : 
    5087           0 : __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
    5088             : {
    5089           0 :         return map_lex_lte(isl_space_map_from_set(set_dim), 1);
    5090             : }
    5091             : 
    5092           0 : static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
    5093             :         unsigned n, int equal)
    5094             : {
    5095             :         struct isl_map *map;
    5096             :         int i;
    5097             : 
    5098           0 :         if (n == 0 && equal)
    5099           0 :                 return isl_map_universe(dims);
    5100             : 
    5101           0 :         map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
    5102             : 
    5103           0 :         for (i = 0; i + 1 < n; ++i)
    5104           0 :                 map = isl_map_add_basic_map(map,
    5105             :                                   isl_basic_map_more_at(isl_space_copy(dims), i));
    5106           0 :         if (n > 0) {
    5107           0 :                 if (equal)
    5108           0 :                         map = isl_map_add_basic_map(map,
    5109             :                               isl_basic_map_more_or_equal_at(dims, n - 1));
    5110             :                 else
    5111           0 :                         map = isl_map_add_basic_map(map,
    5112             :                               isl_basic_map_more_at(dims, n - 1));
    5113             :         } else
    5114           0 :                 isl_space_free(dims);
    5115             : 
    5116           0 :         return map;
    5117             : }
    5118             : 
    5119           0 : static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
    5120             : {
    5121           0 :         if (!dims)
    5122           0 :                 return NULL;
    5123           0 :         return map_lex_gte_first(dims, dims->n_out, equal);
    5124             : }
    5125             : 
    5126           0 : __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
    5127             : {
    5128           0 :         return map_lex_gte_first(dim, n, 0);
    5129             : }
    5130             : 
    5131           0 : __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
    5132             : {
    5133           0 :         return map_lex_gte_first(dim, n, 1);
    5134             : }
    5135             : 
    5136           0 : __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
    5137             : {
    5138           0 :         return map_lex_gte(isl_space_map_from_set(set_dim), 0);
    5139             : }
    5140             : 
    5141           0 : __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
    5142             : {
    5143           0 :         return map_lex_gte(isl_space_map_from_set(set_dim), 1);
    5144             : }
    5145             : 
    5146           0 : __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
    5147             :         __isl_take isl_set *set2)
    5148             : {
    5149             :         isl_map *map;
    5150           0 :         map = isl_map_lex_le(isl_set_get_space(set1));
    5151           0 :         map = isl_map_intersect_domain(map, set1);
    5152           0 :         map = isl_map_intersect_range(map, set2);
    5153           0 :         return map;
    5154             : }
    5155             : 
    5156           0 : __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
    5157             :         __isl_take isl_set *set2)
    5158             : {
    5159             :         isl_map *map;
    5160           0 :         map = isl_map_lex_lt(isl_set_get_space(set1));
    5161           0 :         map = isl_map_intersect_domain(map, set1);
    5162           0 :         map = isl_map_intersect_range(map, set2);
    5163           0 :         return map;
    5164             : }
    5165             : 
    5166           0 : __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
    5167             :         __isl_take isl_set *set2)
    5168             : {
    5169             :         isl_map *map;
    5170           0 :         map = isl_map_lex_ge(isl_set_get_space(set1));
    5171           0 :         map = isl_map_intersect_domain(map, set1);
    5172           0 :         map = isl_map_intersect_range(map, set2);
    5173           0 :         return map;
    5174             : }
    5175             : 
    5176           0 : __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
    5177             :         __isl_take isl_set *set2)
    5178             : {
    5179             :         isl_map *map;
    5180           0 :         map = isl_map_lex_gt(isl_set_get_space(set1));
    5181           0 :         map = isl_map_intersect_domain(map, set1);
    5182           0 :         map = isl_map_intersect_range(map, set2);
    5183           0 :         return map;
    5184             : }
    5185             : 
    5186           0 : __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
    5187             :         __isl_take isl_map *map2)
    5188             : {
    5189             :         isl_map *map;
    5190           0 :         map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
    5191           0 :         map = isl_map_apply_domain(map, isl_map_reverse(map1));
    5192           0 :         map = isl_map_apply_range(map, isl_map_reverse(map2));
    5193           0 :         return map;
    5194             : }
    5195             : 
    5196           0 : __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
    5197             :         __isl_take isl_map *map2)
    5198             : {
    5199             :         isl_map *map;
    5200           0 :         map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
    5201           0 :         map = isl_map_apply_domain(map, isl_map_reverse(map1));
    5202           0 :         map = isl_map_apply_range(map, isl_map_reverse(map2));
    5203           0 :         return map;
    5204             : }
    5205             : 
    5206           0 : __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
    5207             :         __isl_take isl_map *map2)
    5208             : {
    5209             :         isl_map *map;
    5210           0 :         map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
    5211           0 :         map = isl_map_apply_domain(map, isl_map_reverse(map1));
    5212           0 :         map = isl_map_apply_range(map, isl_map_reverse(map2));
    5213           0 :         return map;
    5214             : }
    5215             : 
    5216           0 : __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
    5217             :         __isl_take isl_map *map2)
    5218             : {
    5219             :         isl_map *map;
    5220           0 :         map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
    5221           0 :         map = isl_map_apply_domain(map, isl_map_reverse(map1));
    5222           0 :         map = isl_map_apply_range(map, isl_map_reverse(map2));
    5223           0 :         return map;
    5224             : }
    5225             : 
    5226             : /* For a div d = floor(f/m), add the constraint
    5227             :  *
    5228             :  *              f - m d >= 0
    5229             :  */
    5230           0 : static isl_stat add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
    5231             :         unsigned pos, isl_int *div)
    5232             : {
    5233             :         int i;
    5234           0 :         unsigned total = isl_basic_map_total_dim(bmap);
    5235             : 
    5236           0 :         i = isl_basic_map_alloc_inequality(bmap);
    5237           0 :         if (i < 0)
    5238           0 :                 return isl_stat_error;
    5239           0 :         isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
    5240           0 :         isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
    5241             : 
    5242           0 :         return isl_stat_ok;
    5243             : }
    5244             : 
    5245             : /* For a div d = floor(f/m), add the constraint
    5246             :  *
    5247             :  *              -(f-(m-1)) + m d >= 0
    5248             :  */
    5249           0 : static isl_stat add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
    5250             :         unsigned pos, isl_int *div)
    5251             : {
    5252             :         int i;
    5253           0 :         unsigned total = isl_basic_map_total_dim(bmap);
    5254             : 
    5255           0 :         i = isl_basic_map_alloc_inequality(bmap);
    5256           0 :         if (i < 0)
    5257           0 :                 return isl_stat_error;
    5258           0 :         isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
    5259           0 :         isl_int_set(bmap->ineq[i][1 + pos], div[0]);
    5260           0 :         isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
    5261           0 :         isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
    5262             : 
    5263           0 :         return isl_stat_ok;
    5264             : }
    5265             : 
    5266             : /* For a div d = floor(f/m), add the constraints
    5267             :  *
    5268             :  *              f - m d >= 0
    5269             :  *              -(f-(m-1)) + m d >= 0
    5270             :  *
    5271             :  * Note that the second constraint is the negation of
    5272             :  *
    5273             :  *              f - m d >= m
    5274             :  */
    5275           0 : int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
    5276             :         unsigned pos, isl_int *div)
    5277             : {
    5278           0 :         if (add_upper_div_constraint(bmap, pos, div) < 0)
    5279           0 :                 return -1;
    5280           0 :         if (add_lower_div_constraint(bmap, pos, div) < 0)
    5281           0 :                 return -1;
    5282           0 :         return 0;
    5283             : }
    5284             : 
    5285           0 : int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
    5286             :         unsigned pos, isl_int *div)
    5287             : {
    5288           0 :         return isl_basic_map_add_div_constraints_var(bset_to_bmap(bset),
    5289             :                                                         pos, div);
    5290             : }
    5291             : 
    5292           0 : int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
    5293             : {
    5294           0 :         unsigned total = isl_basic_map_total_dim(bmap);
    5295           0 :         unsigned div_pos = total - bmap->n_div + div;
    5296             : 
    5297           0 :         return isl_basic_map_add_div_constraints_var(bmap, div_pos,
    5298           0 :                                                         bmap->div[div]);
    5299             : }
    5300             : 
    5301             : /* For each known div d = floor(f/m), add the constraints
    5302             :  *
    5303             :  *              f - m d >= 0
    5304             :  *              -(f-(m-1)) + m d >= 0
    5305             :  *
    5306             :  * Remove duplicate constraints in case of some these div constraints
    5307             :  * already appear in "bmap".
    5308             :  */
    5309    16283673 : __isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
    5310             :         __isl_take isl_basic_map *bmap)
    5311             : {
    5312             :         unsigned n_div;
    5313             : 
    5314    16283673 :         if (!bmap)
    5315           0 :                 return NULL;
    5316    16283673 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
    5317    16283673 :         if (n_div == 0)
    5318    16283673 :                 return bmap;
    5319             : 
    5320           0 :         bmap = add_known_div_constraints(bmap);
    5321           0 :         bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
    5322           0 :         bmap = isl_basic_map_finalize(bmap);
    5323           0 :         return bmap;
    5324             : }
    5325             : 
    5326             : /* Add the div constraint of sign "sign" for div "div" of "bmap".
    5327             :  *
    5328             :  * In particular, if this div is of the form d = floor(f/m),
    5329             :  * then add the constraint
    5330             :  *
    5331             :  *              f - m d >= 0
    5332             :  *
    5333             :  * if sign < 0 or the constraint
    5334             :  *
    5335             :  *              -(f-(m-1)) + m d >= 0
    5336             :  *
    5337             :  * if sign > 0.
    5338             :  */
    5339           0 : int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
    5340             :         unsigned div, int sign)
    5341             : {
    5342             :         unsigned total;
    5343             :         unsigned div_pos;
    5344             : 
    5345           0 :         if (!bmap)
    5346           0 :                 return -1;
    5347             : 
    5348           0 :         total = isl_basic_map_total_dim(bmap);
    5349           0 :         div_pos = total - bmap->n_div + div;
    5350             : 
    5351           0 :         if (sign < 0)
    5352           0 :                 return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
    5353             :         else
    5354           0 :                 return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
    5355             : }
    5356             : 
    5357  1246363237 : __isl_give isl_basic_set *isl_basic_map_underlying_set(
    5358             :         __isl_take isl_basic_map *bmap)
    5359             : {
    5360  1246363237 :         if (!bmap)
    5361           0 :                 goto error;
    5362  2492726474 :         if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
    5363  2492726474 :             bmap->n_div == 0 &&
    5364  2435001936 :             !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
    5365  1188638699 :             !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
    5366  1188638699 :                 return bset_from_bmap(bmap);
    5367    57724538 :         bmap = isl_basic_map_cow(bmap);
    5368    57724538 :         if (!bmap)
    5369           0 :                 goto error;
    5370    57724538 :         bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
    5371    57724538 :         if (!bmap->dim)
    5372           0 :                 goto error;
    5373    57724538 :         bmap->extra -= bmap->n_div;
    5374    57724538 :         bmap->n_div = 0;
    5375    57724538 :         bmap = isl_basic_map_finalize(bmap);
    5376    57724538 :         return bset_from_bmap(bmap);
    5377             : error:
    5378           0 :         isl_basic_map_free(bmap);
    5379           0 :         return NULL;
    5380             : }
    5381             : 
    5382           0 : __isl_give isl_basic_set *isl_basic_set_underlying_set(
    5383             :                 __isl_take isl_basic_set *bset)
    5384             : {
    5385           0 :         return isl_basic_map_underlying_set(bset_to_bmap(bset));
    5386             : }
    5387             : 
    5388             : /* Replace each element in "list" by the result of applying
    5389             :  * isl_basic_map_underlying_set to the element.
    5390             :  */
    5391           0 : __isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
    5392             :         __isl_take isl_basic_map_list *list)
    5393             : {
    5394             :         int i, n;
    5395             : 
    5396           0 :         if (!list)
    5397           0 :                 return NULL;
    5398             : 
    5399           0 :         n = isl_basic_map_list_n_basic_map(list);
    5400           0 :         for (i = 0; i < n; ++i) {
    5401             :                 isl_basic_map *bmap;
    5402             :                 isl_basic_set *bset;
    5403             : 
    5404           0 :                 bmap = isl_basic_map_list_get_basic_map(list, i);
    5405           0 :                 bset = isl_basic_set_underlying_set(bmap);
    5406           0 :                 list = isl_basic_set_list_set_basic_set(list, i, bset);
    5407             :         }
    5408             : 
    5409           0 :         return list;
    5410             : }
    5411             : 
    5412   647337746 : __isl_give isl_basic_map *isl_basic_map_overlying_set(
    5413             :         __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
    5414             : {
    5415             :         struct isl_basic_map *bmap;
    5416             :         struct isl_ctx *ctx;
    5417             :         unsigned total;
    5418             :         int i;
    5419             : 
    5420   647337746 :         if (!bset || !like)
    5421             :                 goto error;
    5422   647337746 :         ctx = bset->ctx;
    5423   647337746 :         isl_assert(ctx, bset->n_div == 0, goto error);
    5424   647337746 :         isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
    5425   647337746 :         isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
    5426             :                         goto error);
    5427   647337746 :         if (like->n_div == 0) {
    5428   647337746 :                 isl_space *space = isl_basic_map_get_space(like);
    5429   647337746 :                 isl_basic_map_free(like);
    5430   647337746 :                 return isl_basic_map_reset_space(bset, space);
    5431             :         }
    5432           0 :         bset = isl_basic_set_cow(bset);
    5433           0 :         if (!bset)
    5434           0 :                 goto error;
    5435           0 :         total = bset->dim->n_out + bset->extra;
    5436           0 :         bmap = bset_to_bmap(bset);
    5437           0 :         isl_space_free(bmap->dim);
    5438           0 :         bmap->dim = isl_space_copy(like->dim);
    5439           0 :         if (!bmap->dim)
    5440           0 :                 goto error;
    5441           0 :         bmap->n_div = like->n_div;
    5442           0 :         bmap->extra += like->n_div;
    5443           0 :         if (bmap->extra) {
    5444             :                 unsigned ltotal;
    5445             :                 isl_int **div;
    5446           0 :                 ltotal = total - bmap->extra + like->extra;
    5447           0 :                 if (ltotal > total)
    5448           0 :                         ltotal = total;
    5449           0 :                 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
    5450           0 :                                         bmap->extra * (1 + 1 + total));
    5451           0 :                 if (isl_blk_is_error(bmap->block2))
    5452           0 :                         goto error;
    5453           0 :                 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
    5454           0 :                 if (!div)
    5455           0 :                         goto error;
    5456           0 :                 bmap->div = div;
    5457           0 :                 for (i = 0; i < bmap->extra; ++i)
    5458           0 :                         bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
    5459           0 :                 for (i = 0; i < like->n_div; ++i) {
    5460           0 :                         isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
    5461           0 :                         isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
    5462             :                 }
    5463           0 :                 bmap = isl_basic_map_add_known_div_constraints(bmap);
    5464             :         }
    5465           0 :         isl_basic_map_free(like);
    5466           0 :         bmap = isl_basic_map_simplify(bmap);
    5467           0 :         bmap = isl_basic_map_finalize(bmap);
    5468           0 :         return bmap;
    5469             : error:
    5470           0 :         isl_basic_map_free(like);
    5471           0 :         isl_basic_set_free(bset);
    5472           0 :         return NULL;
    5473             : }
    5474             : 
    5475     1395249 : struct isl_basic_set *isl_basic_set_from_underlying_set(
    5476             :         struct isl_basic_set *bset, struct isl_basic_set *like)
    5477             : {
    5478     1395249 :         return bset_from_bmap(isl_basic_map_overlying_set(bset,
    5479             :                                                         bset_to_bmap(like)));
    5480             : }
    5481             : 
    5482   645942497 : __isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
    5483             : {
    5484             :         int i;
    5485             : 
    5486   645942497 :         map = isl_map_cow(map);
    5487   645942497 :         if (!map)
    5488           0 :                 return NULL;
    5489   645942497 :         map->dim = isl_space_cow(map->dim);
    5490   645942497 :         if (!map->dim)
    5491           0 :                 goto error;
    5492             : 
    5493  1189547712 :         for (i = 1; i < map->n; ++i)
    5494   543605215 :                 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
    5495             :                                 goto error);
    5496  1835490209 :         for (i = 0; i < map->n; ++i) {
    5497  1189547712 :                 map->p[i] = bset_to_bmap(
    5498  1189547712 :                                 isl_basic_map_underlying_set(map->p[i]));
    5499  1189547712 :                 if (!map->p[i])
    5500           0 :                         goto error;
    5501             :         }
    5502   645942497 :         if (map->n == 0)
    5503           0 :                 map->dim = isl_space_underlying(map->dim, 0);
    5504             :         else {
    5505   645942497 :                 isl_space_free(map->dim);
    5506   645942497 :                 map->dim = isl_space_copy(map->p[0]->dim);
    5507             :         }
    5508   645942497 :         if (!map->dim)
    5509           0 :                 goto error;
    5510   645942497 :         return set_from_map(map);
    5511             : error:
    5512           0 :         isl_map_free(map);
    5513           0 :         return NULL;
    5514             : }
    5515             : 
    5516             : /* Replace the space of "bmap" by "space".
    5517             :  *
    5518             :  * If the space of "bmap" is identical to "space" (including the identifiers
    5519             :  * of the input and output dimensions), then simply return the original input.
    5520             :  */
    5521   647337746 : __isl_give isl_basic_map *isl_basic_map_reset_space(
    5522             :         __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
    5523             : {
    5524             :         isl_bool equal;
    5525             :         isl_space *bmap_space;
    5526             : 
    5527   647337746 :         bmap_space = isl_basic_map_peek_space(bmap);
    5528   647337746 :         equal = isl_space_is_equal(bmap_space, space);
    5529   647337746 :         if (equal >= 0 && equal)
    5530   647224802 :                 equal = isl_space_has_equal_ids(bmap_space, space);
    5531   647337746 :         if (equal < 0)
    5532           0 :                 goto error;
    5533   647337746 :         if (equal) {
    5534   647224802 :                 isl_space_free(space);
    5535   647224802 :                 return bmap;
    5536             :         }
    5537      112944 :         bmap = isl_basic_map_cow(bmap);
    5538      112944 :         if (!bmap || !space)
    5539             :                 goto error;
    5540             : 
    5541      112944 :         isl_space_free(bmap->dim);
    5542      112944 :         bmap->dim = space;
    5543             : 
    5544      112944 :         bmap = isl_basic_map_finalize(bmap);
    5545             : 
    5546      112944 :         return bmap;
    5547             : error:
    5548           0 :         isl_basic_map_free(bmap);
    5549           0 :         isl_space_free(space);
    5550           0 :         return NULL;
    5551             : }
    5552             : 
    5553           0 : __isl_give isl_basic_set *isl_basic_set_reset_space(
    5554             :         __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
    5555             : {
    5556           0 :         return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
    5557             :                                                         dim));
    5558             : }
    5559             : 
    5560             : /* Check that the total dimensions of "map" and "space" are the same.
    5561             :  */
    5562           0 : static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
    5563             :         __isl_keep isl_space *space)
    5564             : {
    5565             :         unsigned dim1, dim2;
    5566             : 
    5567           0 :         if (!map || !space)
    5568           0 :                 return isl_stat_error;
    5569           0 :         dim1 = isl_map_dim(map, isl_dim_all);
    5570           0 :         dim2 = isl_space_dim(space, isl_dim_all);
    5571           0 :         if (dim1 == dim2)
    5572           0 :                 return isl_stat_ok;
    5573           0 :         isl_die(isl_map_get_ctx(map), isl_error_invalid,
    5574             :                 "total dimensions do not match", return isl_stat_error);
    5575             : }
    5576             : 
    5577           0 : __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
    5578             :         __isl_take isl_space *dim)
    5579             : {
    5580             :         int i;
    5581             : 
    5582           0 :         map = isl_map_cow(map);
    5583           0 :         if (!map || !dim)
    5584             :                 goto error;
    5585             : 
    5586           0 :         for (i = 0; i < map->n; ++i) {
    5587           0 :                 map->p[i] = isl_basic_map_reset_space(map->p[i],
    5588             :                                                     isl_space_copy(dim));
    5589           0 :                 if (!map->p[i])
    5590           0 :                         goto error;
    5591             :         }
    5592           0 :         isl_space_free(map->dim);
    5593           0 :         map->dim = dim;
    5594             : 
    5595           0 :         return map;
    5596             : error:
    5597           0 :         isl_map_free(map);
    5598           0 :         isl_space_free(dim);
    5599           0 :         return NULL;
    5600             : }
    5601             : 
    5602             : /* Replace the space of "map" by "space", without modifying
    5603             :  * the dimension of "map".
    5604             :  *
    5605             :  * If the space of "map" is identical to "space" (including the identifiers
    5606             :  * of the input and output dimensions), then simply return the original input.
    5607             :  */
    5608           0 : __isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
    5609             :         __isl_take isl_space *space)
    5610             : {
    5611             :         isl_bool equal;
    5612             :         isl_space *map_space;
    5613             : 
    5614           0 :         map_space = isl_map_peek_space(map);
    5615           0 :         equal = isl_space_is_equal(map_space, space);
    5616           0 :         if (equal >= 0 && equal)
    5617           0 :                 equal = isl_space_has_equal_ids(map_space, space);
    5618           0 :         if (equal < 0)
    5619           0 :                 goto error;
    5620           0 :         if (equal) {
    5621           0 :                 isl_space_free(space);
    5622           0 :                 return map;
    5623             :         }
    5624           0 :         if (check_map_space_equal_total_dim(map, space) < 0)
    5625           0 :                 goto error;
    5626           0 :         return isl_map_reset_space(map, space);
    5627             : error:
    5628           0 :         isl_map_free(map);
    5629           0 :         isl_space_free(space);
    5630           0 :         return NULL;
    5631             : }
    5632             : 
    5633           0 : __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
    5634             :         __isl_take isl_space *dim)
    5635             : {
    5636           0 :         return set_from_map(isl_map_reset_space(set_to_map(set), dim));
    5637             : }
    5638             : 
    5639             : /* Compute the parameter domain of the given basic set.
    5640             :  */
    5641           0 : __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
    5642             : {
    5643             :         isl_bool is_params;
    5644             :         isl_space *space;
    5645             :         unsigned n;
    5646             : 
    5647           0 :         is_params = isl_basic_set_is_params(bset);
    5648           0 :         if (is_params < 0)
    5649           0 :                 return isl_basic_set_free(bset);
    5650           0 :         if (is_params)
    5651           0 :                 return bset;
    5652             : 
    5653           0 :         n = isl_basic_set_dim(bset, isl_dim_set);
    5654           0 :         bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
    5655           0 :         space = isl_basic_set_get_space(bset);
    5656           0 :         space = isl_space_params(space);
    5657           0 :         bset = isl_basic_set_reset_space(bset, space);
    5658           0 :         return bset;
    5659             : }
    5660             : 
    5661             : /* Construct a zero-dimensional basic set with the given parameter domain.
    5662             :  */
    5663           0 : __isl_give isl_basic_set *isl_basic_set_from_params(
    5664             :         __isl_take isl_basic_set *bset)
    5665             : {
    5666             :         isl_space *space;
    5667           0 :         space = isl_basic_set_get_space(bset);
    5668           0 :         space = isl_space_set_from_params(space);
    5669           0 :         bset = isl_basic_set_reset_space(bset, space);
    5670           0 :         return bset;
    5671             : }
    5672             : 
    5673             : /* Compute the parameter domain of the given set.
    5674             :  */
    5675           0 : __isl_give isl_set *isl_set_params(__isl_take isl_set *set)
    5676             : {
    5677             :         isl_space *space;
    5678             :         unsigned n;
    5679             : 
    5680           0 :         if (isl_set_is_params(set))
    5681           0 :                 return set;
    5682             : 
    5683           0 :         n = isl_set_dim(set, isl_dim_set);
    5684           0 :         set = isl_set_project_out(set, isl_dim_set, 0, n);
    5685           0 :         space = isl_set_get_space(set);
    5686           0 :         space = isl_space_params(space);
    5687           0 :         set = isl_set_reset_space(set, space);
    5688           0 :         return set;
    5689             : }
    5690             : 
    5691             : /* Construct a zero-dimensional set with the given parameter domain.
    5692             :  */
    5693           0 : __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
    5694             : {
    5695             :         isl_space *space;
    5696           0 :         space = isl_set_get_space(set);
    5697           0 :         space = isl_space_set_from_params(space);
    5698           0 :         set = isl_set_reset_space(set, space);
    5699           0 :         return set;
    5700             : }
    5701             : 
    5702             : /* Compute the parameter domain of the given map.
    5703             :  */
    5704           0 : __isl_give isl_set *isl_map_params(__isl_take isl_map *map)
    5705             : {
    5706             :         isl_space *space;
    5707             :         unsigned n;
    5708             : 
    5709           0 :         n = isl_map_dim(map, isl_dim_in);
    5710           0 :         map = isl_map_project_out(map, isl_dim_in, 0, n);
    5711           0 :         n = isl_map_dim(map, isl_dim_out);
    5712           0 :         map = isl_map_project_out(map, isl_dim_out, 0, n);
    5713           0 :         space = isl_map_get_space(map);
    5714           0 :         space = isl_space_params(space);
    5715           0 :         map = isl_map_reset_space(map, space);
    5716           0 :         return map;
    5717             : }
    5718             : 
    5719           0 : struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
    5720             : {
    5721             :         isl_space *space;
    5722             :         unsigned n_out;
    5723             : 
    5724           0 :         if (!bmap)
    5725           0 :                 return NULL;
    5726           0 :         space = isl_space_domain(isl_basic_map_get_space(bmap));
    5727             : 
    5728           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
    5729           0 :         bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
    5730             : 
    5731           0 :         return isl_basic_map_reset_space(bmap, space);
    5732             : }
    5733             : 
    5734           0 : isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
    5735             : {
    5736           0 :         if (!bmap)
    5737           0 :                 return isl_bool_error;
    5738           0 :         return isl_space_may_be_set(bmap->dim);
    5739             : }
    5740             : 
    5741             : /* Is this basic map actually a set?
    5742             :  * Users should never call this function.  Outside of isl,
    5743             :  * the type should indicate whether something is a set or a map.
    5744             :  */
    5745           0 : isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
    5746             : {
    5747           0 :         if (!bmap)
    5748           0 :                 return isl_bool_error;
    5749           0 :         return isl_space_is_set(bmap->dim);
    5750             : }
    5751             : 
    5752           0 : struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
    5753             : {
    5754             :         isl_bool is_set;
    5755             : 
    5756           0 :         is_set = isl_basic_map_is_set(bmap);
    5757           0 :         if (is_set < 0)
    5758           0 :                 goto error;
    5759           0 :         if (is_set)
    5760           0 :                 return bmap;
    5761           0 :         return isl_basic_map_domain(isl_basic_map_reverse(bmap));
    5762             : error:
    5763           0 :         isl_basic_map_free(bmap);
    5764           0 :         return NULL;
    5765             : }
    5766             : 
    5767           0 : __isl_give isl_basic_map *isl_basic_map_domain_map(
    5768             :         __isl_take isl_basic_map *bmap)
    5769             : {
    5770             :         int i;
    5771             :         isl_space *dim;
    5772             :         isl_basic_map *domain;
    5773             :         int nparam, n_in, n_out;
    5774             : 
    5775           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    5776           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    5777           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
    5778             : 
    5779           0 :         dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
    5780           0 :         domain = isl_basic_map_universe(dim);
    5781             : 
    5782           0 :         bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
    5783           0 :         bmap = isl_basic_map_apply_range(bmap, domain);
    5784           0 :         bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
    5785             : 
    5786           0 :         for (i = 0; i < n_in; ++i)
    5787           0 :                 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
    5788             :                                                     isl_dim_out, i);
    5789             : 
    5790           0 :         bmap = isl_basic_map_gauss(bmap, NULL);
    5791           0 :         return isl_basic_map_finalize(bmap);
    5792             : }
    5793             : 
    5794           0 : __isl_give isl_basic_map *isl_basic_map_range_map(
    5795             :         __isl_take isl_basic_map *bmap)
    5796             : {
    5797             :         int i;
    5798             :         isl_space *dim;
    5799             :         isl_basic_map *range;
    5800             :         int nparam, n_in, n_out;
    5801             : 
    5802           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    5803           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    5804           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
    5805             : 
    5806           0 :         dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
    5807           0 :         range = isl_basic_map_universe(dim);
    5808             : 
    5809           0 :         bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
    5810           0 :         bmap = isl_basic_map_apply_range(bmap, range);
    5811           0 :         bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
    5812             : 
    5813           0 :         for (i = 0; i < n_out; ++i)
    5814           0 :                 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
    5815             :                                                     isl_dim_out, i);
    5816             : 
    5817           0 :         bmap = isl_basic_map_gauss(bmap, NULL);
    5818           0 :         return isl_basic_map_finalize(bmap);
    5819             : }
    5820             : 
    5821           0 : int isl_map_may_be_set(__isl_keep isl_map *map)
    5822             : {
    5823           0 :         if (!map)
    5824           0 :                 return -1;
    5825           0 :         return isl_space_may_be_set(map->dim);
    5826             : }
    5827             : 
    5828             : /* Is this map actually a set?
    5829             :  * Users should never call this function.  Outside of isl,
    5830             :  * the type should indicate whether something is a set or a map.
    5831             :  */
    5832           0 : isl_bool isl_map_is_set(__isl_keep isl_map *map)
    5833             : {
    5834           0 :         if (!map)
    5835           0 :                 return isl_bool_error;
    5836           0 :         return isl_space_is_set(map->dim);
    5837             : }
    5838             : 
    5839           0 : __isl_give isl_set *isl_map_range(__isl_take isl_map *map)
    5840             : {
    5841             :         int i;
    5842             :         isl_bool is_set;
    5843             :         struct isl_set *set;
    5844             : 
    5845           0 :         is_set = isl_map_is_set(map);
    5846           0 :         if (is_set < 0)
    5847           0 :                 goto error;
    5848           0 :         if (is_set)
    5849           0 :                 return set_from_map(map);
    5850             : 
    5851           0 :         map = isl_map_cow(map);
    5852           0 :         if (!map)
    5853           0 :                 goto error;
    5854             : 
    5855           0 :         set = set_from_map(map);
    5856           0 :         set->dim = isl_space_range(set->dim);
    5857           0 :         if (!set->dim)
    5858           0 :                 goto error;
    5859           0 :         for (i = 0; i < map->n; ++i) {
    5860           0 :                 set->p[i] = isl_basic_map_range(map->p[i]);
    5861           0 :                 if (!set->p[i])
    5862           0 :                         goto error;
    5863             :         }
    5864           0 :         ISL_F_CLR(set, ISL_MAP_DISJOINT);
    5865           0 :         ISL_F_CLR(set, ISL_SET_NORMALIZED);
    5866           0 :         return set;
    5867             : error:
    5868           0 :         isl_map_free(map);
    5869           0 :         return NULL;
    5870             : }
    5871             : 
    5872           0 : __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
    5873             : {
    5874             :         int i;
    5875             : 
    5876           0 :         map = isl_map_cow(map);
    5877           0 :         if (!map)
    5878           0 :                 return NULL;
    5879             : 
    5880           0 :         map->dim = isl_space_domain_map(map->dim);
    5881           0 :         if (!map->dim)
    5882           0 :                 goto error;
    5883           0 :         for (i = 0; i < map->n; ++i) {
    5884           0 :                 map->p[i] = isl_basic_map_domain_map(map->p[i]);
    5885           0 :                 if (!map->p[i])
    5886           0 :                         goto error;
    5887             :         }
    5888           0 :         ISL_F_CLR(map, ISL_MAP_DISJOINT);
    5889           0 :         map = isl_map_unmark_normalized(map);
    5890           0 :         return map;
    5891             : error:
    5892           0 :         isl_map_free(map);
    5893           0 :         return NULL;
    5894             : }
    5895             : 
    5896           0 : __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
    5897             : {
    5898             :         int i;
    5899             :         isl_space *range_dim;
    5900             : 
    5901           0 :         map = isl_map_cow(map);
    5902           0 :         if (!map)
    5903           0 :                 return NULL;
    5904             : 
    5905           0 :         range_dim = isl_space_range(isl_map_get_space(map));
    5906           0 :         range_dim = isl_space_from_range(range_dim);
    5907           0 :         map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
    5908           0 :         map->dim = isl_space_join(map->dim, range_dim);
    5909           0 :         if (!map->dim)
    5910           0 :                 goto error;
    5911           0 :         for (i = 0; i < map->n; ++i) {
    5912           0 :                 map->p[i] = isl_basic_map_range_map(map->p[i]);
    5913           0 :                 if (!map->p[i])
    5914           0 :                         goto error;
    5915             :         }
    5916           0 :         ISL_F_CLR(map, ISL_MAP_DISJOINT);
    5917           0 :         map = isl_map_unmark_normalized(map);
    5918           0 :         return map;
    5919             : error:
    5920           0 :         isl_map_free(map);
    5921           0 :         return NULL;
    5922             : }
    5923             : 
    5924             : /* Given a wrapped map of the form A[B -> C],
    5925             :  * return the map A[B -> C] -> B.
    5926             :  */
    5927           0 : __isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
    5928             : {
    5929             :         isl_id *id;
    5930             :         isl_map *map;
    5931             : 
    5932           0 :         if (!set)
    5933           0 :                 return NULL;
    5934           0 :         if (!isl_set_has_tuple_id(set))
    5935           0 :                 return isl_map_domain_map(isl_set_unwrap(set));
    5936             : 
    5937           0 :         id = isl_set_get_tuple_id(set);
    5938           0 :         map = isl_map_domain_map(isl_set_unwrap(set));
    5939           0 :         map = isl_map_set_tuple_id(map, isl_dim_in, id);
    5940             : 
    5941           0 :         return map;
    5942             : }
    5943             : 
    5944           0 : __isl_give isl_basic_map *isl_basic_map_from_domain(
    5945             :         __isl_take isl_basic_set *bset)
    5946             : {
    5947           0 :         return isl_basic_map_reverse(isl_basic_map_from_range(bset));
    5948             : }
    5949             : 
    5950           0 : __isl_give isl_basic_map *isl_basic_map_from_range(
    5951             :         __isl_take isl_basic_set *bset)
    5952             : {
    5953             :         isl_space *space;
    5954           0 :         space = isl_basic_set_get_space(bset);
    5955           0 :         space = isl_space_from_range(space);
    5956           0 :         bset = isl_basic_set_reset_space(bset, space);
    5957           0 :         return bset_to_bmap(bset);
    5958             : }
    5959             : 
    5960             : /* Create a relation with the given set as range.
    5961             :  * The domain of the created relation is a zero-dimensional
    5962             :  * flat anonymous space.
    5963             :  */
    5964           0 : __isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
    5965             : {
    5966             :         isl_space *space;
    5967           0 :         space = isl_set_get_space(set);
    5968           0 :         space = isl_space_from_range(space);
    5969           0 :         set = isl_set_reset_space(set, space);
    5970           0 :         return set_to_map(set);
    5971             : }
    5972             : 
    5973             : /* Create a relation with the given set as domain.
    5974             :  * The range of the created relation is a zero-dimensional
    5975             :  * flat anonymous space.
    5976             :  */
    5977           0 : __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
    5978             : {
    5979           0 :         return isl_map_reverse(isl_map_from_range(set));
    5980             : }
    5981             : 
    5982           0 : __isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
    5983             :         __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
    5984             : {
    5985           0 :         return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
    5986             : }
    5987             : 
    5988           0 : __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
    5989             :         __isl_take isl_set *range)
    5990             : {
    5991           0 :         return isl_map_apply_range(isl_map_reverse(domain), range);
    5992             : }
    5993             : 
    5994             : /* Return a newly allocated isl_map with given space and flags and
    5995             :  * room for "n" basic maps.
    5996             :  * Make sure that all cached information is cleared.
    5997             :  */
    5998  3097843431 : __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
    5999             :         unsigned flags)
    6000             : {
    6001             :         struct isl_map *map;
    6002             : 
    6003  3097843431 :         if (!space)
    6004           0 :                 return NULL;
    6005  3097843431 :         if (n < 0)
    6006           0 :                 isl_die(space->ctx, isl_error_internal,
    6007             :                         "negative number of basic maps", goto error);
    6008  3097843431 :         map = isl_calloc(space->ctx, struct isl_map,
    6009             :                         sizeof(struct isl_map) +
    6010             :                         (n - 1) * sizeof(struct isl_basic_map *));
    6011  3097843431 :         if (!map)
    6012           0 :                 goto error;
    6013             : 
    6014  3097843431 :         map->ctx = space->ctx;
    6015  3097843431 :         isl_ctx_ref(map->ctx);
    6016  3097843431 :         map->ref = 1;
    6017  3097843431 :         map->size = n;
    6018  3097843431 :         map->n = 0;
    6019  3097843431 :         map->dim = space;
    6020  3097843431 :         map->flags = flags;
    6021  3097843431 :         return map;
    6022             : error:
    6023           0 :         isl_space_free(space);
    6024           0 :         return NULL;
    6025             : }
    6026             : 
    6027           0 : __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
    6028             : {
    6029             :         struct isl_basic_map *bmap;
    6030           0 :         bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
    6031           0 :         bmap = isl_basic_map_set_to_empty(bmap);
    6032           0 :         return bmap;
    6033             : }
    6034             : 
    6035     1395249 : __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
    6036             : {
    6037             :         struct isl_basic_set *bset;
    6038     1395249 :         bset = isl_basic_set_alloc_space(space, 0, 1, 0);
    6039     1395249 :         bset = isl_basic_set_set_to_empty(bset);
    6040     1395249 :         return bset;
    6041             : }
    6042             : 
    6043     2497658 : __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
    6044             : {
    6045             :         struct isl_basic_map *bmap;
    6046     2497658 :         bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
    6047     2497658 :         bmap = isl_basic_map_finalize(bmap);
    6048     2497658 :         return bmap;
    6049             : }
    6050             : 
    6051    44198346 : __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
    6052             : {
    6053             :         struct isl_basic_set *bset;
    6054    44198346 :         bset = isl_basic_set_alloc_space(space, 0, 0, 0);
    6055    44198346 :         bset = isl_basic_set_finalize(bset);
    6056    44198346 :         return bset;
    6057             : }
    6058             : 
    6059           0 : __isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
    6060             : {
    6061             :         int i;
    6062           0 :         unsigned total = isl_space_dim(dim, isl_dim_all);
    6063             :         isl_basic_map *bmap;
    6064             : 
    6065           0 :         bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
    6066           0 :         for (i = 0; i < total; ++i) {
    6067           0 :                 int k = isl_basic_map_alloc_inequality(bmap);
    6068           0 :                 if (k < 0)
    6069           0 :                         goto error;
    6070           0 :                 isl_seq_clr(bmap->ineq[k], 1 + total);
    6071           0 :                 isl_int_set_si(bmap->ineq[k][1 + i], 1);
    6072             :         }
    6073           0 :         return bmap;
    6074             : error:
    6075           0 :         isl_basic_map_free(bmap);
    6076           0 :         return NULL;
    6077             : }
    6078             : 
    6079           0 : __isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
    6080             : {
    6081           0 :         return isl_basic_map_nat_universe(dim);
    6082             : }
    6083             : 
    6084           0 : __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
    6085             : {
    6086           0 :         return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
    6087             : }
    6088             : 
    6089           0 : __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
    6090             : {
    6091           0 :         return isl_map_nat_universe(dim);
    6092             : }
    6093             : 
    6094     9372002 : __isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
    6095             : {
    6096     9372002 :         return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
    6097             : }
    6098             : 
    6099      112944 : __isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
    6100             : {
    6101      112944 :         return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
    6102             : }
    6103             : 
    6104     2497658 : __isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
    6105             : {
    6106             :         struct isl_map *map;
    6107     2497658 :         if (!space)
    6108           0 :                 return NULL;
    6109     2497658 :         map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
    6110     2497658 :         map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
    6111     2497658 :         return map;
    6112             : }
    6113             : 
    6114           0 : __isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
    6115             : {
    6116             :         struct isl_set *set;
    6117           0 :         if (!space)
    6118           0 :                 return NULL;
    6119           0 :         set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
    6120           0 :         set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
    6121           0 :         return set;
    6122             : }
    6123             : 
    6124  3004729040 : struct isl_map *isl_map_dup(struct isl_map *map)
    6125             : {
    6126             :         int i;
    6127             :         struct isl_map *dup;
    6128             : 
    6129  3004729040 :         if (!map)
    6130           0 :                 return NULL;
    6131  3004729040 :         dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
    6132 13794417009 :         for (i = 0; i < map->n; ++i)
    6133 10789687969 :                 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
    6134  3004729040 :         return dup;
    6135             : }
    6136             : 
    6137 12132986604 : __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
    6138             :                                                 __isl_take isl_basic_map *bmap)
    6139             : {
    6140 12132986604 :         if (!bmap || !map)
    6141             :                 goto error;
    6142 12132986604 :         if (isl_basic_map_plain_is_empty(bmap)) {
    6143    93152530 :                 isl_basic_map_free(bmap);
    6144    93152530 :                 return map;
    6145             :         }
    6146 12039834074 :         isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
    6147 12039834074 :         isl_assert(map->ctx, map->n < map->size, goto error);
    6148 12039834074 :         map->p[map->n] = bmap;
    6149 12039834074 :         map->n++;
    6150 12039834074 :         map = isl_map_unmark_normalized(map);
    6151 12039834074 :         return map;
    6152             : error:
    6153           0 :         if (map)
    6154           0 :                 isl_map_free(map);
    6155           0 :         if (bmap)
    6156           0 :                 isl_basic_map_free(bmap);
    6157           0 :         return NULL;
    6158             : }
    6159             : 
    6160  3146216809 : __isl_null isl_map *isl_map_free(__isl_take isl_map *map)
    6161             : {
    6162             :         int i;
    6163             : 
    6164  3146216809 :         if (!map)
    6165           0 :                 return NULL;
    6166             : 
    6167  3146216809 :         if (--map->ref > 0)
    6168    48373378 :                 return NULL;
    6169             : 
    6170  3097843431 :         clear_caches(map);
    6171  3097843431 :         isl_ctx_deref(map->ctx);
    6172 12345747275 :         for (i = 0; i < map->n; ++i)
    6173  9247903844 :                 isl_basic_map_free(map->p[i]);
    6174  3097843431 :         isl_space_free(map->dim);
    6175  3097843431 :         free(map);
    6176             : 
    6177  3097843431 :         return NULL;
    6178             : }
    6179             : 
    6180           0 : static struct isl_basic_map *isl_basic_map_fix_pos_si(
    6181             :         struct isl_basic_map *bmap, unsigned pos, int value)
    6182             : {
    6183             :         int j;
    6184             : 
    6185           0 :         bmap = isl_basic_map_cow(bmap);
    6186           0 :         bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
    6187           0 :         j = isl_basic_map_alloc_equality(bmap);
    6188           0 :         if (j < 0)
    6189           0 :                 goto error;
    6190           0 :         isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
    6191           0 :         isl_int_set_si(bmap->eq[j][pos], -1);
    6192           0 :         isl_int_set_si(bmap->eq[j][0], value);
    6193           0 :         bmap = isl_basic_map_simplify(bmap);
    6194           0 :         return isl_basic_map_finalize(bmap);
    6195             : error:
    6196           0 :         isl_basic_map_free(bmap);
    6197           0 :         return NULL;
    6198             : }
    6199             : 
    6200           0 : static __isl_give isl_basic_map *isl_basic_map_fix_pos(
    6201             :         __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
    6202             : {
    6203             :         int j;
    6204             : 
    6205           0 :         bmap = isl_basic_map_cow(bmap);
    6206           0 :         bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
    6207           0 :         j = isl_basic_map_alloc_equality(bmap);
    6208           0 :         if (j < 0)
    6209           0 :                 goto error;
    6210           0 :         isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
    6211           0 :         isl_int_set_si(bmap->eq[j][pos], -1);
    6212           0 :         isl_int_set(bmap->eq[j][0], value);
    6213           0 :         bmap = isl_basic_map_simplify(bmap);
    6214           0 :         return isl_basic_map_finalize(bmap);
    6215             : error:
    6216           0 :         isl_basic_map_free(bmap);
    6217           0 :         return NULL;
    6218             : }
    6219             : 
    6220           0 : __isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
    6221             :                 enum isl_dim_type type, unsigned pos, int value)
    6222             : {
    6223           0 :         if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
    6224           0 :                 return isl_basic_map_free(bmap);
    6225           0 :         return isl_basic_map_fix_pos_si(bmap,
    6226           0 :                 isl_basic_map_offset(bmap, type) + pos, value);
    6227             : }
    6228             : 
    6229           0 : __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
    6230             :                 enum isl_dim_type type, unsigned pos, isl_int value)
    6231             : {
    6232           0 :         if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
    6233           0 :                 return isl_basic_map_free(bmap);
    6234           0 :         return isl_basic_map_fix_pos(bmap,
    6235           0 :                 isl_basic_map_offset(bmap, type) + pos, value);
    6236             : }
    6237             : 
    6238             : /* Fix the value of the variable at position "pos" of type "type" of "bmap"
    6239             :  * to be equal to "v".
    6240             :  */
    6241           0 : __isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
    6242             :         enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
    6243             : {
    6244           0 :         if (!bmap || !v)
    6245             :                 goto error;
    6246           0 :         if (!isl_val_is_int(v))
    6247           0 :                 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
    6248             :                         "expecting integer value", goto error);
    6249           0 :         if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
    6250           0 :                 goto error;
    6251           0 :         pos += isl_basic_map_offset(bmap, type);
    6252           0 :         bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
    6253           0 :         isl_val_free(v);
    6254           0 :         return bmap;
    6255             : error:
    6256           0 :         isl_basic_map_free(bmap);
    6257           0 :         isl_val_free(v);
    6258           0 :         return NULL;
    6259             : }
    6260             : 
    6261             : /* Fix the value of the variable at position "pos" of type "type" of "bset"
    6262             :  * to be equal to "v".
    6263             :  */
    6264           0 : __isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
    6265             :         enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
    6266             : {
    6267           0 :         return isl_basic_map_fix_val(bset, type, pos, v);
    6268             : }
    6269             : 
    6270           0 : struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
    6271             :                 enum isl_dim_type type, unsigned pos, int value)
    6272             : {
    6273           0 :         return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
    6274             :                                                     type, pos, value));
    6275             : }
    6276             : 
    6277           0 : __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
    6278             :                 enum isl_dim_type type, unsigned pos, isl_int value)
    6279             : {
    6280           0 :         return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
    6281             :                                                     type, pos, value));
    6282             : }
    6283             : 
    6284           0 : struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
    6285             :                 unsigned input, int value)
    6286             : {
    6287           0 :         return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
    6288             : }
    6289             : 
    6290           0 : struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
    6291             :                 unsigned dim, int value)
    6292             : {
    6293           0 :         return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
    6294             :                                         isl_dim_set, dim, value));
    6295             : }
    6296             : 
    6297             : /* Remove the basic map at position "i" from "map" if this basic map
    6298             :  * is (obviously) empty.
    6299             :  */
    6300 13325972331 : static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
    6301             : {
    6302             :         isl_bool empty;
    6303             : 
    6304 13325972331 :         if (!map)
    6305           0 :                 return NULL;
    6306             : 
    6307 13325972331 :         empty = isl_basic_map_plain_is_empty(map->p[i]);
    6308 13325972331 :         if (empty < 0)
    6309           0 :                 return isl_map_free(map);
    6310 13325972331 :         if (!empty)
    6311 11078470650 :                 return map;
    6312             : 
    6313  2247501681 :         isl_basic_map_free(map->p[i]);
    6314  2247501681 :         map->n--;
    6315  2247501681 :         if (i != map->n) {
    6316  1477095453 :                 map->p[i] = map->p[map->n];
    6317  1477095453 :                 map = isl_map_unmark_normalized(map);
    6318             : 
    6319             :         }
    6320             : 
    6321  2247501681 :         return map;
    6322             : }
    6323             : 
    6324             : /* Perform "fn" on each basic map of "map", where we may not be holding
    6325             :  * the only reference to "map".
    6326             :  * In particular, "fn" should be a semantics preserving operation
    6327             :  * that we want to apply to all copies of "map".  We therefore need
    6328             :  * to be careful not to modify "map" in a way that breaks "map"
    6329             :  * in case anything goes wrong.
    6330             :  */
    6331  1854329904 : __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
    6332             :         __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
    6333             : {
    6334             :         struct isl_basic_map *bmap;
    6335             :         int i;
    6336             : 
    6337  1854329904 :         if (!map)
    6338           0 :                 return NULL;
    6339             : 
    6340  6932353310 :         for (i = map->n - 1; i >= 0; --i) {
    6341  5078023406 :                 bmap = isl_basic_map_copy(map->p[i]);
    6342  5078023406 :                 bmap = fn(bmap);
    6343  5078023406 :                 if (!bmap)
    6344           0 :                         goto error;
    6345  5078023406 :                 isl_basic_map_free(map->p[i]);
    6346  5078023406 :                 map->p[i] = bmap;
    6347  5078023406 :                 map = remove_if_empty(map, i);
    6348  5078023406 :                 if (!map)
    6349           0 :                         return NULL;
    6350             :         }
    6351             : 
    6352  1854329904 :         return map;
    6353             : error:
    6354           0 :         isl_map_free(map);
    6355           0 :         return NULL;
    6356             : }
    6357             : 
    6358           0 : __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
    6359             :                 enum isl_dim_type type, unsigned pos, int value)
    6360             : {
    6361             :         int i;
    6362             : 
    6363           0 :         map = isl_map_cow(map);
    6364           0 :         if (!map)
    6365           0 :                 return NULL;
    6366             : 
    6367           0 :         isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
    6368           0 :         for (i = map->n - 1; i >= 0; --i) {
    6369           0 :                 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
    6370           0 :                 map = remove_if_empty(map, i);
    6371           0 :                 if (!map)
    6372           0 :                         return NULL;
    6373             :         }
    6374           0 :         map = isl_map_unmark_normalized(map);
    6375           0 :         return map;
    6376             : error:
    6377           0 :         isl_map_free(map);
    6378           0 :         return NULL;
    6379             : }
    6380             : 
    6381           0 : __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
    6382             :                 enum isl_dim_type type, unsigned pos, int value)
    6383             : {
    6384           0 :         return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
    6385             : }
    6386             : 
    6387           0 : __isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
    6388             :                 enum isl_dim_type type, unsigned pos, isl_int value)
    6389             : {
    6390             :         int i;
    6391             : 
    6392           0 :         map = isl_map_cow(map);
    6393           0 :         if (!map)
    6394           0 :                 return NULL;
    6395             : 
    6396           0 :         isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
    6397           0 :         for (i = 0; i < map->n; ++i) {
    6398           0 :                 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
    6399           0 :                 if (!map->p[i])
    6400           0 :                         goto error;
    6401             :         }
    6402           0 :         map = isl_map_unmark_normalized(map);
    6403           0 :         return map;
    6404             : error:
    6405           0 :         isl_map_free(map);
    6406           0 :         return NULL;
    6407             : }
    6408             : 
    6409           0 : __isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
    6410             :                 enum isl_dim_type type, unsigned pos, isl_int value)
    6411             : {
    6412           0 :         return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
    6413             : }
    6414             : 
    6415             : /* Fix the value of the variable at position "pos" of type "type" of "map"
    6416             :  * to be equal to "v".
    6417             :  */
    6418           0 : __isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
    6419             :         enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
    6420             : {
    6421             :         int i;
    6422             : 
    6423           0 :         map = isl_map_cow(map);
    6424           0 :         if (!map || !v)
    6425             :                 goto error;
    6426             : 
    6427           0 :         if (!isl_val_is_int(v))
    6428           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
    6429             :                         "expecting integer value", goto error);
    6430           0 :         if (pos >= isl_map_dim(map, type))
    6431           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
    6432             :                         "index out of bounds", goto error);
    6433           0 :         for (i = map->n - 1; i >= 0; --i) {
    6434           0 :                 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
    6435             :                                                         isl_val_copy(v));
    6436           0 :                 map = remove_if_empty(map, i);
    6437           0 :                 if (!map)
    6438           0 :                         goto error;
    6439             :         }
    6440           0 :         map = isl_map_unmark_normalized(map);
    6441           0 :         isl_val_free(v);
    6442           0 :         return map;
    6443             : error:
    6444           0 :         isl_map_free(map);
    6445           0 :         isl_val_free(v);
    6446           0 :         return NULL;
    6447             : }
    6448             : 
    6449             : /* Fix the value of the variable at position "pos" of type "type" of "set"
    6450             :  * to be equal to "v".
    6451             :  */
    6452           0 : __isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
    6453             :         enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
    6454             : {
    6455           0 :         return isl_map_fix_val(set, type, pos, v);
    6456             : }
    6457             : 
    6458           0 : struct isl_map *isl_map_fix_input_si(struct isl_map *map,
    6459             :                 unsigned input, int value)
    6460             : {
    6461           0 :         return isl_map_fix_si(map, isl_dim_in, input, value);
    6462             : }
    6463             : 
    6464           0 : struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
    6465             : {
    6466           0 :         return set_from_map(isl_map_fix_si(set_to_map(set),
    6467             :                                                 isl_dim_set, dim, value));
    6468             : }
    6469             : 
    6470           0 : static __isl_give isl_basic_map *basic_map_bound_si(
    6471             :         __isl_take isl_basic_map *bmap,
    6472             :         enum isl_dim_type type, unsigned pos, int value, int upper)
    6473             : {
    6474             :         int j;
    6475             : 
    6476           0 :         if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
    6477           0 :                 return isl_basic_map_free(bmap);
    6478           0 :         pos += isl_basic_map_offset(bmap, type);
    6479           0 :         bmap = isl_basic_map_cow(bmap);
    6480           0 :         bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
    6481           0 :         j = isl_basic_map_alloc_inequality(bmap);
    6482           0 :         if (j < 0)
    6483           0 :                 goto error;
    6484           0 :         isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
    6485           0 :         if (upper) {
    6486           0 :                 isl_int_set_si(bmap->ineq[j][pos], -1);
    6487           0 :                 isl_int_set_si(bmap->ineq[j][0], value);
    6488             :         } else {
    6489           0 :                 isl_int_set_si(bmap->ineq[j][pos], 1);
    6490           0 :                 isl_int_set_si(bmap->ineq[j][0], -value);
    6491             :         }
    6492           0 :         bmap = isl_basic_map_simplify(bmap);
    6493           0 :         return isl_basic_map_finalize(bmap);
    6494             : error:
    6495           0 :         isl_basic_map_free(bmap);
    6496           0 :         return NULL;
    6497             : }
    6498             : 
    6499           0 : __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
    6500             :         __isl_take isl_basic_map *bmap,
    6501             :         enum isl_dim_type type, unsigned pos, int value)
    6502             : {
    6503           0 :         return basic_map_bound_si(bmap, type, pos, value, 0);
    6504             : }
    6505             : 
    6506             : /* Constrain the values of the given dimension to be no greater than "value".
    6507             :  */
    6508           0 : __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
    6509             :         __isl_take isl_basic_map *bmap,
    6510             :         enum isl_dim_type type, unsigned pos, int value)
    6511             : {
    6512           0 :         return basic_map_bound_si(bmap, type, pos, value, 1);
    6513             : }
    6514             : 
    6515           0 : static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
    6516             :         enum isl_dim_type type, unsigned pos, int value, int upper)
    6517             : {
    6518             :         int i;
    6519             : 
    6520           0 :         map = isl_map_cow(map);
    6521           0 :         if (!map)
    6522           0 :                 return NULL;
    6523             : 
    6524           0 :         isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
    6525           0 :         for (i = 0; i < map->n; ++i) {
    6526           0 :                 map->p[i] = basic_map_bound_si(map->p[i],
    6527             :                                                  type, pos, value, upper);
    6528           0 :                 if (!map->p[i])
    6529           0 :                         goto error;
    6530             :         }
    6531           0 :         map = isl_map_unmark_normalized(map);
    6532           0 :         return map;
    6533             : error:
    6534           0 :         isl_map_free(map);
    6535           0 :         return NULL;
    6536             : }
    6537             : 
    6538           0 : __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
    6539             :         enum isl_dim_type type, unsigned pos, int value)
    6540             : {
    6541           0 :         return map_bound_si(map, type, pos, value, 0);
    6542             : }
    6543             : 
    6544           0 : __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
    6545             :         enum isl_dim_type type, unsigned pos, int value)
    6546             : {
    6547           0 :         return map_bound_si(map, type, pos, value, 1);
    6548             : }
    6549             : 
    6550           0 : __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
    6551             :                 enum isl_dim_type type, unsigned pos, int value)
    6552             : {
    6553           0 :         return set_from_map(isl_map_lower_bound_si(set_to_map(set),
    6554             :                                                         type, pos, value));
    6555             : }
    6556             : 
    6557           0 : __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
    6558             :         enum isl_dim_type type, unsigned pos, int value)
    6559             : {
    6560           0 :         return isl_map_upper_bound_si(set, type, pos, value);
    6561             : }
    6562             : 
    6563             : /* Bound the given variable of "bmap" from below (or above is "upper"
    6564             :  * is set) to "value".
    6565             :  */
    6566           0 : static __isl_give isl_basic_map *basic_map_bound(
    6567             :         __isl_take isl_basic_map *bmap,
    6568             :         enum isl_dim_type type, unsigned pos, isl_int value, int upper)
    6569             : {
    6570             :         int j;
    6571             : 
    6572           0 :         if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
    6573           0 :                 return isl_basic_map_free(bmap);
    6574           0 :         pos += isl_basic_map_offset(bmap, type);
    6575           0 :         bmap = isl_basic_map_cow(bmap);
    6576           0 :         bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
    6577           0 :         j = isl_basic_map_alloc_inequality(bmap);
    6578           0 :         if (j < 0)
    6579           0 :                 goto error;
    6580           0 :         isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
    6581           0 :         if (upper) {
    6582           0 :                 isl_int_set_si(bmap->ineq[j][pos], -1);
    6583           0 :                 isl_int_set(bmap->ineq[j][0], value);
    6584             :         } else {
    6585           0 :                 isl_int_set_si(bmap->ineq[j][pos], 1);
    6586           0 :                 isl_int_neg(bmap->ineq[j][0], value);
    6587             :         }
    6588           0 :         bmap = isl_basic_map_simplify(bmap);
    6589           0 :         return isl_basic_map_finalize(bmap);
    6590             : error:
    6591           0 :         isl_basic_map_free(bmap);
    6592           0 :         return NULL;
    6593             : }
    6594             : 
    6595             : /* Bound the given variable of "map" from below (or above is "upper"
    6596             :  * is set) to "value".
    6597             :  */
    6598           0 : static __isl_give isl_map *map_bound(__isl_take isl_map *map,
    6599             :         enum isl_dim_type type, unsigned pos, isl_int value, int upper)
    6600             : {
    6601             :         int i;
    6602             : 
    6603           0 :         map = isl_map_cow(map);
    6604           0 :         if (!map)
    6605           0 :                 return NULL;
    6606             : 
    6607           0 :         if (pos >= isl_map_dim(map, type))
    6608           0 :                 isl_die(map->ctx, isl_error_invalid,
    6609             :                         "index out of bounds", goto error);
    6610           0 :         for (i = map->n - 1; i >= 0; --i) {
    6611           0 :                 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
    6612           0 :                 map = remove_if_empty(map, i);
    6613           0 :                 if (!map)
    6614           0 :                         return NULL;
    6615             :         }
    6616           0 :         map = isl_map_unmark_normalized(map);
    6617           0 :         return map;
    6618             : error:
    6619           0 :         isl_map_free(map);
    6620           0 :         return NULL;
    6621             : }
    6622             : 
    6623           0 : __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
    6624             :         enum isl_dim_type type, unsigned pos, isl_int value)
    6625             : {
    6626           0 :         return map_bound(map, type, pos, value, 0);
    6627             : }
    6628             : 
    6629           0 : __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
    6630             :         enum isl_dim_type type, unsigned pos, isl_int value)
    6631             : {
    6632           0 :         return map_bound(map, type, pos, value, 1);
    6633             : }
    6634             : 
    6635           0 : __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
    6636             :         enum isl_dim_type type, unsigned pos, isl_int value)
    6637             : {
    6638           0 :         return isl_map_lower_bound(set, type, pos, value);
    6639             : }
    6640             : 
    6641           0 : __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
    6642             :         enum isl_dim_type type, unsigned pos, isl_int value)
    6643             : {
    6644           0 :         return isl_map_upper_bound(set, type, pos, value);
    6645             : }
    6646             : 
    6647             : /* Force the values of the variable at position "pos" of type "type" of "set"
    6648             :  * to be no smaller than "value".
    6649             :  */
    6650           0 : __isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
    6651             :         enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
    6652             : {
    6653           0 :         if (!value)
    6654           0 :                 goto error;
    6655           0 :         if (!isl_val_is_int(value))
    6656           0 :                 isl_die(isl_set_get_ctx(set), isl_error_invalid,
    6657             :                         "expecting integer value", goto error);
    6658           0 :         set = isl_set_lower_bound(set, type, pos, value->n);
    6659           0 :         isl_val_free(value);
    6660           0 :         return set;
    6661             : error:
    6662           0 :         isl_val_free(value);
    6663           0 :         isl_set_free(set);
    6664           0 :         return NULL;
    6665             : }
    6666             : 
    6667             : /* Force the values of the variable at position "pos" of type "type" of "set"
    6668             :  * to be no greater than "value".
    6669             :  */
    6670           0 : __isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
    6671             :         enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
    6672             : {
    6673           0 :         if (!value)
    6674           0 :                 goto error;
    6675           0 :         if (!isl_val_is_int(value))
    6676           0 :                 isl_die(isl_set_get_ctx(set), isl_error_invalid,
    6677             :                         "expecting integer value", goto error);
    6678           0 :         set = isl_set_upper_bound(set, type, pos, value->n);
    6679           0 :         isl_val_free(value);
    6680           0 :         return set;
    6681             : error:
    6682           0 :         isl_val_free(value);
    6683           0 :         isl_set_free(set);
    6684           0 :         return NULL;
    6685             : }
    6686             : 
    6687             : /* Bound the given variable of "bset" from below (or above is "upper"
    6688             :  * is set) to "value".
    6689             :  */
    6690           0 : static __isl_give isl_basic_set *isl_basic_set_bound(
    6691             :         __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
    6692             :         isl_int value, int upper)
    6693             : {
    6694           0 :         return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
    6695             :                                                 type, pos, value, upper));
    6696             : }
    6697             : 
    6698             : /* Bound the given variable of "bset" from below (or above is "upper"
    6699             :  * is set) to "value".
    6700             :  */
    6701           0 : static __isl_give isl_basic_set *isl_basic_set_bound_val(
    6702             :         __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
    6703             :         __isl_take isl_val *value, int upper)
    6704             : {
    6705           0 :         if (!value)
    6706           0 :                 goto error;
    6707           0 :         if (!isl_val_is_int(value))
    6708           0 :                 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
    6709             :                         "expecting integer value", goto error);
    6710           0 :         bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
    6711           0 :         isl_val_free(value);
    6712           0 :         return bset;
    6713             : error:
    6714           0 :         isl_val_free(value);
    6715           0 :         isl_basic_set_free(bset);
    6716           0 :         return NULL;
    6717             : }
    6718             : 
    6719             : /* Bound the given variable of "bset" from below to "value".
    6720             :  */
    6721           0 : __isl_give isl_basic_set *isl_basic_set_lower_bound_val(
    6722             :         __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
    6723             :         __isl_take isl_val *value)
    6724             : {
    6725           0 :         return isl_basic_set_bound_val(bset, type, pos, value, 0);
    6726             : }
    6727             : 
    6728             : /* Bound the given variable of "bset" from above to "value".
    6729             :  */
    6730           0 : __isl_give isl_basic_set *isl_basic_set_upper_bound_val(
    6731             :         __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
    6732             :         __isl_take isl_val *value)
    6733             : {
    6734           0 :         return isl_basic_set_bound_val(bset, type, pos, value, 1);
    6735             : }
    6736             : 
    6737           0 : __isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
    6738             : {
    6739             :         int i;
    6740             : 
    6741           0 :         map = isl_map_cow(map);
    6742           0 :         if (!map)
    6743           0 :                 return NULL;
    6744             : 
    6745           0 :         map->dim = isl_space_reverse(map->dim);
    6746           0 :         if (!map->dim)
    6747           0 :                 goto error;
    6748           0 :         for (i = 0; i < map->n; ++i) {
    6749           0 :                 map->p[i] = isl_basic_map_reverse(map->p[i]);
    6750           0 :                 if (!map->p[i])
    6751           0 :                         goto error;
    6752             :         }
    6753           0 :         map = isl_map_unmark_normalized(map);
    6754           0 :         return map;
    6755             : error:
    6756           0 :         isl_map_free(map);
    6757           0 :         return NULL;
    6758             : }
    6759             : 
    6760             : #undef TYPE
    6761             : #define TYPE    isl_pw_multi_aff
    6762             : #undef SUFFIX
    6763             : #define SUFFIX  _pw_multi_aff
    6764             : #undef EMPTY
    6765             : #define EMPTY   isl_pw_multi_aff_empty
    6766             : #undef ADD
    6767             : #define ADD     isl_pw_multi_aff_union_add
    6768             : #include "isl_map_lexopt_templ.c"
    6769             : 
    6770             : /* Given a map "map", compute the lexicographically minimal
    6771             :  * (or maximal) image element for each domain element in dom,
    6772             :  * in the form of an isl_pw_multi_aff.
    6773             :  * If "empty" is not NULL, then set *empty to those elements in dom that
    6774             :  * do not have an image element.
    6775             :  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
    6776             :  * should be computed over the domain of "map".  "empty" is also NULL
    6777             :  * in this case.
    6778             :  *
    6779             :  * We first compute the lexicographically minimal or maximal element
    6780             :  * in the first basic map.  This results in a partial solution "res"
    6781             :  * and a subset "todo" of dom that still need to be handled.
    6782             :  * We then consider each of the remaining maps in "map" and successively
    6783             :  * update both "res" and "todo".
    6784             :  * If "empty" is NULL, then the todo sets are not needed and therefore
    6785             :  * also not computed.
    6786             :  */
    6787           0 : static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
    6788             :         __isl_take isl_map *map, __isl_take isl_set *dom,
    6789             :         __isl_give isl_set **empty, unsigned flags)
    6790             : {
    6791             :         int i;
    6792             :         int full;
    6793             :         isl_pw_multi_aff *res;
    6794             :         isl_set *todo;
    6795             : 
    6796           0 :         full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
    6797           0 :         if (!map || (!full && !dom))
    6798             :                 goto error;
    6799             : 
    6800           0 :         if (isl_map_plain_is_empty(map)) {
    6801           0 :                 if (empty)
    6802           0 :                         *empty = dom;
    6803             :                 else
    6804           0 :                         isl_set_free(dom);
    6805           0 :                 return isl_pw_multi_aff_from_map(map);
    6806             :         }
    6807             : 
    6808           0 :         res = basic_map_partial_lexopt_pw_multi_aff(
    6809           0 :                                             isl_basic_map_copy(map->p[0]),
    6810             :                                             isl_set_copy(dom), empty, flags);
    6811             : 
    6812           0 :         if (empty)
    6813           0 :                 todo = *empty;
    6814           0 :         for (i = 1; i < map->n; ++i) {
    6815             :                 isl_pw_multi_aff *res_i;
    6816             : 
    6817           0 :                 res_i = basic_map_partial_lexopt_pw_multi_aff(
    6818           0 :                                             isl_basic_map_copy(map->p[i]),
    6819             :                                             isl_set_copy(dom), empty, flags);
    6820             : 
    6821           0 :                 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
    6822           0 :                         res = isl_pw_multi_aff_union_lexmax(res, res_i);
    6823             :                 else
    6824           0 :                         res = isl_pw_multi_aff_union_lexmin(res, res_i);
    6825             : 
    6826           0 :                 if (empty)
    6827           0 :                         todo = isl_set_intersect(todo, *empty);
    6828             :         }
    6829             : 
    6830           0 :         isl_set_free(dom);
    6831           0 :         isl_map_free(map);
    6832             : 
    6833           0 :         if (empty)
    6834           0 :                 *empty = todo;
    6835             : 
    6836           0 :         return res;
    6837             : error:
    6838           0 :         if (empty)
    6839           0 :                 *empty = NULL;
    6840           0 :         isl_set_free(dom);
    6841           0 :         isl_map_free(map);
    6842           0 :         return NULL;
    6843             : }
    6844             : 
    6845             : #undef TYPE
    6846             : #define TYPE    isl_map
    6847             : #undef SUFFIX
    6848             : #define SUFFIX
    6849             : #undef EMPTY
    6850             : #define EMPTY   isl_map_empty
    6851             : #undef ADD
    6852             : #define ADD     isl_map_union_disjoint
    6853             : #include "isl_map_lexopt_templ.c"
    6854             : 
    6855             : /* Given a map "map", compute the lexicographically minimal
    6856             :  * (or maximal) image element for each domain element in "dom",
    6857             :  * in the form of an isl_map.
    6858             :  * If "empty" is not NULL, then set *empty to those elements in "dom" that
    6859             :  * do not have an image element.
    6860             :  * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
    6861             :  * should be computed over the domain of "map".  "empty" is also NULL
    6862             :  * in this case.
    6863             :  *
    6864             :  * If the input consists of more than one disjunct, then first
    6865             :  * compute the desired result in the form of an isl_pw_multi_aff and
    6866             :  * then convert that into an isl_map.
    6867             :  *
    6868             :  * This function used to have an explicit implementation in terms
    6869             :  * of isl_maps, but it would continually intersect the domains of
    6870             :  * partial results with the complement of the domain of the next
    6871             :  * partial solution, potentially leading to an explosion in the number
    6872             :  * of disjuncts if there are several disjuncts in the input.
    6873             :  * An even earlier implementation of this function would look for
    6874             :  * better results in the domain of the partial result and for extra
    6875             :  * results in the complement of this domain, which would lead to
    6876             :  * even more splintering.
    6877             :  */
    6878           0 : static __isl_give isl_map *isl_map_partial_lexopt_aligned(
    6879             :         __isl_take isl_map *map, __isl_take isl_set *dom,
    6880             :         __isl_give isl_set **empty, unsigned flags)
    6881             : {
    6882             :         int full;
    6883             :         struct isl_map *res;
    6884             :         isl_pw_multi_aff *pma;
    6885             : 
    6886           0 :         full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
    6887           0 :         if (!map || (!full && !dom))
    6888             :                 goto error;
    6889             : 
    6890           0 :         if (isl_map_plain_is_empty(map)) {
    6891           0 :                 if (empty)
    6892           0 :                         *empty = dom;
    6893             :                 else
    6894           0 :                         isl_set_free(dom);
    6895           0 :                 return map;
    6896             :         }
    6897             : 
    6898           0 :         if (map->n == 1) {
    6899           0 :                 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
    6900             :                                                 dom, empty, flags);
    6901           0 :                 isl_map_free(map);
    6902           0 :                 return res;
    6903             :         }
    6904             : 
    6905           0 :         pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
    6906             :                                                         flags);
    6907           0 :         return isl_map_from_pw_multi_aff(pma);
    6908             : error:
    6909           0 :         if (empty)
    6910           0 :                 *empty = NULL;
    6911           0 :         isl_set_free(dom);
    6912           0 :         isl_map_free(map);
    6913           0 :         return NULL;
    6914             : }
    6915             : 
    6916           0 : __isl_give isl_map *isl_map_partial_lexmax(
    6917             :                 __isl_take isl_map *map, __isl_take isl_set *dom,
    6918             :                 __isl_give isl_set **empty)
    6919             : {
    6920           0 :         return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
    6921             : }
    6922             : 
    6923           0 : __isl_give isl_map *isl_map_partial_lexmin(
    6924             :                 __isl_take isl_map *map, __isl_take isl_set *dom,
    6925             :                 __isl_give isl_set **empty)
    6926             : {
    6927           0 :         return isl_map_partial_lexopt(map, dom, empty, 0);
    6928             : }
    6929             : 
    6930           0 : __isl_give isl_set *isl_set_partial_lexmin(
    6931             :                 __isl_take isl_set *set, __isl_take isl_set *dom,
    6932             :                 __isl_give isl_set **empty)
    6933             : {
    6934           0 :         return set_from_map(isl_map_partial_lexmin(set_to_map(set),
    6935             :                                                     dom, empty));
    6936             : }
    6937             : 
    6938           0 : __isl_give isl_set *isl_set_partial_lexmax(
    6939             :                 __isl_take isl_set *set, __isl_take isl_set *dom,
    6940             :                 __isl_give isl_set **empty)
    6941             : {
    6942           0 :         return set_from_map(isl_map_partial_lexmax(set_to_map(set),
    6943             :                                                     dom, empty));
    6944             : }
    6945             : 
    6946             : /* Compute the lexicographic minimum (or maximum if "flags" includes
    6947             :  * ISL_OPT_MAX) of "bset" over its parametric domain.
    6948             :  */
    6949           0 : __isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
    6950             :         unsigned flags)
    6951             : {
    6952           0 :         return isl_basic_map_lexopt(bset, flags);
    6953             : }
    6954             : 
    6955           0 : __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
    6956             : {
    6957           0 :         return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
    6958             : }
    6959             : 
    6960           0 : __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
    6961             : {
    6962           0 :         return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
    6963             : }
    6964             : 
    6965           0 : __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
    6966             : {
    6967           0 :         return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
    6968             : }
    6969             : 
    6970             : /* Compute the lexicographic minimum of "bset" over its parametric domain
    6971             :  * for the purpose of quantifier elimination.
    6972             :  * That is, find an explicit representation for all the existentially
    6973             :  * quantified variables in "bset" by computing their lexicographic
    6974             :  * minimum.
    6975             :  */
    6976           0 : static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
    6977             :         __isl_take isl_basic_set *bset)
    6978             : {
    6979           0 :         return isl_basic_set_lexopt(bset, ISL_OPT_QE);
    6980             : }
    6981             : 
    6982             : /* Given a basic map with one output dimension, compute the minimum or
    6983             :  * maximum of that dimension as an isl_pw_aff.
    6984             :  *
    6985             :  * Compute the optimum as a lexicographic optimum over the single
    6986             :  * output dimension and extract the single isl_pw_aff from the result.
    6987             :  */
    6988           0 : static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
    6989             :         int max)
    6990             : {
    6991             :         isl_pw_multi_aff *pma;
    6992             :         isl_pw_aff *pwaff;
    6993             : 
    6994           0 :         bmap = isl_basic_map_copy(bmap);
    6995           0 :         pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
    6996           0 :         pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
    6997           0 :         isl_pw_multi_aff_free(pma);
    6998             : 
    6999           0 :         return pwaff;
    7000             : }
    7001             : 
    7002             : /* Compute the minimum or maximum of the given output dimension
    7003             :  * as a function of the parameters and the input dimensions,
    7004             :  * but independently of the other output dimensions.
    7005             :  *
    7006             :  * We first project out the other output dimension and then compute
    7007             :  * the "lexicographic" maximum in each basic map, combining the results
    7008             :  * using isl_pw_aff_union_max.
    7009             :  */
    7010           0 : static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
    7011             :         int max)
    7012             : {
    7013             :         int i;
    7014             :         isl_pw_aff *pwaff;
    7015             :         unsigned n_out;
    7016             : 
    7017           0 :         n_out = isl_map_dim(map, isl_dim_out);
    7018           0 :         map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
    7019           0 :         map = isl_map_project_out(map, isl_dim_out, 0, pos);
    7020           0 :         if (!map)
    7021           0 :                 return NULL;
    7022             : 
    7023           0 :         if (map->n == 0) {
    7024           0 :                 isl_space *dim = isl_map_get_space(map);
    7025           0 :                 isl_map_free(map);
    7026           0 :                 return isl_pw_aff_empty(dim);
    7027             :         }
    7028             : 
    7029           0 :         pwaff = basic_map_dim_opt(map->p[0], max);
    7030           0 :         for (i = 1; i < map->n; ++i) {
    7031             :                 isl_pw_aff *pwaff_i;
    7032             : 
    7033           0 :                 pwaff_i = basic_map_dim_opt(map->p[i], max);
    7034           0 :                 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
    7035             :         }
    7036             : 
    7037           0 :         isl_map_free(map);
    7038             : 
    7039           0 :         return pwaff;
    7040             : }
    7041             : 
    7042             : /* Compute the minimum of the given output dimension as a function of the
    7043             :  * parameters and input dimensions, but independently of
    7044             :  * the other output dimensions.
    7045             :  */
    7046           0 : __isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
    7047             : {
    7048           0 :         return map_dim_opt(map, pos, 0);
    7049             : }
    7050             : 
    7051             : /* Compute the maximum of the given output dimension as a function of the
    7052             :  * parameters and input dimensions, but independently of
    7053             :  * the other output dimensions.
    7054             :  */
    7055           0 : __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
    7056             : {
    7057           0 :         return map_dim_opt(map, pos, 1);
    7058             : }
    7059             : 
    7060             : /* Compute the minimum or maximum of the given set dimension
    7061             :  * as a function of the parameters,
    7062             :  * but independently of the other set dimensions.
    7063             :  */
    7064           0 : static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
    7065             :         int max)
    7066             : {
    7067           0 :         return map_dim_opt(set, pos, max);
    7068             : }
    7069             : 
    7070             : /* Compute the maximum of the given set dimension as a function of the
    7071             :  * parameters, but independently of the other set dimensions.
    7072             :  */
    7073           0 : __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
    7074             : {
    7075           0 :         return set_dim_opt(set, pos, 1);
    7076             : }
    7077             : 
    7078             : /* Compute the minimum of the given set dimension as a function of the
    7079             :  * parameters, but independently of the other set dimensions.
    7080             :  */
    7081           0 : __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
    7082             : {
    7083           0 :         return set_dim_opt(set, pos, 0);
    7084             : }
    7085             : 
    7086             : /* Apply a preimage specified by "mat" on the parameters of "bset".
    7087             :  * bset is assumed to have only parameters and divs.
    7088             :  */
    7089           0 : static __isl_give isl_basic_set *basic_set_parameter_preimage(
    7090             :         __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
    7091             : {
    7092             :         unsigned nparam;
    7093             : 
    7094           0 :         if (!bset || !mat)
    7095             :                 goto error;
    7096             : 
    7097           0 :         bset->dim = isl_space_cow(bset->dim);
    7098           0 :         if (!bset->dim)
    7099           0 :                 goto error;
    7100             : 
    7101           0 :         nparam = isl_basic_set_dim(bset, isl_dim_param);
    7102             : 
    7103           0 :         isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
    7104             : 
    7105           0 :         bset->dim->nparam = 0;
    7106           0 :         bset->dim->n_out = nparam;
    7107           0 :         bset = isl_basic_set_preimage(bset, mat);
    7108           0 :         if (bset) {
    7109           0 :                 bset->dim->nparam = bset->dim->n_out;
    7110           0 :                 bset->dim->n_out = 0;
    7111             :         }
    7112           0 :         return bset;
    7113             : error:
    7114           0 :         isl_mat_free(mat);
    7115           0 :         isl_basic_set_free(bset);
    7116           0 :         return NULL;
    7117             : }
    7118             : 
    7119             : /* Apply a preimage specified by "mat" on the parameters of "set".
    7120             :  * set is assumed to have only parameters and divs.
    7121             :  */
    7122           0 : static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
    7123             :         __isl_take isl_mat *mat)
    7124             : {
    7125             :         isl_space *space;
    7126             :         unsigned nparam;
    7127             : 
    7128           0 :         if (!set || !mat)
    7129             :                 goto error;
    7130             : 
    7131           0 :         nparam = isl_set_dim(set, isl_dim_param);
    7132             : 
    7133           0 :         if (mat->n_row != 1 + nparam)
    7134           0 :                 isl_die(isl_set_get_ctx(set), isl_error_internal,
    7135             :                         "unexpected number of rows", goto error);
    7136             : 
    7137           0 :         space = isl_set_get_space(set);
    7138           0 :         space = isl_space_move_dims(space, isl_dim_set, 0,
    7139             :                                     isl_dim_param, 0, nparam);
    7140           0 :         set = isl_set_reset_space(set, space);
    7141           0 :         set = isl_set_preimage(set, mat);
    7142           0 :         nparam = isl_set_dim(set, isl_dim_out);
    7143           0 :         space = isl_set_get_space(set);
    7144           0 :         space = isl_space_move_dims(space, isl_dim_param, 0,
    7145             :                                     isl_dim_out, 0, nparam);
    7146           0 :         set = isl_set_reset_space(set, space);
    7147           0 :         return set;
    7148             : error:
    7149           0 :         isl_mat_free(mat);
    7150           0 :         isl_set_free(set);
    7151           0 :         return NULL;
    7152             : }
    7153             : 
    7154             : /* Intersect the basic set "bset" with the affine space specified by the
    7155             :  * equalities in "eq".
    7156             :  */
    7157           0 : static __isl_give isl_basic_set *basic_set_append_equalities(
    7158             :         __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
    7159             : {
    7160             :         int i, k;
    7161             :         unsigned len;
    7162             : 
    7163           0 :         if (!bset || !eq)
    7164             :                 goto error;
    7165             : 
    7166           0 :         bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
    7167             :                                         eq->n_row, 0);
    7168           0 :         if (!bset)
    7169           0 :                 goto error;
    7170             : 
    7171           0 :         len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
    7172           0 :         for (i = 0; i < eq->n_row; ++i) {
    7173           0 :                 k = isl_basic_set_alloc_equality(bset);
    7174           0 :                 if (k < 0)
    7175           0 :                         goto error;
    7176           0 :                 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
    7177           0 :                 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
    7178             :         }
    7179           0 :         isl_mat_free(eq);
    7180             : 
    7181           0 :         bset = isl_basic_set_gauss(bset, NULL);
    7182           0 :         bset = isl_basic_set_finalize(bset);
    7183             : 
    7184           0 :         return bset;
    7185             : error:
    7186           0 :         isl_mat_free(eq);
    7187           0 :         isl_basic_set_free(bset);
    7188           0 :         return NULL;
    7189             : }
    7190             : 
    7191             : /* Intersect the set "set" with the affine space specified by the
    7192             :  * equalities in "eq".
    7193             :  */
    7194           0 : static struct isl_set *set_append_equalities(struct isl_set *set,
    7195             :         struct isl_mat *eq)
    7196             : {
    7197             :         int i;
    7198             : 
    7199           0 :         if (!set || !eq)
    7200             :                 goto error;
    7201             : 
    7202           0 :         for (i = 0; i < set->n; ++i) {
    7203           0 :                 set->p[i] = basic_set_append_equalities(set->p[i],
    7204             :                                         isl_mat_copy(eq));
    7205           0 :                 if (!set->p[i])
    7206           0 :                         goto error;
    7207             :         }
    7208           0 :         isl_mat_free(eq);
    7209           0 :         return set;
    7210             : error:
    7211           0 :         isl_mat_free(eq);
    7212           0 :         isl_set_free(set);
    7213           0 :         return NULL;
    7214             : }
    7215             : 
    7216             : /* Given a basic set "bset" that only involves parameters and existentially
    7217             :  * quantified variables, return the index of the first equality
    7218             :  * that only involves parameters.  If there is no such equality then
    7219             :  * return bset->n_eq.
    7220             :  *
    7221             :  * This function assumes that isl_basic_set_gauss has been called on "bset".
    7222             :  */
    7223           0 : static int first_parameter_equality(__isl_keep isl_basic_set *bset)
    7224             : {
    7225             :         int i, j;
    7226             :         unsigned nparam, n_div;
    7227             : 
    7228           0 :         if (!bset)
    7229           0 :                 return -1;
    7230             : 
    7231           0 :         nparam = isl_basic_set_dim(bset, isl_dim_param);
    7232           0 :         n_div = isl_basic_set_dim(bset, isl_dim_div);
    7233             : 
    7234           0 :         for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
    7235           0 :                 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
    7236           0 :                         ++i;
    7237             :         }
    7238             : 
    7239           0 :         return i;
    7240             : }
    7241             : 
    7242             : /* Compute an explicit representation for the existentially quantified
    7243             :  * variables in "bset" by computing the "minimal value" of the set
    7244             :  * variables.  Since there are no set variables, the computation of
    7245             :  * the minimal value essentially computes an explicit representation
    7246             :  * of the non-empty part(s) of "bset".
    7247             :  *
    7248             :  * The input only involves parameters and existentially quantified variables.
    7249             :  * All equalities among parameters have been removed.
    7250             :  *
    7251             :  * Since the existentially quantified variables in the result are in general
    7252             :  * going to be different from those in the input, we first replace
    7253             :  * them by the minimal number of variables based on their equalities.
    7254             :  * This should simplify the parametric integer programming.
    7255             :  */
    7256           0 : static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
    7257             : {
    7258             :         isl_morph *morph1, *morph2;
    7259             :         isl_set *set;
    7260             :         unsigned n;
    7261             : 
    7262           0 :         if (!bset)
    7263           0 :                 return NULL;
    7264           0 :         if (bset->n_eq == 0)
    7265           0 :                 return isl_basic_set_lexmin_compute_divs(bset);
    7266             : 
    7267           0 :         morph1 = isl_basic_set_parameter_compression(bset);
    7268           0 :         bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
    7269           0 :         bset = isl_basic_set_lift(bset);
    7270           0 :         morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
    7271           0 :         bset = isl_morph_basic_set(morph2, bset);
    7272           0 :         n = isl_basic_set_dim(bset, isl_dim_set);
    7273           0 :         bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
    7274             : 
    7275           0 :         set = isl_basic_set_lexmin_compute_divs(bset);
    7276             : 
    7277           0 :         set = isl_morph_set(isl_morph_inverse(morph1), set);
    7278             : 
    7279           0 :         return set;
    7280             : }
    7281             : 
    7282             : /* Project the given basic set onto its parameter domain, possibly introducing
    7283             :  * new, explicit, existential variables in the constraints.
    7284             :  * The input has parameters and (possibly implicit) existential variables.
    7285             :  * The output has the same parameters, but only
    7286             :  * explicit existentially quantified variables.
    7287             :  *
    7288             :  * The actual projection is performed by pip, but pip doesn't seem
    7289             :  * to like equalities very much, so we first remove the equalities
    7290             :  * among the parameters by performing a variable compression on
    7291             :  * the parameters.  Afterward, an inverse transformation is performed
    7292             :  * and the equalities among the parameters are inserted back in.
    7293             :  *
    7294             :  * The variable compression on the parameters may uncover additional
    7295             :  * equalities that were only implicit before.  We therefore check
    7296             :  * if there are any new parameter equalities in the result and
    7297             :  * if so recurse.  The removal of parameter equalities is required
    7298             :  * for the parameter compression performed by base_compute_divs.
    7299             :  */
    7300           0 : static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
    7301             : {
    7302             :         int i;
    7303             :         struct isl_mat *eq;
    7304             :         struct isl_mat *T, *T2;
    7305             :         struct isl_set *set;
    7306             :         unsigned nparam;
    7307             : 
    7308           0 :         bset = isl_basic_set_cow(bset);
    7309           0 :         if (!bset)
    7310           0 :                 return NULL;
    7311             : 
    7312           0 :         if (bset->n_eq == 0)
    7313           0 :                 return base_compute_divs(bset);
    7314             : 
    7315           0 :         bset = isl_basic_set_gauss(bset, NULL);
    7316           0 :         if (!bset)
    7317           0 :                 return NULL;
    7318           0 :         if (isl_basic_set_plain_is_empty(bset))
    7319           0 :                 return isl_set_from_basic_set(bset);
    7320             : 
    7321           0 :         i = first_parameter_equality(bset);
    7322           0 :         if (i == bset->n_eq)
    7323           0 :                 return base_compute_divs(bset);
    7324             : 
    7325           0 :         nparam = isl_basic_set_dim(bset, isl_dim_param);
    7326           0 :         eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
    7327             :                 0, 1 + nparam);
    7328           0 :         eq = isl_mat_cow(eq);
    7329           0 :         T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
    7330           0 :         if (T && T->n_col == 0) {
    7331           0 :                 isl_mat_free(T);
    7332           0 :                 isl_mat_free(T2);
    7333           0 :                 isl_mat_free(eq);
    7334           0 :                 bset = isl_basic_set_set_to_empty(bset);
    7335           0 :                 return isl_set_from_basic_set(bset);
    7336             :         }
    7337           0 :         bset = basic_set_parameter_preimage(bset, T);
    7338             : 
    7339           0 :         i = first_parameter_equality(bset);
    7340           0 :         if (!bset)
    7341           0 :                 set = NULL;
    7342           0 :         else if (i == bset->n_eq)
    7343           0 :                 set = base_compute_divs(bset);
    7344             :         else
    7345           0 :                 set = parameter_compute_divs(bset);
    7346           0 :         set = set_parameter_preimage(set, T2);
    7347           0 :         set = set_append_equalities(set, eq);
    7348           0 :         return set;
    7349             : }
    7350             : 
    7351             : /* Insert the divs from "ls" before those of "bmap".
    7352             :  *
    7353             :  * The number of columns is not changed, which means that the last
    7354             :  * dimensions of "bmap" are being reintepreted as the divs from "ls".
    7355             :  * The caller is responsible for removing the same number of dimensions
    7356             :  * from the space of "bmap".
    7357             :  */
    7358           0 : static __isl_give isl_basic_map *insert_divs_from_local_space(
    7359             :         __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
    7360             : {
    7361             :         int i;
    7362             :         int n_div;
    7363             :         int old_n_div;
    7364             : 
    7365           0 :         n_div = isl_local_space_dim(ls, isl_dim_div);
    7366           0 :         if (n_div == 0)
    7367           0 :                 return bmap;
    7368             : 
    7369           0 :         old_n_div = bmap->n_div;
    7370           0 :         bmap = insert_div_rows(bmap, n_div);
    7371           0 :         if (!bmap)
    7372           0 :                 return NULL;
    7373             : 
    7374           0 :         for (i = 0; i < n_div; ++i) {
    7375           0 :                 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
    7376           0 :                 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
    7377             :         }
    7378             : 
    7379           0 :         return bmap;
    7380             : }
    7381             : 
    7382             : /* Replace the space of "bmap" by the space and divs of "ls".
    7383             :  *
    7384             :  * If "ls" has any divs, then we simplify the result since we may
    7385             :  * have discovered some additional equalities that could simplify
    7386             :  * the div expressions.
    7387             :  */
    7388           0 : static __isl_give isl_basic_map *basic_replace_space_by_local_space(
    7389             :         __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
    7390             : {
    7391             :         int n_div;
    7392             : 
    7393           0 :         bmap = isl_basic_map_cow(bmap);
    7394           0 :         if (!bmap || !ls)
    7395             :                 goto error;
    7396             : 
    7397           0 :         n_div = isl_local_space_dim(ls, isl_dim_div);
    7398           0 :         bmap = insert_divs_from_local_space(bmap, ls);
    7399           0 :         if (!bmap)
    7400           0 :                 goto error;
    7401             : 
    7402           0 :         isl_space_free(bmap->dim);
    7403           0 :         bmap->dim = isl_local_space_get_space(ls);
    7404           0 :         if (!bmap->dim)
    7405           0 :                 goto error;
    7406             : 
    7407           0 :         isl_local_space_free(ls);
    7408           0 :         if (n_div > 0)
    7409           0 :                 bmap = isl_basic_map_simplify(bmap);
    7410           0 :         bmap = isl_basic_map_finalize(bmap);
    7411           0 :         return bmap;
    7412             : error:
    7413           0 :         isl_basic_map_free(bmap);
    7414           0 :         isl_local_space_free(ls);
    7415           0 :         return NULL;
    7416             : }
    7417             : 
    7418             : /* Replace the space of "map" by the space and divs of "ls".
    7419             :  */
    7420           0 : static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
    7421             :         __isl_take isl_local_space *ls)
    7422             : {
    7423             :         int i;
    7424             : 
    7425           0 :         map = isl_map_cow(map);
    7426           0 :         if (!map || !ls)
    7427             :                 goto error;
    7428             : 
    7429           0 :         for (i = 0; i < map->n; ++i) {
    7430           0 :                 map->p[i] = basic_replace_space_by_local_space(map->p[i],
    7431             :                                                     isl_local_space_copy(ls));
    7432           0 :                 if (!map->p[i])
    7433           0 :                         goto error;
    7434             :         }
    7435           0 :         isl_space_free(map->dim);
    7436           0 :         map->dim = isl_local_space_get_space(ls);
    7437           0 :         if (!map->dim)
    7438           0 :                 goto error;
    7439             : 
    7440           0 :         isl_local_space_free(ls);
    7441           0 :         return map;
    7442             : error:
    7443           0 :         isl_local_space_free(ls);
    7444           0 :         isl_map_free(map);
    7445           0 :         return NULL;
    7446             : }
    7447             : 
    7448             : /* Compute an explicit representation for the existentially
    7449             :  * quantified variables for which do not know any explicit representation yet.
    7450             :  *
    7451             :  * We first sort the existentially quantified variables so that the
    7452             :  * existentially quantified variables for which we already have an explicit
    7453             :  * representation are placed before those for which we do not.
    7454             :  * The input dimensions, the output dimensions and the existentially
    7455             :  * quantified variables for which we already have an explicit
    7456             :  * representation are then turned into parameters.
    7457             :  * compute_divs returns a map with the same parameters and
    7458             :  * no input or output dimensions and the dimension specification
    7459             :  * is reset to that of the input, including the existentially quantified
    7460             :  * variables for which we already had an explicit representation.
    7461             :  */
    7462           0 : static struct isl_map *compute_divs(struct isl_basic_map *bmap)
    7463             : {
    7464             :         struct isl_basic_set *bset;
    7465             :         struct isl_set *set;
    7466             :         struct isl_map *map;
    7467             :         isl_space *dim;
    7468             :         isl_local_space *ls;
    7469             :         unsigned         nparam;
    7470             :         unsigned         n_in;
    7471             :         unsigned         n_out;
    7472             :         int n_known;
    7473             :         int i;
    7474             : 
    7475           0 :         bmap = isl_basic_map_sort_divs(bmap);
    7476           0 :         bmap = isl_basic_map_cow(bmap);
    7477           0 :         if (!bmap)
    7478           0 :                 return NULL;
    7479             : 
    7480           0 :         n_known = isl_basic_map_first_unknown_div(bmap);
    7481           0 :         if (n_known < 0)
    7482           0 :                 return isl_map_from_basic_map(isl_basic_map_free(bmap));
    7483             : 
    7484           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    7485           0 :         n_in = isl_basic_map_dim(bmap, isl_dim_in);
    7486           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
    7487           0 :         dim = isl_space_set_alloc(bmap->ctx,
    7488           0 :                                     nparam + n_in + n_out + n_known, 0);
    7489           0 :         if (!dim)
    7490           0 :                 goto error;
    7491             : 
    7492           0 :         ls = isl_basic_map_get_local_space(bmap);
    7493           0 :         ls = isl_local_space_drop_dims(ls, isl_dim_div,
    7494           0 :                                         n_known, bmap->n_div - n_known);
    7495           0 :         if (n_known > 0) {
    7496           0 :                 for (i = n_known; i < bmap->n_div; ++i)
    7497           0 :                         swap_div(bmap, i - n_known, i);
    7498           0 :                 bmap->n_div -= n_known;
    7499           0 :                 bmap->extra -= n_known;
    7500             :         }
    7501           0 :         bmap = isl_basic_map_reset_space(bmap, dim);
    7502           0 :         bset = bset_from_bmap(bmap);
    7503             : 
    7504           0 :         set = parameter_compute_divs(bset);
    7505           0 :         map = set_to_map(set);
    7506           0 :         map = replace_space_by_local_space(map, ls);
    7507             : 
    7508           0 :         return map;
    7509             : error:
    7510           0 :         isl_basic_map_free(bmap);
    7511           0 :         return NULL;
    7512             : }
    7513             : 
    7514             : /* Remove the explicit representation of local variable "div",
    7515             :  * if there is any.
    7516             :  */
    7517           0 : __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
    7518             :         __isl_take isl_basic_map *bmap, int div)
    7519             : {
    7520             :         isl_bool unknown;
    7521             : 
    7522           0 :         unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
    7523           0 :         if (unknown < 0)
    7524           0 :                 return isl_basic_map_free(bmap);
    7525           0 :         if (unknown)
    7526           0 :                 return bmap;
    7527             : 
    7528           0 :         bmap = isl_basic_map_cow(bmap);
    7529           0 :         if (!bmap)
    7530           0 :                 return NULL;
    7531           0 :         isl_int_set_si(bmap->div[div][0], 0);
    7532           0 :         return bmap;
    7533             : }
    7534             : 
    7535             : /* Is local variable "div" of "bmap" marked as not having an explicit
    7536             :  * representation?
    7537             :  * Note that even if "div" is not marked in this way and therefore
    7538             :  * has an explicit representation, this representation may still
    7539             :  * depend (indirectly) on other local variables that do not
    7540             :  * have an explicit representation.
    7541             :  */
    7542           0 : isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
    7543             :         int div)
    7544             : {
    7545           0 :         if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
    7546           0 :                 return isl_bool_error;
    7547           0 :         return isl_int_is_zero(bmap->div[div][0]);
    7548             : }
    7549             : 
    7550             : /* Return the position of the first local variable that does not
    7551             :  * have an explicit representation.
    7552             :  * Return the total number of local variables if they all have
    7553             :  * an explicit representation.
    7554             :  * Return -1 on error.
    7555             :  */
    7556  4588052277 : int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
    7557             : {
    7558             :         int i;
    7559             : 
    7560  4588052277 :         if (!bmap)
    7561           0 :                 return -1;
    7562             : 
    7563  4588052277 :         for (i = 0; i < bmap->n_div; ++i) {
    7564           0 :                 if (!isl_basic_map_div_is_known(bmap, i))
    7565           0 :                         return i;
    7566             :         }
    7567  4588052277 :         return bmap->n_div;
    7568             : }
    7569             : 
    7570             : /* Return the position of the first local variable that does not
    7571             :  * have an explicit representation.
    7572             :  * Return the total number of local variables if they all have
    7573             :  * an explicit representation.
    7574             :  * Return -1 on error.
    7575             :  */
    7576           0 : int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
    7577             : {
    7578           0 :         return isl_basic_map_first_unknown_div(bset);
    7579             : }
    7580             : 
    7581             : /* Does "bmap" have an explicit representation for all local variables?
    7582             :  */
    7583  4588052277 : isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
    7584             : {
    7585             :         int first, n;
    7586             : 
    7587  4588052277 :         n = isl_basic_map_dim(bmap, isl_dim_div);
    7588  4588052277 :         first = isl_basic_map_first_unknown_div(bmap);
    7589  4588052277 :         if (first < 0)
    7590           0 :                 return isl_bool_error;
    7591  4588052277 :         return first == n;
    7592             : }
    7593             : 
    7594             : /* Do all basic maps in "map" have an explicit representation
    7595             :  * for all local variables?
    7596             :  */
    7597   650525751 : isl_bool isl_map_divs_known(__isl_keep isl_map *map)
    7598             : {
    7599             :         int i;
    7600             : 
    7601   650525751 :         if (!map)
    7602           0 :                 return isl_bool_error;
    7603             : 
    7604  1877974205 :         for (i = 0; i < map->n; ++i) {
    7605  1227448454 :                 int known = isl_basic_map_divs_known(map->p[i]);
    7606  1227448454 :                 if (known <= 0)
    7607           0 :                         return known;
    7608             :         }
    7609             : 
    7610   650525751 :         return isl_bool_true;
    7611             : }
    7612             : 
    7613             : /* If bmap contains any unknown divs, then compute explicit
    7614             :  * expressions for them.  However, this computation may be
    7615             :  * quite expensive, so first try to remove divs that aren't
    7616             :  * strictly needed.
    7617             :  */
    7618           0 : __isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
    7619             : {
    7620             :         int known;
    7621             :         struct isl_map *map;
    7622             : 
    7623           0 :         known = isl_basic_map_divs_known(bmap);
    7624           0 :         if (known < 0)
    7625           0 :                 goto error;
    7626           0 :         if (known)
    7627           0 :                 return isl_map_from_basic_map(bmap);
    7628             : 
    7629           0 :         bmap = isl_basic_map_drop_redundant_divs(bmap);
    7630             : 
    7631           0 :         known = isl_basic_map_divs_known(bmap);
    7632           0 :         if (known < 0)
    7633           0 :                 goto error;
    7634           0 :         if (known)
    7635           0 :                 return isl_map_from_basic_map(bmap);
    7636             : 
    7637           0 :         map = compute_divs(bmap);
    7638           0 :         return map;
    7639             : error:
    7640           0 :         isl_basic_map_free(bmap);
    7641           0 :         return NULL;
    7642             : }
    7643             : 
    7644   650525751 : __isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
    7645             : {
    7646             :         int i;
    7647             :         int known;
    7648             :         struct isl_map *res;
    7649             : 
    7650   650525751 :         if (!map)
    7651           0 :                 return NULL;
    7652   650525751 :         if (map->n == 0)
    7653           0 :                 return map;
    7654             : 
    7655   650525751 :         known = isl_map_divs_known(map);
    7656   650525751 :         if (known < 0) {
    7657           0 :                 isl_map_free(map);
    7658           0 :                 return NULL;
    7659             :         }
    7660   650525751 :         if (known)
    7661   650525751 :                 return map;
    7662             : 
    7663           0 :         res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
    7664           0 :         for (i = 1 ; i < map->n; ++i) {
    7665             :                 struct isl_map *r2;
    7666           0 :                 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
    7667           0 :                 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
    7668           0 :                         res = isl_map_union_disjoint(res, r2);
    7669             :                 else
    7670           0 :                         res = isl_map_union(res, r2);
    7671             :         }
    7672           0 :         isl_map_free(map);
    7673             : 
    7674           0 :         return res;
    7675             : }
    7676             : 
    7677           0 : __isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
    7678             : {
    7679           0 :         return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
    7680             : }
    7681             : 
    7682           0 : struct isl_set *isl_set_compute_divs(struct isl_set *set)
    7683             : {
    7684           0 :         return set_from_map(isl_map_compute_divs(set_to_map(set)));
    7685             : }
    7686             : 
    7687           0 : __isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
    7688             : {
    7689             :         int i;
    7690             :         struct isl_set *set;
    7691             : 
    7692           0 :         if (!map)
    7693           0 :                 goto error;
    7694             : 
    7695           0 :         map = isl_map_cow(map);
    7696           0 :         if (!map)
    7697           0 :                 return NULL;
    7698             : 
    7699           0 :         set = set_from_map(map);
    7700           0 :         set->dim = isl_space_domain(set->dim);
    7701           0 :         if (!set->dim)
    7702           0 :                 goto error;
    7703           0 :         for (i = 0; i < map->n; ++i) {
    7704           0 :                 set->p[i] = isl_basic_map_domain(map->p[i]);
    7705           0 :                 if (!set->p[i])
    7706           0 :                         goto error;
    7707             :         }
    7708           0 :         ISL_F_CLR(set, ISL_MAP_DISJOINT);
    7709           0 :         ISL_F_CLR(set, ISL_SET_NORMALIZED);
    7710           0 :         return set;
    7711             : error:
    7712           0 :         isl_map_free(map);
    7713           0 :         return NULL;
    7714             : }
    7715             : 
    7716             : /* Return the union of "map1" and "map2", where we assume for now that
    7717             :  * "map1" and "map2" are disjoint.  Note that the basic maps inside
    7718             :  * "map1" or "map2" may not be disjoint from each other.
    7719             :  * Also note that this function is also called from isl_map_union,
    7720             :  * which takes care of handling the situation where "map1" and "map2"
    7721             :  * may not be disjoint.
    7722             :  *
    7723             :  * If one of the inputs is empty, we can simply return the other input.
    7724             :  * Similarly, if one of the inputs is universal, then it is equal to the union.
    7725             :  */
    7726    47714600 : static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
    7727             :         __isl_take isl_map *map2)
    7728             : {
    7729             :         int i;
    7730    47714600 :         unsigned flags = 0;
    7731    47714600 :         struct isl_map *map = NULL;
    7732             :         int is_universe;
    7733             : 
    7734    47714600 :         if (!map1 || !map2)
    7735             :                 goto error;
    7736             : 
    7737    47714600 :         if (!isl_space_is_equal(map1->dim, map2->dim))
    7738           0 :                 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
    7739             :                         "spaces don't match", goto error);
    7740             : 
    7741    47714600 :         if (map1->n == 0) {
    7742     7870890 :                 isl_map_free(map1);
    7743     7870890 :                 return map2;
    7744             :         }
    7745    39843710 :         if (map2->n == 0) {
    7746      662968 :                 isl_map_free(map2);
    7747      662968 :                 return map1;
    7748             :         }
    7749             : 
    7750    39180742 :         is_universe = isl_map_plain_is_universe(map1);
    7751    39180742 :         if (is_universe < 0)
    7752           0 :                 goto error;
    7753    39180742 :         if (is_universe) {
    7754       80471 :                 isl_map_free(map2);
    7755       80471 :                 return map1;
    7756             :         }
    7757             : 
    7758    39100271 :         is_universe = isl_map_plain_is_universe(map2);
    7759    39100271 :         if (is_universe < 0)
    7760           0 :                 goto error;
    7761    39100271 :         if (is_universe) {
    7762      106763 :                 isl_map_free(map1);
    7763      106763 :                 return map2;
    7764             :         }
    7765             : 
    7766    73780174 :         if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
    7767    34786666 :             ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
    7768    34557533 :                 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
    7769             : 
    7770    38993508 :         map = isl_map_alloc_space(isl_space_copy(map1->dim),
    7771    38993508 :                                 map1->n + map2->n, flags);
    7772    38993508 :         if (!map)
    7773           0 :                 goto error;
    7774  1183790987 :         for (i = 0; i < map1->n; ++i) {
    7775  1144797479 :                 map = isl_map_add_basic_map(map,
    7776  1144797479 :                                   isl_basic_map_copy(map1->p[i]));
    7777  1144797479 :                 if (!map)
    7778           0 :                         goto error;
    7779             :         }
    7780    89291724 :         for (i = 0; i < map2->n; ++i) {
    7781    50298216 :                 map = isl_map_add_basic_map(map,
    7782    50298216 :                                   isl_basic_map_copy(map2->p[i]));
    7783    50298216 :                 if (!map)
    7784           0 :                         goto error;
    7785             :         }
    7786    38993508 :         isl_map_free(map1);
    7787    38993508 :         isl_map_free(map2);
    7788    38993508 :         return map;
    7789             : error:
    7790           0 :         isl_map_free(map);
    7791           0 :         isl_map_free(map1);
    7792           0 :         isl_map_free(map2);
    7793           0 :         return NULL;
    7794             : }
    7795             : 
    7796             : /* Return the union of "map1" and "map2", where "map1" and "map2" are
    7797             :  * guaranteed to be disjoint by the caller.
    7798             :  *
    7799             :  * Note that this functions is called from within isl_map_make_disjoint,
    7800             :  * so we have to be careful not to touch the constraints of the inputs
    7801             :  * in any way.
    7802             :  */
    7803    40752044 : __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
    7804             :         __isl_take isl_map *map2)
    7805             : {
    7806    40752044 :         return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
    7807             : }
    7808             : 
    7809             : /* Return the union of "map1" and "map2", where "map1" and "map2" may
    7810             :  * not be disjoint.  The parameters are assumed to have been aligned.
    7811             :  *
    7812             :  * We currently simply call map_union_disjoint, the internal operation
    7813             :  * of which does not really depend on the inputs being disjoint.
    7814             :  * If the result contains more than one basic map, then we clear
    7815             :  * the disjoint flag since the result may contain basic maps from
    7816             :  * both inputs and these are not guaranteed to be disjoint.
    7817             :  *
    7818             :  * As a special case, if "map1" and "map2" are obviously equal,
    7819             :  * then we simply return "map1".
    7820             :  */
    7821     8119776 : static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
    7822             :         __isl_take isl_map *map2)
    7823             : {
    7824             :         int equal;
    7825             : 
    7826     8119776 :         if (!map1 || !map2)
    7827             :                 goto error;
    7828             : 
    7829     8119776 :         equal = isl_map_plain_is_equal(map1, map2);
    7830     8119776 :         if (equal < 0)
    7831           0 :                 goto error;
    7832     8119776 :         if (equal) {
    7833     1157220 :                 isl_map_free(map2);
    7834     1157220 :                 return map1;
    7835             :         }
    7836             : 
    7837     6962556 :         map1 = map_union_disjoint(map1, map2);
    7838     6962556 :         if (!map1)
    7839           0 :                 return NULL;
    7840     6962556 :         if (map1->n > 1)
    7841     6041431 :                 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
    7842     6962556 :         return map1;
    7843             : error:
    7844           0 :         isl_map_free(map1);
    7845           0 :         isl_map_free(map2);
    7846           0 :         return NULL;
    7847             : }
    7848             : 
    7849             : /* Return the union of "map1" and "map2", where "map1" and "map2" may
    7850             :  * not be disjoint.
    7851             :  */
    7852     8119776 : __isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
    7853             :         __isl_take isl_map *map2)
    7854             : {
    7855     8119776 :         return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
    7856             : }
    7857             : 
    7858           0 : __isl_give isl_set *isl_set_union_disjoint(
    7859             :         __isl_take isl_set *set1, __isl_take isl_set *set2)
    7860             : {
    7861           0 :         return set_from_map(isl_map_union_disjoint(set_to_map(set1),
    7862             :                                                     set_to_map(set2)));
    7863             : }
    7864             : 
    7865     3728909 : struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
    7866             : {
    7867     3728909 :         return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
    7868             : }
    7869             : 
    7870             : /* Apply "fn" to pairs of elements from "map" and "set" and collect
    7871             :  * the results.
    7872             :  *
    7873             :  * "map" and "set" are assumed to be compatible and non-NULL.
    7874             :  */
    7875           0 : static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
    7876             :         __isl_take isl_set *set,
    7877             :         __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
    7878             :                 __isl_take isl_basic_set *bset))
    7879             : {
    7880           0 :         unsigned flags = 0;
    7881             :         struct isl_map *result;
    7882             :         int i, j;
    7883             : 
    7884           0 :         if (isl_set_plain_is_universe(set)) {
    7885           0 :                 isl_set_free(set);
    7886           0 :                 return map;
    7887             :         }
    7888             : 
    7889           0 :         if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
    7890           0 :             ISL_F_ISSET(set, ISL_MAP_DISJOINT))
    7891           0 :                 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
    7892             : 
    7893           0 :         result = isl_map_alloc_space(isl_space_copy(map->dim),
    7894           0 :                                         map->n * set->n, flags);
    7895           0 :         for (i = 0; result && i < map->n; ++i)
    7896           0 :                 for (j = 0; j < set->n; ++j) {
    7897           0 :                         result = isl_map_add_basic_map(result,
    7898           0 :                                         fn(isl_basic_map_copy(map->p[i]),
    7899           0 :                                             isl_basic_set_copy(set->p[j])));
    7900           0 :                         if (!result)
    7901           0 :                                 break;
    7902             :                 }
    7903             : 
    7904           0 :         isl_map_free(map);
    7905           0 :         isl_set_free(set);
    7906           0 :         return result;
    7907             : }
    7908             : 
    7909           0 : static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
    7910             :         __isl_take isl_set *set)
    7911             : {
    7912             :         isl_bool ok;
    7913             : 
    7914           0 :         ok = isl_map_compatible_range(map, set);
    7915           0 :         if (ok < 0)
    7916           0 :                 goto error;
    7917           0 :         if (!ok)
    7918           0 :                 isl_die(set->ctx, isl_error_invalid,
    7919             :                         "incompatible spaces", goto error);
    7920             : 
    7921           0 :         return map_intersect_set(map, set, &isl_basic_map_intersect_range);
    7922             : error:
    7923           0 :         isl_map_free(map);
    7924           0 :         isl_set_free(set);
    7925           0 :         return NULL;
    7926             : }
    7927             : 
    7928           0 : __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
    7929             :         __isl_take isl_set *set)
    7930             : {
    7931           0 :         return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
    7932             : }
    7933             : 
    7934           0 : static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
    7935             :         __isl_take isl_set *set)
    7936             : {
    7937             :         isl_bool ok;
    7938             : 
    7939           0 :         ok = isl_map_compatible_domain(map, set);
    7940           0 :         if (ok < 0)
    7941           0 :                 goto error;
    7942           0 :         if (!ok)
    7943           0 :                 isl_die(set->ctx, isl_error_invalid,
    7944             :                         "incompatible spaces", goto error);
    7945             : 
    7946           0 :         return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
    7947             : error:
    7948           0 :         isl_map_free(map);
    7949           0 :         isl_set_free(set);
    7950           0 :         return NULL;
    7951             : }
    7952             : 
    7953           0 : __isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
    7954             :         __isl_take isl_set *set)
    7955             : {
    7956           0 :         return isl_map_align_params_map_map_and(map, set,
    7957             :                                                 &map_intersect_domain);
    7958             : }
    7959             : 
    7960             : /* Given a map "map" in a space [A -> B] -> C and a map "factor"
    7961             :  * in the space B -> C, return the intersection.
    7962             :  * The parameters are assumed to have been aligned.
    7963             :  *
    7964             :  * The map "factor" is first extended to a map living in the space
    7965             :  * [A -> B] -> C and then a regular intersection is computed.
    7966             :  */
    7967           0 : static __isl_give isl_map *map_intersect_domain_factor_range(
    7968             :         __isl_take isl_map *map, __isl_take isl_map *factor)
    7969             : {
    7970             :         isl_space *space;
    7971             :         isl_map *ext_factor;
    7972             : 
    7973           0 :         space = isl_space_domain_factor_domain(isl_map_get_space(map));
    7974           0 :         ext_factor = isl_map_universe(space);
    7975           0 :         ext_factor = isl_map_domain_product(ext_factor, factor);
    7976           0 :         return map_intersect(map, ext_factor);
    7977             : }
    7978             : 
    7979             : /* Given a map "map" in a space [A -> B] -> C and a map "factor"
    7980             :  * in the space B -> C, return the intersection.
    7981             :  */
    7982           0 : __isl_give isl_map *isl_map_intersect_domain_factor_range(
    7983             :         __isl_take isl_map *map, __isl_take isl_map *factor)
    7984             : {
    7985           0 :         return isl_map_align_params_map_map_and(map, factor,
    7986             :                                             &map_intersect_domain_factor_range);
    7987             : }
    7988             : 
    7989             : /* Given a map "map" in a space A -> [B -> C] and a map "factor"
    7990             :  * in the space A -> C, return the intersection.
    7991             :  *
    7992             :  * The map "factor" is first extended to a map living in the space
    7993             :  * A -> [B -> C] and then a regular intersection is computed.
    7994             :  */
    7995           0 : static __isl_give isl_map *map_intersect_range_factor_range(
    7996             :         __isl_take isl_map *map, __isl_take isl_map *factor)
    7997             : {
    7998             :         isl_space *space;
    7999             :         isl_map *ext_factor;
    8000             : 
    8001           0 :         space = isl_space_range_factor_domain(isl_map_get_space(map));
    8002           0 :         ext_factor = isl_map_universe(space);
    8003           0 :         ext_factor = isl_map_range_product(ext_factor, factor);
    8004           0 :         return isl_map_intersect(map, ext_factor);
    8005             : }
    8006             : 
    8007             : /* Given a map "map" in a space A -> [B -> C] and a map "factor"
    8008             :  * in the space A -> C, return the intersection.
    8009             :  */
    8010           0 : __isl_give isl_map *isl_map_intersect_range_factor_range(
    8011             :         __isl_take isl_map *map, __isl_take isl_map *factor)
    8012             : {
    8013           0 :         return isl_map_align_params_map_map_and(map, factor,
    8014             :                                             &map_intersect_range_factor_range);
    8015             : }
    8016             : 
    8017           0 : static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
    8018             :         __isl_take isl_map *map2)
    8019             : {
    8020           0 :         if (!map1 || !map2)
    8021             :                 goto error;
    8022           0 :         map1 = isl_map_reverse(map1);
    8023           0 :         map1 = isl_map_apply_range(map1, map2);
    8024           0 :         return isl_map_reverse(map1);
    8025             : error:
    8026           0 :         isl_map_free(map1);
    8027           0 :         isl_map_free(map2);
    8028           0 :         return NULL;
    8029             : }
    8030             : 
    8031           0 : __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
    8032             :         __isl_take isl_map *map2)
    8033             : {
    8034           0 :         return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
    8035             : }
    8036             : 
    8037           0 : static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
    8038             :         __isl_take isl_map *map2)
    8039             : {
    8040             :         isl_space *dim_result;
    8041             :         struct isl_map *result;
    8042             :         int i, j;
    8043             : 
    8044           0 :         if (!map1 || !map2)
    8045             :                 goto error;
    8046             : 
    8047           0 :         dim_result = isl_space_join(isl_space_copy(map1->dim),
    8048             :                                   isl_space_copy(map2->dim));
    8049             : 
    8050           0 :         result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
    8051           0 :         if (!result)
    8052           0 :                 goto error;
    8053           0 :         for (i = 0; i < map1->n; ++i)
    8054           0 :                 for (j = 0; j < map2->n; ++j) {
    8055           0 :                         result = isl_map_add_basic_map(result,
    8056             :                             isl_basic_map_apply_range(
    8057           0 :                                 isl_basic_map_copy(map1->p[i]),
    8058           0 :                                 isl_basic_map_copy(map2->p[j])));
    8059           0 :                         if (!result)
    8060           0 :                                 goto error;
    8061             :                 }
    8062           0 :         isl_map_free(map1);
    8063           0 :         isl_map_free(map2);
    8064           0 :         if (result && result->n <= 1)
    8065           0 :                 ISL_F_SET(result, ISL_MAP_DISJOINT);
    8066           0 :         return result;
    8067             : error:
    8068           0 :         isl_map_free(map1);
    8069           0 :         isl_map_free(map2);
    8070           0 :         return NULL;
    8071             : }
    8072             : 
    8073           0 : __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
    8074             :         __isl_take isl_map *map2)
    8075             : {
    8076           0 :         return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
    8077             : }
    8078             : 
    8079             : /*
    8080             :  * returns range - domain
    8081             :  */
    8082           0 : __isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
    8083             : {
    8084             :         isl_space *target_space;
    8085             :         struct isl_basic_set *bset;
    8086             :         unsigned dim;
    8087             :         unsigned nparam;
    8088             :         int i;
    8089             : 
    8090           0 :         if (!bmap)
    8091           0 :                 goto error;
    8092           0 :         isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
    8093             :                                                   bmap->dim, isl_dim_out),
    8094             :                    goto error);
    8095           0 :         target_space = isl_space_domain(isl_basic_map_get_space(bmap));
    8096           0 :         dim = isl_basic_map_dim(bmap, isl_dim_in);
    8097           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    8098           0 :         bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
    8099           0 :         bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
    8100           0 :         bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
    8101           0 :         for (i = 0; i < dim; ++i) {
    8102           0 :                 int j = isl_basic_map_alloc_equality(bmap);
    8103           0 :                 if (j < 0) {
    8104           0 :                         bmap = isl_basic_map_free(bmap);
    8105           0 :                         break;
    8106             :                 }
    8107           0 :                 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
    8108           0 :                 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
    8109           0 :                 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
    8110           0 :                 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
    8111             :         }
    8112           0 :         bset = isl_basic_map_domain(bmap);
    8113           0 :         bset = isl_basic_set_reset_space(bset, target_space);
    8114           0 :         return bset;
    8115             : error:
    8116           0 :         isl_basic_map_free(bmap);
    8117           0 :         return NULL;
    8118             : }
    8119             : 
    8120             : /*
    8121             :  * returns range - domain
    8122             :  */
    8123           0 : __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
    8124             : {
    8125             :         int i;
    8126             :         isl_space *dim;
    8127             :         struct isl_set *result;
    8128             : 
    8129           0 :         if (!map)
    8130           0 :                 return NULL;
    8131             : 
    8132           0 :         isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
    8133             :                                                  map->dim, isl_dim_out),
    8134             :                    goto error);
    8135           0 :         dim = isl_map_get_space(map);
    8136           0 :         dim = isl_space_domain(dim);
    8137           0 :         result = isl_set_alloc_space(dim, map->n, 0);
    8138           0 :         if (!result)
    8139           0 :                 goto error;
    8140           0 :         for (i = 0; i < map->n; ++i)
    8141           0 :                 result = isl_set_add_basic_set(result,
    8142           0 :                           isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
    8143           0 :         isl_map_free(map);
    8144           0 :         return result;
    8145             : error:
    8146           0 :         isl_map_free(map);
    8147           0 :         return NULL;
    8148             : }
    8149             : 
    8150             : /*
    8151             :  * returns [domain -> range] -> range - domain
    8152             :  */
    8153           0 : __isl_give isl_basic_map *isl_basic_map_deltas_map(
    8154             :         __isl_take isl_basic_map *bmap)
    8155             : {
    8156             :         int i, k;
    8157             :         isl_space *dim;
    8158             :         isl_basic_map *domain;
    8159             :         int nparam, n;
    8160             :         unsigned total;
    8161             : 
    8162           0 :         if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
    8163             :                                         bmap->dim, isl_dim_out))
    8164           0 :                 isl_die(bmap->ctx, isl_error_invalid,
    8165             :                         "domain and range don't match", goto error);
    8166             : 
    8167           0 :         nparam = isl_basic_map_dim(bmap, isl_dim_param);
    8168           0 :         n = isl_basic_map_dim(bmap, isl_dim_in);
    8169             : 
    8170           0 :         dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
    8171           0 :         domain = isl_basic_map_universe(dim);
    8172             : 
    8173           0 :         bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
    8174           0 :         bmap = isl_basic_map_apply_range(bmap, domain);
    8175           0 :         bmap = isl_basic_map_extend_constraints(bmap, n, 0);
    8176             : 
    8177           0 :         total = isl_basic_map_total_dim(bmap);
    8178             : 
    8179           0 :         for (i = 0; i < n; ++i) {
    8180           0 :                 k = isl_basic_map_alloc_equality(bmap);
    8181           0 :                 if (k < 0)
    8182           0 :                         goto error;
    8183           0 :                 isl_seq_clr(bmap->eq[k], 1 + total);
    8184           0 :                 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
    8185           0 :                 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
    8186           0 :                 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
    8187             :         }
    8188             : 
    8189           0 :         bmap = isl_basic_map_gauss(bmap, NULL);
    8190           0 :         return isl_basic_map_finalize(bmap);
    8191             : error:
    8192           0 :         isl_basic_map_free(bmap);
    8193           0 :         return NULL;
    8194             : }
    8195             : 
    8196             : /*
    8197             :  * returns [domain -> range] -> range - domain
    8198             :  */
    8199           0 : __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
    8200             : {
    8201             :         int i;
    8202             :         isl_space *domain_dim;
    8203             : 
    8204           0 :         if (!map)
    8205           0 :                 return NULL;
    8206             : 
    8207           0 :         if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
    8208             :                                         map->dim, isl_dim_out))
    8209           0 :                 isl_die(map->ctx, isl_error_invalid,
    8210             :                         "domain and range don't match", goto error);
    8211             : 
    8212           0 :         map = isl_map_cow(map);
    8213           0 :         if (!map)
    8214           0 :                 return NULL;
    8215             : 
    8216           0 :         domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
    8217           0 :         map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
    8218           0 :         map->dim = isl_space_join(map->dim, domain_dim);
    8219           0 :         if (!map->dim)
    8220           0 :                 goto error;
    8221           0 :         for (i = 0; i < map->n; ++i) {
    8222           0 :                 map->p[i] = isl_basic_map_deltas_map(map->p[i]);
    8223           0 :                 if (!map->p[i])
    8224           0 :                         goto error;
    8225             :         }
    8226           0 :         map = isl_map_unmark_normalized(map);
    8227           0 :         return map;
    8228             : error:
    8229           0 :         isl_map_free(map);
    8230           0 :         return NULL;
    8231             : }
    8232             : 
    8233           0 : static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
    8234             : {
    8235             :         struct isl_basic_map *bmap;
    8236             :         unsigned nparam;
    8237             :         unsigned dim;
    8238             :         int i;
    8239             : 
    8240           0 :         if (!dims)
    8241           0 :                 return NULL;
    8242             : 
    8243           0 :         nparam = dims->nparam;
    8244           0 :         dim = dims->n_out;
    8245           0 :         bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
    8246           0 :         if (!bmap)
    8247           0 :                 goto error;
    8248             : 
    8249           0 :         for (i = 0; i < dim; ++i) {
    8250           0 :                 int j = isl_basic_map_alloc_equality(bmap);
    8251           0 :                 if (j < 0)
    8252           0 :                         goto error;
    8253           0 :                 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
    8254           0 :                 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
    8255           0 :                 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
    8256             :         }
    8257           0 :         return isl_basic_map_finalize(bmap);
    8258             : error:
    8259           0 :         isl_basic_map_free(bmap);
    8260           0 :         return NULL;
    8261             : }
    8262             : 
    8263           0 : __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
    8264             : {
    8265           0 :         if (!dim)
    8266           0 :                 return NULL;
    8267           0 :         if (dim->n_in != dim->n_out)
    8268           0 :                 isl_die(dim->ctx, isl_error_invalid,
    8269             :                         "number of input and output dimensions needs to be "
    8270             :                         "the same", goto error);
    8271           0 :         return basic_map_identity(dim);
    8272             : error:
    8273           0 :         isl_space_free(dim);
    8274           0 :         return NULL;
    8275             : }
    8276             : 
    8277           0 : __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
    8278             : {
    8279           0 :         return isl_map_from_basic_map(isl_basic_map_identity(dim));
    8280             : }
    8281             : 
    8282           0 : __isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
    8283             : {
    8284           0 :         isl_space *dim = isl_set_get_space(set);
    8285             :         isl_map *id;
    8286           0 :         id = isl_map_identity(isl_space_map_from_set(dim));
    8287           0 :         return isl_map_intersect_range(id, set);
    8288             : }
    8289             : 
    8290             : /* Construct a basic set with all set dimensions having only non-negative
    8291             :  * values.
    8292             :  */
    8293           0 : __isl_give isl_basic_set *isl_basic_set_positive_orthant(
    8294             :         __isl_take isl_space *space)
    8295             : {
    8296             :         int i;
    8297             :         unsigned nparam;
    8298             :         unsigned dim;
    8299             :         struct isl_basic_set *bset;
    8300             : 
    8301           0 :         if (!space)
    8302           0 :                 return NULL;
    8303           0 :         nparam = space->nparam;
    8304           0 :         dim = space->n_out;
    8305           0 :         bset = isl_basic_set_alloc_space(space, 0, 0, dim);
    8306           0 :         if (!bset)
    8307           0 :                 return NULL;
    8308           0 :         for (i = 0; i < dim; ++i) {
    8309           0 :                 int k = isl_basic_set_alloc_inequality(bset);
    8310           0 :                 if (k < 0)
    8311           0 :                         goto error;
    8312           0 :                 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
    8313           0 :                 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
    8314             :         }
    8315           0 :         return bset;
    8316             : error:
    8317           0 :         isl_basic_set_free(bset);
    8318           0 :         return NULL;
    8319             : }
    8320             : 
    8321             : /* Construct the half-space x_pos >= 0.
    8322             :  */
    8323           0 : static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
    8324             :         int pos)
    8325             : {
    8326             :         int k;
    8327             :         isl_basic_set *nonneg;
    8328             : 
    8329           0 :         nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
    8330           0 :         k = isl_basic_set_alloc_inequality(nonneg);
    8331           0 :         if (k < 0)
    8332           0 :                 goto error;
    8333           0 :         isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
    8334           0 :         isl_int_set_si(nonneg->ineq[k][pos], 1);
    8335             : 
    8336           0 :         return isl_basic_set_finalize(nonneg);
    8337             : error:
    8338           0 :         isl_basic_set_free(nonneg);
    8339           0 :         return NULL;
    8340             : }
    8341             : 
    8342             : /* Construct the half-space x_pos <= -1.
    8343             :  */
    8344           0 : static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
    8345             : {
    8346             :         int k;
    8347             :         isl_basic_set *neg;
    8348             : 
    8349           0 :         neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
    8350           0 :         k = isl_basic_set_alloc_inequality(neg);
    8351           0 :         if (k < 0)
    8352           0 :                 goto error;
    8353           0 :         isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
    8354           0 :         isl_int_set_si(neg->ineq[k][0], -1);
    8355           0 :         isl_int_set_si(neg->ineq[k][pos], -1);
    8356             : 
    8357           0 :         return isl_basic_set_finalize(neg);
    8358             : error:
    8359           0 :         isl_basic_set_free(neg);
    8360           0 :         return NULL;
    8361             : }
    8362             : 
    8363           0 : __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
    8364             :         enum isl_dim_type type, unsigned first, unsigned n)
    8365             : {
    8366             :         int i;
    8367             :         unsigned offset;
    8368             :         isl_basic_set *nonneg;
    8369             :         isl_basic_set *neg;
    8370             : 
    8371           0 :         if (!set)
    8372           0 :                 return NULL;
    8373           0 :         if (n == 0)
    8374           0 :                 return set;
    8375             : 
    8376           0 :         isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
    8377             : 
    8378           0 :         offset = pos(set->dim, type);
    8379           0 :         for (i = 0; i < n; ++i) {
    8380           0 :                 nonneg = nonneg_halfspace(isl_set_get_space(set),
    8381           0 :                                           offset + first + i);
    8382           0 :                 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
    8383             : 
    8384           0 :                 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
    8385             :         }
    8386             : 
    8387           0 :         return set;
    8388             : error:
    8389           0 :         isl_set_free(set);
    8390           0 :         return NULL;
    8391             : }
    8392             : 
    8393           0 : static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
    8394             :         int len,
    8395             :         isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
    8396             :         void *user)
    8397             : {
    8398             :         isl_set *half;
    8399             : 
    8400           0 :         if (!set)
    8401           0 :                 return isl_stat_error;
    8402           0 :         if (isl_set_plain_is_empty(set)) {
    8403           0 :                 isl_set_free(set);
    8404           0 :                 return isl_stat_ok;
    8405             :         }
    8406           0 :         if (first == len)
    8407           0 :                 return fn(set, signs, user);
    8408             : 
    8409           0 :         signs[first] = 1;
    8410           0 :         half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
    8411             :                                                         1 + first));
    8412           0 :         half = isl_set_intersect(half, isl_set_copy(set));
    8413           0 :         if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
    8414           0 :                 goto error;
    8415             : 
    8416           0 :         signs[first] = -1;
    8417           0 :         half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
    8418             :                                                         1 + first));
    8419           0 :         half = isl_set_intersect(half, set);
    8420           0 :         return foreach_orthant(half, signs, first + 1, len, fn, user);
    8421             : error:
    8422           0 :         isl_set_free(set);
    8423           0 :         return isl_stat_error;
    8424             : }
    8425             : 
    8426             : /* Call "fn" on the intersections of "set" with each of the orthants
    8427             :  * (except for obviously empty intersections).  The orthant is identified
    8428             :  * by the signs array, with each entry having value 1 or -1 according
    8429             :  * to the sign of the corresponding variable.
    8430             :  */
    8431           0 : isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
    8432             :         isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
    8433             :         void *user)
    8434             : {
    8435             :         unsigned nparam;
    8436             :         unsigned nvar;
    8437             :         int *signs;
    8438             :         isl_stat r;
    8439             : 
    8440           0 :         if (!set)
    8441           0 :                 return isl_stat_error;
    8442           0 :         if (isl_set_plain_is_empty(set))
    8443           0 :                 return isl_stat_ok;
    8444             : 
    8445           0 :         nparam = isl_set_dim(set, isl_dim_param);
    8446           0 :         nvar = isl_set_dim(set, isl_dim_set);
    8447             : 
    8448           0 :         signs = isl_alloc_array(set->ctx, int, nparam + nvar);
    8449             : 
    8450           0 :         r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
    8451             :                             fn, user);
    8452             : 
    8453           0 :         free(signs);
    8454             : 
    8455           0 :         return r;
    8456             : }
    8457             : 
    8458      752960 : isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
    8459             : {
    8460      752960 :         return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
    8461             : }
    8462             : 
    8463           0 : isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
    8464             :         __isl_keep isl_basic_map *bmap2)
    8465             : {
    8466             :         int is_subset;
    8467             :         struct isl_map *map1;
    8468             :         struct isl_map *map2;
    8469             : 
    8470           0 :         if (!bmap1 || !bmap2)
    8471           0 :                 return isl_bool_error;
    8472             : 
    8473           0 :         map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
    8474           0 :         map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
    8475             : 
    8476           0 :         is_subset = isl_map_is_subset(map1, map2);
    8477             : 
    8478           0 :         isl_map_free(map1);
    8479           0 :         isl_map_free(map2);
    8480             : 
    8481           0 :         return is_subset;
    8482             : }
    8483             : 
    8484           0 : isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
    8485             :         __isl_keep isl_basic_set *bset2)
    8486             : {
    8487           0 :         return isl_basic_map_is_subset(bset1, bset2);
    8488             : }
    8489             : 
    8490           0 : isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
    8491             :         __isl_keep isl_basic_map *bmap2)
    8492             : {
    8493             :         isl_bool is_subset;
    8494             : 
    8495           0 :         if (!bmap1 || !bmap2)
    8496           0 :                 return isl_bool_error;
    8497           0 :         is_subset = isl_basic_map_is_subset(bmap1, bmap2);
    8498           0 :         if (is_subset != isl_bool_true)
    8499           0 :                 return is_subset;
    8500           0 :         is_subset = isl_basic_map_is_subset(bmap2, bmap1);
    8501           0 :         return is_subset;
    8502             : }
    8503             : 
    8504           0 : isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
    8505             :         __isl_keep isl_basic_set *bset2)
    8506             : {
    8507           0 :         return isl_basic_map_is_equal(
    8508             :                 bset_to_bmap(bset1), bset_to_bmap(bset2));
    8509             : }
    8510             : 
    8511     5085426 : isl_bool isl_map_is_empty(__isl_keep isl_map *map)
    8512             : {
    8513             :         int i;
    8514             :         int is_empty;
    8515             : 
    8516     5085426 :         if (!map)
    8517           0 :                 return isl_bool_error;
    8518     5085426 :         for (i = 0; i < map->n; ++i) {
    8519     5085426 :                 is_empty = isl_basic_map_is_empty(map->p[i]);
    8520     5085426 :                 if (is_empty < 0)
    8521           0 :                         return isl_bool_error;
    8522     5085426 :                 if (!is_empty)
    8523     5085426 :                         return isl_bool_false;
    8524             :         }
    8525           0 :         return isl_bool_true;
    8526             : }
    8527             : 
    8528    10026360 : isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
    8529             : {
    8530    10026360 :         return map ? map->n == 0 : isl_bool_error;
    8531             : }
    8532             : 
    8533           0 : isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
    8534             : {
    8535           0 :         return set ? set->n == 0 : isl_bool_error;
    8536             : }
    8537             : 
    8538      119390 : isl_bool isl_set_is_empty(__isl_keep isl_set *set)
    8539             : {
    8540      119390 :         return isl_map_is_empty(set_to_map(set));
    8541             : }
    8542             : 
    8543      203490 : isl_bool isl_map_has_equal_space(__isl_keep isl_map *map1,
    8544             :         __isl_keep isl_map *map2)
    8545             : {
    8546      203490 :         if (!map1 || !map2)
    8547           0 :                 return isl_bool_error;
    8548             : 
    8549      203490 :         return isl_space_is_equal(map1->dim, map2->dim);
    8550             : }
    8551             : 
    8552           0 : isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
    8553             :         __isl_keep isl_set *set2)
    8554             : {
    8555           0 :         if (!set1 || !set2)
    8556           0 :                 return isl_bool_error;
    8557             : 
    8558           0 :         return isl_space_is_equal(set1->dim, set2->dim);
    8559             : }
    8560             : 
    8561      101745 : static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
    8562             : {
    8563             :         isl_bool is_subset;
    8564             : 
    8565      101745 :         if (!map1 || !map2)
    8566           0 :                 return isl_bool_error;
    8567      101745 :         is_subset = isl_map_is_subset(map1, map2);
    8568      101745 :         if (is_subset != isl_bool_true)
    8569           0 :                 return is_subset;
    8570      101745 :         is_subset = isl_map_is_subset(map2, map1);
    8571      101745 :         return is_subset;
    8572             : }
    8573             : 
    8574             : /* Is "map1" equal to "map2"?
    8575             :  *
    8576             :  * First check if they are obviously equal.
    8577             :  * If not, then perform a more detailed analysis.
    8578             :  */
    8579      752960 : isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
    8580             : {
    8581             :         isl_bool equal;
    8582             : 
    8583      752960 :         equal = isl_map_plain_is_equal(map1, map2);
    8584      752960 :         if (equal < 0 || equal)
    8585      651215 :                 return equal;
    8586      101745 :         return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
    8587             : }
    8588             : 
    8589           0 : isl_bool isl_basic_map_is_strict_subset(
    8590             :                 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
    8591             : {
    8592             :         isl_bool is_subset;
    8593             : 
    8594           0 :         if (!bmap1 || !bmap2)
    8595           0 :                 return isl_bool_error;
    8596           0 :         is_subset = isl_basic_map_is_subset(bmap1, bmap2);
    8597           0 :         if (is_subset != isl_bool_true)
    8598           0 :                 return is_subset;
    8599           0 :         is_subset = isl_basic_map_is_subset(bmap2, bmap1);
    8600           0 :         if (is_subset == isl_bool_error)
    8601           0 :                 return is_subset;
    8602           0 :         return !is_subset;
    8603             : }
    8604             : 
    8605           0 : isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
    8606             :         __isl_keep isl_map *map2)
    8607             : {
    8608             :         isl_bool is_subset;
    8609             : 
    8610           0 :         if (!map1 || !map2)
    8611           0 :                 return isl_bool_error;
    8612           0 :         is_subset = isl_map_is_subset(map1, map2);
    8613           0 :         if (is_subset != isl_bool_true)
    8614           0 :                 return is_subset;
    8615           0 :         is_subset = isl_map_is_subset(map2, map1);
    8616           0 :         if (is_subset == isl_bool_error)
    8617           0 :                 return is_subset;
    8618           0 :         return !is_subset;
    8619             : }
    8620             : 
    8621           0 : isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
    8622             :         __isl_keep isl_set *set2)
    8623             : {
    8624           0 :         return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
    8625             : }
    8626             : 
    8627             : /* Is "bmap" obviously equal to the universe with the same space?
    8628             :  *
    8629             :  * That is, does it not have any constraints?
    8630             :  */
    8631  1346532020 : isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
    8632             : {
    8633  1346532020 :         if (!bmap)
    8634           0 :                 return isl_bool_error;
    8635  1346532020 :         return bmap->n_eq == 0 && bmap->n_ineq == 0;
    8636             : }
    8637             : 
    8638             : /* Is "bset" obviously equal to the universe with the same space?
    8639             :  */
    8640           0 : isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
    8641             : {
    8642           0 :         return isl_basic_map_plain_is_universe(bset);
    8643             : }
    8644             : 
    8645             : /* If "c" does not involve any existentially quantified variables,
    8646             :  * then set *univ to false and abort
    8647             :  */
    8648           0 : static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
    8649             : {
    8650           0 :         isl_bool *univ = user;
    8651             :         unsigned n;
    8652             : 
    8653           0 :         n = isl_constraint_dim(c, isl_dim_div);
    8654           0 :         *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
    8655           0 :         isl_constraint_free(c);
    8656           0 :         if (*univ < 0 || !*univ)
    8657           0 :                 return isl_stat_error;
    8658           0 :         return isl_stat_ok;
    8659             : }
    8660             : 
    8661             : /* Is "bmap" equal to the universe with the same space?
    8662             :  *
    8663             :  * First check if it is obviously equal to the universe.
    8664             :  * If not and if there are any constraints not involving
    8665             :  * existentially quantified variables, then it is certainly
    8666             :  * not equal to the universe.
    8667             :  * Otherwise, check if the universe is a subset of "bmap".
    8668             :  */
    8669           0 : isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
    8670             : {
    8671             :         isl_bool univ;
    8672             :         isl_basic_map *test;
    8673             : 
    8674           0 :         univ = isl_basic_map_plain_is_universe(bmap);
    8675           0 :         if (univ < 0 || univ)
    8676           0 :                 return univ;
    8677           0 :         if (isl_basic_map_dim(bmap, isl_dim_div) == 0)
    8678           0 :                 return isl_bool_false;
    8679           0 :         univ = isl_bool_true;
    8680           0 :         if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
    8681             :             univ)
    8682           0 :                 return isl_bool_error;
    8683           0 :         if (univ < 0 || !univ)
    8684           0 :                 return univ;
    8685           0 :         test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
    8686           0 :         univ = isl_basic_map_is_subset(test, bmap);
    8687           0 :         isl_basic_map_free(test);
    8688           0 :         return univ;
    8689             : }
    8690             : 
    8691             : /* Is "bset" equal to the universe with the same space?
    8692             :  */
    8693           0 : isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
    8694             : {
    8695           0 :         return isl_basic_map_is_universe(bset);
    8696             : }
    8697             : 
    8698    84864156 : isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
    8699             : {
    8700             :         int i;
    8701             : 
    8702    84864156 :         if (!map)
    8703           0 :                 return isl_bool_error;
    8704             : 
    8705  1316076933 :         for (i = 0; i < map->n; ++i) {
    8706  1233451023 :                 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
    8707  1233451023 :                 if (r < 0 || r)
    8708     2238246 :                         return r;
    8709             :         }
    8710             : 
    8711    82625910 :         return isl_bool_false;
    8712             : }
    8713             : 
    8714           0 : isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
    8715             : {
    8716           0 :         return isl_map_plain_is_universe(set_to_map(set));
    8717             : }
    8718             : 
    8719   173528979 : isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
    8720             : {
    8721   173528979 :         struct isl_basic_set *bset = NULL;
    8722   173528979 :         struct isl_vec *sample = NULL;
    8723             :         isl_bool empty, non_empty;
    8724             : 
    8725   173528979 :         if (!bmap)
    8726           0 :                 return isl_bool_error;
    8727             : 
    8728   173528979 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
    8729    70674466 :                 return isl_bool_true;
    8730             : 
    8731   102854513 :         if (isl_basic_map_plain_is_universe(bmap))
    8732     3883363 :                 return isl_bool_false;
    8733             : 
    8734    98971150 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
    8735           0 :                 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
    8736           0 :                 copy = isl_basic_map_remove_redundancies(copy);
    8737           0 :                 empty = isl_basic_map_plain_is_empty(copy);
    8738           0 :                 isl_basic_map_free(copy);
    8739           0 :                 return empty;
    8740             :         }
    8741             : 
    8742    98971150 :         non_empty = isl_basic_map_plain_is_non_empty(bmap);
    8743    98971150 :         if (non_empty < 0)
    8744           0 :                 return isl_bool_error;
    8745    98971150 :         if (non_empty)
    8746    43442723 :                 return isl_bool_false;
    8747    55528427 :         isl_vec_free(bmap->sample);
    8748    55528427 :         bmap->sample = NULL;
    8749    55528427 :         bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
    8750    55528427 :         if (!bset)
    8751           0 :                 return isl_bool_error;
    8752    55528427 :         sample = isl_basic_set_sample_vec(bset);
    8753    55528427 :         if (!sample)
    8754           0 :                 return isl_bool_error;
    8755    55528427 :         empty = sample->size == 0;
    8756    55528427 :         isl_vec_free(bmap->sample);
    8757    55528427 :         bmap->sample = sample;
    8758    55528427 :         if (empty)
    8759    28606928 :                 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
    8760             : 
    8761    55528427 :         return empty;
    8762             : }
    8763             : 
    8764 42735581661 : isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
    8765             : {
    8766 42735581661 :         if (!bmap)
    8767           0 :                 return isl_bool_error;
    8768 42735581661 :         return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
    8769             : }
    8770             : 
    8771   135474501 : isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
    8772             : {
    8773   135474501 :         if (!bset)
    8774           0 :                 return isl_bool_error;
    8775   135474501 :         return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
    8776             : }
    8777             : 
    8778             : /* Is "bmap" known to be non-empty?
    8779             :  *
    8780             :  * That is, is the cached sample still valid?
    8781             :  */
    8782    98971150 : isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
    8783             : {
    8784             :         unsigned total;
    8785             : 
    8786    98971150 :         if (!bmap)
    8787           0 :                 return isl_bool_error;
    8788    98971150 :         if (!bmap->sample)
    8789    21455809 :                 return isl_bool_false;
    8790    77515341 :         total = 1 + isl_basic_map_total_dim(bmap);
    8791    77515341 :         if (bmap->sample->size != total)
    8792           0 :                 return isl_bool_false;
    8793    77515341 :         return isl_basic_map_contains(bmap, bmap->sample);
    8794             : }
    8795             : 
    8796           0 : isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
    8797             : {
    8798           0 :         return isl_basic_map_is_empty(bset_to_bmap(bset));
    8799             : }
    8800             : 
    8801           0 : __isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
    8802             :         __isl_take isl_basic_map *bmap2)
    8803             : {
    8804             :         struct isl_map *map;
    8805           0 :         if (!bmap1 || !bmap2)
    8806             :                 goto error;
    8807             : 
    8808           0 :         isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
    8809             : 
    8810           0 :         map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
    8811           0 :         if (!map)
    8812           0 :                 goto error;
    8813           0 :         map = isl_map_add_basic_map(map, bmap1);
    8814           0 :         map = isl_map_add_basic_map(map, bmap2);
    8815           0 :         return map;
    8816             : error:
    8817           0 :         isl_basic_map_free(bmap1);
    8818           0 :         isl_basic_map_free(bmap2);
    8819           0 :         return NULL;
    8820             : }
    8821             : 
    8822           0 : struct isl_set *isl_basic_set_union(
    8823             :                 struct isl_basic_set *bset1, struct isl_basic_set *bset2)
    8824             : {
    8825           0 :         return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
    8826             :                                                 bset_to_bmap(bset2)));
    8827             : }
    8828             : 
    8829             : /* Order divs such that any div only depends on previous divs */
    8830 66312699388 : __isl_give isl_basic_map *isl_basic_map_order_divs(
    8831             :         __isl_take isl_basic_map *bmap)
    8832             : {
    8833             :         int i;
    8834             :         unsigned off;
    8835             : 
    8836 66312699388 :         if (!bmap)
    8837           0 :                 return NULL;
    8838             : 
    8839 66312699388 :         off = isl_space_dim(bmap->dim, isl_dim_all);
    8840             : 
    8841 66312699388 :         for (i = 0; i < bmap->n_div; ++i) {
    8842             :                 int pos;
    8843           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
    8844           0 :                         continue;
    8845           0 :                 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
    8846           0 :                                                             bmap->n_div-i);
    8847           0 :                 if (pos == -1)
    8848           0 :                         continue;
    8849           0 :                 if (pos == 0)
    8850           0 :                         isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
    8851             :                                 "integer division depends on itself",
    8852             :                                 return isl_basic_map_free(bmap));
    8853           0 :                 isl_basic_map_swap_div(bmap, i, i + pos);
    8854           0 :                 --i;
    8855             :         }
    8856 66312699388 :         return bmap;
    8857             : }
    8858             : 
    8859           0 : struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
    8860             : {
    8861           0 :         return bset_from_bmap(isl_basic_map_order_divs(bset_to_bmap(bset)));
    8862             : }
    8863             : 
    8864    11827020 : __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
    8865             : {
    8866             :         int i;
    8867             : 
    8868    11827020 :         if (!map)
    8869           0 :                 return 0;
    8870             : 
    8871   536370494 :         for (i = 0; i < map->n; ++i) {
    8872   524543474 :                 map->p[i] = isl_basic_map_order_divs(map->p[i]);
    8873   524543474 :                 if (!map->p[i])
    8874           0 :                         goto error;
    8875             :         }
    8876             : 
    8877    11827020 :         return map;
    8878             : error:
    8879           0 :         isl_map_free(map);
    8880           0 :         return NULL;
    8881             : }
    8882             : 
    8883             : /* Sort the local variables of "bset".
    8884             :  */
    8885           0 : __isl_give isl_basic_set *isl_basic_set_sort_divs(
    8886             :         __isl_take isl_basic_set *bset)
    8887             : {
    8888           0 :         return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
    8889             : }
    8890             : 
    8891             : /* Apply the expansion computed by isl_merge_divs.
    8892             :  * The expansion itself is given by "exp" while the resulting
    8893             :  * list of divs is given by "div".
    8894             :  *
    8895             :  * Move the integer divisions of "bmap" into the right position
    8896             :  * according to "exp" and then introduce the additional integer
    8897             :  * divisions, adding div constraints.
    8898             :  * The moving should be done first to avoid moving coefficients
    8899             :  * in the definitions of the extra integer divisions.
    8900             :  */
    8901           0 : __isl_give isl_basic_map *isl_basic_map_expand_divs(
    8902             :         __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
    8903             : {
    8904             :         int i, j;
    8905             :         int n_div;
    8906             : 
    8907           0 :         bmap = isl_basic_map_cow(bmap);
    8908           0 :         if (!bmap || !div)
    8909             :                 goto error;
    8910             : 
    8911           0 :         if (div->n_row < bmap->n_div)
    8912           0 :                 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
    8913             :                         "not an expansion", goto error);
    8914             : 
    8915           0 :         n_div = bmap->n_div;
    8916           0 :         bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
    8917           0 :                                             div->n_row - n_div, 0,
    8918           0 :                                             2 * (div->n_row - n_div));
    8919             : 
    8920           0 :         for (i = n_div; i < div->n_row; ++i)
    8921           0 :                 if (isl_basic_map_alloc_div(bmap) < 0)
    8922           0 :                         goto error;
    8923             : 
    8924           0 :         for (j = n_div - 1; j >= 0; --j) {
    8925           0 :                 if (exp[j] == j)
    8926           0 :                         break;
    8927           0 :                 isl_basic_map_swap_div(bmap, j, exp[j]);
    8928             :         }
    8929           0 :         j = 0;
    8930           0 :         for (i = 0; i < div->n_row; ++i) {
    8931           0 :                 if (j < n_div && exp[j] == i) {
    8932           0 :                         j++;
    8933             :                 } else {
    8934           0 :                         isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
    8935           0 :                         if (isl_basic_map_div_is_marked_unknown(bmap, i))
    8936           0 :                                 continue;
    8937           0 :                         if (isl_basic_map_add_div_constraints(bmap, i) < 0)
    8938           0 :                                 goto error;
    8939             :                 }
    8940             :         }
    8941             : 
    8942           0 :         isl_mat_free(div);
    8943           0 :         return bmap;
    8944             : error:
    8945           0 :         isl_basic_map_free(bmap);
    8946           0 :         isl_mat_free(div);
    8947           0 :         return NULL;
    8948             : }
    8949             : 
    8950             : /* Apply the expansion computed by isl_merge_divs.
    8951             :  * The expansion itself is given by "exp" while the resulting
    8952             :  * list of divs is given by "div".
    8953             :  */
    8954           0 : __isl_give isl_basic_set *isl_basic_set_expand_divs(
    8955             :         __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
    8956             : {
    8957           0 :         return isl_basic_map_expand_divs(bset, div, exp);
    8958             : }
    8959             : 
    8960             : /* Look for a div in dst that corresponds to the div "div" in src.
    8961             :  * The divs before "div" in src and dst are assumed to be the same.
    8962             :  * 
    8963             :  * Returns -1 if no corresponding div was found and the position
    8964             :  * of the corresponding div in dst otherwise.
    8965             :  */
    8966           0 : static int find_div(__isl_keep isl_basic_map *dst,
    8967             :         __isl_keep isl_basic_map *src, unsigned div)
    8968             : {
    8969             :         int i;
    8970             : 
    8971           0 :         unsigned total = isl_space_dim(src->dim, isl_dim_all);
    8972             : 
    8973           0 :         isl_assert(dst->ctx, div <= dst->n_div, return -1);
    8974           0 :         for (i = div; i < dst->n_div; ++i)
    8975           0 :                 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
    8976           0 :                     isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
    8977           0 :                                                 dst->n_div - div) == -1)
    8978           0 :                         return i;
    8979           0 :         return -1;
    8980             : }
    8981             : 
    8982             : /* Align the divs of "dst" to those of "src", adding divs from "src"
    8983             :  * if needed.  That is, make sure that the first src->n_div divs
    8984             :  * of the result are equal to those of src.
    8985             :  *
    8986             :  * The result is not finalized as by design it will have redundant
    8987             :  * divs if any divs from "src" were copied.
    8988             :  */
    8989  1087210430 : __isl_give isl_basic_map *isl_basic_map_align_divs(
    8990             :         __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
    8991             : {
    8992             :         int i;
    8993             :         int known, extended;
    8994             :         unsigned total;
    8995             : 
    8996  1087210430 :         if (!dst || !src)
    8997           0 :                 return isl_basic_map_free(dst);
    8998             : 
    8999  1087210430 :         if (src->n_div == 0)
    9000  1087210430 :                 return dst;
    9001             : 
    9002           0 :         known = isl_basic_map_divs_known(src);
    9003           0 :         if (known < 0)
    9004           0 :                 return isl_basic_map_free(dst);
    9005           0 :         if (!known)
    9006           0 :                 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
    9007             :                         "some src divs are unknown",
    9008             :                         return isl_basic_map_free(dst));
    9009             : 
    9010           0 :         src = isl_basic_map_order_divs(isl_basic_map_copy(src));
    9011           0 :         if (!src)
    9012           0 :                 return isl_basic_map_free(dst);
    9013             : 
    9014           0 :         extended = 0;
    9015           0 :         total = isl_space_dim(src->dim, isl_dim_all);
    9016           0 :         for (i = 0; i < src->n_div; ++i) {
    9017           0 :                 int j = find_div(dst, src, i);
    9018           0 :                 if (j < 0) {
    9019           0 :                         if (!extended) {
    9020           0 :                                 int extra = src->n_div - i;
    9021           0 :                                 dst = isl_basic_map_cow(dst);
    9022           0 :                                 if (!dst)
    9023           0 :                                         goto error;
    9024           0 :                                 dst = isl_basic_map_extend_space(dst,
    9025             :                                                 isl_space_copy(dst->dim),
    9026           0 :                                                 extra, 0, 2 * extra);
    9027           0 :                                 extended = 1;
    9028             :                         }
    9029           0 :                         j = isl_basic_map_alloc_div(dst);
    9030           0 :                         if (j < 0)
    9031           0 :                                 goto error;
    9032           0 :                         isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
    9033           0 :                         isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
    9034           0 :                         if (isl_basic_map_add_div_constraints(dst, j) < 0)
    9035           0 :                                 goto error;
    9036             :                 }
    9037           0 :                 if (j != i)
    9038           0 :                         isl_basic_map_swap_div(dst, i, j);
    9039             :         }
    9040           0 :         isl_basic_map_free(src);
    9041           0 :         return dst;
    9042             : error:
    9043           0 :         isl_basic_map_free(src);
    9044           0 :         isl_basic_map_free(dst);
    9045           0 :         return NULL;
    9046             : }
    9047             : 
    9048   645942497 : __isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
    9049             : {
    9050             :         int i;
    9051             : 
    9052   645942497 :         if (!map)
    9053           0 :                 return NULL;
    9054   645942497 :         if (map->n == 0)
    9055           0 :                 return map;
    9056   645942497 :         map = isl_map_compute_divs(map);
    9057   645942497 :         map = isl_map_cow(map);
    9058   645942497 :         if (!map)
    9059           0 :                 return NULL;
    9060             : 
    9061  1189547712 :         for (i = 1; i < map->n; ++i)
    9062   543605215 :                 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
    9063  1189547712 :         for (i = 1; i < map->n; ++i) {
    9064   543605215 :                 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
    9065   543605215 :                 if (!map->p[i])
    9066           0 :                         return isl_map_free(map);
    9067             :         }
    9068             : 
    9069   645942497 :         map = isl_map_unmark_normalized(map);
    9070   645942497 :         return map;
    9071             : }
    9072             : 
    9073           0 : __isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
    9074             : {
    9075           0 :         return isl_map_align_divs_internal(map);
    9076             : }
    9077             : 
    9078           0 : struct isl_set *isl_set_align_divs(struct isl_set *set)
    9079             : {
    9080           0 :         return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
    9081             : }
    9082             : 
    9083             : /* Align the divs of the basic maps in "map" to those
    9084             :  * of the basic maps in "list", as well as to the other basic maps in "map".
    9085             :  * The elements in "list" are assumed to have known divs.
    9086             :  */
    9087           0 : __isl_give isl_map *isl_map_align_divs_to_basic_map_list(
    9088             :         __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
    9089             : {
    9090             :         int i, n;
    9091             : 
    9092           0 :         map = isl_map_compute_divs(map);
    9093           0 :         map = isl_map_cow(map);
    9094           0 :         if (!map || !list)
    9095           0 :                 return isl_map_free(map);
    9096           0 :         if (map->n == 0)
    9097           0 :                 return map;
    9098             : 
    9099           0 :         n = isl_basic_map_list_n_basic_map(list);
    9100           0 :         for (i = 0; i < n; ++i) {
    9101             :                 isl_basic_map *bmap;
    9102             : 
    9103           0 :                 bmap = isl_basic_map_list_get_basic_map(list, i);
    9104           0 :                 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
    9105           0 :                 isl_basic_map_free(bmap);
    9106             :         }
    9107           0 :         if (!map->p[0])
    9108           0 :                 return isl_map_free(map);
    9109             : 
    9110           0 :         return isl_map_align_divs_internal(map);
    9111             : }
    9112             : 
    9113             : /* Align the divs of each element of "list" to those of "bmap".
    9114             :  * Both "bmap" and the elements of "list" are assumed to have known divs.
    9115             :  */
    9116           0 : __isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
    9117             :         __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
    9118             : {
    9119             :         int i, n;
    9120             : 
    9121           0 :         if (!list || !bmap)
    9122           0 :                 return isl_basic_map_list_free(list);
    9123             : 
    9124           0 :         n = isl_basic_map_list_n_basic_map(list);
    9125           0 :         for (i = 0; i < n; ++i) {
    9126             :                 isl_basic_map *bmap_i;
    9127             : 
    9128           0 :                 bmap_i = isl_basic_map_list_get_basic_map(list, i);
    9129           0 :                 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
    9130           0 :                 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
    9131             :         }
    9132             : 
    9133           0 :         return list;
    9134             : }
    9135             : 
    9136           0 : static __isl_give isl_set *set_apply( __isl_take isl_set *set,
    9137             :         __isl_take isl_map *map)
    9138             : {
    9139             :         isl_bool ok;
    9140             : 
    9141           0 :         ok = isl_map_compatible_domain(map, set);
    9142           0 :         if (ok < 0)
    9143           0 :                 goto error;
    9144           0 :         if (!ok)
    9145           0 :                 isl_die(isl_set_get_ctx(set), isl_error_invalid,
    9146             :                         "incompatible spaces", goto error);
    9147           0 :         map = isl_map_intersect_domain(map, set);
    9148           0 :         set = isl_map_range(map);
    9149           0 :         return set;
    9150             : error:
    9151           0 :         isl_set_free(set);
    9152           0 :         isl_map_free(map);
    9153           0 :         return NULL;
    9154             : }
    9155             : 
    9156           0 : __isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
    9157             :         __isl_take isl_map *map)
    9158             : {
    9159           0 :         return isl_map_align_params_map_map_and(set, map, &set_apply);
    9160             : }
    9161             : 
    9162             : /* There is no need to cow as removing empty parts doesn't change
    9163             :  * the meaning of the set.
    9164             :  */
    9165  2726435354 : __isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
    9166             : {
    9167             :         int i;
    9168             : 
    9169  2726435354 :         if (!map)
    9170           0 :                 return NULL;
    9171             : 
    9172 10974384279 :         for (i = map->n - 1; i >= 0; --i)
    9173  8247948925 :                 map = remove_if_empty(map, i);
    9174             : 
    9175  2726435354 :         return map;
    9176             : }
    9177             : 
    9178   840305892 : struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
    9179             : {
    9180   840305892 :         return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
    9181             : }
    9182             : 
    9183             : /* Create a binary relation that maps the shared initial "pos" dimensions
    9184             :  * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
    9185             :  */
    9186           0 : static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
    9187             :         __isl_keep isl_basic_set *bset2, int pos)
    9188             : {
    9189             :         isl_basic_map *bmap1;
    9190             :         isl_basic_map *bmap2;
    9191             : 
    9192           0 :         bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
    9193           0 :         bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
    9194           0 :         bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
    9195             :                                         isl_dim_out, 0, pos);
    9196           0 :         bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
    9197             :                                         isl_dim_out, 0, pos);
    9198           0 :         return isl_basic_map_range_product(bmap1, bmap2);
    9199             : }
    9200             : 
    9201             : /* Given two basic sets bset1 and bset2, compute the maximal difference
    9202             :  * between the values of dimension pos in bset1 and those in bset2
    9203             :  * for any common value of the parameters and dimensions preceding pos.
    9204             :  */
    9205           0 : static enum isl_lp_result basic_set_maximal_difference_at(
    9206             :         __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
    9207             :         int pos, isl_int *opt)
    9208             : {
    9209             :         isl_basic_map *bmap1;
    9210             :         struct isl_ctx *ctx;
    9211             :         struct isl_vec *obj;
    9212             :         unsigned total;
    9213             :         unsigned nparam;
    9214             :         unsigned dim1;
    9215             :         enum isl_lp_result res;
    9216             : 
    9217           0 :         if (!bset1 || !bset2)
    9218           0 :                 return isl_lp_error;
    9219             : 
    9220           0 :         nparam = isl_basic_set_n_param(bset1);
    9221           0 :         dim1 = isl_basic_set_n_dim(bset1);
    9222             : 
    9223           0 :         bmap1 = join_initial(bset1, bset2, pos);
    9224           0 :         if (!bmap1)
    9225           0 :                 return isl_lp_error;
    9226             : 
    9227           0 :         total = isl_basic_map_total_dim(bmap1);
    9228           0 :         ctx = bmap1->ctx;
    9229           0 :         obj = isl_vec_alloc(ctx, 1 + total);
    9230           0 :         if (!obj)
    9231           0 :                 goto error;
    9232           0 :         isl_seq_clr(obj->block.data, 1 + total);
    9233           0 :         isl_int_set_si(obj->block.data[1+nparam+pos], 1);
    9234           0 :         isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
    9235           0 :         res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
    9236             :                                         opt, NULL, NULL);
    9237           0 :         isl_basic_map_free(bmap1);
    9238           0 :         isl_vec_free(obj);
    9239           0 :         return res;
    9240             : error:
    9241           0 :         isl_basic_map_free(bmap1);
    9242           0 :         return isl_lp_error;
    9243             : }
    9244             : 
    9245             : /* Given two _disjoint_ basic sets bset1 and bset2, check whether
    9246             :  * for any common value of the parameters and dimensions preceding pos
    9247             :  * in both basic sets, the values of dimension pos in bset1 are
    9248             :  * smaller or larger than those in bset2.
    9249             :  *
    9250             :  * Returns
    9251             :  *       1 if bset1 follows bset2
    9252             :  *      -1 if bset1 precedes bset2
    9253             :  *       0 if bset1 and bset2 are incomparable
    9254             :  *      -2 if some error occurred.
    9255             :  */
    9256           0 : int isl_basic_set_compare_at(struct isl_basic_set *bset1,
    9257             :         struct isl_basic_set *bset2, int pos)
    9258             : {
    9259             :         isl_int opt;
    9260             :         enum isl_lp_result res;
    9261             :         int cmp;
    9262             : 
    9263           0 :         isl_int_init(opt);
    9264             : 
    9265           0 :         res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
    9266             : 
    9267           0 :         if (res == isl_lp_empty)
    9268           0 :                 cmp = 0;
    9269           0 :         else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
    9270             :                   res == isl_lp_unbounded)
    9271           0 :                 cmp = 1;
    9272           0 :         else if (res == isl_lp_ok && isl_int_is_neg(opt))
    9273           0 :                 cmp = -1;
    9274             :         else
    9275           0 :                 cmp = -2;
    9276             : 
    9277           0 :         isl_int_clear(opt);
    9278           0 :         return cmp;
    9279             : }
    9280             : 
    9281             : /* Given two basic sets bset1 and bset2, check whether
    9282             :  * for any common value of the parameters and dimensions preceding pos
    9283             :  * there is a value of dimension pos in bset1 that is larger
    9284             :  * than a value of the same dimension in bset2.
    9285             :  *
    9286             :  * Return
    9287             :  *       1 if there exists such a pair
    9288             :  *       0 if there is no such pair, but there is a pair of equal values
    9289             :  *      -1 otherwise
    9290             :  *      -2 if some error occurred.
    9291             :  */
    9292           0 : int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
    9293             :         __isl_keep isl_basic_set *bset2, int pos)
    9294             : {
    9295             :         isl_bool empty;
    9296             :         isl_basic_map *bmap;
    9297             :         unsigned dim1;
    9298             : 
    9299           0 :         dim1 = isl_basic_set_dim(bset1, isl_dim_set);
    9300           0 :         bmap = join_initial(bset1, bset2, pos);
    9301           0 :         bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
    9302           0 :                                             isl_dim_out, dim1 - pos);
    9303           0 :         empty = isl_basic_map_is_empty(bmap);
    9304           0 :         if (empty < 0)
    9305           0 :                 goto error;
    9306           0 :         if (empty) {
    9307           0 :                 isl_basic_map_free(bmap);
    9308           0 :                 return -1;
    9309             :         }
    9310           0 :         bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
    9311           0 :                                             isl_dim_out, dim1 - pos);
    9312           0 :         empty = isl_basic_map_is_empty(bmap);
    9313           0 :         if (empty < 0)
    9314           0 :                 goto error;
    9315           0 :         isl_basic_map_free(bmap);
    9316           0 :         if (empty)
    9317           0 :                 return 0;
    9318           0 :         return 1;
    9319             : error:
    9320           0 :         isl_basic_map_free(bmap);
    9321           0 :         return -2;
    9322             : }
    9323             : 
    9324             : /* Given two sets set1 and set2, check whether
    9325             :  * for any common value of the parameters and dimensions preceding pos
    9326             :  * there is a value of dimension pos in set1 that is larger
    9327             :  * than a value of the same dimension in set2.
    9328             :  *
    9329             :  * Return
    9330             :  *       1 if there exists such a pair
    9331             :  *       0 if there is no such pair, but there is a pair of equal values
    9332             :  *      -1 otherwise
    9333             :  *      -2 if some error occurred.
    9334             :  */
    9335           0 : int isl_set_follows_at(__isl_keep isl_set *set1,
    9336             :         __isl_keep isl_set *set2, int pos)
    9337             : {
    9338             :         int i, j;
    9339           0 :         int follows = -1;
    9340             : 
    9341           0 :         if (!set1 || !set2)
    9342           0 :                 return -2;
    9343             : 
    9344           0 :         for (i = 0; i < set1->n; ++i)
    9345           0 :                 for (j = 0; j < set2->n; ++j) {
    9346             :                         int f;
    9347           0 :                         f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
    9348           0 :                         if (f == 1 || f == -2)
    9349           0 :                                 return f;
    9350           0 :                         if (f > follows)
    9351           0 :                                 follows = f;
    9352             :                 }
    9353             : 
    9354           0 :         return follows;
    9355             : }
    9356             : 
    9357           0 : static isl_bool isl_basic_map_plain_has_fixed_var(
    9358             :         __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
    9359             : {
    9360             :         int i;
    9361             :         int d;
    9362             :         unsigned total;
    9363             : 
    9364           0 :         if (!bmap)
    9365           0 :                 return isl_bool_error;
    9366           0 :         total = isl_basic_map_total_dim(bmap);
    9367           0 :         for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
    9368           0 :                 for (; d+1 > pos; --d)
    9369           0 :                         if (!isl_int_is_zero(bmap->eq[i][1+d]))
    9370             :                                 break;
    9371           0 :                 if (d != pos)
    9372           0 :                         continue;
    9373           0 :                 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
    9374           0 :                         return isl_bool_false;
    9375           0 :                 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
    9376           0 :                         return isl_bool_false;
    9377           0 :                 if (!isl_int_is_one(bmap->eq[i][1+d]))
    9378           0 :                         return isl_bool_false;
    9379           0 :                 if (val)
    9380           0 :                         isl_int_neg(*val, bmap->eq[i][0]);
    9381           0 :                 return isl_bool_true;
    9382             :         }
    9383           0 :         return isl_bool_false;
    9384             : }
    9385             : 
    9386           0 : static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
    9387             :         unsigned pos, isl_int *val)
    9388             : {
    9389             :         int i;
    9390             :         isl_int v;
    9391             :         isl_int tmp;
    9392             :         isl_bool fixed;
    9393             : 
    9394           0 :         if (!map)
    9395           0 :                 return isl_bool_error;
    9396           0 :         if (map->n == 0)
    9397           0 :                 return isl_bool_false;
    9398           0 :         if (map->n == 1)
    9399           0 :                 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val); 
    9400           0 :         isl_int_init(v);
    9401           0 :         isl_int_init(tmp);
    9402           0 :         fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v); 
    9403           0 :         for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
    9404           0 :                 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp); 
    9405           0 :                 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
    9406           0 :                         fixed = isl_bool_false;
    9407             :         }
    9408           0 :         if (val)
    9409           0 :                 isl_int_set(*val, v);
    9410           0 :         isl_int_clear(tmp);
    9411           0 :         isl_int_clear(v);
    9412           0 :         return fixed;
    9413             : }
    9414             : 
    9415           0 : static isl_bool isl_basic_set_plain_has_fixed_var(
    9416             :         __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
    9417             : {
    9418           0 :         return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
    9419             :                                                 pos, val);
    9420             : }
    9421             : 
    9422           0 : isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
    9423             :         enum isl_dim_type type, unsigned pos, isl_int *val)
    9424             : {
    9425           0 :         if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
    9426           0 :                 return isl_bool_error;
    9427           0 :         return isl_basic_map_plain_has_fixed_var(bmap,
    9428           0 :                 isl_basic_map_offset(bmap, type) - 1 + pos, val);
    9429             : }
    9430             : 
    9431             : /* If "bmap" obviously lies on a hyperplane where the given dimension
    9432             :  * has a fixed value, then return that value.
    9433             :  * Otherwise return NaN.
    9434             :  */
    9435           0 : __isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
    9436             :         __isl_keep isl_basic_map *bmap,
    9437             :         enum isl_dim_type type, unsigned pos)
    9438             : {
    9439             :         isl_ctx *ctx;
    9440             :         isl_val *v;
    9441             :         isl_bool fixed;
    9442             : 
    9443           0 :         if (!bmap)
    9444           0 :                 return NULL;
    9445           0 :         ctx = isl_basic_map_get_ctx(bmap);
    9446           0 :         v = isl_val_alloc(ctx);
    9447           0 :         if (!v)
    9448           0 :                 return NULL;
    9449           0 :         fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
    9450           0 :         if (fixed < 0)
    9451           0 :                 return isl_val_free(v);
    9452           0 :         if (fixed) {
    9453           0 :                 isl_int_set_si(v->d, 1);
    9454           0 :                 return v;
    9455             :         }
    9456           0 :         isl_val_free(v);
    9457           0 :         return isl_val_nan(ctx);
    9458             : }
    9459             : 
    9460           0 : isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
    9461             :         enum isl_dim_type type, unsigned pos, isl_int *val)
    9462             : {
    9463           0 :         if (pos >= isl_map_dim(map, type))
    9464           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
    9465             :                         "position out of bounds", return isl_bool_error);
    9466           0 :         return isl_map_plain_has_fixed_var(map,
    9467           0 :                 map_offset(map, type) - 1 + pos, val);
    9468             : }
    9469             : 
    9470             : /* If "map" obviously lies on a hyperplane where the given dimension
    9471             :  * has a fixed value, then return that value.
    9472             :  * Otherwise return NaN.
    9473             :  */
    9474           0 : __isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
    9475             :         enum isl_dim_type type, unsigned pos)
    9476             : {
    9477             :         isl_ctx *ctx;
    9478             :         isl_val *v;
    9479             :         isl_bool fixed;
    9480             : 
    9481           0 :         if (!map)
    9482           0 :                 return NULL;
    9483           0 :         ctx = isl_map_get_ctx(map);
    9484           0 :         v = isl_val_alloc(ctx);
    9485           0 :         if (!v)
    9486           0 :                 return NULL;
    9487           0 :         fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
    9488           0 :         if (fixed < 0)
    9489           0 :                 return isl_val_free(v);
    9490           0 :         if (fixed) {
    9491           0 :                 isl_int_set_si(v->d, 1);
    9492           0 :                 return v;
    9493             :         }
    9494           0 :         isl_val_free(v);
    9495           0 :         return isl_val_nan(ctx);
    9496             : }
    9497             : 
    9498             : /* If "set" obviously lies on a hyperplane where the given dimension
    9499             :  * has a fixed value, then return that value.
    9500             :  * Otherwise return NaN.
    9501             :  */
    9502           0 : __isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
    9503             :         enum isl_dim_type type, unsigned pos)
    9504             : {
    9505           0 :         return isl_map_plain_get_val_if_fixed(set, type, pos);
    9506             : }
    9507             : 
    9508             : /* Check if dimension dim has fixed value and if so and if val is not NULL,
    9509             :  * then return this fixed value in *val.
    9510             :  */
    9511           0 : isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
    9512             :         unsigned dim, isl_int *val)
    9513             : {
    9514           0 :         return isl_basic_set_plain_has_fixed_var(bset,
    9515           0 :                                         isl_basic_set_n_param(bset) + dim, val);
    9516             : }
    9517             : 
    9518             : /* Return -1 if the constraint "c1" should be sorted before "c2"
    9519             :  * and 1 if it should be sorted after "c2".
    9520             :  * Return 0 if the two constraints are the same (up to the constant term).
    9521             :  *
    9522             :  * In particular, if a constraint involves later variables than another
    9523             :  * then it is sorted after this other constraint.
    9524             :  * uset_gist depends on constraints without existentially quantified
    9525             :  * variables sorting first.
    9526             :  *
    9527             :  * For constraints that have the same latest variable, those
    9528             :  * with the same coefficient for this latest variable (first in absolute value
    9529             :  * and then in actual value) are grouped together.
    9530             :  * This is useful for detecting pairs of constraints that can
    9531             :  * be chained in their printed representation.
    9532             :  *
    9533             :  * Finally, within a group, constraints are sorted according to
    9534             :  * their coefficients (excluding the constant term).
    9535             :  */
    9536  1373361679 : static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
    9537             : {
    9538  1373361679 :         isl_int **c1 = (isl_int **) p1;
    9539  1373361679 :         isl_int **c2 = (isl_int **) p2;
    9540             :         int l1, l2;
    9541  1373361679 :         unsigned size = *(unsigned *) arg;
    9542             :         int cmp;
    9543             : 
    9544  1373361679 :         l1 = isl_seq_last_non_zero(*c1 + 1, size);
    9545  1373361679 :         l2 = isl_seq_last_non_zero(*c2 + 1, size);
    9546             : 
    9547  1373361679 :         if (l1 != l2)
    9548   550522862 :                 return l1 - l2;
    9549             : 
    9550   822838817 :         cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
    9551   822838817 :         if (cmp != 0)
    9552   657556559 :                 return cmp;
    9553   165282258 :         cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
    9554   165282258 :         if (cmp != 0)
    9555    76621626 :                 return -cmp;
    9556             : 
    9557    88660632 :         return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
    9558             : }
    9559             : 
    9560             : /* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
    9561             :  * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
    9562             :  * and 0 if the two constraints are the same (up to the constant term).
    9563             :  */
    9564           0 : int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
    9565             :         isl_int *c1, isl_int *c2)
    9566             : {
    9567             :         unsigned total;
    9568             : 
    9569           0 :         if (!bmap)
    9570           0 :                 return -2;
    9571           0 :         total = isl_basic_map_total_dim(bmap);
    9572           0 :         return sort_constraint_cmp(&c1, &c2, &total);
    9573             : }
    9574             : 
    9575  2996082145 : __isl_give isl_basic_map *isl_basic_map_sort_constraints(
    9576             :         __isl_take isl_basic_map *bmap)
    9577             : {
    9578             :         unsigned total;
    9579             : 
    9580  2996082145 :         if (!bmap)
    9581           0 :                 return NULL;
    9582  2996082145 :         if (bmap->n_ineq == 0)
    9583  2902432119 :                 return bmap;
    9584    93650026 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
    9585           0 :                 return bmap;
    9586    93650026 :         total = isl_basic_map_total_dim(bmap);
    9587    93650026 :         if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
    9588             :                     &sort_constraint_cmp, &total) < 0)
    9589           0 :                 return isl_basic_map_free(bmap);
    9590    93650026 :         return bmap;
    9591             : }
    9592             : 
    9593           0 : __isl_give isl_basic_set *isl_basic_set_sort_constraints(
    9594             :         __isl_take isl_basic_set *bset)
    9595             : {
    9596           0 :         isl_basic_map *bmap = bset_to_bmap(bset);
    9597           0 :         return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
    9598             : }
    9599             : 
    9600  3087899880 : __isl_give isl_basic_map *isl_basic_map_normalize(
    9601             :         __isl_take isl_basic_map *bmap)
    9602             : {
    9603  3087899880 :         if (!bmap)
    9604           0 :                 return NULL;
    9605  3087899880 :         if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
    9606   140543858 :                 return bmap;
    9607  2947356022 :         bmap = isl_basic_map_remove_redundancies(bmap);
    9608  2947356022 :         bmap = isl_basic_map_sort_constraints(bmap);
    9609  2947356022 :         if (bmap)
    9610  2947356022 :                 ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
    9611  2947356022 :         return bmap;
    9612             : }
    9613   734560829 : int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
    9614             :         __isl_keep isl_basic_map *bmap2)
    9615             : {
    9616             :         int i, cmp;
    9617             :         unsigned total;
    9618             :         isl_space *space1, *space2;
    9619             : 
    9620   734560829 :         if (!bmap1 || !bmap2)
    9621           0 :                 return -1;
    9622             : 
    9623   734560829 :         if (bmap1 == bmap2)
    9624     2153190 :                 return 0;
    9625   732407639 :         space1 = isl_basic_map_peek_space(bmap1);
    9626   732407639 :         space2 = isl_basic_map_peek_space(bmap2);
    9627   732407639 :         cmp = isl_space_cmp(space1, space2);
    9628   732407639 :         if (cmp)
    9629           0 :                 return cmp;
    9630  1464815278 :         if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
    9631   732407639 :             ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
    9632           0 :                 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
    9633   732407639 :         if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
    9634           0 :             ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
    9635           0 :                 return 0;
    9636   732407639 :         if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
    9637           0 :                 return 1;
    9638   732407639 :         if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
    9639           0 :                 return -1;
    9640   732407639 :         if (bmap1->n_eq != bmap2->n_eq)
    9641    86665875 :                 return bmap1->n_eq - bmap2->n_eq;
    9642   645741764 :         if (bmap1->n_ineq != bmap2->n_ineq)
    9643   265343721 :                 return bmap1->n_ineq - bmap2->n_ineq;
    9644   380398043 :         if (bmap1->n_div != bmap2->n_div)
    9645           0 :                 return bmap1->n_div - bmap2->n_div;
    9646   380398043 :         total = isl_basic_map_total_dim(bmap1);
    9647   570221926 :         for (i = 0; i < bmap1->n_eq; ++i) {
    9648   225702282 :                 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
    9649   225702282 :                 if (cmp)
    9650    35878399 :                         return cmp;
    9651             :         }
    9652   802704874 :         for (i = 0; i < bmap1->n_ineq; ++i) {
    9653   797669532 :                 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
    9654   797669532 :                 if (cmp)
    9655   339484302 :                         return cmp;
    9656             :         }
    9657     5035342 :         for (i = 0; i < bmap1->n_div; ++i) {
    9658           0 :                 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
    9659           0 :                 if (cmp)
    9660           0 :                         return cmp;
    9661             :         }
    9662     5035342 :         return 0;
    9663             : }
    9664             : 
    9665           0 : int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
    9666             :         __isl_keep isl_basic_set *bset2)
    9667             : {
    9668           0 :         return isl_basic_map_plain_cmp(bset1, bset2);
    9669             : }
    9670             : 
    9671           0 : int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
    9672             : {
    9673             :         int i, cmp;
    9674             : 
    9675           0 :         if (set1 == set2)
    9676           0 :                 return 0;
    9677           0 :         if (set1->n != set2->n)
    9678           0 :                 return set1->n - set2->n;
    9679             : 
    9680           0 :         for (i = 0; i < set1->n; ++i) {
    9681           0 :                 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
    9682           0 :                 if (cmp)
    9683           0 :                         return cmp;
    9684             :         }
    9685             : 
    9686           0 :         return 0;
    9687             : }
    9688             : 
    9689   181131617 : isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
    9690             :         __isl_keep isl_basic_map *bmap2)
    9691             : {
    9692   181131617 :         if (!bmap1 || !bmap2)
    9693           0 :                 return isl_bool_error;
    9694   181131617 :         return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
    9695             : }
    9696             : 
    9697           0 : isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
    9698             :         __isl_keep isl_basic_set *bset2)
    9699             : {
    9700           0 :         return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
    9701             :                                             bset_to_bmap(bset2));
    9702             : }
    9703             : 
    9704   553429212 : static int qsort_bmap_cmp(const void *p1, const void *p2)
    9705             : {
    9706   553429212 :         isl_basic_map *bmap1 = *(isl_basic_map **) p1;
    9707   553429212 :         isl_basic_map *bmap2 = *(isl_basic_map **) p2;
    9708             : 
    9709   553429212 :         return isl_basic_map_plain_cmp(bmap1, bmap2);
    9710             : }
    9711             : 
    9712             : /* Sort the basic maps of "map" and remove duplicate basic maps.
    9713             :  *
    9714             :  * While removing basic maps, we make sure that the basic maps remain
    9715             :  * sorted because isl_map_normalize expects the basic maps of the result
    9716             :  * to be sorted.
    9717             :  */
    9718    17491798 : static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
    9719             : {
    9720             :         int i, j;
    9721             : 
    9722    17491798 :         map = isl_map_remove_empty_parts(map);
    9723    17491798 :         if (!map)
    9724           0 :                 return NULL;
    9725    17491798 :         qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
    9726   191771641 :         for (i = map->n - 1; i >= 1; --i) {
    9727   174279843 :                 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
    9728   172739681 :                         continue;
    9729     1540162 :                 isl_basic_map_free(map->p[i-1]);
    9730    38600045 :                 for (j = i; j < map->n; ++j)
    9731    37059883 :                         map->p[j - 1] = map->p[j];
    9732     1540162 :                 map->n--;
    9733             :         }
    9734             : 
    9735    17491798 :         return map;
    9736             : }
    9737             : 
    9738             : /* Remove obvious duplicates among the basic maps of "map".
    9739             :  *
    9740             :  * Unlike isl_map_normalize, this function does not remove redundant
    9741             :  * constraints and only removes duplicates that have exactly the same
    9742             :  * constraints in the input.  It does sort the constraints and
    9743             :  * the basic maps to ease the detection of duplicates.
    9744             :  *
    9745             :  * If "map" has already been normalized or if the basic maps are
    9746             :  * disjoint, then there can be no duplicates.
    9747             :  */
    9748           0 : __isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
    9749             : {
    9750             :         int i;
    9751             :         isl_basic_map *bmap;
    9752             : 
    9753           0 :         if (!map)
    9754           0 :                 return NULL;
    9755           0 :         if (map->n <= 1)
    9756           0 :                 return map;
    9757           0 :         if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
    9758           0 :                 return map;
    9759           0 :         for (i = 0; i < map->n; ++i) {
    9760           0 :                 bmap = isl_basic_map_copy(map->p[i]);
    9761           0 :                 bmap = isl_basic_map_sort_constraints(bmap);
    9762           0 :                 if (!bmap)
    9763           0 :                         return isl_map_free(map);
    9764           0 :                 isl_basic_map_free(map->p[i]);
    9765           0 :                 map->p[i] = bmap;
    9766             :         }
    9767             : 
    9768           0 :         map = sort_and_remove_duplicates(map);
    9769           0 :         return map;
    9770             : }
    9771             : 
    9772             : /* We normalize in place, but if anything goes wrong we need
    9773             :  * to return NULL, so we need to make sure we don't change the
    9774             :  * meaning of any possible other copies of map.
    9775             :  */
    9776    27226356 : __isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
    9777             : {
    9778             :         int i;
    9779             :         struct isl_basic_map *bmap;
    9780             : 
    9781    27226356 :         if (!map)
    9782           0 :                 return NULL;
    9783    27226356 :         if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
    9784     9734558 :                 return map;
    9785   206471662 :         for (i = 0; i < map->n; ++i) {
    9786   188979864 :                 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
    9787   188979864 :                 if (!bmap)
    9788           0 :                         goto error;
    9789   188979864 :                 isl_basic_map_free(map->p[i]);
    9790   188979864 :                 map->p[i] = bmap;
    9791             :         }
    9792             : 
    9793    17491798 :         map = sort_and_remove_duplicates(map);
    9794    17491798 :         if (map)
    9795    17491798 :                 ISL_F_SET(map, ISL_MAP_NORMALIZED);
    9796    17491798 :         return map;
    9797             : error:
    9798           0 :         isl_map_free(map);
    9799           0 :         return NULL;
    9800             : }
    9801             : 
    9802           0 : struct isl_set *isl_set_normalize(struct isl_set *set)
    9803             : {
    9804           0 :         return set_from_map(isl_map_normalize(set_to_map(set)));
    9805             : }
    9806             : 
    9807    13942842 : isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
    9808             :         __isl_keep isl_map *map2)
    9809             : {
    9810             :         int i;
    9811             :         isl_bool equal;
    9812             : 
    9813    13942842 :         if (!map1 || !map2)
    9814           0 :                 return isl_bool_error;
    9815             : 
    9816    13942842 :         if (map1 == map2)
    9817      329664 :                 return isl_bool_true;
    9818    13613178 :         if (!isl_space_is_equal(map1->dim, map2->dim))
    9819           0 :                 return isl_bool_false;
    9820             : 
    9821    13613178 :         map1 = isl_map_copy(map1);
    9822    13613178 :         map2 = isl_map_copy(map2);
    9823    13613178 :         map1 = isl_map_normalize(map1);
    9824    13613178 :         map2 = isl_map_normalize(map2);
    9825    13613178 :         if (!map1 || !map2)
    9826             :                 goto error;
    9827    13613178 :         equal = map1->n == map2->n;
    9828    20464952 :         for (i = 0; equal && i < map1->n; ++i) {
    9829     6851774 :                 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
    9830     6851774 :                 if (equal < 0)
    9831           0 :                         goto error;
    9832             :         }
    9833    13613178 :         isl_map_free(map1);
    9834    13613178 :         isl_map_free(map2);
    9835    13613178 :         return equal;
    9836             : error:
    9837           0 :         isl_map_free(map1);
    9838           0 :         isl_map_free(map2);
    9839           0 :         return isl_bool_error;
    9840             : }
    9841             : 
    9842           0 : isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
    9843             :         __isl_keep isl_set *set2)
    9844             : {
    9845           0 :         return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
    9846             : }
    9847             : 
    9848             : /* Return the basic maps in "map" as a list.
    9849             :  */
    9850           0 : __isl_give isl_basic_map_list *isl_map_get_basic_map_list(
    9851             :         __isl_keep isl_map *map)
    9852             : {
    9853             :         int i;
    9854             :         isl_ctx *ctx;
    9855             :         isl_basic_map_list *list;
    9856             : 
    9857           0 :         if (!map)
    9858           0 :                 return NULL;
    9859           0 :         ctx = isl_map_get_ctx(map);
    9860           0 :         list = isl_basic_map_list_alloc(ctx, map->n);
    9861             : 
    9862           0 :         for (i = 0; i < map->n; ++i) {
    9863             :                 isl_basic_map *bmap;
    9864             : 
    9865           0 :                 bmap = isl_basic_map_copy(map->p[i]);
    9866           0 :                 list = isl_basic_map_list_add(list, bmap);
    9867             :         }
    9868             : 
    9869           0 :         return list;
    9870             : }
    9871             : 
    9872             : /* Return the intersection of the elements in the non-empty list "list".
    9873             :  * All elements are assumed to live in the same space.
    9874             :  */
    9875           0 : __isl_give isl_basic_map *isl_basic_map_list_intersect(
    9876             :         __isl_take isl_basic_map_list *list)
    9877             : {
    9878             :         int i, n;
    9879             :         isl_basic_map *bmap;
    9880             : 
    9881           0 :         if (!list)
    9882           0 :                 return NULL;
    9883           0 :         n = isl_basic_map_list_n_basic_map(list);
    9884           0 :         if (n < 1)
    9885           0 :                 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
    9886             :                         "expecting non-empty list", goto error);
    9887             : 
    9888           0 :         bmap = isl_basic_map_list_get_basic_map(list, 0);
    9889           0 :         for (i = 1; i < n; ++i) {
    9890             :                 isl_basic_map *bmap_i;
    9891             : 
    9892           0 :                 bmap_i = isl_basic_map_list_get_basic_map(list, i);
    9893           0 :                 bmap = isl_basic_map_intersect(bmap, bmap_i);
    9894             :         }
    9895             : 
    9896           0 :         isl_basic_map_list_free(list);
    9897           0 :         return bmap;
    9898             : error:
    9899           0 :         isl_basic_map_list_free(list);
    9900           0 :         return NULL;
    9901             : }
    9902             : 
    9903             : /* Return the intersection of the elements in the non-empty list "list".
    9904             :  * All elements are assumed to live in the same space.
    9905             :  */
    9906           0 : __isl_give isl_basic_set *isl_basic_set_list_intersect(
    9907             :         __isl_take isl_basic_set_list *list)
    9908             : {
    9909           0 :         return isl_basic_map_list_intersect(list);
    9910             : }
    9911             : 
    9912             : /* Return the union of the elements of "list".
    9913             :  * The list is required to have at least one element.
    9914             :  */
    9915           0 : __isl_give isl_set *isl_basic_set_list_union(
    9916             :         __isl_take isl_basic_set_list *list)
    9917             : {
    9918             :         int i, n;
    9919             :         isl_space *space;
    9920             :         isl_basic_set *bset;
    9921             :         isl_set *set;
    9922             : 
    9923           0 :         if (!list)
    9924           0 :                 return NULL;
    9925           0 :         n = isl_basic_set_list_n_basic_set(list);
    9926           0 :         if (n < 1)
    9927           0 :                 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
    9928             :                         "expecting non-empty list", goto error);
    9929             : 
    9930           0 :         bset = isl_basic_set_list_get_basic_set(list, 0);
    9931           0 :         space = isl_basic_set_get_space(bset);
    9932           0 :         isl_basic_set_free(bset);
    9933             : 
    9934           0 :         set = isl_set_alloc_space(space, n, 0);
    9935           0 :         for (i = 0; i < n; ++i) {
    9936           0 :                 bset = isl_basic_set_list_get_basic_set(list, i);
    9937           0 :                 set = isl_set_add_basic_set(set, bset);
    9938             :         }
    9939             : 
    9940           0 :         isl_basic_set_list_free(list);
    9941           0 :         return set;
    9942             : error:
    9943           0 :         isl_basic_set_list_free(list);
    9944           0 :         return NULL;
    9945             : }
    9946             : 
    9947             : /* Return the union of the elements in the non-empty list "list".
    9948             :  * All elements are assumed to live in the same space.
    9949             :  */
    9950           0 : __isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
    9951             : {
    9952             :         int i, n;
    9953             :         isl_set *set;
    9954             : 
    9955           0 :         if (!list)
    9956           0 :                 return NULL;
    9957           0 :         n = isl_set_list_n_set(list);
    9958           0 :         if (n < 1)
    9959           0 :                 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
    9960             :                         "expecting non-empty list", goto error);
    9961             : 
    9962           0 :         set = isl_set_list_get_set(list, 0);
    9963           0 :         for (i = 1; i < n; ++i) {
    9964             :                 isl_set *set_i;
    9965             : 
    9966           0 :                 set_i = isl_set_list_get_set(list, i);
    9967           0 :                 set = isl_set_union(set, set_i);
    9968             :         }
    9969             : 
    9970           0 :         isl_set_list_free(list);
    9971           0 :         return set;
    9972             : error:
    9973           0 :         isl_set_list_free(list);
    9974           0 :         return NULL;
    9975             : }
    9976             : 
    9977           0 : __isl_give isl_basic_map *isl_basic_map_product(
    9978             :         __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
    9979             : {
    9980           0 :         isl_space *dim_result = NULL;
    9981             :         struct isl_basic_map *bmap;
    9982             :         unsigned in1, in2, out1, out2, nparam, total, pos;
    9983             :         struct isl_dim_map *dim_map1, *dim_map2;
    9984             : 
    9985           0 :         if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
    9986           0 :                 goto error;
    9987           0 :         dim_result = isl_space_product(isl_space_copy(bmap1->dim),
    9988             :                                                    isl_space_copy(bmap2->dim));
    9989             : 
    9990           0 :         in1 = isl_basic_map_dim(bmap1, isl_dim_in);
    9991           0 :         in2 = isl_basic_map_dim(bmap2, isl_dim_in);
    9992           0 :         out1 = isl_basic_map_dim(bmap1, isl_dim_out);
    9993           0 :         out2 = isl_basic_map_dim(bmap2, isl_dim_out);
    9994           0 :         nparam = isl_basic_map_dim(bmap1, isl_dim_param);
    9995             : 
    9996           0 :         total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
    9997           0 :         dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
    9998           0 :         dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
    9999           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
   10000           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
   10001           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
   10002           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
   10003           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
   10004           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
   10005           0 :         isl_dim_map_div(dim_map1, bmap1, pos += out2);
   10006           0 :         isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
   10007             : 
   10008           0 :         bmap = isl_basic_map_alloc_space(dim_result,
   10009           0 :                         bmap1->n_div + bmap2->n_div,
   10010           0 :                         bmap1->n_eq + bmap2->n_eq,
   10011           0 :                         bmap1->n_ineq + bmap2->n_ineq);
   10012           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
   10013           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
   10014           0 :         bmap = isl_basic_map_simplify(bmap);
   10015           0 :         return isl_basic_map_finalize(bmap);
   10016             : error:
   10017           0 :         isl_basic_map_free(bmap1);
   10018           0 :         isl_basic_map_free(bmap2);
   10019           0 :         return NULL;
   10020             : }
   10021             : 
   10022           0 : __isl_give isl_basic_map *isl_basic_map_flat_product(
   10023             :         __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
   10024             : {
   10025             :         isl_basic_map *prod;
   10026             : 
   10027           0 :         prod = isl_basic_map_product(bmap1, bmap2);
   10028           0 :         prod = isl_basic_map_flatten(prod);
   10029           0 :         return prod;
   10030             : }
   10031             : 
   10032           0 : __isl_give isl_basic_set *isl_basic_set_flat_product(
   10033             :         __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
   10034             : {
   10035           0 :         return isl_basic_map_flat_range_product(bset1, bset2);
   10036             : }
   10037             : 
   10038           0 : __isl_give isl_basic_map *isl_basic_map_domain_product(
   10039             :         __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
   10040             : {
   10041           0 :         isl_space *space_result = NULL;
   10042             :         isl_basic_map *bmap;
   10043             :         unsigned in1, in2, out, nparam, total, pos;
   10044             :         struct isl_dim_map *dim_map1, *dim_map2;
   10045             : 
   10046           0 :         if (!bmap1 || !bmap2)
   10047             :                 goto error;
   10048             : 
   10049           0 :         space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
   10050             :                                                 isl_space_copy(bmap2->dim));
   10051             : 
   10052           0 :         in1 = isl_basic_map_dim(bmap1, isl_dim_in);
   10053           0 :         in2 = isl_basic_map_dim(bmap2, isl_dim_in);
   10054           0 :         out = isl_basic_map_dim(bmap1, isl_dim_out);
   10055           0 :         nparam = isl_basic_map_dim(bmap1, isl_dim_param);
   10056             : 
   10057           0 :         total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
   10058           0 :         dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
   10059           0 :         dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
   10060           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
   10061           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
   10062           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
   10063           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
   10064           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
   10065           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
   10066           0 :         isl_dim_map_div(dim_map1, bmap1, pos += out);
   10067           0 :         isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
   10068             : 
   10069           0 :         bmap = isl_basic_map_alloc_space(space_result,
   10070           0 :                         bmap1->n_div + bmap2->n_div,
   10071           0 :                         bmap1->n_eq + bmap2->n_eq,
   10072           0 :                         bmap1->n_ineq + bmap2->n_ineq);
   10073           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
   10074           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
   10075           0 :         bmap = isl_basic_map_simplify(bmap);
   10076           0 :         return isl_basic_map_finalize(bmap);
   10077             : error:
   10078           0 :         isl_basic_map_free(bmap1);
   10079           0 :         isl_basic_map_free(bmap2);
   10080           0 :         return NULL;
   10081             : }
   10082             : 
   10083           0 : __isl_give isl_basic_map *isl_basic_map_range_product(
   10084             :         __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
   10085             : {
   10086             :         isl_bool rational;
   10087           0 :         isl_space *dim_result = NULL;
   10088             :         isl_basic_map *bmap;
   10089             :         unsigned in, out1, out2, nparam, total, pos;
   10090             :         struct isl_dim_map *dim_map1, *dim_map2;
   10091             : 
   10092           0 :         rational = isl_basic_map_is_rational(bmap1);
   10093           0 :         if (rational >= 0 && rational)
   10094           0 :                 rational = isl_basic_map_is_rational(bmap2);
   10095           0 :         if (!bmap1 || !bmap2 || rational < 0)
   10096             :                 goto error;
   10097             : 
   10098           0 :         if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
   10099           0 :                 goto error;
   10100             : 
   10101           0 :         dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
   10102             :                                            isl_space_copy(bmap2->dim));
   10103             : 
   10104           0 :         in = isl_basic_map_dim(bmap1, isl_dim_in);
   10105           0 :         out1 = isl_basic_map_dim(bmap1, isl_dim_out);
   10106           0 :         out2 = isl_basic_map_dim(bmap2, isl_dim_out);
   10107           0 :         nparam = isl_basic_map_dim(bmap1, isl_dim_param);
   10108             : 
   10109           0 :         total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
   10110           0 :         dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
   10111           0 :         dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
   10112           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
   10113           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
   10114           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
   10115           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
   10116           0 :         isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
   10117           0 :         isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
   10118           0 :         isl_dim_map_div(dim_map1, bmap1, pos += out2);
   10119           0 :         isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
   10120             : 
   10121           0 :         bmap = isl_basic_map_alloc_space(dim_result,
   10122           0 :                         bmap1->n_div + bmap2->n_div,
   10123           0 :                         bmap1->n_eq + bmap2->n_eq,
   10124           0 :                         bmap1->n_ineq + bmap2->n_ineq);
   10125           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
   10126           0 :         bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
   10127           0 :         if (rational)
   10128           0 :                 bmap = isl_basic_map_set_rational(bmap);
   10129           0 :         bmap = isl_basic_map_simplify(bmap);
   10130           0 :         return isl_basic_map_finalize(bmap);
   10131             : error:
   10132           0 :         isl_basic_map_free(bmap1);
   10133           0 :         isl_basic_map_free(bmap2);
   10134           0 :         return NULL;
   10135             : }
   10136             : 
   10137           0 : __isl_give isl_basic_map *isl_basic_map_flat_range_product(
   10138             :         __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
   10139             : {
   10140             :         isl_basic_map *prod;
   10141             : 
   10142           0 :         prod = isl_basic_map_range_product(bmap1, bmap2);
   10143           0 :         prod = isl_basic_map_flatten_range(prod);
   10144           0 :         return prod;
   10145             : }
   10146             : 
   10147             : /* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
   10148             :  * and collect the results.
   10149             :  * The result live in the space obtained by calling "space_product"
   10150             :  * on the spaces of "map1" and "map2".
   10151             :  * If "remove_duplicates" is set then the result may contain duplicates
   10152             :  * (even if the inputs do not) and so we try and remove the obvious
   10153             :  * duplicates.
   10154             :  */
   10155           0 : static __isl_give isl_map *map_product(__isl_take isl_map *map1,
   10156             :         __isl_take isl_map *map2,
   10157             :         __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
   10158             :                                            __isl_take isl_space *right),
   10159             :         __isl_give isl_basic_map *(*basic_map_product)(
   10160             :                 __isl_take isl_basic_map *left,
   10161             :                 __isl_take isl_basic_map *right),
   10162             :         int remove_duplicates)
   10163             : {
   10164           0 :         unsigned flags = 0;
   10165             :         struct isl_map *result;
   10166             :         int i, j;
   10167             :         isl_bool m;
   10168             : 
   10169           0 :         m = isl_map_has_equal_params(map1, map2);
   10170           0 :         if (m < 0)
   10171           0 :                 goto error;
   10172           0 :         if (!m)
   10173           0 :                 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
   10174             :                         "parameters don't match", goto error);
   10175             : 
   10176           0 :         if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
   10177           0 :             ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
   10178           0 :                 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
   10179             : 
   10180           0 :         result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
   10181             :                                                isl_space_copy(map2->dim)),
   10182           0 :                                 map1->n * map2->n, flags);
   10183           0 :         if (!result)
   10184           0 :                 goto error;
   10185           0 :         for (i = 0; i < map1->n; ++i)
   10186           0 :                 for (j = 0; j < map2->n; ++j) {
   10187             :                         struct isl_basic_map *part;
   10188           0 :                         part = basic_map_product(isl_basic_map_copy(map1->p[i]),
   10189           0 :                                                  isl_basic_map_copy(map2->p[j]));
   10190           0 :                         if (isl_basic_map_is_empty(part))
   10191           0 :                                 isl_basic_map_free(part);
   10192             :                         else
   10193           0 :                                 result = isl_map_add_basic_map(result, part);
   10194           0 :                         if (!result)
   10195           0 :                                 goto error;
   10196             :                 }
   10197           0 :         if (remove_duplicates)
   10198           0 :                 result = isl_map_remove_obvious_duplicates(result);
   10199           0 :         isl_map_free(map1);
   10200           0 :         isl_map_free(map2);
   10201           0 :         return result;
   10202             : error:
   10203           0 :         isl_map_free(map1);
   10204           0 :         isl_map_free(map2);
   10205           0 :         return NULL;
   10206             : }
   10207             : 
   10208             : /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
   10209             :  */
   10210           0 : static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
   10211             :         __isl_take isl_map *map2)
   10212             : {
   10213           0 :         return map_product(map1, map2, &isl_space_product,
   10214             :                         &isl_basic_map_product, 0);
   10215             : }
   10216             : 
   10217           0 : __isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
   10218             :         __isl_take isl_map *map2)
   10219             : {
   10220           0 :         return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
   10221             : }
   10222             : 
   10223             : /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
   10224             :  */
   10225           0 : __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
   10226             :         __isl_take isl_map *map2)
   10227             : {
   10228             :         isl_map *prod;
   10229             : 
   10230           0 :         prod = isl_map_product(map1, map2);
   10231           0 :         prod = isl_map_flatten(prod);
   10232           0 :         return prod;
   10233             : }
   10234             : 
   10235             : /* Given two set A and B, construct its Cartesian product A x B.
   10236             :  */
   10237           0 : struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
   10238             : {
   10239           0 :         return isl_map_range_product(set1, set2);
   10240             : }
   10241             : 
   10242           0 : __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
   10243             :         __isl_take isl_set *set2)
   10244             : {
   10245           0 :         return isl_map_flat_range_product(set1, set2);
   10246             : }
   10247             : 
   10248             : /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
   10249             :  */
   10250           0 : static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
   10251             :         __isl_take isl_map *map2)
   10252             : {
   10253           0 :         return map_product(map1, map2, &isl_space_domain_product,
   10254             :                                 &isl_basic_map_domain_product, 1);
   10255             : }
   10256             : 
   10257             : /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
   10258             :  */
   10259           0 : static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
   10260             :         __isl_take isl_map *map2)
   10261             : {
   10262           0 :         return map_product(map1, map2, &isl_space_range_product,
   10263             :                                 &isl_basic_map_range_product, 1);
   10264             : }
   10265             : 
   10266           0 : __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
   10267             :         __isl_take isl_map *map2)
   10268             : {
   10269           0 :         return isl_map_align_params_map_map_and(map1, map2,
   10270             :                                                 &map_domain_product_aligned);
   10271             : }
   10272             : 
   10273           0 : __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
   10274             :         __isl_take isl_map *map2)
   10275             : {
   10276           0 :         return isl_map_align_params_map_map_and(map1, map2,
   10277             :                                                 &map_range_product_aligned);
   10278             : }
   10279             : 
   10280             : /* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
   10281             :  */
   10282           0 : __isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
   10283             : {
   10284             :         isl_space *space;
   10285             :         int total1, keep1, total2, keep2;
   10286             : 
   10287           0 :         if (!map)
   10288           0 :                 return NULL;
   10289           0 :         if (!isl_space_domain_is_wrapping(map->dim) ||
   10290           0 :             !isl_space_range_is_wrapping(map->dim))
   10291           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
   10292             :                         "not a product", return isl_map_free(map));
   10293             : 
   10294           0 :         space = isl_map_get_space(map);
   10295           0 :         total1 = isl_space_dim(space, isl_dim_in);
   10296           0 :         total2 = isl_space_dim(space, isl_dim_out);
   10297           0 :         space = isl_space_factor_domain(space);
   10298           0 :         keep1 = isl_space_dim(space, isl_dim_in);
   10299           0 :         keep2 = isl_space_dim(space, isl_dim_out);
   10300           0 :         map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
   10301           0 :         map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
   10302           0 :         map = isl_map_reset_space(map, space);
   10303             : 
   10304           0 :         return map;
   10305             : }
   10306             : 
   10307             : /* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
   10308             :  */
   10309           0 : __isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
   10310             : {
   10311             :         isl_space *space;
   10312             :         int total1, keep1, total2, keep2;
   10313             : 
   10314           0 :         if (!map)
   10315           0 :                 return NULL;
   10316           0 :         if (!isl_space_domain_is_wrapping(map->dim) ||
   10317           0 :             !isl_space_range_is_wrapping(map->dim))
   10318           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
   10319             :                         "not a product", return isl_map_free(map));
   10320             : 
   10321           0 :         space = isl_map_get_space(map);
   10322           0 :         total1 = isl_space_dim(space, isl_dim_in);
   10323           0 :         total2 = isl_space_dim(space, isl_dim_out);
   10324           0 :         space = isl_space_factor_range(space);
   10325           0 :         keep1 = isl_space_dim(space, isl_dim_in);
   10326           0 :         keep2 = isl_space_dim(space, isl_dim_out);
   10327           0 :         map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
   10328           0 :         map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
   10329           0 :         map = isl_map_reset_space(map, space);
   10330             : 
   10331           0 :         return map;
   10332             : }
   10333             : 
   10334             : /* Given a map of the form [A -> B] -> C, return the map A -> C.
   10335             :  */
   10336           0 : __isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
   10337             : {
   10338             :         isl_space *space;
   10339             :         int total, keep;
   10340             : 
   10341           0 :         if (!map)
   10342           0 :                 return NULL;
   10343           0 :         if (!isl_space_domain_is_wrapping(map->dim))
   10344           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
   10345             :                         "domain is not a product", return isl_map_free(map));
   10346             : 
   10347           0 :         space = isl_map_get_space(map);
   10348           0 :         total = isl_space_dim(space, isl_dim_in);
   10349           0 :         space = isl_space_domain_factor_domain(space);
   10350           0 :         keep = isl_space_dim(space, isl_dim_in);
   10351           0 :         map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
   10352           0 :         map = isl_map_reset_space(map, space);
   10353             : 
   10354           0 :         return map;
   10355             : }
   10356             : 
   10357             : /* Given a map of the form [A -> B] -> C, return the map B -> C.
   10358             :  */
   10359           0 : __isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
   10360             : {
   10361             :         isl_space *space;
   10362             :         int total, keep;
   10363             : 
   10364           0 :         if (!map)
   10365           0 :                 return NULL;
   10366           0 :         if (!isl_space_domain_is_wrapping(map->dim))
   10367           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
   10368             :                         "domain is not a product", return isl_map_free(map));
   10369             : 
   10370           0 :         space = isl_map_get_space(map);
   10371           0 :         total = isl_space_dim(space, isl_dim_in);
   10372           0 :         space = isl_space_domain_factor_range(space);
   10373           0 :         keep = isl_space_dim(space, isl_dim_in);
   10374           0 :         map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
   10375           0 :         map = isl_map_reset_space(map, space);
   10376             : 
   10377           0 :         return map;
   10378             : }
   10379             : 
   10380             : /* Given a map A -> [B -> C], extract the map A -> B.
   10381             :  */
   10382           0 : __isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
   10383             : {
   10384             :         isl_space *space;
   10385             :         int total, keep;
   10386             : 
   10387           0 :         if (!map)
   10388           0 :                 return NULL;
   10389           0 :         if (!isl_space_range_is_wrapping(map->dim))
   10390           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
   10391             :                         "range is not a product", return isl_map_free(map));
   10392             : 
   10393           0 :         space = isl_map_get_space(map);
   10394           0 :         total = isl_space_dim(space, isl_dim_out);
   10395           0 :         space = isl_space_range_factor_domain(space);
   10396           0 :         keep = isl_space_dim(space, isl_dim_out);
   10397           0 :         map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
   10398           0 :         map = isl_map_reset_space(map, space);
   10399             : 
   10400           0 :         return map;
   10401             : }
   10402             : 
   10403             : /* Given a map A -> [B -> C], extract the map A -> C.
   10404             :  */
   10405           0 : __isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
   10406             : {
   10407             :         isl_space *space;
   10408             :         int total, keep;
   10409             : 
   10410           0 :         if (!map)
   10411           0 :                 return NULL;
   10412           0 :         if (!isl_space_range_is_wrapping(map->dim))
   10413           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
   10414             :                         "range is not a product", return isl_map_free(map));
   10415             : 
   10416           0 :         space = isl_map_get_space(map);
   10417           0 :         total = isl_space_dim(space, isl_dim_out);
   10418           0 :         space = isl_space_range_factor_range(space);
   10419           0 :         keep = isl_space_dim(space, isl_dim_out);
   10420           0 :         map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
   10421           0 :         map = isl_map_reset_space(map, space);
   10422             : 
   10423           0 :         return map;
   10424             : }
   10425             : 
   10426             : /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
   10427             :  */
   10428           0 : __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
   10429             :         __isl_take isl_map *map2)
   10430             : {
   10431             :         isl_map *prod;
   10432             : 
   10433           0 :         prod = isl_map_domain_product(map1, map2);
   10434           0 :         prod = isl_map_flatten_domain(prod);
   10435           0 :         return prod;
   10436             : }
   10437             : 
   10438             : /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
   10439             :  */
   10440           0 : __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
   10441             :         __isl_take isl_map *map2)
   10442             : {
   10443             :         isl_map *prod;
   10444             : 
   10445           0 :         prod = isl_map_range_product(map1, map2);
   10446           0 :         prod = isl_map_flatten_range(prod);
   10447           0 :         return prod;
   10448             : }
   10449             : 
   10450  2898920016 : uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
   10451             : {
   10452             :         int i;
   10453  2898920016 :         uint32_t hash = isl_hash_init();
   10454             :         unsigned total;
   10455             : 
   10456  2898920016 :         if (!bmap)
   10457           0 :                 return 0;
   10458  2898920016 :         bmap = isl_basic_map_copy(bmap);
   10459  2898920016 :         bmap = isl_basic_map_normalize(bmap);
   10460  2898920016 :         if (!bmap)
   10461           0 :                 return 0;
   10462  2898920016 :         total = isl_basic_map_total_dim(bmap);
   10463  2898920016 :         isl_hash_byte(hash, bmap->n_eq & 0xFF);
   10464  7457623895 :         for (i = 0; i < bmap->n_eq; ++i) {
   10465             :                 uint32_t c_hash;
   10466  4558703879 :                 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
   10467  4558703879 :                 isl_hash_hash(hash, c_hash);
   10468             :         }
   10469  2898920016 :         isl_hash_byte(hash, bmap->n_ineq & 0xFF);
   10470  2898920016 :         for (i = 0; i < bmap->n_ineq; ++i) {
   10471             :                 uint32_t c_hash;
   10472           0 :                 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
   10473           0 :                 isl_hash_hash(hash, c_hash);
   10474             :         }
   10475  2898920016 :         isl_hash_byte(hash, bmap->n_div & 0xFF);
   10476  2898920016 :         for (i = 0; i < bmap->n_div; ++i) {
   10477             :                 uint32_t c_hash;
   10478           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
   10479           0 :                         continue;
   10480           0 :                 isl_hash_byte(hash, i & 0xFF);
   10481           0 :                 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
   10482           0 :                 isl_hash_hash(hash, c_hash);
   10483             :         }
   10484  2898920016 :         isl_basic_map_free(bmap);
   10485  2898920016 :         return hash;
   10486             : }
   10487             : 
   10488           0 : uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
   10489             : {
   10490           0 :         return isl_basic_map_get_hash(bset_to_bmap(bset));
   10491             : }
   10492             : 
   10493           0 : uint32_t isl_map_get_hash(__isl_keep isl_map *map)
   10494             : {
   10495             :         int i;
   10496             :         uint32_t hash;
   10497             : 
   10498           0 :         if (!map)
   10499           0 :                 return 0;
   10500           0 :         map = isl_map_copy(map);
   10501           0 :         map = isl_map_normalize(map);
   10502           0 :         if (!map)
   10503           0 :                 return 0;
   10504             : 
   10505           0 :         hash = isl_hash_init();
   10506           0 :         for (i = 0; i < map->n; ++i) {
   10507             :                 uint32_t bmap_hash;
   10508           0 :                 bmap_hash = isl_basic_map_get_hash(map->p[i]);
   10509           0 :                 isl_hash_hash(hash, bmap_hash);
   10510             :         }
   10511             :                 
   10512           0 :         isl_map_free(map);
   10513             : 
   10514           0 :         return hash;
   10515             : }
   10516             : 
   10517           0 : uint32_t isl_set_get_hash(__isl_keep isl_set *set)
   10518             : {
   10519           0 :         return isl_map_get_hash(set_to_map(set));
   10520             : }
   10521             : 
   10522             : /* Return the number of basic maps in the (current) representation of "map".
   10523             :  */
   10524           0 : int isl_map_n_basic_map(__isl_keep isl_map *map)
   10525             : {
   10526           0 :         return map ? map->n : 0;
   10527             : }
   10528             : 
   10529      112944 : int isl_set_n_basic_set(__isl_keep isl_set *set)
   10530             : {
   10531      112944 :         return set ? set->n : 0;
   10532             : }
   10533             : 
   10534           0 : isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
   10535             :         isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
   10536             : {
   10537             :         int i;
   10538             : 
   10539           0 :         if (!map)
   10540           0 :                 return isl_stat_error;
   10541             : 
   10542           0 :         for (i = 0; i < map->n; ++i)
   10543           0 :                 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
   10544           0 :                         return isl_stat_error;
   10545             : 
   10546           0 :         return isl_stat_ok;
   10547             : }
   10548             : 
   10549      112944 : isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
   10550             :         isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
   10551             : {
   10552             :         int i;
   10553             : 
   10554      112944 :         if (!set)
   10555           0 :                 return isl_stat_error;
   10556             : 
   10557      225888 :         for (i = 0; i < set->n; ++i)
   10558      112944 :                 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
   10559           0 :                         return isl_stat_error;
   10560             : 
   10561      112944 :         return isl_stat_ok;
   10562             : }
   10563             : 
   10564             : /* Return a list of basic sets, the union of which is equal to "set".
   10565             :  */
   10566           0 : __isl_give isl_basic_set_list *isl_set_get_basic_set_list(
   10567             :         __isl_keep isl_set *set)
   10568             : {
   10569             :         int i;
   10570             :         isl_basic_set_list *list;
   10571             : 
   10572           0 :         if (!set)
   10573           0 :                 return NULL;
   10574             : 
   10575           0 :         list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
   10576           0 :         for (i = 0; i < set->n; ++i) {
   10577             :                 isl_basic_set *bset;
   10578             : 
   10579           0 :                 bset = isl_basic_set_copy(set->p[i]);
   10580           0 :                 list = isl_basic_set_list_add(list, bset);
   10581             :         }
   10582             : 
   10583           0 :         return list;
   10584             : }
   10585             : 
   10586           0 : __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
   10587             : {
   10588             :         isl_space *dim;
   10589             : 
   10590           0 :         if (!bset)
   10591           0 :                 return NULL;
   10592             : 
   10593           0 :         bset = isl_basic_set_cow(bset);
   10594           0 :         if (!bset)
   10595           0 :                 return NULL;
   10596             : 
   10597           0 :         dim = isl_basic_set_get_space(bset);
   10598           0 :         dim = isl_space_lift(dim, bset->n_div);
   10599           0 :         if (!dim)
   10600           0 :                 goto error;
   10601           0 :         isl_space_free(bset->dim);
   10602           0 :         bset->dim = dim;
   10603           0 :         bset->extra -= bset->n_div;
   10604           0 :         bset->n_div = 0;
   10605             : 
   10606           0 :         bset = isl_basic_set_finalize(bset);
   10607             : 
   10608           0 :         return bset;
   10609             : error:
   10610           0 :         isl_basic_set_free(bset);
   10611           0 :         return NULL;
   10612             : }
   10613             : 
   10614           0 : __isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
   10615             : {
   10616             :         int i;
   10617             :         isl_space *dim;
   10618             :         unsigned n_div;
   10619             : 
   10620           0 :         set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
   10621             : 
   10622           0 :         if (!set)
   10623           0 :                 return NULL;
   10624             : 
   10625           0 :         set = isl_set_cow(set);
   10626           0 :         if (!set)
   10627           0 :                 return NULL;
   10628             : 
   10629           0 :         n_div = set->p[0]->n_div;
   10630           0 :         dim = isl_set_get_space(set);
   10631           0 :         dim = isl_space_lift(dim, n_div);
   10632           0 :         if (!dim)
   10633           0 :                 goto error;
   10634           0 :         isl_space_free(set->dim);
   10635           0 :         set->dim = dim;
   10636             : 
   10637           0 :         for (i = 0; i < set->n; ++i) {
   10638           0 :                 set->p[i] = isl_basic_set_lift(set->p[i]);
   10639           0 :                 if (!set->p[i])
   10640           0 :                         goto error;
   10641             :         }
   10642             : 
   10643           0 :         return set;
   10644             : error:
   10645           0 :         isl_set_free(set);
   10646           0 :         return NULL;
   10647             : }
   10648             : 
   10649           0 : int isl_basic_set_size(__isl_keep isl_basic_set *bset)
   10650             : {
   10651             :         unsigned dim;
   10652           0 :         int size = 0;
   10653             : 
   10654           0 :         if (!bset)
   10655           0 :                 return -1;
   10656             : 
   10657           0 :         dim = isl_basic_set_total_dim(bset);
   10658           0 :         size += bset->n_eq * (1 + dim);
   10659           0 :         size += bset->n_ineq * (1 + dim);
   10660           0 :         size += bset->n_div * (2 + dim);
   10661             : 
   10662           0 :         return size;
   10663             : }
   10664             : 
   10665           0 : int isl_set_size(__isl_keep isl_set *set)
   10666             : {
   10667             :         int i;
   10668           0 :         int size = 0;
   10669             : 
   10670           0 :         if (!set)
   10671           0 :                 return -1;
   10672             : 
   10673           0 :         for (i = 0; i < set->n; ++i)
   10674           0 :                 size += isl_basic_set_size(set->p[i]);
   10675             : 
   10676           0 :         return size;
   10677             : }
   10678             : 
   10679             : /* Check if there is any lower bound (if lower == 0) and/or upper
   10680             :  * bound (if upper == 0) on the specified dim.
   10681             :  */
   10682           0 : static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
   10683             :         enum isl_dim_type type, unsigned pos, int lower, int upper)
   10684             : {
   10685             :         int i;
   10686             : 
   10687           0 :         if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
   10688           0 :                 return isl_bool_error;
   10689             : 
   10690           0 :         pos += isl_basic_map_offset(bmap, type);
   10691             : 
   10692           0 :         for (i = 0; i < bmap->n_div; ++i) {
   10693           0 :                 if (isl_int_is_zero(bmap->div[i][0]))
   10694           0 :                         continue;
   10695           0 :                 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
   10696           0 :                         return isl_bool_true;
   10697             :         }
   10698             : 
   10699           0 :         for (i = 0; i < bmap->n_eq; ++i)
   10700           0 :                 if (!isl_int_is_zero(bmap->eq[i][pos]))
   10701           0 :                         return isl_bool_true;
   10702             : 
   10703           0 :         for (i = 0; i < bmap->n_ineq; ++i) {
   10704           0 :                 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
   10705           0 :                 if (sgn > 0)
   10706           0 :                         lower = 1;
   10707           0 :                 if (sgn < 0)
   10708           0 :                         upper = 1;
   10709             :         }
   10710             : 
   10711           0 :         return lower && upper;
   10712             : }
   10713             : 
   10714           0 : isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
   10715             :         enum isl_dim_type type, unsigned pos)
   10716             : {
   10717           0 :         return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
   10718             : }
   10719             : 
   10720           0 : isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
   10721             :         enum isl_dim_type type, unsigned pos)
   10722             : {
   10723           0 :         return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
   10724             : }
   10725             : 
   10726           0 : isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
   10727             :         enum isl_dim_type type, unsigned pos)
   10728             : {
   10729           0 :         return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
   10730             : }
   10731             : 
   10732           0 : isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
   10733             :         enum isl_dim_type type, unsigned pos)
   10734             : {
   10735             :         int i;
   10736             : 
   10737           0 :         if (!map)
   10738           0 :                 return isl_bool_error;
   10739             : 
   10740           0 :         for (i = 0; i < map->n; ++i) {
   10741             :                 isl_bool bounded;
   10742           0 :                 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
   10743           0 :                 if (bounded < 0 || !bounded)
   10744           0 :                         return bounded;
   10745             :         }
   10746             : 
   10747           0 :         return isl_bool_true;
   10748             : }
   10749             : 
   10750             : /* Return true if the specified dim is involved in both an upper bound
   10751             :  * and a lower bound.
   10752             :  */
   10753           0 : isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
   10754             :         enum isl_dim_type type, unsigned pos)
   10755             : {
   10756           0 :         return isl_map_dim_is_bounded(set_to_map(set), type, pos);
   10757             : }
   10758             : 
   10759             : /* Does "map" have a bound (according to "fn") for any of its basic maps?
   10760             :  */
   10761           0 : static isl_bool has_any_bound(__isl_keep isl_map *map,
   10762             :         enum isl_dim_type type, unsigned pos,
   10763             :         isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
   10764             :                   enum isl_dim_type type, unsigned pos))
   10765             : {
   10766             :         int i;
   10767             : 
   10768           0 :         if (!map)
   10769           0 :                 return isl_bool_error;
   10770             : 
   10771           0 :         for (i = 0; i < map->n; ++i) {
   10772             :                 isl_bool bounded;
   10773           0 :                 bounded = fn(map->p[i], type, pos);
   10774           0 :                 if (bounded < 0 || bounded)
   10775           0 :                         return bounded;
   10776             :         }
   10777             : 
   10778           0 :         return isl_bool_false;
   10779             : }
   10780             : 
   10781             : /* Return 1 if the specified dim is involved in any lower bound.
   10782             :  */
   10783           0 : isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
   10784             :         enum isl_dim_type type, unsigned pos)
   10785             : {
   10786           0 :         return has_any_bound(set, type, pos,
   10787             :                                 &isl_basic_map_dim_has_lower_bound);
   10788             : }
   10789             : 
   10790             : /* Return 1 if the specified dim is involved in any upper bound.
   10791             :  */
   10792           0 : isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
   10793             :         enum isl_dim_type type, unsigned pos)
   10794             : {
   10795           0 :         return has_any_bound(set, type, pos,
   10796             :                                 &isl_basic_map_dim_has_upper_bound);
   10797             : }
   10798             : 
   10799             : /* Does "map" have a bound (according to "fn") for all of its basic maps?
   10800             :  */
   10801           0 : static isl_bool has_bound(__isl_keep isl_map *map,
   10802             :         enum isl_dim_type type, unsigned pos,
   10803             :         isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
   10804             :                   enum isl_dim_type type, unsigned pos))
   10805             : {
   10806             :         int i;
   10807             : 
   10808           0 :         if (!map)
   10809           0 :                 return isl_bool_error;
   10810             : 
   10811           0 :         for (i = 0; i < map->n; ++i) {
   10812             :                 isl_bool bounded;
   10813           0 :                 bounded = fn(map->p[i], type, pos);
   10814           0 :                 if (bounded < 0 || !bounded)
   10815           0 :                         return bounded;
   10816             :         }
   10817             : 
   10818           0 :         return isl_bool_true;
   10819             : }
   10820             : 
   10821             : /* Return 1 if the specified dim has a lower bound (in each of its basic sets).
   10822             :  */
   10823           0 : isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
   10824             :         enum isl_dim_type type, unsigned pos)
   10825             : {
   10826           0 :         return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
   10827             : }
   10828             : 
   10829             : /* Return 1 if the specified dim has an upper bound (in each of its basic sets).
   10830             :  */
   10831           0 : isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
   10832             :         enum isl_dim_type type, unsigned pos)
   10833             : {
   10834           0 :         return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
   10835             : }
   10836             : 
   10837             : /* For each of the "n" variables starting at "first", determine
   10838             :  * the sign of the variable and put the results in the first "n"
   10839             :  * elements of the array "signs".
   10840             :  * Sign
   10841             :  *      1 means that the variable is non-negative
   10842             :  *      -1 means that the variable is non-positive
   10843             :  *      0 means the variable attains both positive and negative values.
   10844             :  */
   10845           0 : isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
   10846             :         unsigned first, unsigned n, int *signs)
   10847             : {
   10848           0 :         isl_vec *bound = NULL;
   10849           0 :         struct isl_tab *tab = NULL;
   10850             :         struct isl_tab_undo *snap;
   10851             :         int i;
   10852             : 
   10853           0 :         if (!bset || !signs)
   10854           0 :                 return isl_stat_error;
   10855             : 
   10856           0 :         bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
   10857           0 :         tab = isl_tab_from_basic_set(bset, 0);
   10858           0 :         if (!bound || !tab)
   10859             :                 goto error;
   10860             : 
   10861           0 :         isl_seq_clr(bound->el, bound->size);
   10862           0 :         isl_int_set_si(bound->el[0], -1);
   10863             : 
   10864           0 :         snap = isl_tab_snap(tab);
   10865           0 :         for (i = 0; i < n; ++i) {
   10866             :                 int empty;
   10867             : 
   10868           0 :                 isl_int_set_si(bound->el[1 + first + i], -1);
   10869           0 :                 if (isl_tab_add_ineq(tab, bound->el) < 0)
   10870           0 :                         goto error;
   10871           0 :                 empty = tab->empty;
   10872           0 :                 isl_int_set_si(bound->el[1 + first + i], 0);
   10873           0 :                 if (isl_tab_rollback(tab, snap) < 0)
   10874           0 :                         goto error;
   10875             : 
   10876           0 :                 if (empty) {
   10877           0 :                         signs[i] = 1;
   10878           0 :                         continue;
   10879             :                 }
   10880             : 
   10881           0 :                 isl_int_set_si(bound->el[1 + first + i], 1);
   10882           0 :                 if (isl_tab_add_ineq(tab, bound->el) < 0)
   10883           0 :                         goto error;
   10884           0 :                 empty = tab->empty;
   10885           0 :                 isl_int_set_si(bound->el[1 + first + i], 0);
   10886           0 :                 if (isl_tab_rollback(tab, snap) < 0)
   10887           0 :                         goto error;
   10888             : 
   10889           0 :                 signs[i] = empty ? -1 : 0;
   10890             :         }
   10891             : 
   10892           0 :         isl_tab_free(tab);
   10893           0 :         isl_vec_free(bound);
   10894           0 :         return isl_stat_ok;
   10895             : error:
   10896           0 :         isl_tab_free(tab);
   10897           0 :         isl_vec_free(bound);
   10898           0 :         return isl_stat_error;
   10899             : }
   10900             : 
   10901           0 : isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
   10902             :         enum isl_dim_type type, unsigned first, unsigned n, int *signs)
   10903             : {
   10904           0 :         if (!bset || !signs)
   10905           0 :                 return isl_stat_error;
   10906           0 :         isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
   10907             :                 return isl_stat_error);
   10908             : 
   10909           0 :         first += pos(bset->dim, type) - 1;
   10910           0 :         return isl_basic_set_vars_get_sign(bset, first, n, signs);
   10911             : }
   10912             : 
   10913             : /* Is it possible for the integer division "div" to depend (possibly
   10914             :  * indirectly) on any output dimensions?
   10915             :  *
   10916             :  * If the div is undefined, then we conservatively assume that it
   10917             :  * may depend on them.
   10918             :  * Otherwise, we check if it actually depends on them or on any integer
   10919             :  * divisions that may depend on them.
   10920             :  */
   10921           0 : static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
   10922             : {
   10923             :         int i;
   10924             :         unsigned n_out, o_out;
   10925             :         unsigned n_div, o_div;
   10926             : 
   10927           0 :         if (isl_int_is_zero(bmap->div[div][0]))
   10928           0 :                 return isl_bool_true;
   10929             : 
   10930           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
   10931           0 :         o_out = isl_basic_map_offset(bmap, isl_dim_out);
   10932             : 
   10933           0 :         if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
   10934           0 :                 return isl_bool_true;
   10935             : 
   10936           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
   10937           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
   10938             : 
   10939           0 :         for (i = 0; i < n_div; ++i) {
   10940             :                 isl_bool may_involve;
   10941             : 
   10942           0 :                 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
   10943           0 :                         continue;
   10944           0 :                 may_involve = div_may_involve_output(bmap, i);
   10945           0 :                 if (may_involve < 0 || may_involve)
   10946           0 :                         return may_involve;
   10947             :         }
   10948             : 
   10949           0 :         return isl_bool_false;
   10950             : }
   10951             : 
   10952             : /* Return the first integer division of "bmap" in the range
   10953             :  * [first, first + n[ that may depend on any output dimensions and
   10954             :  * that has a non-zero coefficient in "c" (where the first coefficient
   10955             :  * in "c" corresponds to integer division "first").
   10956             :  */
   10957           0 : static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
   10958             :         isl_int *c, int first, int n)
   10959             : {
   10960             :         int k;
   10961             : 
   10962           0 :         if (!bmap)
   10963           0 :                 return -1;
   10964             : 
   10965           0 :         for (k = first; k < first + n; ++k) {
   10966             :                 isl_bool may_involve;
   10967             : 
   10968           0 :                 if (isl_int_is_zero(c[k]))
   10969           0 :                         continue;
   10970           0 :                 may_involve = div_may_involve_output(bmap, k);
   10971           0 :                 if (may_involve < 0)
   10972           0 :                         return -1;
   10973           0 :                 if (may_involve)
   10974           0 :                         return k;
   10975             :         }
   10976             : 
   10977           0 :         return first + n;
   10978             : }
   10979             : 
   10980             : /* Look for a pair of inequality constraints in "bmap" of the form
   10981             :  *
   10982             :  *      -l + i >= 0          or              i >= l
   10983             :  * and
   10984             :  *      n + l - i >= 0               or              i <= l + n
   10985             :  *
   10986             :  * with n < "m" and i the output dimension at position "pos".
   10987             :  * (Note that n >= 0 as otherwise the two constraints would conflict.)
   10988             :  * Furthermore, "l" is only allowed to involve parameters, input dimensions
   10989             :  * and earlier output dimensions, as well as integer divisions that do
   10990             :  * not involve any of the output dimensions.
   10991             :  *
   10992             :  * Return the index of the first inequality constraint or bmap->n_ineq
   10993             :  * if no such pair can be found.
   10994             :  */
   10995           0 : static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
   10996             :         int pos, isl_int m)
   10997             : {
   10998             :         int i, j;
   10999             :         isl_ctx *ctx;
   11000             :         unsigned total;
   11001             :         unsigned n_div, o_div;
   11002             :         unsigned n_out, o_out;
   11003             :         int less;
   11004             : 
   11005           0 :         if (!bmap)
   11006           0 :                 return -1;
   11007             : 
   11008           0 :         ctx = isl_basic_map_get_ctx(bmap);
   11009           0 :         total = isl_basic_map_total_dim(bmap);
   11010           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
   11011           0 :         o_out = isl_basic_map_offset(bmap, isl_dim_out);
   11012           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
   11013           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
   11014           0 :         for (i = 0; i < bmap->n_ineq; ++i) {
   11015           0 :                 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
   11016           0 :                         continue;
   11017           0 :                 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
   11018           0 :                                         n_out - (pos + 1)) != -1)
   11019           0 :                         continue;
   11020           0 :                 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
   11021           0 :                                                 0, n_div) < n_div)
   11022           0 :                         continue;
   11023           0 :                 for (j = i + 1; j < bmap->n_ineq; ++j) {
   11024           0 :                         if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
   11025             :                                             ctx->one))
   11026           0 :                                 continue;
   11027           0 :                         if (!isl_seq_is_neg(bmap->ineq[i] + 1,
   11028           0 :                                             bmap->ineq[j] + 1, total))
   11029           0 :                                 continue;
   11030           0 :                         break;
   11031             :                 }
   11032           0 :                 if (j >= bmap->n_ineq)
   11033           0 :                         continue;
   11034           0 :                 isl_int_add(bmap->ineq[i][0],
   11035             :                             bmap->ineq[i][0], bmap->ineq[j][0]);
   11036           0 :                 less = isl_int_abs_lt(bmap->ineq[i][0], m);
   11037           0 :                 isl_int_sub(bmap->ineq[i][0],
   11038             :                             bmap->ineq[i][0], bmap->ineq[j][0]);
   11039           0 :                 if (!less)
   11040           0 :                         continue;
   11041           0 :                 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
   11042           0 :                         return i;
   11043             :                 else
   11044           0 :                         return j;
   11045             :         }
   11046             : 
   11047           0 :         return bmap->n_ineq;
   11048             : }
   11049             : 
   11050             : /* Return the index of the equality of "bmap" that defines
   11051             :  * the output dimension "pos" in terms of earlier dimensions.
   11052             :  * The equality may also involve integer divisions, as long
   11053             :  * as those integer divisions are defined in terms of
   11054             :  * parameters or input dimensions.
   11055             :  * In this case, *div is set to the number of integer divisions and
   11056             :  * *ineq is set to the number of inequality constraints (provided
   11057             :  * div and ineq are not NULL).
   11058             :  *
   11059             :  * The equality may also involve a single integer division involving
   11060             :  * the output dimensions (typically only output dimension "pos") as
   11061             :  * long as the coefficient of output dimension "pos" is 1 or -1 and
   11062             :  * there is a pair of constraints i >= l and i <= l + n, with i referring
   11063             :  * to output dimension "pos", l an expression involving only earlier
   11064             :  * dimensions and n smaller than the coefficient of the integer division
   11065             :  * in the equality.  In this case, the output dimension can be defined
   11066             :  * in terms of a modulo expression that does not involve the integer division.
   11067             :  * *div is then set to this single integer division and
   11068             :  * *ineq is set to the index of constraint i >= l.
   11069             :  *
   11070             :  * Return bmap->n_eq if there is no such equality.
   11071             :  * Return -1 on error.
   11072             :  */
   11073           0 : int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
   11074             :         int pos, int *div, int *ineq)
   11075             : {
   11076             :         int j, k, l;
   11077             :         unsigned n_out, o_out;
   11078             :         unsigned n_div, o_div;
   11079             : 
   11080           0 :         if (!bmap)
   11081           0 :                 return -1;
   11082             : 
   11083           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
   11084           0 :         o_out = isl_basic_map_offset(bmap, isl_dim_out);
   11085           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
   11086           0 :         o_div = isl_basic_map_offset(bmap, isl_dim_div);
   11087             : 
   11088           0 :         if (ineq)
   11089           0 :                 *ineq = bmap->n_ineq;
   11090           0 :         if (div)
   11091           0 :                 *div = n_div;
   11092           0 :         for (j = 0; j < bmap->n_eq; ++j) {
   11093           0 :                 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
   11094           0 :                         continue;
   11095           0 :                 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
   11096           0 :                                         n_out - (pos + 1)) != -1)
   11097           0 :                         continue;
   11098           0 :                 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
   11099             :                                                 0, n_div);
   11100           0 :                 if (k >= n_div)
   11101           0 :                         return j;
   11102           0 :                 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
   11103           0 :                     !isl_int_is_negone(bmap->eq[j][o_out + pos]))
   11104           0 :                         continue;
   11105           0 :                 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
   11106           0 :                                                 k + 1, n_div - (k+1)) < n_div)
   11107           0 :                         continue;
   11108           0 :                 l = find_modulo_constraint_pair(bmap, pos,
   11109           0 :                                                 bmap->eq[j][o_div + k]);
   11110           0 :                 if (l < 0)
   11111           0 :                         return -1;
   11112           0 :                 if (l >= bmap->n_ineq)
   11113           0 :                         continue;
   11114           0 :                 if (div)
   11115           0 :                         *div = k;
   11116           0 :                 if (ineq)
   11117           0 :                         *ineq = l;
   11118           0 :                 return j;
   11119             :         }
   11120             : 
   11121           0 :         return bmap->n_eq;
   11122             : }
   11123             : 
   11124             : /* Check if the given basic map is obviously single-valued.
   11125             :  * In particular, for each output dimension, check that there is
   11126             :  * an equality that defines the output dimension in terms of
   11127             :  * earlier dimensions.
   11128             :  */
   11129           0 : isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
   11130             : {
   11131             :         int i;
   11132             :         unsigned n_out;
   11133             : 
   11134           0 :         if (!bmap)
   11135           0 :                 return isl_bool_error;
   11136             : 
   11137           0 :         n_out = isl_basic_map_dim(bmap, isl_dim_out);
   11138             : 
   11139           0 :         for (i = 0; i < n_out; ++i) {
   11140             :                 int eq;
   11141             : 
   11142           0 :                 eq = isl_basic_map_output_defining_equality(bmap, i,
   11143             :                                                             NULL, NULL);
   11144           0 :                 if (eq < 0)
   11145           0 :                         return isl_bool_error;
   11146           0 :                 if (eq >= bmap->n_eq)
   11147           0 :                         return isl_bool_false;
   11148             :         }
   11149             : 
   11150           0 :         return isl_bool_true;
   11151             : }
   11152             : 
   11153             : /* Check if the given basic map is single-valued.
   11154             :  * We simply compute
   11155             :  *
   11156             :  *      M \circ M^-1
   11157             :  *
   11158             :  * and check if the result is a subset of the identity mapping.
   11159             :  */
   11160           0 : isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
   11161             : {
   11162             :         isl_space *space;
   11163             :         isl_basic_map *test;
   11164             :         isl_basic_map *id;
   11165             :         isl_bool sv;
   11166             : 
   11167           0 :         sv = isl_basic_map_plain_is_single_valued(bmap);
   11168           0 :         if (sv < 0 || sv)
   11169           0 :                 return sv;
   11170             : 
   11171           0 :         test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
   11172           0 :         test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
   11173             : 
   11174           0 :         space = isl_basic_map_get_space(bmap);
   11175           0 :         space = isl_space_map_from_set(isl_space_range(space));
   11176           0 :         id = isl_basic_map_identity(space);
   11177             : 
   11178           0 :         sv = isl_basic_map_is_subset(test, id);
   11179             : 
   11180           0 :         isl_basic_map_free(test);
   11181           0 :         isl_basic_map_free(id);
   11182             : 
   11183           0 :         return sv;
   11184             : }
   11185             : 
   11186             : /* Check if the given map is obviously single-valued.
   11187             :  */
   11188           0 : isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
   11189             : {
   11190           0 :         if (!map)
   11191           0 :                 return isl_bool_error;
   11192           0 :         if (map->n == 0)
   11193           0 :                 return isl_bool_true;
   11194           0 :         if (map->n >= 2)
   11195           0 :                 return isl_bool_false;
   11196             : 
   11197           0 :         return isl_basic_map_plain_is_single_valued(map->p[0]);
   11198             : }
   11199             : 
   11200             : /* Check if the given map is single-valued.
   11201             :  * We simply compute
   11202             :  *
   11203             :  *      M \circ M^-1
   11204             :  *
   11205             :  * and check if the result is a subset of the identity mapping.
   11206             :  */
   11207           0 : isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
   11208             : {
   11209             :         isl_space *dim;
   11210             :         isl_map *test;
   11211             :         isl_map *id;
   11212             :         isl_bool sv;
   11213             : 
   11214           0 :         sv = isl_map_plain_is_single_valued(map);
   11215           0 :         if (sv < 0 || sv)
   11216           0 :                 return sv;
   11217             : 
   11218           0 :         test = isl_map_reverse(isl_map_copy(map));
   11219           0 :         test = isl_map_apply_range(test, isl_map_copy(map));
   11220             : 
   11221           0 :         dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
   11222           0 :         id = isl_map_identity(dim);
   11223             : 
   11224           0 :         sv = isl_map_is_subset(test, id);
   11225             : 
   11226           0 :         isl_map_free(test);
   11227           0 :         isl_map_free(id);
   11228             : 
   11229           0 :         return sv;
   11230             : }
   11231             : 
   11232           0 : isl_bool isl_map_is_injective(__isl_keep isl_map *map)
   11233             : {
   11234             :         isl_bool in;
   11235             : 
   11236           0 :         map = isl_map_copy(map);
   11237           0 :         map = isl_map_reverse(map);
   11238           0 :         in = isl_map_is_single_valued(map);
   11239           0 :         isl_map_free(map);
   11240             : 
   11241           0 :         return in;
   11242             : }
   11243             : 
   11244             : /* Check if the given map is obviously injective.
   11245             :  */
   11246           0 : isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
   11247             : {
   11248             :         isl_bool in;
   11249             : 
   11250           0 :         map = isl_map_copy(map);
   11251           0 :         map = isl_map_reverse(map);
   11252           0 :         in = isl_map_plain_is_single_valued(map);
   11253           0 :         isl_map_free(map);
   11254             : 
   11255           0 :         return in;
   11256             : }
   11257             : 
   11258           0 : isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
   11259             : {
   11260             :         isl_bool sv;
   11261             : 
   11262           0 :         sv = isl_map_is_single_valued(map);
   11263           0 :         if (sv < 0 || !sv)
   11264           0 :                 return sv;
   11265             : 
   11266           0 :         return isl_map_is_injective(map);
   11267             : }
   11268             : 
   11269           0 : isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
   11270             : {
   11271           0 :         return isl_map_is_single_valued(set_to_map(set));
   11272             : }
   11273             : 
   11274             : /* Does "map" only map elements to themselves?
   11275             :  *
   11276             :  * If the domain and range spaces are different, then "map"
   11277             :  * is considered not to be an identity relation, even if it is empty.
   11278             :  * Otherwise, construct the maximal identity relation and
   11279             :  * check whether "map" is a subset of this relation.
   11280             :  */
   11281           0 : isl_bool isl_map_is_identity(__isl_keep isl_map *map)
   11282             : {
   11283             :         isl_space *space;
   11284             :         isl_map *id;
   11285             :         isl_bool equal, is_identity;
   11286             : 
   11287           0 :         space = isl_map_get_space(map);
   11288           0 :         equal = isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
   11289           0 :         isl_space_free(space);
   11290           0 :         if (equal < 0 || !equal)
   11291           0 :                 return equal;
   11292             : 
   11293           0 :         id = isl_map_identity(isl_map_get_space(map));
   11294           0 :         is_identity = isl_map_is_subset(map, id);
   11295           0 :         isl_map_free(id);
   11296             : 
   11297           0 :         return is_identity;
   11298             : }
   11299             : 
   11300           0 : int isl_map_is_translation(__isl_keep isl_map *map)
   11301             : {
   11302             :         int ok;
   11303             :         isl_set *delta;
   11304             : 
   11305           0 :         delta = isl_map_deltas(isl_map_copy(map));
   11306           0 :         ok = isl_set_is_singleton(delta);
   11307           0 :         isl_set_free(delta);
   11308             : 
   11309           0 :         return ok;
   11310             : }
   11311             : 
   11312           0 : static int unique(isl_int *p, unsigned pos, unsigned len)
   11313             : {
   11314           0 :         if (isl_seq_first_non_zero(p, pos) != -1)
   11315           0 :                 return 0;
   11316           0 :         if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
   11317           0 :                 return 0;
   11318           0 :         return 1;
   11319             : }
   11320             : 
   11321           0 : isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
   11322             : {
   11323             :         int i, j;
   11324             :         unsigned nvar;
   11325             :         unsigned ovar;
   11326             : 
   11327           0 :         if (!bset)
   11328           0 :                 return isl_bool_error;
   11329             : 
   11330           0 :         if (isl_basic_set_dim(bset, isl_dim_div) != 0)
   11331           0 :                 return isl_bool_false;
   11332             : 
   11333           0 :         nvar = isl_basic_set_dim(bset, isl_dim_set);
   11334           0 :         ovar = isl_space_offset(bset->dim, isl_dim_set);
   11335           0 :         for (j = 0; j < nvar; ++j) {
   11336           0 :                 int lower = 0, upper = 0;
   11337           0 :                 for (i = 0; i < bset->n_eq; ++i) {
   11338           0 :                         if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
   11339           0 :                                 continue;
   11340           0 :                         if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
   11341           0 :                                 return isl_bool_false;
   11342           0 :                         break;
   11343             :                 }
   11344           0 :                 if (i < bset->n_eq)
   11345           0 :                         continue;
   11346           0 :                 for (i = 0; i < bset->n_ineq; ++i) {
   11347           0 :                         if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
   11348           0 :                                 continue;
   11349           0 :                         if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
   11350           0 :                                 return isl_bool_false;
   11351           0 :                         if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
   11352           0 :                                 lower = 1;
   11353             :                         else
   11354           0 :                                 upper = 1;
   11355             :                 }
   11356           0 :                 if (!lower || !upper)
   11357           0 :                         return isl_bool_false;
   11358             :         }
   11359             : 
   11360           0 :         return isl_bool_true;
   11361             : }
   11362             : 
   11363           0 : isl_bool isl_set_is_box(__isl_keep isl_set *set)
   11364             : {
   11365           0 :         if (!set)
   11366           0 :                 return isl_bool_error;
   11367           0 :         if (set->n != 1)
   11368           0 :                 return isl_bool_false;
   11369             : 
   11370           0 :         return isl_basic_set_is_box(set->p[0]);
   11371             : }
   11372             : 
   11373           0 : isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
   11374             : {
   11375           0 :         if (!bset)
   11376           0 :                 return isl_bool_error;
   11377             :         
   11378           0 :         return isl_space_is_wrapping(bset->dim);
   11379             : }
   11380             : 
   11381           0 : isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
   11382             : {
   11383           0 :         if (!set)
   11384           0 :                 return isl_bool_error;
   11385             :         
   11386           0 :         return isl_space_is_wrapping(set->dim);
   11387             : }
   11388             : 
   11389             : /* Modify the space of "map" through a call to "change".
   11390             :  * If "can_change" is set (not NULL), then first call it to check
   11391             :  * if the modification is allowed, printing the error message "cannot_change"
   11392             :  * if it is not.
   11393             :  */
   11394           0 : static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
   11395             :         isl_bool (*can_change)(__isl_keep isl_map *map),
   11396             :         const char *cannot_change,
   11397             :         __isl_give isl_space *(*change)(__isl_take isl_space *space))
   11398             : {
   11399             :         isl_bool ok;
   11400             :         isl_space *space;
   11401             : 
   11402           0 :         if (!map)
   11403           0 :                 return NULL;
   11404             : 
   11405           0 :         ok = can_change ? can_change(map) : isl_bool_true;
   11406           0 :         if (ok < 0)
   11407           0 :                 return isl_map_free(map);
   11408           0 :         if (!ok)
   11409           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
   11410             :                         return isl_map_free(map));
   11411             : 
   11412           0 :         space = change(isl_map_get_space(map));
   11413           0 :         map = isl_map_reset_space(map, space);
   11414             : 
   11415           0 :         return map;
   11416             : }
   11417             : 
   11418             : /* Is the domain of "map" a wrapped relation?
   11419             :  */
   11420           0 : isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
   11421             : {
   11422           0 :         if (!map)
   11423           0 :                 return isl_bool_error;
   11424             : 
   11425           0 :         return isl_space_domain_is_wrapping(map->dim);
   11426             : }
   11427             : 
   11428             : /* Does "map" have a wrapped relation in both domain and range?
   11429             :  */
   11430           0 : isl_bool isl_map_is_product(__isl_keep isl_map *map)
   11431             : {
   11432           0 :         return isl_space_is_product(isl_map_peek_space(map));
   11433             : }
   11434             : 
   11435             : /* Is the range of "map" a wrapped relation?
   11436             :  */
   11437           0 : isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
   11438             : {
   11439           0 :         if (!map)
   11440           0 :                 return isl_bool_error;
   11441             : 
   11442           0 :         return isl_space_range_is_wrapping(map->dim);
   11443             : }
   11444             : 
   11445           0 : __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
   11446             : {
   11447           0 :         bmap = isl_basic_map_cow(bmap);
   11448           0 :         if (!bmap)
   11449           0 :                 return NULL;
   11450             : 
   11451           0 :         bmap->dim = isl_space_wrap(bmap->dim);
   11452           0 :         if (!bmap->dim)
   11453           0 :                 goto error;
   11454             : 
   11455           0 :         bmap = isl_basic_map_finalize(bmap);
   11456             : 
   11457           0 :         return bset_from_bmap(bmap);
   11458             : error:
   11459           0 :         isl_basic_map_free(bmap);
   11460           0 :         return NULL;
   11461             : }
   11462             : 
   11463             : /* Given a map A -> B, return the set (A -> B).
   11464             :  */
   11465           0 : __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
   11466             : {
   11467           0 :         return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
   11468             : }
   11469             : 
   11470           0 : __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
   11471             : {
   11472           0 :         bset = isl_basic_set_cow(bset);
   11473           0 :         if (!bset)
   11474           0 :                 return NULL;
   11475             : 
   11476           0 :         bset->dim = isl_space_unwrap(bset->dim);
   11477           0 :         if (!bset->dim)
   11478           0 :                 goto error;
   11479             : 
   11480           0 :         bset = isl_basic_set_finalize(bset);
   11481             : 
   11482           0 :         return bset_to_bmap(bset);
   11483             : error:
   11484           0 :         isl_basic_set_free(bset);
   11485           0 :         return NULL;
   11486             : }
   11487             : 
   11488             : /* Given a set (A -> B), return the map A -> B.
   11489             :  * Error out if "set" is not of the form (A -> B).
   11490             :  */
   11491           0 : __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
   11492             : {
   11493           0 :         return isl_map_change_space(set, &isl_set_is_wrapping,
   11494             :                                     "not a wrapping set", &isl_space_unwrap);
   11495             : }
   11496             : 
   11497           0 : __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
   11498             :         enum isl_dim_type type)
   11499             : {
   11500           0 :         if (!bmap)
   11501           0 :                 return NULL;
   11502             : 
   11503           0 :         if (!isl_space_is_named_or_nested(bmap->dim, type))
   11504           0 :                 return bmap;
   11505             : 
   11506           0 :         bmap = isl_basic_map_cow(bmap);
   11507           0 :         if (!bmap)
   11508           0 :                 return NULL;
   11509             : 
   11510           0 :         bmap->dim = isl_space_reset(bmap->dim, type);
   11511           0 :         if (!bmap->dim)
   11512           0 :                 goto error;
   11513             : 
   11514           0 :         bmap = isl_basic_map_finalize(bmap);
   11515             : 
   11516           0 :         return bmap;
   11517             : error:
   11518           0 :         isl_basic_map_free(bmap);
   11519           0 :         return NULL;
   11520             : }
   11521             : 
   11522           0 : __isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
   11523             :         enum isl_dim_type type)
   11524             : {
   11525             :         int i;
   11526             : 
   11527           0 :         if (!map)
   11528           0 :                 return NULL;
   11529             : 
   11530           0 :         if (!isl_space_is_named_or_nested(map->dim, type))
   11531           0 :                 return map;
   11532             : 
   11533           0 :         map = isl_map_cow(map);
   11534           0 :         if (!map)
   11535           0 :                 return NULL;
   11536             : 
   11537           0 :         for (i = 0; i < map->n; ++i) {
   11538           0 :                 map->p[i] = isl_basic_map_reset(map->p[i], type);
   11539           0 :                 if (!map->p[i])
   11540           0 :                         goto error;
   11541             :         }
   11542           0 :         map->dim = isl_space_reset(map->dim, type);
   11543           0 :         if (!map->dim)
   11544           0 :                 goto error;
   11545             : 
   11546           0 :         return map;
   11547             : error:
   11548           0 :         isl_map_free(map);
   11549           0 :         return NULL;
   11550             : }
   11551             : 
   11552           0 : __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
   11553             : {
   11554           0 :         if (!bmap)
   11555           0 :                 return NULL;
   11556             : 
   11557           0 :         if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
   11558           0 :                 return bmap;
   11559             : 
   11560           0 :         bmap = isl_basic_map_cow(bmap);
   11561           0 :         if (!bmap)
   11562           0 :                 return NULL;
   11563             : 
   11564           0 :         bmap->dim = isl_space_flatten(bmap->dim);
   11565           0 :         if (!bmap->dim)
   11566           0 :                 goto error;
   11567             : 
   11568           0 :         bmap = isl_basic_map_finalize(bmap);
   11569             : 
   11570           0 :         return bmap;
   11571             : error:
   11572           0 :         isl_basic_map_free(bmap);
   11573           0 :         return NULL;
   11574             : }
   11575             : 
   11576           0 : __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
   11577             : {
   11578           0 :         return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
   11579             : }
   11580             : 
   11581           0 : __isl_give isl_basic_map *isl_basic_map_flatten_domain(
   11582             :         __isl_take isl_basic_map *bmap)
   11583             : {
   11584           0 :         if (!bmap)
   11585           0 :                 return NULL;
   11586             : 
   11587           0 :         if (!bmap->dim->nested[0])
   11588           0 :                 return bmap;
   11589             : 
   11590           0 :         bmap = isl_basic_map_cow(bmap);
   11591           0 :         if (!bmap)
   11592           0 :                 return NULL;
   11593             : 
   11594           0 :         bmap->dim = isl_space_flatten_domain(bmap->dim);
   11595           0 :         if (!bmap->dim)
   11596           0 :                 goto error;
   11597             : 
   11598           0 :         bmap = isl_basic_map_finalize(bmap);
   11599             : 
   11600           0 :         return bmap;
   11601             : error:
   11602           0 :         isl_basic_map_free(bmap);
   11603           0 :         return NULL;
   11604             : }
   11605             : 
   11606           0 : __isl_give isl_basic_map *isl_basic_map_flatten_range(
   11607             :         __isl_take isl_basic_map *bmap)
   11608             : {
   11609           0 :         if (!bmap)
   11610           0 :                 return NULL;
   11611             : 
   11612           0 :         if (!bmap->dim->nested[1])
   11613           0 :                 return bmap;
   11614             : 
   11615           0 :         bmap = isl_basic_map_cow(bmap);
   11616           0 :         if (!bmap)
   11617           0 :                 return NULL;
   11618             : 
   11619           0 :         bmap->dim = isl_space_flatten_range(bmap->dim);
   11620           0 :         if (!bmap->dim)
   11621           0 :                 goto error;
   11622             : 
   11623           0 :         bmap = isl_basic_map_finalize(bmap);
   11624             : 
   11625           0 :         return bmap;
   11626             : error:
   11627           0 :         isl_basic_map_free(bmap);
   11628           0 :         return NULL;
   11629             : }
   11630             : 
   11631             : /* Remove any internal structure from the spaces of domain and range of "map".
   11632             :  */
   11633           0 : __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
   11634             : {
   11635           0 :         if (!map)
   11636           0 :                 return NULL;
   11637             : 
   11638           0 :         if (!map->dim->nested[0] && !map->dim->nested[1])
   11639           0 :                 return map;
   11640             : 
   11641           0 :         return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
   11642             : }
   11643             : 
   11644           0 : __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
   11645             : {
   11646           0 :         return set_from_map(isl_map_flatten(set_to_map(set)));
   11647             : }
   11648             : 
   11649           0 : __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
   11650             : {
   11651             :         isl_space *dim, *flat_dim;
   11652             :         isl_map *map;
   11653             : 
   11654           0 :         dim = isl_set_get_space(set);
   11655           0 :         flat_dim = isl_space_flatten(isl_space_copy(dim));
   11656           0 :         map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
   11657           0 :         map = isl_map_intersect_domain(map, set);
   11658             : 
   11659           0 :         return map;
   11660             : }
   11661             : 
   11662             : /* Remove any internal structure from the space of the domain of "map".
   11663             :  */
   11664           0 : __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
   11665             : {
   11666           0 :         if (!map)
   11667           0 :                 return NULL;
   11668             : 
   11669           0 :         if (!map->dim->nested[0])
   11670           0 :                 return map;
   11671             : 
   11672           0 :         return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
   11673             : }
   11674             : 
   11675             : /* Remove any internal structure from the space of the range of "map".
   11676             :  */
   11677           0 : __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
   11678             : {
   11679           0 :         if (!map)
   11680           0 :                 return NULL;
   11681             : 
   11682           0 :         if (!map->dim->nested[1])
   11683           0 :                 return map;
   11684             : 
   11685           0 :         return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
   11686             : }
   11687             : 
   11688             : /* Reorder the dimensions of "bmap" according to the given dim_map
   11689             :  * and set the dimension specification to "space" and
   11690             :  * perform Gaussian elimination on the result.
   11691             :  */
   11692           0 : __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
   11693             :         __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
   11694             : {
   11695             :         isl_basic_map *res;
   11696             :         unsigned flags;
   11697             :         unsigned n_div;
   11698             : 
   11699           0 :         if (!bmap || !space || !dim_map)
   11700             :                 goto error;
   11701             : 
   11702           0 :         flags = bmap->flags;
   11703           0 :         ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
   11704           0 :         ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
   11705           0 :         ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
   11706           0 :         n_div = isl_basic_map_dim(bmap, isl_dim_div);
   11707           0 :         res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
   11708           0 :         res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
   11709           0 :         if (res)
   11710           0 :                 res->flags = flags;
   11711           0 :         res = isl_basic_map_gauss(res, NULL);
   11712           0 :         res = isl_basic_map_finalize(res);
   11713           0 :         return res;
   11714             : error:
   11715           0 :         free(dim_map);
   11716           0 :         isl_basic_map_free(bmap);
   11717           0 :         isl_space_free(space);
   11718           0 :         return NULL;
   11719             : }
   11720             : 
   11721             : /* Reorder the dimensions of "map" according to given reordering.
   11722             :  */
   11723           0 : __isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
   11724             :         __isl_take isl_reordering *r)
   11725             : {
   11726             :         int i;
   11727             :         struct isl_dim_map *dim_map;
   11728             : 
   11729           0 :         map = isl_map_cow(map);
   11730           0 :         dim_map = isl_dim_map_from_reordering(r);
   11731           0 :         if (!map || !r || !dim_map)
   11732             :                 goto error;
   11733             : 
   11734           0 :         for (i = 0; i < map->n; ++i) {
   11735             :                 struct isl_dim_map *dim_map_i;
   11736             :                 isl_space *space;
   11737             : 
   11738           0 :                 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
   11739             : 
   11740           0 :                 space = isl_reordering_get_space(r);
   11741           0 :                 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
   11742             : 
   11743           0 :                 if (!map->p[i])
   11744           0 :                         goto error;
   11745             :         }
   11746             : 
   11747           0 :         map = isl_map_reset_space(map, isl_reordering_get_space(r));
   11748           0 :         map = isl_map_unmark_normalized(map);
   11749             : 
   11750           0 :         isl_reordering_free(r);
   11751           0 :         free(dim_map);
   11752           0 :         return map;
   11753             : error:
   11754           0 :         free(dim_map);
   11755           0 :         isl_map_free(map);
   11756           0 :         isl_reordering_free(r);
   11757           0 :         return NULL;
   11758             : }
   11759             : 
   11760           0 : __isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
   11761             :         __isl_take isl_reordering *r)
   11762             : {
   11763           0 :         return set_from_map(isl_map_realign(set_to_map(set), r));
   11764             : }
   11765             : 
   11766           0 : __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
   11767             :         __isl_take isl_space *model)
   11768             : {
   11769             :         isl_ctx *ctx;
   11770             :         isl_bool aligned;
   11771             : 
   11772           0 :         if (!map || !model)
   11773             :                 goto error;
   11774             : 
   11775           0 :         ctx = isl_space_get_ctx(model);
   11776           0 :         if (!isl_space_has_named_params(model))
   11777           0 :                 isl_die(ctx, isl_error_invalid,
   11778             :                         "model has unnamed parameters", goto error);
   11779           0 :         if (isl_map_check_named_params(map) < 0)
   11780           0 :                 goto error;
   11781           0 :         aligned = isl_map_space_has_equal_params(map, model);
   11782           0 :         if (aligned < 0)
   11783           0 :                 goto error;
   11784           0 :         if (!aligned) {
   11785             :                 isl_reordering *exp;
   11786             : 
   11787           0 :                 exp = isl_parameter_alignment_reordering(map->dim, model);
   11788           0 :                 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
   11789           0 :                 map = isl_map_realign(map, exp);
   11790             :         }
   11791             : 
   11792           0 :         isl_space_free(model);
   11793           0 :         return map;
   11794             : error:
   11795           0 :         isl_space_free(model);
   11796           0 :         isl_map_free(map);
   11797           0 :         return NULL;
   11798             : }
   11799             : 
   11800           0 : __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
   11801             :         __isl_take isl_space *model)
   11802             : {
   11803           0 :         return isl_map_align_params(set, model);
   11804             : }
   11805             : 
   11806             : /* Align the parameters of "bmap" to those of "model", introducing
   11807             :  * additional parameters if needed.
   11808             :  */
   11809           0 : __isl_give isl_basic_map *isl_basic_map_align_params(
   11810             :         __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
   11811             : {
   11812             :         isl_ctx *ctx;
   11813             :         isl_bool equal_params;
   11814             : 
   11815           0 :         if (!bmap || !model)
   11816             :                 goto error;
   11817             : 
   11818           0 :         ctx = isl_space_get_ctx(model);
   11819           0 :         if (!isl_space_has_named_params(model))
   11820           0 :                 isl_die(ctx, isl_error_invalid,
   11821             :                         "model has unnamed parameters", goto error);
   11822           0 :         if (isl_basic_map_check_named_params(bmap) < 0)
   11823           0 :                 goto error;
   11824           0 :         equal_params = isl_space_has_equal_params(bmap->dim, model);
   11825           0 :         if (equal_params < 0)
   11826           0 :                 goto error;
   11827           0 :         if (!equal_params) {
   11828             :                 isl_reordering *exp;
   11829             :                 struct isl_dim_map *dim_map;
   11830             : 
   11831           0 :                 exp = isl_parameter_alignment_reordering(bmap->dim, model);
   11832           0 :                 exp = isl_reordering_extend_space(exp,
   11833             :                                         isl_basic_map_get_space(bmap));
   11834           0 :                 dim_map = isl_dim_map_from_reordering(exp);
   11835           0 :                 bmap = isl_basic_map_realign(bmap,
   11836             :                                     isl_reordering_get_space(exp),
   11837           0 :                                     isl_dim_map_extend(dim_map, bmap));
   11838           0 :                 isl_reordering_free(exp);
   11839           0 :                 free(dim_map);
   11840             :         }
   11841             : 
   11842           0 :         isl_space_free(model);
   11843           0 :         return bmap;
   11844             : error:
   11845           0 :         isl_space_free(model);
   11846           0 :         isl_basic_map_free(bmap);
   11847           0 :         return NULL;
   11848             : }
   11849             : 
   11850             : /* Do "bset" and "space" have the same parameters?
   11851             :  */
   11852           0 : isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
   11853             :         __isl_keep isl_space *space)
   11854             : {
   11855             :         isl_space *bset_space;
   11856             : 
   11857           0 :         bset_space = isl_basic_set_peek_space(bset);
   11858           0 :         return isl_space_has_equal_params(bset_space, space);
   11859             : }
   11860             : 
   11861             : /* Do "map" and "space" have the same parameters?
   11862             :  */
   11863           0 : isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
   11864             :         __isl_keep isl_space *space)
   11865             : {
   11866             :         isl_space *map_space;
   11867             : 
   11868           0 :         map_space = isl_map_peek_space(map);
   11869           0 :         return isl_space_has_equal_params(map_space, space);
   11870             : }
   11871             : 
   11872             : /* Do "set" and "space" have the same parameters?
   11873             :  */
   11874           0 : isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
   11875             :         __isl_keep isl_space *space)
   11876             : {
   11877           0 :         return isl_map_space_has_equal_params(set_to_map(set), space);
   11878             : }
   11879             : 
   11880             : /* Align the parameters of "bset" to those of "model", introducing
   11881             :  * additional parameters if needed.
   11882             :  */
   11883           0 : __isl_give isl_basic_set *isl_basic_set_align_params(
   11884             :         __isl_take isl_basic_set *bset, __isl_take isl_space *model)
   11885             : {
   11886           0 :         return isl_basic_map_align_params(bset, model);
   11887             : }
   11888             : 
   11889             : /* Drop all parameters not referenced by "map".
   11890             :  */
   11891           0 : __isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
   11892             : {
   11893             :         int i;
   11894             : 
   11895           0 :         if (isl_map_check_named_params(map) < 0)
   11896           0 :                 return isl_map_free(map);
   11897             : 
   11898           0 :         for (i = isl_map_dim(map, isl_dim_param) - 1; i >= 0; i--) {
   11899             :                 isl_bool involves;
   11900             : 
   11901           0 :                 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
   11902           0 :                 if (involves < 0)
   11903           0 :                         return isl_map_free(map);
   11904           0 :                 if (!involves)
   11905           0 :                         map = isl_map_project_out(map, isl_dim_param, i, 1);
   11906             :         }
   11907             : 
   11908           0 :         return map;
   11909             : }
   11910             : 
   11911             : /* Drop all parameters not referenced by "set".
   11912             :  */
   11913           0 : __isl_give isl_set *isl_set_drop_unused_params(
   11914             :         __isl_take isl_set *set)
   11915             : {
   11916           0 :         return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
   11917             : }
   11918             : 
   11919             : /* Drop all parameters not referenced by "bmap".
   11920             :  */
   11921           0 : __isl_give isl_basic_map *isl_basic_map_drop_unused_params(
   11922             :         __isl_take isl_basic_map *bmap)
   11923             : {
   11924             :         int i;
   11925             : 
   11926           0 :         if (isl_basic_map_check_named_params(bmap) < 0)
   11927           0 :                 return isl_basic_map_free(bmap);
   11928             : 
   11929           0 :         for (i = isl_basic_map_dim(bmap, isl_dim_param) - 1; i >= 0; i--) {
   11930             :                 isl_bool involves;
   11931             : 
   11932           0 :                 involves = isl_basic_map_involves_dims(bmap,
   11933             :                                                         isl_dim_param, i, 1);
   11934           0 :                 if (involves < 0)
   11935           0 :                         return isl_basic_map_free(bmap);
   11936           0 :                 if (!involves)
   11937           0 :                         bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
   11938             :         }
   11939             : 
   11940           0 :         return bmap;
   11941             : }
   11942             : 
   11943             : /* Drop all parameters not referenced by "bset".
   11944             :  */
   11945           0 : __isl_give isl_basic_set *isl_basic_set_drop_unused_params(
   11946             :         __isl_take isl_basic_set *bset)
   11947             : {
   11948           0 :         return bset_from_bmap(isl_basic_map_drop_unused_params(
   11949             :                                                         bset_to_bmap(bset)));
   11950             : }
   11951             : 
   11952           0 : __isl_give isl_mat *isl_basic_map_equalities_matrix(
   11953             :                 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
   11954             :                 enum isl_dim_type c2, enum isl_dim_type c3,
   11955             :                 enum isl_dim_type c4, enum isl_dim_type c5)
   11956             : {
   11957           0 :         enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
   11958             :         struct isl_mat *mat;
   11959             :         int i, j, k;
   11960             :         int pos;
   11961             : 
   11962           0 :         if (!bmap)
   11963           0 :                 return NULL;
   11964           0 :         mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
   11965           0 :                                 isl_basic_map_total_dim(bmap) + 1);
   11966           0 :         if (!mat)
   11967           0 :                 return NULL;
   11968           0 :         for (i = 0; i < bmap->n_eq; ++i)
   11969           0 :                 for (j = 0, pos = 0; j < 5; ++j) {
   11970           0 :                         int off = isl_basic_map_offset(bmap, c[j]);
   11971           0 :                         for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
   11972           0 :                                 isl_int_set(mat->row[i][pos],
   11973             :                                             bmap->eq[i][off + k]);
   11974           0 :                                 ++pos;
   11975             :                         }
   11976             :                 }
   11977             : 
   11978           0 :         return mat;
   11979             : }
   11980             : 
   11981           0 : __isl_give isl_mat *isl_basic_map_inequalities_matrix(
   11982             :                 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
   11983             :                 enum isl_dim_type c2, enum isl_dim_type c3,
   11984             :                 enum isl_dim_type c4, enum isl_dim_type c5)
   11985             : {
   11986           0 :         enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
   11987             :         struct isl_mat *mat;
   11988             :         int i, j, k;
   11989             :         int pos;
   11990             : 
   11991           0 :         if (!bmap)
   11992           0 :                 return NULL;
   11993           0 :         mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
   11994           0 :                                 isl_basic_map_total_dim(bmap) + 1);
   11995           0 :         if (!mat)
   11996           0 :                 return NULL;
   11997           0 :         for (i = 0; i < bmap->n_ineq; ++i)
   11998           0 :                 for (j = 0, pos = 0; j < 5; ++j) {
   11999           0 :                         int off = isl_basic_map_offset(bmap, c[j]);
   12000           0 :                         for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
   12001           0 :                                 isl_int_set(mat->row[i][pos],
   12002             :                                             bmap->ineq[i][off + k]);
   12003           0 :                                 ++pos;
   12004             :                         }
   12005             :                 }
   12006             : 
   12007           0 :         return mat;
   12008             : }
   12009             : 
   12010           0 : __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
   12011             :         __isl_take isl_space *dim,
   12012             :         __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
   12013             :         enum isl_dim_type c2, enum isl_dim_type c3,
   12014             :         enum isl_dim_type c4, enum isl_dim_type c5)
   12015             : {
   12016           0 :         enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
   12017           0 :         isl_basic_map *bmap = NULL;
   12018             :         unsigned total;
   12019             :         unsigned extra;
   12020             :         int i, j, k, l;
   12021             :         int pos;
   12022             : 
   12023           0 :         if (!dim || !eq || !ineq)
   12024             :                 goto error;
   12025             : 
   12026           0 :         if (eq->n_col != ineq->n_col)
   12027           0 :                 isl_die(dim->ctx, isl_error_invalid,
   12028             :                         "equalities and inequalities matrices should have "
   12029             :                         "same number of columns", goto error);
   12030             : 
   12031           0 :         total = 1 + isl_space_dim(dim, isl_dim_all);
   12032             : 
   12033           0 :         if (eq->n_col < total)
   12034           0 :                 isl_die(dim->ctx, isl_error_invalid,
   12035             :                         "number of columns too small", goto error);
   12036             : 
   12037           0 :         extra = eq->n_col - total;
   12038             : 
   12039           0 :         bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
   12040             :                                        eq->n_row, ineq->n_row);
   12041           0 :         if (!bmap)
   12042           0 :                 goto error;
   12043           0 :         for (i = 0; i < extra; ++i) {
   12044           0 :                 k = isl_basic_map_alloc_div(bmap);
   12045           0 :                 if (k < 0)
   12046           0 :                         goto error;
   12047           0 :                 isl_int_set_si(bmap->div[k][0], 0);
   12048             :         }
   12049           0 :         for (i = 0; i < eq->n_row; ++i) {
   12050           0 :                 l = isl_basic_map_alloc_equality(bmap);
   12051           0 :                 if (l < 0)
   12052           0 :                         goto error;
   12053           0 :                 for (j = 0, pos = 0; j < 5; ++j) {
   12054           0 :                         int off = isl_basic_map_offset(bmap, c[j]);
   12055           0 :                         for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
   12056           0 :                                 isl_int_set(bmap->eq[l][off + k], 
   12057             :                                             eq->row[i][pos]);
   12058           0 :                                 ++pos;
   12059             :                         }
   12060             :                 }
   12061             :         }
   12062           0 :         for (i = 0; i < ineq->n_row; ++i) {
   12063           0 :                 l = isl_basic_map_alloc_inequality(bmap);
   12064           0 :                 if (l < 0)
   12065           0 :                         goto error;
   12066           0 :                 for (j = 0, pos = 0; j < 5; ++j) {
   12067           0 :                         int off = isl_basic_map_offset(bmap, c[j]);
   12068           0 :                         for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
   12069           0 :                                 isl_int_set(bmap->ineq[l][off + k], 
   12070             :                                             ineq->row[i][pos]);
   12071           0 :                                 ++pos;
   12072             :                         }
   12073             :                 }
   12074             :         }
   12075             : 
   12076           0 :         isl_space_free(dim);
   12077           0 :         isl_mat_free(eq);
   12078           0 :         isl_mat_free(ineq);
   12079             : 
   12080           0 :         bmap = isl_basic_map_simplify(bmap);
   12081           0 :         return isl_basic_map_finalize(bmap);
   12082             : error:
   12083           0 :         isl_space_free(dim);
   12084           0 :         isl_mat_free(eq);
   12085           0 :         isl_mat_free(ineq);
   12086           0 :         isl_basic_map_free(bmap);
   12087           0 :         return NULL;
   12088             : }
   12089             : 
   12090           0 : __isl_give isl_mat *isl_basic_set_equalities_matrix(
   12091             :         __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
   12092             :         enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
   12093             : {
   12094           0 :         return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
   12095             :                                                 c1, c2, c3, c4, isl_dim_in);
   12096             : }
   12097             : 
   12098           0 : __isl_give isl_mat *isl_basic_set_inequalities_matrix(
   12099             :         __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
   12100             :         enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
   12101             : {
   12102           0 :         return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
   12103             :                                                  c1, c2, c3, c4, isl_dim_in);
   12104             : }
   12105             : 
   12106           0 : __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
   12107             :         __isl_take isl_space *dim,
   12108             :         __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
   12109             :         enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
   12110             : {
   12111             :         isl_basic_map *bmap;
   12112           0 :         bmap = isl_basic_map_from_constraint_matrices(dim, eq, ineq,
   12113             :                                                    c1, c2, c3, c4, isl_dim_in);
   12114           0 :         return bset_from_bmap(bmap);
   12115             : }
   12116             : 
   12117           0 : isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
   12118             : {
   12119           0 :         if (!bmap)
   12120           0 :                 return isl_bool_error;
   12121             :         
   12122           0 :         return isl_space_can_zip(bmap->dim);
   12123             : }
   12124             : 
   12125           0 : isl_bool isl_map_can_zip(__isl_keep isl_map *map)
   12126             : {
   12127           0 :         if (!map)
   12128           0 :                 return isl_bool_error;
   12129             :         
   12130           0 :         return isl_space_can_zip(map->dim);
   12131             : }
   12132             : 
   12133             : /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
   12134             :  * (A -> C) -> (B -> D).
   12135             :  */
   12136           0 : __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
   12137             : {
   12138             :         unsigned pos;
   12139             :         unsigned n1;
   12140             :         unsigned n2;
   12141             : 
   12142           0 :         if (!bmap)
   12143           0 :                 return NULL;
   12144             : 
   12145           0 :         if (!isl_basic_map_can_zip(bmap))
   12146           0 :                 isl_die(bmap->ctx, isl_error_invalid,
   12147             :                         "basic map cannot be zipped", goto error);
   12148           0 :         pos = isl_basic_map_offset(bmap, isl_dim_in) +
   12149           0 :                 isl_space_dim(bmap->dim->nested[0], isl_dim_in);
   12150           0 :         n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
   12151           0 :         n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
   12152           0 :         bmap = isl_basic_map_cow(bmap);
   12153           0 :         bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
   12154           0 :         if (!bmap)
   12155           0 :                 return NULL;
   12156           0 :         bmap->dim = isl_space_zip(bmap->dim);
   12157           0 :         if (!bmap->dim)
   12158           0 :                 goto error;
   12159           0 :         bmap = isl_basic_map_mark_final(bmap);
   12160           0 :         return bmap;
   12161             : error:
   12162           0 :         isl_basic_map_free(bmap);
   12163           0 :         return NULL;
   12164             : }
   12165             : 
   12166             : /* Given a map (A -> B) -> (C -> D), return the corresponding map
   12167             :  * (A -> C) -> (B -> D).
   12168             :  */
   12169           0 : __isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
   12170             : {
   12171             :         int i;
   12172             : 
   12173           0 :         if (!map)
   12174           0 :                 return NULL;
   12175             : 
   12176           0 :         if (!isl_map_can_zip(map))
   12177           0 :                 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
   12178             :                         goto error);
   12179             : 
   12180           0 :         map = isl_map_cow(map);
   12181           0 :         if (!map)
   12182           0 :                 return NULL;
   12183             : 
   12184           0 :         for (i = 0; i < map->n; ++i) {
   12185           0 :                 map->p[i] = isl_basic_map_zip(map->p[i]);
   12186           0 :                 if (!map->p[i])
   12187           0 :                         goto error;
   12188             :         }
   12189             : 
   12190           0 :         map->dim = isl_space_zip(map->dim);
   12191           0 :         if (!map->dim)
   12192           0 :                 goto error;
   12193             : 
   12194           0 :         return map;
   12195             : error:
   12196           0 :         isl_map_free(map);
   12197           0 :         return NULL;
   12198             : }
   12199             : 
   12200             : /* Can we apply isl_basic_map_curry to "bmap"?
   12201             :  * That is, does it have a nested relation in its domain?
   12202             :  */
   12203           0 : isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
   12204             : {
   12205           0 :         if (!bmap)
   12206           0 :                 return isl_bool_error;
   12207             : 
   12208           0 :         return isl_space_can_curry(bmap->dim);
   12209             : }
   12210             : 
   12211             : /* Can we apply isl_map_curry to "map"?
   12212             :  * That is, does it have a nested relation in its domain?
   12213             :  */
   12214           0 : isl_bool isl_map_can_curry(__isl_keep isl_map *map)
   12215             : {
   12216           0 :         if (!map)
   12217           0 :                 return isl_bool_error;
   12218             : 
   12219           0 :         return isl_space_can_curry(map->dim);
   12220             : }
   12221             : 
   12222             : /* Given a basic map (A -> B) -> C, return the corresponding basic map
   12223             :  * A -> (B -> C).
   12224             :  */
   12225           0 : __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
   12226             : {
   12227             : 
   12228           0 :         if (!bmap)
   12229           0 :                 return NULL;
   12230             : 
   12231           0 :         if (!isl_basic_map_can_curry(bmap))
   12232           0 :                 isl_die(bmap->ctx, isl_error_invalid,
   12233             :                         "basic map cannot be curried", goto error);
   12234           0 :         bmap = isl_basic_map_cow(bmap);
   12235           0 :         if (!bmap)
   12236           0 :                 return NULL;
   12237           0 :         bmap->dim = isl_space_curry(bmap->dim);
   12238           0 :         if (!bmap->dim)
   12239           0 :                 goto error;
   12240           0 :         bmap = isl_basic_map_mark_final(bmap);
   12241           0 :         return bmap;
   12242             : error:
   12243           0 :         isl_basic_map_free(bmap);
   12244           0 :         return NULL;
   12245             : }
   12246             : 
   12247             : /* Given a map (A -> B) -> C, return the corresponding map
   12248             :  * A -> (B -> C).
   12249             :  */
   12250           0 : __isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
   12251             : {
   12252           0 :         return isl_map_change_space(map, &isl_map_can_curry,
   12253             :                                     "map cannot be curried", &isl_space_curry);
   12254             : }
   12255             : 
   12256             : /* Can isl_map_range_curry be applied to "map"?
   12257             :  * That is, does it have a nested relation in its range,
   12258             :  * the domain of which is itself a nested relation?
   12259             :  */
   12260           0 : isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
   12261             : {
   12262           0 :         if (!map)
   12263           0 :                 return isl_bool_error;
   12264             : 
   12265           0 :         return isl_space_can_range_curry(map->dim);
   12266             : }
   12267             : 
   12268             : /* Given a map A -> ((B -> C) -> D), return the corresponding map
   12269             :  * A -> (B -> (C -> D)).
   12270             :  */
   12271           0 : __isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
   12272             : {
   12273           0 :         return isl_map_change_space(map, &isl_map_can_range_curry,
   12274             :                                     "map range cannot be curried",
   12275             :                                     &isl_space_range_curry);
   12276             : }
   12277             : 
   12278             : /* Can we apply isl_basic_map_uncurry to "bmap"?
   12279             :  * That is, does it have a nested relation in its domain?
   12280             :  */
   12281           0 : isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
   12282             : {
   12283           0 :         if (!bmap)
   12284           0 :                 return isl_bool_error;
   12285             : 
   12286           0 :         return isl_space_can_uncurry(bmap->dim);
   12287             : }
   12288             : 
   12289             : /* Can we apply isl_map_uncurry to "map"?
   12290             :  * That is, does it have a nested relation in its domain?
   12291             :  */
   12292           0 : isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
   12293             : {
   12294           0 :         if (!map)
   12295           0 :                 return isl_bool_error;
   12296             : 
   12297           0 :         return isl_space_can_uncurry(map->dim);
   12298             : }
   12299             : 
   12300             : /* Given a basic map A -> (B -> C), return the corresponding basic map
   12301             :  * (A -> B) -> C.
   12302             :  */
   12303           0 : __isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
   12304             : {
   12305             : 
   12306           0 :         if (!bmap)
   12307           0 :                 return NULL;
   12308             : 
   12309           0 :         if (!isl_basic_map_can_uncurry(bmap))
   12310           0 :                 isl_die(bmap->ctx, isl_error_invalid,
   12311             :                         "basic map cannot be uncurried",
   12312             :                         return isl_basic_map_free(bmap));
   12313           0 :         bmap = isl_basic_map_cow(bmap);
   12314           0 :         if (!bmap)
   12315           0 :                 return NULL;
   12316           0 :         bmap->dim = isl_space_uncurry(bmap->dim);
   12317           0 :         if (!bmap->dim)
   12318           0 :                 return isl_basic_map_free(bmap);
   12319           0 :         bmap = isl_basic_map_mark_final(bmap);
   12320           0 :         return bmap;
   12321             : }
   12322             : 
   12323             : /* Given a map A -> (B -> C), return the corresponding map
   12324             :  * (A -> B) -> C.
   12325             :  */
   12326           0 : __isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
   12327             : {
   12328           0 :         return isl_map_change_space(map, &isl_map_can_uncurry,
   12329             :                                 "map cannot be uncurried", &isl_space_uncurry);
   12330             : }
   12331             : 
   12332           0 : __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
   12333             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12334             : {
   12335           0 :         return isl_map_equate(set, type1, pos1, type2, pos2);
   12336             : }
   12337             : 
   12338             : /* Construct a basic map where the given dimensions are equal to each other.
   12339             :  */
   12340           0 : static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
   12341             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12342             : {
   12343           0 :         isl_basic_map *bmap = NULL;
   12344             :         int i;
   12345             : 
   12346           0 :         if (!space)
   12347           0 :                 return NULL;
   12348             : 
   12349           0 :         if (pos1 >= isl_space_dim(space, type1))
   12350           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
   12351             :                         "index out of bounds", goto error);
   12352           0 :         if (pos2 >= isl_space_dim(space, type2))
   12353           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
   12354             :                         "index out of bounds", goto error);
   12355             : 
   12356           0 :         if (type1 == type2 && pos1 == pos2)
   12357           0 :                 return isl_basic_map_universe(space);
   12358             : 
   12359           0 :         bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
   12360           0 :         i = isl_basic_map_alloc_equality(bmap);
   12361           0 :         if (i < 0)
   12362           0 :                 goto error;
   12363           0 :         isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
   12364           0 :         pos1 += isl_basic_map_offset(bmap, type1);
   12365           0 :         pos2 += isl_basic_map_offset(bmap, type2);
   12366           0 :         isl_int_set_si(bmap->eq[i][pos1], -1);
   12367           0 :         isl_int_set_si(bmap->eq[i][pos2], 1);
   12368           0 :         bmap = isl_basic_map_finalize(bmap);
   12369           0 :         isl_space_free(space);
   12370           0 :         return bmap;
   12371             : error:
   12372           0 :         isl_space_free(space);
   12373           0 :         isl_basic_map_free(bmap);
   12374           0 :         return NULL;
   12375             : }
   12376             : 
   12377             : /* Add a constraint imposing that the given two dimensions are equal.
   12378             :  */
   12379           0 : __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
   12380             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12381             : {
   12382             :         isl_basic_map *eq;
   12383             : 
   12384           0 :         eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
   12385             : 
   12386           0 :         bmap = isl_basic_map_intersect(bmap, eq);
   12387             : 
   12388           0 :         return bmap;
   12389             : }
   12390             : 
   12391             : /* Add a constraint imposing that the given two dimensions are equal.
   12392             :  */
   12393           0 : __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
   12394             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12395             : {
   12396             :         isl_basic_map *bmap;
   12397             : 
   12398           0 :         bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
   12399             : 
   12400           0 :         map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
   12401             : 
   12402           0 :         return map;
   12403             : }
   12404             : 
   12405             : /* Add a constraint imposing that the given two dimensions have opposite values.
   12406             :  */
   12407           0 : __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
   12408             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12409             : {
   12410           0 :         isl_basic_map *bmap = NULL;
   12411             :         int i;
   12412             : 
   12413           0 :         if (!map)
   12414           0 :                 return NULL;
   12415             : 
   12416           0 :         if (pos1 >= isl_map_dim(map, type1))
   12417           0 :                 isl_die(map->ctx, isl_error_invalid,
   12418             :                         "index out of bounds", goto error);
   12419           0 :         if (pos2 >= isl_map_dim(map, type2))
   12420           0 :                 isl_die(map->ctx, isl_error_invalid,
   12421             :                         "index out of bounds", goto error);
   12422             : 
   12423           0 :         bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
   12424           0 :         i = isl_basic_map_alloc_equality(bmap);
   12425           0 :         if (i < 0)
   12426           0 :                 goto error;
   12427           0 :         isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
   12428           0 :         pos1 += isl_basic_map_offset(bmap, type1);
   12429           0 :         pos2 += isl_basic_map_offset(bmap, type2);
   12430           0 :         isl_int_set_si(bmap->eq[i][pos1], 1);
   12431           0 :         isl_int_set_si(bmap->eq[i][pos2], 1);
   12432           0 :         bmap = isl_basic_map_finalize(bmap);
   12433             : 
   12434           0 :         map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
   12435             : 
   12436           0 :         return map;
   12437             : error:
   12438           0 :         isl_basic_map_free(bmap);
   12439           0 :         isl_map_free(map);
   12440           0 :         return NULL;
   12441             : }
   12442             : 
   12443             : /* Construct a constraint imposing that the value of the first dimension is
   12444             :  * greater than or equal to that of the second.
   12445             :  */
   12446           0 : static __isl_give isl_constraint *constraint_order_ge(
   12447             :         __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
   12448             :         enum isl_dim_type type2, int pos2)
   12449             : {
   12450             :         isl_constraint *c;
   12451             : 
   12452           0 :         if (!space)
   12453           0 :                 return NULL;
   12454             : 
   12455           0 :         c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
   12456             : 
   12457           0 :         if (pos1 >= isl_constraint_dim(c, type1))
   12458           0 :                 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
   12459             :                         "index out of bounds", return isl_constraint_free(c));
   12460           0 :         if (pos2 >= isl_constraint_dim(c, type2))
   12461           0 :                 isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
   12462             :                         "index out of bounds", return isl_constraint_free(c));
   12463             : 
   12464           0 :         if (type1 == type2 && pos1 == pos2)
   12465           0 :                 return c;
   12466             : 
   12467           0 :         c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
   12468           0 :         c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
   12469             : 
   12470           0 :         return c;
   12471             : }
   12472             : 
   12473             : /* Add a constraint imposing that the value of the first dimension is
   12474             :  * greater than or equal to that of the second.
   12475             :  */
   12476           0 : __isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
   12477             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12478             : {
   12479             :         isl_constraint *c;
   12480             :         isl_space *space;
   12481             : 
   12482           0 :         if (type1 == type2 && pos1 == pos2)
   12483           0 :                 return bmap;
   12484           0 :         space = isl_basic_map_get_space(bmap);
   12485           0 :         c = constraint_order_ge(space, type1, pos1, type2, pos2);
   12486           0 :         bmap = isl_basic_map_add_constraint(bmap, c);
   12487             : 
   12488           0 :         return bmap;
   12489             : }
   12490             : 
   12491             : /* Add a constraint imposing that the value of the first dimension is
   12492             :  * greater than or equal to that of the second.
   12493             :  */
   12494           0 : __isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
   12495             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12496             : {
   12497             :         isl_constraint *c;
   12498             :         isl_space *space;
   12499             : 
   12500           0 :         if (type1 == type2 && pos1 == pos2)
   12501           0 :                 return map;
   12502           0 :         space = isl_map_get_space(map);
   12503           0 :         c = constraint_order_ge(space, type1, pos1, type2, pos2);
   12504           0 :         map = isl_map_add_constraint(map, c);
   12505             : 
   12506           0 :         return map;
   12507             : }
   12508             : 
   12509             : /* Add a constraint imposing that the value of the first dimension is
   12510             :  * less than or equal to that of the second.
   12511             :  */
   12512           0 : __isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
   12513             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12514             : {
   12515           0 :         return isl_map_order_ge(map, type2, pos2, type1, pos1);
   12516             : }
   12517             : 
   12518             : /* Construct a basic map where the value of the first dimension is
   12519             :  * greater than that of the second.
   12520             :  */
   12521           0 : static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
   12522             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12523             : {
   12524           0 :         isl_basic_map *bmap = NULL;
   12525             :         int i;
   12526             : 
   12527           0 :         if (!space)
   12528           0 :                 return NULL;
   12529             : 
   12530           0 :         if (pos1 >= isl_space_dim(space, type1))
   12531           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
   12532             :                         "index out of bounds", goto error);
   12533           0 :         if (pos2 >= isl_space_dim(space, type2))
   12534           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
   12535             :                         "index out of bounds", goto error);
   12536             : 
   12537           0 :         if (type1 == type2 && pos1 == pos2)
   12538           0 :                 return isl_basic_map_empty(space);
   12539             : 
   12540           0 :         bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
   12541           0 :         i = isl_basic_map_alloc_inequality(bmap);
   12542           0 :         if (i < 0)
   12543           0 :                 return isl_basic_map_free(bmap);
   12544           0 :         isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
   12545           0 :         pos1 += isl_basic_map_offset(bmap, type1);
   12546           0 :         pos2 += isl_basic_map_offset(bmap, type2);
   12547           0 :         isl_int_set_si(bmap->ineq[i][pos1], 1);
   12548           0 :         isl_int_set_si(bmap->ineq[i][pos2], -1);
   12549           0 :         isl_int_set_si(bmap->ineq[i][0], -1);
   12550           0 :         bmap = isl_basic_map_finalize(bmap);
   12551             : 
   12552           0 :         return bmap;
   12553             : error:
   12554           0 :         isl_space_free(space);
   12555           0 :         isl_basic_map_free(bmap);
   12556           0 :         return NULL;
   12557             : }
   12558             : 
   12559             : /* Add a constraint imposing that the value of the first dimension is
   12560             :  * greater than that of the second.
   12561             :  */
   12562           0 : __isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
   12563             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12564             : {
   12565             :         isl_basic_map *gt;
   12566             : 
   12567           0 :         gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
   12568             : 
   12569           0 :         bmap = isl_basic_map_intersect(bmap, gt);
   12570             : 
   12571           0 :         return bmap;
   12572             : }
   12573             : 
   12574             : /* Add a constraint imposing that the value of the first dimension is
   12575             :  * greater than that of the second.
   12576             :  */
   12577           0 : __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
   12578             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12579             : {
   12580             :         isl_basic_map *bmap;
   12581             : 
   12582           0 :         bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
   12583             : 
   12584           0 :         map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
   12585             : 
   12586           0 :         return map;
   12587             : }
   12588             : 
   12589             : /* Add a constraint imposing that the value of the first dimension is
   12590             :  * smaller than that of the second.
   12591             :  */
   12592           0 : __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
   12593             :         enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
   12594             : {
   12595           0 :         return isl_map_order_gt(map, type2, pos2, type1, pos1);
   12596             : }
   12597             : 
   12598           0 : __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
   12599             :         int pos)
   12600             : {
   12601             :         isl_aff *div;
   12602             :         isl_local_space *ls;
   12603             : 
   12604           0 :         if (!bmap)
   12605           0 :                 return NULL;
   12606             : 
   12607           0 :         if (!isl_basic_map_divs_known(bmap))
   12608           0 :                 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
   12609             :                         "some divs are unknown", return NULL);
   12610             : 
   12611           0 :         ls = isl_basic_map_get_local_space(bmap);
   12612           0 :         div = isl_local_space_get_div(ls, pos);
   12613           0 :         isl_local_space_free(ls);
   12614             : 
   12615           0 :         return div;
   12616             : }
   12617             : 
   12618           0 : __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
   12619             :         int pos)
   12620             : {
   12621           0 :         return isl_basic_map_get_div(bset, pos);
   12622             : }
   12623             : 
   12624             : /* Plug in "subs" for dimension "type", "pos" of "bset".
   12625             :  *
   12626             :  * Let i be the dimension to replace and let "subs" be of the form
   12627             :  *
   12628             :  *      f/d
   12629             :  *
   12630             :  * Any integer division with a non-zero coefficient for i,
   12631             :  *
   12632             :  *      floor((a i + g)/m)
   12633             :  *
   12634             :  * is replaced by
   12635             :  *
   12636             :  *      floor((a f + d g)/(m d))
   12637             :  *
   12638             :  * Constraints of the form
   12639             :  *
   12640             :  *      a i + g
   12641             :  *
   12642             :  * are replaced by
   12643             :  *
   12644             :  *      a f + d g
   12645             :  *
   12646             :  * We currently require that "subs" is an integral expression.
   12647             :  * Handling rational expressions may require us to add stride constraints
   12648             :  * as we do in isl_basic_set_preimage_multi_aff.
   12649             :  */
   12650           0 : __isl_give isl_basic_set *isl_basic_set_substitute(
   12651             :         __isl_take isl_basic_set *bset,
   12652             :         enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
   12653             : {
   12654             :         int i;
   12655             :         isl_int v;
   12656             :         isl_ctx *ctx;
   12657             : 
   12658           0 :         if (bset && isl_basic_set_plain_is_empty(bset))
   12659           0 :                 return bset;
   12660             : 
   12661           0 :         bset = isl_basic_set_cow(bset);
   12662           0 :         if (!bset || !subs)
   12663             :                 goto error;
   12664             : 
   12665           0 :         ctx = isl_basic_set_get_ctx(bset);
   12666           0 :         if (!isl_space_is_equal(bset->dim, subs->ls->dim))
   12667           0 :                 isl_die(ctx, isl_error_invalid,
   12668             :                         "spaces don't match", goto error);
   12669           0 :         if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
   12670           0 :                 isl_die(ctx, isl_error_unsupported,
   12671             :                         "cannot handle divs yet", goto error);
   12672           0 :         if (!isl_int_is_one(subs->v->el[0]))
   12673           0 :                 isl_die(ctx, isl_error_invalid,
   12674             :                         "can only substitute integer expressions", goto error);
   12675             : 
   12676           0 :         pos += isl_basic_set_offset(bset, type);
   12677             : 
   12678           0 :         isl_int_init(v);
   12679             : 
   12680           0 :         for (i = 0; i < bset->n_eq; ++i) {
   12681           0 :                 if (isl_int_is_zero(bset->eq[i][pos]))
   12682           0 :                         continue;
   12683           0 :                 isl_int_set(v, bset->eq[i][pos]);
   12684           0 :                 isl_int_set_si(bset->eq[i][pos], 0);
   12685           0 :                 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
   12686           0 :                                 v, subs->v->el + 1, subs->v->size - 1);
   12687             :         }
   12688             : 
   12689           0 :         for (i = 0; i < bset->n_ineq; ++i) {
   12690           0 :                 if (isl_int_is_zero(bset->ineq[i][pos]))
   12691           0 :                         continue;
   12692           0 :                 isl_int_set(v, bset->ineq[i][pos]);
   12693           0 :                 isl_int_set_si(bset->ineq[i][pos], 0);
   12694           0 :                 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
   12695           0 :                                 v, subs->v->el + 1, subs->v->size - 1);
   12696             :         }
   12697             : 
   12698           0 :         for (i = 0; i < bset->n_div; ++i) {
   12699           0 :                 if (isl_int_is_zero(bset->div[i][1 + pos]))
   12700           0 :                         continue;
   12701           0 :                 isl_int_set(v, bset->div[i][1 + pos]);
   12702           0 :                 isl_int_set_si(bset->div[i][1 + pos], 0);
   12703           0 :                 isl_seq_combine(bset->div[i] + 1,
   12704           0 :                                 subs->v->el[0], bset->div[i] + 1,
   12705           0 :                                 v, subs->v->el + 1, subs->v->size - 1);
   12706           0 :                 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
   12707             :         }
   12708             : 
   12709           0 :         isl_int_clear(v);
   12710             : 
   12711           0 :         bset = isl_basic_set_simplify(bset);
   12712           0 :         return isl_basic_set_finalize(bset);
   12713             : error:
   12714           0 :         isl_basic_set_free(bset);
   12715           0 :         return NULL;
   12716             : }
   12717             : 
   12718             : /* Plug in "subs" for dimension "type", "pos" of "set".
   12719             :  */
   12720           0 : __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
   12721             :         enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
   12722             : {
   12723             :         int i;
   12724             : 
   12725           0 :         if (set && isl_set_plain_is_empty(set))
   12726           0 :                 return set;
   12727             : 
   12728           0 :         set = isl_set_cow(set);
   12729           0 :         if (!set || !subs)
   12730             :                 goto error;
   12731             : 
   12732           0 :         for (i = set->n - 1; i >= 0; --i) {
   12733           0 :                 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
   12734           0 :                 set = set_from_map(remove_if_empty(set_to_map(set), i));
   12735           0 :                 if (!set)
   12736           0 :                         return NULL;
   12737             :         }
   12738             : 
   12739           0 :         return set;
   12740             : error:
   12741           0 :         isl_set_free(set);
   12742           0 :         return NULL;
   12743             : }
   12744             : 
   12745             : /* Check if the range of "ma" is compatible with the domain or range
   12746             :  * (depending on "type") of "bmap".
   12747             :  */
   12748           0 : static isl_stat check_basic_map_compatible_range_multi_aff(
   12749             :         __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
   12750             :         __isl_keep isl_multi_aff *ma)
   12751             : {
   12752             :         isl_bool m;
   12753             :         isl_space *ma_space;
   12754             : 
   12755           0 :         ma_space = isl_multi_aff_get_space(ma);
   12756             : 
   12757           0 :         m = isl_space_has_equal_params(bmap->dim, ma_space);
   12758           0 :         if (m < 0)
   12759           0 :                 goto error;
   12760           0 :         if (!m)
   12761           0 :                 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
   12762             :                         "parameters don't match", goto error);
   12763           0 :         m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
   12764           0 :         if (m < 0)
   12765           0 :                 goto error;
   12766           0 :         if (!m)
   12767           0 :                 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
   12768             :                         "spaces don't match", goto error);
   12769             : 
   12770           0 :         isl_space_free(ma_space);
   12771           0 :         return isl_stat_ok;
   12772             : error:
   12773           0 :         isl_space_free(ma_space);
   12774           0 :         return isl_stat_error;
   12775             : }
   12776             : 
   12777             : /* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
   12778             :  * coefficients before the transformed range of dimensions,
   12779             :  * the "n_after" coefficients after the transformed range of dimensions
   12780             :  * and the coefficients of the other divs in "bmap".
   12781             :  */
   12782           0 : static int set_ma_divs(__isl_keep isl_basic_map *bmap,
   12783             :         __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
   12784             : {
   12785             :         int i;
   12786             :         int n_param;
   12787             :         int n_set;
   12788             :         isl_local_space *ls;
   12789             : 
   12790           0 :         if (n_div == 0)
   12791           0 :                 return 0;
   12792             : 
   12793           0 :         ls = isl_aff_get_domain_local_space(ma->u.p[0]);
   12794           0 :         if (!ls)
   12795           0 :                 return -1;
   12796             : 
   12797           0 :         n_param = isl_local_space_dim(ls, isl_dim_param);
   12798           0 :         n_set = isl_local_space_dim(ls, isl_dim_set);
   12799           0 :         for (i = 0; i < n_div; ++i) {
   12800           0 :                 int o_bmap = 0, o_ls = 0;
   12801             : 
   12802           0 :                 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
   12803           0 :                 o_bmap += 1 + 1 + n_param;
   12804           0 :                 o_ls += 1 + 1 + n_param;
   12805           0 :                 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
   12806           0 :                 o_bmap += n_before;
   12807           0 :                 isl_seq_cpy(bmap->div[i] + o_bmap,
   12808           0 :                             ls->div->row[i] + o_ls, n_set);
   12809           0 :                 o_bmap += n_set;
   12810           0 :                 o_ls += n_set;
   12811           0 :                 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
   12812           0 :                 o_bmap += n_after;
   12813           0 :                 isl_seq_cpy(bmap->div[i] + o_bmap,
   12814           0 :                             ls->div->row[i] + o_ls, n_div);
   12815           0 :                 o_bmap += n_div;
   12816           0 :                 o_ls += n_div;
   12817           0 :                 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
   12818           0 :                 if (isl_basic_map_add_div_constraints(bmap, i) < 0)
   12819           0 :                         goto error;
   12820             :         }
   12821             : 
   12822           0 :         isl_local_space_free(ls);
   12823           0 :         return 0;
   12824             : error:
   12825           0 :         isl_local_space_free(ls);
   12826           0 :         return -1;
   12827             : }
   12828             : 
   12829             : /* How many stride constraints does "ma" enforce?
   12830             :  * That is, how many of the affine expressions have a denominator
   12831             :  * different from one?
   12832             :  */
   12833           0 : static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
   12834             : {
   12835             :         int i;
   12836           0 :         int strides = 0;
   12837             : 
   12838           0 :         for (i = 0; i < ma->n; ++i)
   12839           0 :                 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
   12840           0 :                         strides++;
   12841             : 
   12842           0 :         return strides;
   12843             : }
   12844             : 
   12845             : /* For each affine expression in ma of the form
   12846             :  *
   12847             :  *      x_i = (f_i y + h_i)/m_i
   12848             :  *
   12849             :  * with m_i different from one, add a constraint to "bmap"
   12850             :  * of the form
   12851             :  *
   12852             :  *      f_i y + h_i = m_i alpha_i
   12853             :  *
   12854             :  * with alpha_i an additional existentially quantified variable.
   12855             :  *
   12856             :  * The input variables of "ma" correspond to a subset of the variables
   12857             :  * of "bmap".  There are "n_before" variables in "bmap" before this
   12858             :  * subset and "n_after" variables after this subset.
   12859             :  * The integer divisions of the affine expressions in "ma" are assumed
   12860             :  * to have been aligned.  There are "n_div_ma" of them and
   12861             :  * they appear first in "bmap", straight after the "n_after" variables.
   12862             :  */
   12863           0 : static __isl_give isl_basic_map *add_ma_strides(
   12864             :         __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
   12865             :         int n_before, int n_after, int n_div_ma)
   12866             : {
   12867             :         int i, k;
   12868             :         int div;
   12869             :         int total;
   12870             :         int n_param;
   12871             :         int n_in;
   12872             : 
   12873           0 :         total = isl_basic_map_total_dim(bmap);
   12874           0 :         n_param = isl_multi_aff_dim(ma, isl_dim_param);
   12875           0 :         n_in = isl_multi_aff_dim(ma, isl_dim_in);
   12876           0 :         for (i = 0; i < ma->n; ++i) {
   12877           0 :                 int o_bmap = 0, o_ma = 1;
   12878             : 
   12879           0 :                 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
   12880           0 :                         continue;
   12881           0 :                 div = isl_basic_map_alloc_div(bmap);
   12882           0 :                 k = isl_basic_map_alloc_equality(bmap);
   12883           0 :                 if (div < 0 || k < 0)
   12884             :                         goto error;
   12885           0 :                 isl_int_set_si(bmap->div[div][0], 0);
   12886           0 :                 isl_seq_cpy(bmap->eq[k] + o_bmap,
   12887           0 :                             ma->u.p[i]->v->el + o_ma, 1 + n_param);
   12888           0 :                 o_bmap += 1 + n_param;
   12889           0 :                 o_ma += 1 + n_param;
   12890           0 :                 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
   12891           0 :                 o_bmap += n_before;
   12892           0 :                 isl_seq_cpy(bmap->eq[k] + o_bmap,
   12893           0 :                             ma->u.p[i]->v->el + o_ma, n_in);
   12894           0 :                 o_bmap += n_in;
   12895           0 :                 o_ma += n_in;
   12896           0 :                 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
   12897           0 :                 o_bmap += n_after;
   12898           0 :                 isl_seq_cpy(bmap->eq[k] + o_bmap,
   12899           0 :                             ma->u.p[i]->v->el + o_ma, n_div_ma);
   12900           0 :                 o_bmap += n_div_ma;
   12901           0 :                 o_ma += n_div_ma;
   12902           0 :                 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
   12903           0 :                 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
   12904           0 :                 total++;
   12905             :         }
   12906             : 
   12907           0 :         return bmap;
   12908             : error:
   12909           0 :         isl_basic_map_free(bmap);
   12910           0 :         return NULL;
   12911             : }
   12912             : 
   12913             : /* Replace the domain or range space (depending on "type) of "space" by "set".
   12914             :  */
   12915           0 : static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
   12916             :         enum isl_dim_type type, __isl_take isl_space *set)
   12917             : {
   12918           0 :         if (type == isl_dim_in) {
   12919           0 :                 space = isl_space_range(space);
   12920           0 :                 space = isl_space_map_from_domain_and_range(set, space);
   12921             :         } else {
   12922           0 :                 space = isl_space_domain(space);
   12923           0 :                 space = isl_space_map_from_domain_and_range(space, set);
   12924             :         }
   12925             : 
   12926           0 :         return space;
   12927             : }
   12928             : 
   12929             : /* Compute the preimage of the domain or range (depending on "type")
   12930             :  * of "bmap" under the function represented by "ma".
   12931             :  * In other words, plug in "ma" in the domain or range of "bmap".
   12932             :  * The result is a basic map that lives in the same space as "bmap"
   12933             :  * except that the domain or range has been replaced by
   12934             :  * the domain space of "ma".
   12935             :  *
   12936             :  * If bmap is represented by
   12937             :  *
   12938             :  *      A(p) + S u + B x + T v + C(divs) >= 0,
   12939             :  *
   12940             :  * where u and x are input and output dimensions if type == isl_dim_out
   12941             :  * while x and v are input and output dimensions if type == isl_dim_in,
   12942             :  * and ma is represented by
   12943             :  *
   12944             :  *      x = D(p) + F(y) + G(divs')
   12945             :  *
   12946             :  * then the result is
   12947             :  *
   12948             :  *      A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
   12949             :  *
   12950             :  * The divs in the input set are similarly adjusted.
   12951             :  * In particular
   12952             :  *
   12953             :  *      floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
   12954             :  *
   12955             :  * becomes
   12956             :  *
   12957             :  *      floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
   12958             :  *              B_i G(divs') + c_i(divs))/n_i)
   12959             :  *
   12960             :  * If bmap is not a rational map and if F(y) involves any denominators
   12961             :  *
   12962             :  *      x_i = (f_i y + h_i)/m_i
   12963             :  *
   12964             :  * then additional constraints are added to ensure that we only
   12965             :  * map back integer points.  That is we enforce
   12966             :  *
   12967             :  *      f_i y + h_i = m_i alpha_i
   12968             :  *
   12969             :  * with alpha_i an additional existentially quantified variable.
   12970             :  *
   12971             :  * We first copy over the divs from "ma".
   12972             :  * Then we add the modified constraints and divs from "bmap".
   12973             :  * Finally, we add the stride constraints, if needed.
   12974             :  */
   12975           0 : __isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
   12976             :         __isl_take isl_basic_map *bmap, enum isl_dim_type type,
   12977             :         __isl_take isl_multi_aff *ma)
   12978             : {
   12979             :         int i, k;
   12980             :         isl_space *space;
   12981           0 :         isl_basic_map *res = NULL;
   12982             :         int n_before, n_after, n_div_bmap, n_div_ma;
   12983             :         isl_int f, c1, c2, g;
   12984             :         isl_bool rational;
   12985             :         int strides;
   12986             : 
   12987           0 :         isl_int_init(f);
   12988           0 :         isl_int_init(c1);
   12989           0 :         isl_int_init(c2);
   12990           0 :         isl_int_init(g);
   12991             : 
   12992           0 :         ma = isl_multi_aff_align_divs(ma);
   12993           0 :         if (!bmap || !ma)
   12994             :                 goto error;
   12995           0 :         if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
   12996           0 :                 goto error;
   12997             : 
   12998           0 :         if (type == isl_dim_in) {
   12999           0 :                 n_before = 0;
   13000           0 :                 n_after = isl_basic_map_dim(bmap, isl_dim_out);
   13001             :         } else {
   13002           0 :                 n_before = isl_basic_map_dim(bmap, isl_dim_in);
   13003           0 :                 n_after = 0;
   13004             :         }
   13005           0 :         n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
   13006           0 :         n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
   13007             : 
   13008           0 :         space = isl_multi_aff_get_domain_space(ma);
   13009           0 :         space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
   13010           0 :         rational = isl_basic_map_is_rational(bmap);
   13011           0 :         strides = rational ? 0 : multi_aff_strides(ma);
   13012           0 :         res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
   13013           0 :                             bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
   13014           0 :         if (rational)
   13015           0 :                 res = isl_basic_map_set_rational(res);
   13016             : 
   13017           0 :         for (i = 0; i < n_div_ma + n_div_bmap; ++i)
   13018           0 :                 if (isl_basic_map_alloc_div(res) < 0)
   13019           0 :                         goto error;
   13020             : 
   13021           0 :         if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
   13022           0 :                 goto error;
   13023             : 
   13024           0 :         for (i = 0; i < bmap->n_eq; ++i) {
   13025           0 :                 k = isl_basic_map_alloc_equality(res);
   13026           0 :                 if (k < 0)
   13027           0 :                         goto error;
   13028           0 :                 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
   13029             :                                 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
   13030             :         }
   13031             : 
   13032           0 :         for (i = 0; i < bmap->n_ineq; ++i) {
   13033           0 :                 k = isl_basic_map_alloc_inequality(res);
   13034           0 :                 if (k < 0)
   13035           0 :                         goto error;
   13036           0 :                 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
   13037             :                                 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
   13038             :         }
   13039             : 
   13040           0 :         for (i = 0; i < bmap->n_div; ++i) {
   13041           0 :                 if (isl_int_is_zero(bmap->div[i][0])) {
   13042           0 :                         isl_int_set_si(res->div[n_div_ma + i][0], 0);
   13043           0 :                         continue;
   13044             :                 }
   13045           0 :                 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
   13046             :                                     n_before, n_after, n_div_ma, n_div_bmap,
   13047             :                                     f, c1, c2, g, 1);
   13048             :         }
   13049             : 
   13050           0 :         if (strides)
   13051           0 :                 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
   13052             : 
   13053           0 :         isl_int_clear(f);
   13054           0 :         isl_int_clear(c1);
   13055           0 :         isl_int_clear(c2);
   13056           0 :         isl_int_clear(g);
   13057           0 :         isl_basic_map_free(bmap);
   13058           0 :         isl_multi_aff_free(ma);
   13059           0 :         res = isl_basic_map_simplify(res);
   13060           0 :         return isl_basic_map_finalize(res);
   13061             : error:
   13062           0 :         isl_int_clear(f);
   13063           0 :         isl_int_clear(c1);
   13064           0 :         isl_int_clear(c2);
   13065           0 :         isl_int_clear(g);
   13066           0 :         isl_basic_map_free(bmap);
   13067           0 :         isl_multi_aff_free(ma);
   13068           0 :         isl_basic_map_free(res);
   13069           0 :         return NULL;
   13070             : }
   13071             : 
   13072             : /* Compute the preimage of "bset" under the function represented by "ma".
   13073             :  * In other words, plug in "ma" in "bset".  The result is a basic set
   13074             :  * that lives in the domain space of "ma".
   13075             :  */
   13076           0 : __isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
   13077             :         __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
   13078             : {
   13079           0 :         return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
   13080             : }
   13081             : 
   13082             : /* Compute the preimage of the domain of "bmap" under the function
   13083             :  * represented by "ma".
   13084             :  * In other words, plug in "ma" in the domain of "bmap".
   13085             :  * The result is a basic map that lives in the same space as "bmap"
   13086             :  * except that the domain has been replaced by the domain space of "ma".
   13087             :  */
   13088           0 : __isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
   13089             :         __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
   13090             : {
   13091           0 :         return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
   13092             : }
   13093             : 
   13094             : /* Compute the preimage of the range of "bmap" under the function
   13095             :  * represented by "ma".
   13096             :  * In other words, plug in "ma" in the range of "bmap".
   13097             :  * The result is a basic map that lives in the same space as "bmap"
   13098             :  * except that the range has been replaced by the domain space of "ma".
   13099             :  */
   13100           0 : __isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
   13101             :         __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
   13102             : {
   13103           0 :         return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
   13104             : }
   13105             : 
   13106             : /* Check if the range of "ma" is compatible with the domain or range
   13107             :  * (depending on "type") of "map".
   13108             :  * Return isl_stat_error if anything is wrong.
   13109             :  */
   13110           0 : static isl_stat check_map_compatible_range_multi_aff(
   13111             :         __isl_keep isl_map *map, enum isl_dim_type type,
   13112             :         __isl_keep isl_multi_aff *ma)
   13113             : {
   13114             :         isl_bool m;
   13115             :         isl_space *ma_space;
   13116             : 
   13117           0 :         ma_space = isl_multi_aff_get_space(ma);
   13118           0 :         m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
   13119           0 :         isl_space_free(ma_space);
   13120           0 :         if (m < 0)
   13121           0 :                 return isl_stat_error;
   13122           0 :         if (!m)
   13123           0 :                 isl_die(isl_map_get_ctx(map), isl_error_invalid,
   13124             :                         "spaces don't match", return isl_stat_error);
   13125           0 :         return isl_stat_ok;
   13126             : }
   13127             : 
   13128             : /* Compute the preimage of the domain or range (depending on "type")
   13129             :  * of "map" under the function represented by "ma".
   13130             :  * In other words, plug in "ma" in the domain or range of "map".
   13131             :  * The result is a map that lives in the same space as "map"
   13132             :  * except that the domain or range has been replaced by
   13133             :  * the domain space of "ma".
   13134             :  *
   13135             :  * The parameters are assumed to have been aligned.
   13136             :  */
   13137           0 : static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
   13138             :         enum isl_dim_type type, __isl_take isl_multi_aff *ma)
   13139             : {
   13140             :         int i;
   13141             :         isl_space *space;
   13142             : 
   13143           0 :         map = isl_map_cow(map);
   13144           0 :         ma = isl_multi_aff_align_divs(ma);
   13145           0 :         if (!map || !ma)
   13146             :                 goto error;
   13147           0 :         if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
   13148           0 :                 goto error;
   13149             : 
   13150           0 :         for (i = 0; i < map->n; ++i) {
   13151           0 :                 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
   13152             :                                                         isl_multi_aff_copy(ma));
   13153           0 :                 if (!map->p[i])
   13154           0 :                         goto error;
   13155             :         }
   13156             : 
   13157           0 :         space = isl_multi_aff_get_domain_space(ma);
   13158           0 :         space = isl_space_set(isl_map_get_space(map), type, space);
   13159             : 
   13160           0 :         isl_space_free(map->dim);
   13161           0 :         map->dim = space;
   13162           0 :         if (!map->dim)
   13163           0 :                 goto error;
   13164             : 
   13165           0 :         isl_multi_aff_free(ma);
   13166           0 :         if (map->n > 1)
   13167           0 :                 ISL_F_CLR(map, ISL_MAP_DISJOINT);
   13168           0 :         ISL_F_CLR(map, ISL_SET_NORMALIZED);
   13169           0 :         return map;
   13170             : error:
   13171           0 :         isl_multi_aff_free(ma);
   13172           0 :         isl_map_free(map);
   13173           0 :         return NULL;
   13174             : }
   13175             : 
   13176             : /* Compute the preimage of the domain or range (depending on "type")
   13177             :  * of "map" under the function represented by "ma".
   13178             :  * In other words, plug in "ma" in the domain or range of "map".
   13179             :  * The result is a map that lives in the same space as "map"
   13180             :  * except that the domain or range has been replaced by
   13181             :  * the domain space of "ma".
   13182             :  */
   13183           0 : __isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
   13184             :         enum isl_dim_type type, __isl_take isl_multi_aff *ma)
   13185             : {
   13186             :         isl_bool aligned;
   13187             : 
   13188           0 :         if (!map || !ma)
   13189             :                 goto error;
   13190             : 
   13191           0 :         aligned = isl_map_space_has_equal_params(map, ma->space);
   13192           0 :         if (aligned < 0)
   13193           0 :                 goto error;
   13194           0 :         if (aligned)
   13195           0 :                 return map_preimage_multi_aff(map, type, ma);
   13196             : 
   13197           0 :         if (isl_map_check_named_params(map) < 0)
   13198           0 :                 goto error;
   13199           0 :         if (!isl_space_has_named_params(ma->space))
   13200           0 :                 isl_die(map->ctx, isl_error_invalid,
   13201             :                         "unaligned unnamed parameters", goto error);
   13202           0 :         map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
   13203           0 :         ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
   13204             : 
   13205           0 :         return map_preimage_multi_aff(map, type, ma);
   13206             : error:
   13207           0 :         isl_multi_aff_free(ma);
   13208           0 :         return isl_map_free(map);
   13209             : }
   13210             : 
   13211             : /* Compute the preimage of "set" under the function represented by "ma".
   13212             :  * In other words, plug in "ma" in "set".  The result is a set
   13213             :  * that lives in the domain space of "ma".
   13214             :  */
   13215           0 : __isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
   13216             :         __isl_take isl_multi_aff *ma)
   13217             : {
   13218           0 :         return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
   13219             : }
   13220             : 
   13221             : /* Compute the preimage of the domain of "map" under the function
   13222             :  * represented by "ma".
   13223             :  * In other words, plug in "ma" in the domain of "map".
   13224             :  * The result is a map that lives in the same space as "map"
   13225             :  * except that the domain has been replaced by the domain space of "ma".
   13226             :  */
   13227           0 : __isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
   13228             :         __isl_take isl_multi_aff *ma)
   13229             : {
   13230           0 :         return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
   13231             : }
   13232             : 
   13233             : /* Compute the preimage of the range of "map" under the function
   13234             :  * represented by "ma".
   13235             :  * In other words, plug in "ma" in the range of "map".
   13236             :  * The result is a map that lives in the same space as "map"
   13237             :  * except that the range has been replaced by the domain space of "ma".
   13238             :  */
   13239           0 : __isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
   13240             :         __isl_take isl_multi_aff *ma)
   13241             : {
   13242           0 :         return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
   13243             : }
   13244             : 
   13245             : /* Compute the preimage of "map" under the function represented by "pma".
   13246             :  * In other words, plug in "pma" in the domain or range of "map".
   13247             :  * The result is a map that lives in the same space as "map",
   13248             :  * except that the space of type "type" has been replaced by
   13249             :  * the domain space of "pma".
   13250             :  *
   13251             :  * The parameters of "map" and "pma" are assumed to have been aligned.
   13252             :  */
   13253           0 : static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
   13254             :         __isl_take isl_map *map, enum isl_dim_type type,
   13255             :         __isl_take isl_pw_multi_aff *pma)
   13256             : {
   13257             :         int i;
   13258             :         isl_map *res;
   13259             : 
   13260           0 :         if (!pma)
   13261           0 :                 goto error;
   13262             : 
   13263           0 :         if (pma->n == 0) {
   13264           0 :                 isl_pw_multi_aff_free(pma);
   13265           0 :                 res = isl_map_empty(isl_map_get_space(map));
   13266           0 :                 isl_map_free(map);
   13267           0 :                 return res;
   13268             :         }
   13269             : 
   13270           0 :         res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
   13271             :                                         isl_multi_aff_copy(pma->p[0].maff));
   13272           0 :         if (type == isl_dim_in)
   13273           0 :                 res = isl_map_intersect_domain(res,
   13274             :                                                 isl_map_copy(pma->p[0].set));
   13275             :         else
   13276           0 :                 res = isl_map_intersect_range(res,
   13277             :                                                 isl_map_copy(pma->p[0].set));
   13278             : 
   13279           0 :         for (i = 1; i < pma->n; ++i) {
   13280             :                 isl_map *res_i;
   13281             : 
   13282           0 :                 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
   13283             :                                         isl_multi_aff_copy(pma->p[i].maff));
   13284           0 :                 if (type == isl_dim_in)
   13285           0 :                         res_i = isl_map_intersect_domain(res_i,
   13286             :                                                 isl_map_copy(pma->p[i].set));
   13287             :                 else
   13288           0 :                         res_i = isl_map_intersect_range(res_i,
   13289             :                                                 isl_map_copy(pma->p[i].set));
   13290           0 :                 res = isl_map_union(res, res_i);
   13291             :         }
   13292             : 
   13293           0 :         isl_pw_multi_aff_free(pma);
   13294           0 :         isl_map_free(map);
   13295           0 :         return res;
   13296             : error:
   13297           0 :         isl_pw_multi_aff_free(pma);
   13298           0 :         isl_map_free(map);
   13299           0 :         return NULL;
   13300             : }
   13301             : 
   13302             : /* Compute the preimage of "map" under the function represented by "pma".
   13303             :  * In other words, plug in "pma" in the domain or range of "map".
   13304             :  * The result is a map that lives in the same space as "map",
   13305             :  * except that the space of type "type" has been replaced by
   13306             :  * the domain space of "pma".
   13307             :  */
   13308           0 : __isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
   13309             :         enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
   13310             : {
   13311             :         isl_bool aligned;
   13312             : 
   13313           0 :         if (!map || !pma)
   13314             :                 goto error;
   13315             : 
   13316           0 :         aligned = isl_map_space_has_equal_params(map, pma->dim);
   13317           0 :         if (aligned < 0)
   13318           0 :                 goto error;
   13319           0 :         if (aligned)
   13320           0 :                 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
   13321             : 
   13322           0 :         if (isl_map_check_named_params(map) < 0)
   13323           0 :                 goto error;
   13324           0 :         if (isl_pw_multi_aff_check_named_params(pma) < 0)
   13325           0 :                 goto error;
   13326           0 :         map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
   13327           0 :         pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
   13328             : 
   13329           0 :         return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
   13330             : error:
   13331           0 :         isl_pw_multi_aff_free(pma);
   13332           0 :         return isl_map_free(map);
   13333             : }
   13334             : 
   13335             : /* Compute the preimage of "set" under the function represented by "pma".
   13336             :  * In other words, plug in "pma" in "set".  The result is a set
   13337             :  * that lives in the domain space of "pma".
   13338             :  */
   13339           0 : __isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
   13340             :         __isl_take isl_pw_multi_aff *pma)
   13341             : {
   13342           0 :         return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
   13343             : }
   13344             : 
   13345             : /* Compute the preimage of the domain of "map" under the function
   13346             :  * represented by "pma".
   13347             :  * In other words, plug in "pma" in the domain of "map".
   13348             :  * The result is a map that lives in the same space as "map",
   13349             :  * except that domain space has been replaced by the domain space of "pma".
   13350             :  */
   13351           0 : __isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
   13352             :         __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
   13353             : {
   13354           0 :         return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
   13355             : }
   13356             : 
   13357             : /* Compute the preimage of the range of "map" under the function
   13358             :  * represented by "pma".
   13359             :  * In other words, plug in "pma" in the range of "map".
   13360             :  * The result is a map that lives in the same space as "map",
   13361             :  * except that range space has been replaced by the domain space of "pma".
   13362             :  */
   13363           0 : __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
   13364             :         __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
   13365             : {
   13366           0 :         return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
   13367             : }
   13368             : 
   13369             : /* Compute the preimage of "map" under the function represented by "mpa".
   13370             :  * In other words, plug in "mpa" in the domain or range of "map".
   13371             :  * The result is a map that lives in the same space as "map",
   13372             :  * except that the space of type "type" has been replaced by
   13373             :  * the domain space of "mpa".
   13374             :  *
   13375             :  * If the map does not involve any constraints that refer to the
   13376             :  * dimensions of the substituted space, then the only possible
   13377             :  * effect of "mpa" on the map is to map the space to a different space.
   13378             :  * We create a separate isl_multi_aff to effectuate this change
   13379             :  * in order to avoid spurious splitting of the map along the pieces
   13380             :  * of "mpa".
   13381             :  * If "mpa" has a non-trivial explicit domain, however,
   13382             :  * then the full substitution should be performed.
   13383             :  */
   13384           0 : __isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
   13385             :         enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
   13386             : {
   13387             :         int n;
   13388             :         isl_bool full;
   13389             :         isl_pw_multi_aff *pma;
   13390             : 
   13391           0 :         if (!map || !mpa)
   13392             :                 goto error;
   13393             : 
   13394           0 :         n = isl_map_dim(map, type);
   13395           0 :         full = isl_map_involves_dims(map, type, 0, n);
   13396           0 :         if (full >= 0 && !full)
   13397           0 :                 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
   13398           0 :         if (full < 0)
   13399           0 :                 goto error;
   13400           0 :         if (!full) {
   13401             :                 isl_space *space;
   13402             :                 isl_multi_aff *ma;
   13403             : 
   13404           0 :                 space = isl_multi_pw_aff_get_space(mpa);
   13405           0 :                 isl_multi_pw_aff_free(mpa);
   13406           0 :                 ma = isl_multi_aff_zero(space);
   13407           0 :                 return isl_map_preimage_multi_aff(map, type, ma);
   13408             :         }
   13409             : 
   13410           0 :         pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
   13411           0 :         return isl_map_preimage_pw_multi_aff(map, type, pma);
   13412             : error:
   13413           0 :         isl_map_free(map);
   13414           0 :         isl_multi_pw_aff_free(mpa);
   13415           0 :         return NULL;
   13416             : }
   13417             : 
   13418             : /* Compute the preimage of "map" under the function represented by "mpa".
   13419             :  * In other words, plug in "mpa" in the domain "map".
   13420             :  * The result is a map that lives in the same space as "map",
   13421             :  * except that domain space has been replaced by the domain space of "mpa".
   13422             :  */
   13423           0 : __isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
   13424             :         __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
   13425             : {
   13426           0 :         return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
   13427             : }
   13428             : 
   13429             : /* Compute the preimage of "set" by the function represented by "mpa".
   13430             :  * In other words, plug in "mpa" in "set".
   13431             :  */
   13432           0 : __isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
   13433             :         __isl_take isl_multi_pw_aff *mpa)
   13434             : {
   13435           0 :         return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
   13436             : }
   13437             : 
   13438             : /* Return a copy of the equality constraints of "bset" as a matrix.
   13439             :  */
   13440           0 : __isl_give isl_mat *isl_basic_set_extract_equalities(
   13441             :         __isl_keep isl_basic_set *bset)
   13442             : {
   13443             :         isl_ctx *ctx;
   13444             :         unsigned total;
   13445             : 
   13446           0 :         if (!bset)
   13447           0 :                 return NULL;
   13448             : 
   13449           0 :         ctx = isl_basic_set_get_ctx(bset);
   13450           0 :         total = 1 + isl_basic_set_dim(bset, isl_dim_all);
   13451           0 :         return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, total);
   13452             : }
   13453             : 
   13454             : /* Are the "n" "coefficients" starting at "first" of the integer division
   13455             :  * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
   13456             :  * to each other?
   13457             :  * The "coefficient" at position 0 is the denominator.
   13458             :  * The "coefficient" at position 1 is the constant term.
   13459             :  */
   13460           0 : isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
   13461             :         int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
   13462             :         unsigned first, unsigned n)
   13463             : {
   13464           0 :         if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
   13465           0 :                 return isl_bool_error;
   13466           0 :         if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
   13467           0 :                 return isl_bool_error;
   13468           0 :         return isl_seq_eq(bmap1->div[pos1] + first,
   13469           0 :                           bmap2->div[pos2] + first, n);
   13470             : }
   13471             : 
   13472             : /* Are the integer division expressions at position "pos1" in "bmap1" and
   13473             :  * "pos2" in "bmap2" equal to each other, except that the constant terms
   13474             :  * are different?
   13475             :  */
   13476           0 : isl_bool isl_basic_map_equal_div_expr_except_constant(
   13477             :         __isl_keep isl_basic_map *bmap1, int pos1,
   13478             :         __isl_keep isl_basic_map *bmap2, int pos2)
   13479             : {
   13480             :         isl_bool equal;
   13481             :         unsigned total;
   13482             : 
   13483           0 :         if (!bmap1 || !bmap2)
   13484           0 :                 return isl_bool_error;
   13485           0 :         total = isl_basic_map_total_dim(bmap1);
   13486           0 :         if (total != isl_basic_map_total_dim(bmap2))
   13487           0 :                 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
   13488             :                         "incomparable div expressions", return isl_bool_error);
   13489           0 :         equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
   13490             :                                                 0, 1);
   13491           0 :         if (equal < 0 || !equal)
   13492           0 :                 return equal;
   13493           0 :         equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
   13494             :                                                 1, 1);
   13495           0 :         if (equal < 0 || equal)
   13496           0 :                 return isl_bool_not(equal);
   13497           0 :         return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
   13498             :                                                 2, total);
   13499             : }
   13500             : 
   13501             : /* Replace the numerator of the constant term of the integer division
   13502             :  * expression at position "div" in "bmap" by "value".
   13503             :  * The caller guarantees that this does not change the meaning
   13504             :  * of the input.
   13505             :  */
   13506           0 : __isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
   13507             :         __isl_take isl_basic_map *bmap, int div, int value)
   13508             : {
   13509           0 :         if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
   13510           0 :                 return isl_basic_map_free(bmap);
   13511             : 
   13512           0 :         isl_int_set_si(bmap->div[div][1], value);
   13513             : 
   13514           0 :         return bmap;
   13515             : }
   13516             : 
   13517             : /* Is the point "inner" internal to inequality constraint "ineq"
   13518             :  * of "bset"?
   13519             :  * The point is considered to be internal to the inequality constraint,
   13520             :  * if it strictly lies on the positive side of the inequality constraint,
   13521             :  * or if it lies on the constraint and the constraint is lexico-positive.
   13522             :  */
   13523           0 : static isl_bool is_internal(__isl_keep isl_vec *inner,
   13524             :         __isl_keep isl_basic_set *bset, int ineq)
   13525             : {
   13526             :         isl_ctx *ctx;
   13527             :         int pos;
   13528             :         unsigned total;
   13529             : 
   13530           0 :         if (!inner || !bset)
   13531           0 :                 return isl_bool_error;
   13532             : 
   13533           0 :         ctx = isl_basic_set_get_ctx(bset);
   13534           0 :         isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
   13535             :                                 &ctx->normalize_gcd);
   13536           0 :         if (!isl_int_is_zero(ctx->normalize_gcd))
   13537           0 :                 return isl_int_is_nonneg(ctx->normalize_gcd);
   13538             : 
   13539           0 :         total = isl_basic_set_dim(bset, isl_dim_all);
   13540           0 :         pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
   13541           0 :         return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
   13542             : }
   13543             : 
   13544             : /* Tighten the inequality constraints of "bset" that are outward with respect
   13545             :  * to the point "vec".
   13546             :  * That is, tighten the constraints that are not satisfied by "vec".
   13547             :  *
   13548             :  * "vec" is a point internal to some superset S of "bset" that is used
   13549             :  * to make the subsets of S disjoint, by tightening one half of the constraints
   13550             :  * that separate two subsets.  In particular, the constraints of S
   13551             :  * are all satisfied by "vec" and should not be tightened.
   13552             :  * Of the internal constraints, those that have "vec" on the outside
   13553             :  * are tightened.  The shared facet is included in the adjacent subset
   13554             :  * with the opposite constraint.
   13555             :  * For constraints that saturate "vec", this criterion cannot be used
   13556             :  * to determine which of the two sides should be tightened.
   13557             :  * Instead, the sign of the first non-zero coefficient is used
   13558             :  * to make this choice.  Note that this second criterion is never used
   13559             :  * on the constraints of S since "vec" is interior to "S".
   13560             :  */
   13561           0 : __isl_give isl_basic_set *isl_basic_set_tighten_outward(
   13562             :         __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
   13563             : {
   13564             :         int j;
   13565             : 
   13566           0 :         bset = isl_basic_set_cow(bset);
   13567           0 :         if (!bset)
   13568           0 :                 return NULL;
   13569           0 :         for (j = 0; j < bset->n_ineq; ++j) {
   13570             :                 isl_bool internal;
   13571             : 
   13572           0 :                 internal = is_internal(vec, bset, j);
   13573           0 :                 if (internal < 0)
   13574           0 :                         return isl_basic_set_free(bset);
   13575           0 :                 if (internal)
   13576           0 :                         continue;
   13577           0 :                 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
   13578             :         }
   13579             : 
   13580           0 :         return bset;
   13581             : }
   13582             : 
   13583             : /* Replace the variables x of type "type" starting at "first" in "bmap"
   13584             :  * by x' with x = M x' with M the matrix trans.
   13585             :  * That is, replace the corresponding coefficients c by c M.
   13586             :  *
   13587             :  * The transformation matrix should be a square matrix.
   13588             :  */
   13589           0 : __isl_give isl_basic_map *isl_basic_map_transform_dims(
   13590             :         __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
   13591             :         __isl_take isl_mat *trans)
   13592             : {
   13593             :         unsigned pos;
   13594             : 
   13595           0 :         bmap = isl_basic_map_cow(bmap);
   13596           0 :         if (!bmap || !trans)
   13597             :                 goto error;
   13598             : 
   13599           0 :         if (trans->n_row != trans->n_col)
   13600           0 :                 isl_die(trans->ctx, isl_error_invalid,
   13601             :                         "expecting square transformation matrix", goto error);
   13602           0 :         if (first + trans->n_row > isl_basic_map_dim(bmap, type))
   13603           0 :                 isl_die(trans->ctx, isl_error_invalid,
   13604             :                         "oversized transformation matrix", goto error);
   13605             : 
   13606           0 :         pos = isl_basic_map_offset(bmap, type) + first;
   13607             : 
   13608           0 :         if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
   13609             :                         isl_mat_copy(trans)) < 0)
   13610           0 :                 goto error;
   13611           0 :         if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
   13612             :                       isl_mat_copy(trans)) < 0)
   13613           0 :                 goto error;
   13614           0 :         if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
   13615             :                       isl_mat_copy(trans)) < 0)
   13616           0 :                 goto error;
   13617             : 
   13618           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
   13619           0 :         ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
   13620             : 
   13621           0 :         isl_mat_free(trans);
   13622           0 :         return bmap;
   13623             : error:
   13624           0 :         isl_mat_free(trans);
   13625           0 :         isl_basic_map_free(bmap);
   13626           0 :         return NULL;
   13627             : }
   13628             : 
   13629             : /* Replace the variables x of type "type" starting at "first" in "bset"
   13630             :  * by x' with x = M x' with M the matrix trans.
   13631             :  * That is, replace the corresponding coefficients c by c M.
   13632             :  *
   13633             :  * The transformation matrix should be a square matrix.
   13634             :  */
   13635           0 : __isl_give isl_basic_set *isl_basic_set_transform_dims(
   13636             :         __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
   13637             :         __isl_take isl_mat *trans)
   13638             : {
   13639           0 :         return isl_basic_map_transform_dims(bset, type, first, trans);
   13640             : }

Generated by: LCOV version 1.12