LCOV - code coverage report
Current view: top level - metalib_isl - isl_space.c (source / functions) Hit Total Coverage
Test: 2018-10-31_point_maint_greina16.lcov Lines: 251 1461 17.2 %
Date: 2018-11-01 11:27:00 Functions: 36 128 28.1 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008-2009 Katholieke Universiteit Leuven
       3             :  * Copyright 2010      INRIA Saclay
       4             :  * Copyright 2013-2014 Ecole Normale Superieure
       5             :  *
       6             :  * Use of this software is governed by the MIT license
       7             :  *
       8             :  * Written by Sven Verdoolaege, K.U.Leuven, Departement
       9             :  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
      10             :  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
      11             :  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
      12             :  * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
      13             :  */
      14             : 
      15             : #include <stdlib.h>
      16             : #include <string.h>
      17             : #include <isl_space_private.h>
      18             : #include <isl_id_private.h>
      19             : #include <isl_reordering.h>
      20             : 
      21      112959 : isl_ctx *isl_space_get_ctx(__isl_keep isl_space *dim)
      22             : {
      23      112959 :         return dim ? dim->ctx : NULL;
      24             : }
      25             : 
      26 13928997624 : __isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
      27             :                         unsigned nparam, unsigned n_in, unsigned n_out)
      28             : {
      29             :         isl_space *dim;
      30             : 
      31 13928997624 :         dim = isl_alloc_type(ctx, struct isl_space);
      32 13928997624 :         if (!dim)
      33           0 :                 return NULL;
      34             : 
      35 13928997624 :         dim->ctx = ctx;
      36 13928997624 :         isl_ctx_ref(ctx);
      37 13928997624 :         dim->ref = 1;
      38 13928997624 :         dim->nparam = nparam;
      39 13928997624 :         dim->n_in = n_in;
      40 13928997624 :         dim->n_out = n_out;
      41             : 
      42 13928997624 :         dim->tuple_id[0] = NULL;
      43 13928997624 :         dim->tuple_id[1] = NULL;
      44             : 
      45 13928997624 :         dim->nested[0] = NULL;
      46 13928997624 :         dim->nested[1] = NULL;
      47             : 
      48 13928997624 :         dim->n_id = 0;
      49 13928997624 :         dim->ids = NULL;
      50             : 
      51 13928997624 :         return dim;
      52             : }
      53             : 
      54             : /* Mark the space as being that of a set, by setting the domain tuple
      55             :  * to isl_id_none.
      56             :  */
      57  1973577593 : static __isl_give isl_space *mark_as_set(__isl_take isl_space *space)
      58             : {
      59  1973577593 :         space = isl_space_cow(space);
      60  1973577593 :         if (!space)
      61           0 :                 return NULL;
      62  1973577593 :         space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
      63  1973577593 :         return space;
      64             : }
      65             : 
      66             : /* Is the space that of a set?
      67             :  */
      68    12664439 : isl_bool isl_space_is_set(__isl_keep isl_space *space)
      69             : {
      70    12664439 :         if (!space)
      71           0 :                 return isl_bool_error;
      72    12664439 :         if (space->n_in != 0 || space->nested[0])
      73           0 :                 return isl_bool_false;
      74    12664439 :         if (space->tuple_id[0] != &isl_id_none)
      75           0 :                 return isl_bool_false;
      76    12664439 :         return isl_bool_true;
      77             : }
      78             : 
      79             : /* Is the given space that of a map?
      80             :  */
      81           0 : isl_bool isl_space_is_map(__isl_keep isl_space *space)
      82             : {
      83           0 :         if (!space)
      84           0 :                 return isl_bool_error;
      85           0 :         return space->tuple_id[0] != &isl_id_none &&
      86           0 :                 space->tuple_id[1] != &isl_id_none;
      87             : }
      88             : 
      89  1973577593 : __isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
      90             :                         unsigned nparam, unsigned dim)
      91             : {
      92             :         isl_space *space;
      93  1973577593 :         space = isl_space_alloc(ctx, nparam, 0, dim);
      94  1973577593 :         space = mark_as_set(space);
      95  1973577593 :         return space;
      96             : }
      97             : 
      98             : /* Mark the space as being that of a parameter domain, by setting
      99             :  * both tuples to isl_id_none.
     100             :  */
     101           0 : static __isl_give isl_space *mark_as_params(isl_space *space)
     102             : {
     103           0 :         if (!space)
     104           0 :                 return NULL;
     105           0 :         space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
     106           0 :         space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none);
     107           0 :         return space;
     108             : }
     109             : 
     110             : /* Is the space that of a parameter domain?
     111             :  */
     112      225918 : isl_bool isl_space_is_params(__isl_keep isl_space *space)
     113             : {
     114      225918 :         if (!space)
     115           0 :                 return isl_bool_error;
     116      451836 :         if (space->n_in != 0 || space->nested[0] ||
     117      225918 :             space->n_out != 0 || space->nested[1])
     118      225918 :                 return isl_bool_false;
     119           0 :         if (space->tuple_id[0] != &isl_id_none)
     120           0 :                 return isl_bool_false;
     121           0 :         if (space->tuple_id[1] != &isl_id_none)
     122           0 :                 return isl_bool_false;
     123           0 :         return isl_bool_true;
     124             : }
     125             : 
     126             : /* Create a space for a parameter domain.
     127             :  */
     128           0 : __isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam)
     129             : {
     130             :         isl_space *space;
     131           0 :         space = isl_space_alloc(ctx, nparam, 0, 0);
     132           0 :         space = mark_as_params(space);
     133           0 :         return space;
     134             : }
     135             : 
     136    89783096 : static unsigned global_pos(__isl_keep isl_space *dim,
     137             :                                  enum isl_dim_type type, unsigned pos)
     138             : {
     139    89783096 :         struct isl_ctx *ctx = dim->ctx;
     140             : 
     141    89783096 :         switch (type) {
     142             :         case isl_dim_param:
     143           0 :                 isl_assert(ctx, pos < dim->nparam,
     144             :                             return isl_space_dim(dim, isl_dim_all));
     145           0 :                 return pos;
     146             :         case isl_dim_in:
     147           0 :                 isl_assert(ctx, pos < dim->n_in,
     148             :                             return isl_space_dim(dim, isl_dim_all));
     149           0 :                 return pos + dim->nparam;
     150             :         case isl_dim_out:
     151    89783096 :                 isl_assert(ctx, pos < dim->n_out,
     152             :                             return isl_space_dim(dim, isl_dim_all));
     153    89783096 :                 return pos + dim->nparam + dim->n_in;
     154             :         default:
     155           0 :                 isl_assert(ctx, 0, return isl_space_dim(dim, isl_dim_all));
     156             :         }
     157             :         return isl_space_dim(dim, isl_dim_all);
     158             : }
     159             : 
     160             : /* Extend length of ids array to the total number of dimensions.
     161             :  */
     162           0 : static __isl_give isl_space *extend_ids(__isl_take isl_space *dim)
     163             : {
     164             :         isl_id **ids;
     165             :         int i;
     166             : 
     167           0 :         if (isl_space_dim(dim, isl_dim_all) <= dim->n_id)
     168           0 :                 return dim;
     169             : 
     170           0 :         if (!dim->ids) {
     171           0 :                 dim->ids = isl_calloc_array(dim->ctx,
     172             :                                 isl_id *, isl_space_dim(dim, isl_dim_all));
     173           0 :                 if (!dim->ids)
     174           0 :                         goto error;
     175             :         } else {
     176           0 :                 ids = isl_realloc_array(dim->ctx, dim->ids,
     177             :                                 isl_id *, isl_space_dim(dim, isl_dim_all));
     178           0 :                 if (!ids)
     179           0 :                         goto error;
     180           0 :                 dim->ids = ids;
     181           0 :                 for (i = dim->n_id; i < isl_space_dim(dim, isl_dim_all); ++i)
     182           0 :                         dim->ids[i] = NULL;
     183             :         }
     184             : 
     185           0 :         dim->n_id = isl_space_dim(dim, isl_dim_all);
     186             : 
     187           0 :         return dim;
     188             : error:
     189           0 :         isl_space_free(dim);
     190           0 :         return NULL;
     191             : }
     192             : 
     193           0 : static __isl_give isl_space *set_id(__isl_take isl_space *dim,
     194             :         enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
     195             : {
     196           0 :         dim = isl_space_cow(dim);
     197             : 
     198           0 :         if (!dim)
     199           0 :                 goto error;
     200             : 
     201           0 :         pos = global_pos(dim, type, pos);
     202           0 :         if (pos == isl_space_dim(dim, isl_dim_all))
     203           0 :                 goto error;
     204             : 
     205           0 :         if (pos >= dim->n_id) {
     206           0 :                 if (!id)
     207           0 :                         return dim;
     208           0 :                 dim = extend_ids(dim);
     209           0 :                 if (!dim)
     210           0 :                         goto error;
     211             :         }
     212             : 
     213           0 :         dim->ids[pos] = id;
     214             : 
     215           0 :         return dim;
     216             : error:
     217           0 :         isl_id_free(id);
     218           0 :         isl_space_free(dim);
     219           0 :         return NULL;
     220             : }
     221             : 
     222    89783096 : static __isl_keep isl_id *get_id(__isl_keep isl_space *dim,
     223             :                                  enum isl_dim_type type, unsigned pos)
     224             : {
     225    89783096 :         if (!dim)
     226           0 :                 return NULL;
     227             : 
     228    89783096 :         pos = global_pos(dim, type, pos);
     229    89783096 :         if (pos == isl_space_dim(dim, isl_dim_all))
     230           0 :                 return NULL;
     231    89783096 :         if (pos >= dim->n_id)
     232    89783096 :                 return NULL;
     233           0 :         return dim->ids[pos];
     234             : }
     235             : 
     236    91102969 : static unsigned offset(__isl_keep isl_space *dim, enum isl_dim_type type)
     237             : {
     238    91102969 :         switch (type) {
     239           0 :         case isl_dim_param:     return 0;
     240           0 :         case isl_dim_in:        return dim->nparam;
     241    91102969 :         case isl_dim_out:       return dim->nparam + dim->n_in;
     242           0 :         default:                return 0;
     243             :         }
     244             : }
     245             : 
     246 >69719*10^7 : static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
     247             : {
     248 >69719*10^7 :         switch (type) {
     249 75256146426 :         case isl_dim_param:     return dim->nparam;
     250 69511701589 :         case isl_dim_in:        return dim->n_in;
     251 75008277992 :         case isl_dim_out:       return dim->n_out;
     252 >47742*10^7 :         case isl_dim_all:       return dim->nparam + dim->n_in + dim->n_out;
     253           0 :         default:                return 0;
     254             :         }
     255             : }
     256             : 
     257 >60126*10^7 : unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type)
     258             : {
     259 >60126*10^7 :         if (!dim)
     260           0 :                 return 0;
     261 >60126*10^7 :         return n(dim, type);
     262             : }
     263             : 
     264    91102969 : unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type)
     265             : {
     266    91102969 :         if (!dim)
     267           0 :                 return 0;
     268    91102969 :         return offset(dim, type);
     269             : }
     270             : 
     271           0 : static __isl_give isl_space *copy_ids(__isl_take isl_space *dst,
     272             :         enum isl_dim_type dst_type, unsigned offset, __isl_keep isl_space *src,
     273             :         enum isl_dim_type src_type)
     274             : {
     275             :         int i;
     276             :         isl_id *id;
     277             : 
     278           0 :         if (!dst)
     279           0 :                 return NULL;
     280             : 
     281           0 :         for (i = 0; i < n(src, src_type); ++i) {
     282           0 :                 id = get_id(src, src_type, i);
     283           0 :                 if (!id)
     284           0 :                         continue;
     285           0 :                 dst = set_id(dst, dst_type, offset + i, isl_id_copy(id));
     286           0 :                 if (!dst)
     287           0 :                         return NULL;
     288             :         }
     289           0 :         return dst;
     290             : }
     291             : 
     292  6116091432 : __isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim)
     293             : {
     294             :         isl_space *dup;
     295  6116091432 :         if (!dim)
     296           0 :                 return NULL;
     297  6116091432 :         dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
     298  6116091432 :         if (!dup)
     299           0 :                 return NULL;
     300  6173934432 :         if (dim->tuple_id[0] &&
     301    57843000 :             !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0])))
     302           0 :                 goto error;
     303  6116091432 :         if (dim->tuple_id[1] &&
     304           0 :             !(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1])))
     305           0 :                 goto error;
     306  6116091432 :         if (dim->nested[0] && !(dup->nested[0] = isl_space_copy(dim->nested[0])))
     307           0 :                 goto error;
     308  6116091432 :         if (dim->nested[1] && !(dup->nested[1] = isl_space_copy(dim->nested[1])))
     309           0 :                 goto error;
     310  6116091432 :         if (!dim->ids)
     311  6116091432 :                 return dup;
     312           0 :         dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param);
     313           0 :         dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in);
     314           0 :         dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out);
     315           0 :         return dup;
     316             : error:
     317           0 :         isl_space_free(dup);
     318           0 :         return NULL;
     319             : }
     320             : 
     321 10086773820 : __isl_give isl_space *isl_space_cow(__isl_take isl_space *dim)
     322             : {
     323 10086773820 :         if (!dim)
     324           0 :                 return NULL;
     325             : 
     326 10086773820 :         if (dim->ref == 1)
     327  3970682388 :                 return dim;
     328  6116091432 :         dim->ref--;
     329  6116091432 :         return isl_space_dup(dim);
     330             : }
     331             : 
     332 27555601089 : __isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim)
     333             : {
     334 27555601089 :         if (!dim)
     335           0 :                 return NULL;
     336             : 
     337 27555601089 :         dim->ref++;
     338 27555601089 :         return dim;
     339             : }
     340             : 
     341 63284232570 : __isl_null isl_space *isl_space_free(__isl_take isl_space *space)
     342             : {
     343             :         int i;
     344             : 
     345 63284232570 :         if (!space)
     346 27915725289 :                 return NULL;
     347             : 
     348 35368507281 :         if (--space->ref > 0)
     349 21439509657 :                 return NULL;
     350             : 
     351 13928997624 :         isl_id_free(space->tuple_id[0]);
     352 13928997624 :         isl_id_free(space->tuple_id[1]);
     353             : 
     354 13928997624 :         isl_space_free(space->nested[0]);
     355 13928997624 :         isl_space_free(space->nested[1]);
     356             : 
     357 13928997624 :         for (i = 0; i < space->n_id; ++i)
     358           0 :                 isl_id_free(space->ids[i]);
     359 13928997624 :         free(space->ids);
     360 13928997624 :         isl_ctx_deref(space->ctx);
     361             :         
     362 13928997624 :         free(space);
     363             : 
     364 13928997624 :         return NULL;
     365             : }
     366             : 
     367             : /* Check if "s" is a valid dimension or tuple name.
     368             :  * We currently only forbid names that look like a number.
     369             :  *
     370             :  * s is assumed to be non-NULL.
     371             :  */
     372           0 : static int name_ok(isl_ctx *ctx, const char *s)
     373             : {
     374             :         char *p;
     375             :         long dummy;
     376             : 
     377           0 :         dummy = strtol(s, &p, 0);
     378           0 :         if (p != s)
     379           0 :                 isl_die(ctx, isl_error_invalid, "name looks like a number",
     380             :                         return 0);
     381             : 
     382           0 :         return 1;
     383             : }
     384             : 
     385             : /* Is it possible for the given dimension type to have a tuple id?
     386             :  */
     387           0 : static int space_can_have_id(__isl_keep isl_space *space,
     388             :         enum isl_dim_type type)
     389             : {
     390           0 :         if (!space)
     391           0 :                 return 0;
     392           0 :         if (isl_space_is_params(space))
     393           0 :                 isl_die(space->ctx, isl_error_invalid,
     394             :                         "parameter spaces don't have tuple ids", return 0);
     395           0 :         if (isl_space_is_set(space) && type != isl_dim_set)
     396           0 :                 isl_die(space->ctx, isl_error_invalid,
     397             :                         "set spaces can only have a set id", return 0);
     398           0 :         if (type != isl_dim_in && type != isl_dim_out)
     399           0 :                 isl_die(space->ctx, isl_error_invalid,
     400             :                         "only input, output and set tuples can have ids",
     401             :                         return 0);
     402             : 
     403           0 :         return 1;
     404             : }
     405             : 
     406             : /* Does the tuple have an id?
     407             :  */
     408           0 : isl_bool isl_space_has_tuple_id(__isl_keep isl_space *dim,
     409             :         enum isl_dim_type type)
     410             : {
     411           0 :         if (!space_can_have_id(dim, type))
     412           0 :                 return isl_bool_error;
     413           0 :         return dim->tuple_id[type - isl_dim_in] != NULL;
     414             : }
     415             : 
     416           0 : __isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
     417             :         enum isl_dim_type type)
     418             : {
     419             :         int has_id;
     420             : 
     421           0 :         if (!dim)
     422           0 :                 return NULL;
     423           0 :         has_id = isl_space_has_tuple_id(dim, type);
     424           0 :         if (has_id < 0)
     425           0 :                 return NULL;
     426           0 :         if (!has_id)
     427           0 :                 isl_die(dim->ctx, isl_error_invalid,
     428             :                         "tuple has no id", return NULL);
     429           0 :         return isl_id_copy(dim->tuple_id[type - isl_dim_in]);
     430             : }
     431             : 
     432  1973577593 : __isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *dim,
     433             :         enum isl_dim_type type, __isl_take isl_id *id)
     434             : {
     435  1973577593 :         dim = isl_space_cow(dim);
     436  1973577593 :         if (!dim || !id)
     437             :                 goto error;
     438  1973577593 :         if (type != isl_dim_in && type != isl_dim_out)
     439           0 :                 isl_die(dim->ctx, isl_error_invalid,
     440             :                         "only input, output and set tuples can have names",
     441             :                         goto error);
     442             : 
     443  1973577593 :         isl_id_free(dim->tuple_id[type - isl_dim_in]);
     444  1973577593 :         dim->tuple_id[type - isl_dim_in] = id;
     445             : 
     446  1973577593 :         return dim;
     447             : error:
     448           0 :         isl_id_free(id);
     449           0 :         isl_space_free(dim);
     450           0 :         return NULL;
     451             : }
     452             : 
     453           0 : __isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
     454             :         enum isl_dim_type type)
     455             : {
     456           0 :         dim = isl_space_cow(dim);
     457           0 :         if (!dim)
     458           0 :                 return NULL;
     459           0 :         if (type != isl_dim_in && type != isl_dim_out)
     460           0 :                 isl_die(dim->ctx, isl_error_invalid,
     461             :                         "only input, output and set tuples can have names",
     462             :                         goto error);
     463             : 
     464           0 :         isl_id_free(dim->tuple_id[type - isl_dim_in]);
     465           0 :         dim->tuple_id[type - isl_dim_in] = NULL;
     466             : 
     467           0 :         return dim;
     468             : error:
     469           0 :         isl_space_free(dim);
     470           0 :         return NULL;
     471             : }
     472             : 
     473             : /* Set the id of the given dimension of "space" to "id".
     474             :  * If the dimension already has an id, then it is replaced.
     475             :  * If the dimension is a parameter, then we need to change it
     476             :  * in the nested spaces (if any) as well.
     477             :  */
     478           0 : __isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *space,
     479             :         enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
     480             : {
     481           0 :         space = isl_space_cow(space);
     482           0 :         if (!space || !id)
     483             :                 goto error;
     484             : 
     485           0 :         if (type == isl_dim_param) {
     486             :                 int i;
     487             : 
     488           0 :                 for (i = 0; i < 2; ++i) {
     489           0 :                         if (!space->nested[i])
     490           0 :                                 continue;
     491           0 :                         space->nested[i] =
     492           0 :                                 isl_space_set_dim_id(space->nested[i],
     493             :                                                 type, pos, isl_id_copy(id));
     494           0 :                         if (!space->nested[i])
     495           0 :                                 goto error;
     496             :                 }
     497             :         }
     498             : 
     499           0 :         isl_id_free(get_id(space, type, pos));
     500           0 :         return set_id(space, type, pos, id);
     501             : error:
     502           0 :         isl_id_free(id);
     503           0 :         isl_space_free(space);
     504           0 :         return NULL;
     505             : }
     506             : 
     507             : /* Reset the id of the given dimension of "space".
     508             :  * If the dimension already has an id, then it is removed.
     509             :  * If the dimension is a parameter, then we need to reset it
     510             :  * in the nested spaces (if any) as well.
     511             :  */
     512           0 : __isl_give isl_space *isl_space_reset_dim_id(__isl_take isl_space *space,
     513             :         enum isl_dim_type type, unsigned pos)
     514             : {
     515           0 :         space = isl_space_cow(space);
     516           0 :         if (!space)
     517           0 :                 goto error;
     518             : 
     519           0 :         if (type == isl_dim_param) {
     520             :                 int i;
     521             : 
     522           0 :                 for (i = 0; i < 2; ++i) {
     523           0 :                         if (!space->nested[i])
     524           0 :                                 continue;
     525           0 :                         space->nested[i] =
     526           0 :                                 isl_space_reset_dim_id(space->nested[i],
     527             :                                                         type, pos);
     528           0 :                         if (!space->nested[i])
     529           0 :                                 goto error;
     530             :                 }
     531             :         }
     532             : 
     533           0 :         isl_id_free(get_id(space, type, pos));
     534           0 :         return set_id(space, type, pos, NULL);
     535             : error:
     536           0 :         isl_space_free(space);
     537           0 :         return NULL;
     538             : }
     539             : 
     540           0 : isl_bool isl_space_has_dim_id(__isl_keep isl_space *dim,
     541             :         enum isl_dim_type type, unsigned pos)
     542             : {
     543           0 :         if (!dim)
     544           0 :                 return isl_bool_error;
     545           0 :         return get_id(dim, type, pos) != NULL;
     546             : }
     547             : 
     548           0 : __isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *dim,
     549             :         enum isl_dim_type type, unsigned pos)
     550             : {
     551           0 :         if (!dim)
     552           0 :                 return NULL;
     553           0 :         if (!get_id(dim, type, pos))
     554           0 :                 isl_die(dim->ctx, isl_error_invalid,
     555             :                         "dim has no id", return NULL);
     556           0 :         return isl_id_copy(get_id(dim, type, pos));
     557             : }
     558             : 
     559           0 : __isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *dim,
     560             :         enum isl_dim_type type, const char *s)
     561             : {
     562             :         isl_id *id;
     563             : 
     564           0 :         if (!dim)
     565           0 :                 return NULL;
     566             : 
     567           0 :         if (!s)
     568           0 :                 return isl_space_reset_tuple_id(dim, type);
     569             : 
     570           0 :         if (!name_ok(dim->ctx, s))
     571           0 :                 goto error;
     572             : 
     573           0 :         id = isl_id_alloc(dim->ctx, s, NULL);
     574           0 :         return isl_space_set_tuple_id(dim, type, id);
     575             : error:
     576           0 :         isl_space_free(dim);
     577           0 :         return NULL;
     578             : }
     579             : 
     580             : /* Does the tuple have a name?
     581             :  */
     582           0 : isl_bool isl_space_has_tuple_name(__isl_keep isl_space *space,
     583             :         enum isl_dim_type type)
     584             : {
     585             :         isl_id *id;
     586             : 
     587           0 :         if (!space_can_have_id(space, type))
     588           0 :                 return isl_bool_error;
     589           0 :         id = space->tuple_id[type - isl_dim_in];
     590           0 :         return id && id->name;
     591             : }
     592             : 
     593      225918 : __isl_keep const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
     594             :          enum isl_dim_type type)
     595             : {
     596             :         isl_id *id;
     597      225918 :         if (!dim)
     598           0 :                 return NULL;
     599      225918 :         if (type != isl_dim_in && type != isl_dim_out)
     600           0 :                 return NULL;
     601      225918 :         id = dim->tuple_id[type - isl_dim_in];
     602      225918 :         return id ? id->name : NULL;
     603             : }
     604             : 
     605           0 : __isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *dim,
     606             :                                  enum isl_dim_type type, unsigned pos,
     607             :                                  const char *s)
     608             : {
     609             :         isl_id *id;
     610             : 
     611           0 :         if (!dim)
     612           0 :                 return NULL;
     613           0 :         if (!s)
     614           0 :                 return isl_space_reset_dim_id(dim, type, pos);
     615           0 :         if (!name_ok(dim->ctx, s))
     616           0 :                 goto error;
     617           0 :         id = isl_id_alloc(dim->ctx, s, NULL);
     618           0 :         return isl_space_set_dim_id(dim, type, pos, id);
     619             : error:
     620           0 :         isl_space_free(dim);
     621           0 :         return NULL;
     622             : }
     623             : 
     624             : /* Does the given dimension have a name?
     625             :  */
     626           0 : isl_bool isl_space_has_dim_name(__isl_keep isl_space *space,
     627             :         enum isl_dim_type type, unsigned pos)
     628             : {
     629             :         isl_id *id;
     630             : 
     631           0 :         if (!space)
     632           0 :                 return isl_bool_error;
     633           0 :         id = get_id(space, type, pos);
     634           0 :         return id && id->name;
     635             : }
     636             : 
     637    89783096 : __isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *dim,
     638             :                                  enum isl_dim_type type, unsigned pos)
     639             : {
     640    89783096 :         isl_id *id = get_id(dim, type, pos);
     641    89783096 :         return id ? id->name : NULL;
     642             : }
     643             : 
     644           0 : int isl_space_find_dim_by_id(__isl_keep isl_space *dim, enum isl_dim_type type,
     645             :         __isl_keep isl_id *id)
     646             : {
     647             :         int i;
     648             :         int offset;
     649             :         int n;
     650             : 
     651           0 :         if (!dim || !id)
     652           0 :                 return -1;
     653             : 
     654           0 :         offset = isl_space_offset(dim, type);
     655           0 :         n = isl_space_dim(dim, type);
     656           0 :         for (i = 0; i < n && offset + i < dim->n_id; ++i)
     657           0 :                 if (dim->ids[offset + i] == id)
     658           0 :                         return i;
     659             : 
     660           0 :         return -1;
     661             : }
     662             : 
     663           0 : int isl_space_find_dim_by_name(__isl_keep isl_space *space,
     664             :         enum isl_dim_type type, const char *name)
     665             : {
     666             :         int i;
     667             :         int offset;
     668             :         int n;
     669             : 
     670           0 :         if (!space || !name)
     671           0 :                 return -1;
     672             : 
     673           0 :         offset = isl_space_offset(space, type);
     674           0 :         n = isl_space_dim(space, type);
     675           0 :         for (i = 0; i < n && offset + i < space->n_id; ++i) {
     676           0 :                 isl_id *id = get_id(space, type, i);
     677           0 :                 if (id && id->name && !strcmp(id->name, name))
     678           0 :                         return i;
     679             :         }
     680             : 
     681           0 :         return -1;
     682             : }
     683             : 
     684             : /* Reset the user pointer on all identifiers of parameters and tuples
     685             :  * of "space".
     686             :  */
     687           0 : __isl_give isl_space *isl_space_reset_user(__isl_take isl_space *space)
     688             : {
     689             :         int i;
     690             :         isl_ctx *ctx;
     691             :         isl_id *id;
     692             :         const char *name;
     693             : 
     694           0 :         if (!space)
     695           0 :                 return NULL;
     696             : 
     697           0 :         ctx = isl_space_get_ctx(space);
     698             : 
     699           0 :         for (i = 0; i < space->nparam && i < space->n_id; ++i) {
     700           0 :                 if (!isl_id_get_user(space->ids[i]))
     701           0 :                         continue;
     702           0 :                 space = isl_space_cow(space);
     703           0 :                 if (!space)
     704           0 :                         return NULL;
     705           0 :                 name = isl_id_get_name(space->ids[i]);
     706           0 :                 id = isl_id_alloc(ctx, name, NULL);
     707           0 :                 isl_id_free(space->ids[i]);
     708           0 :                 space->ids[i] = id;
     709           0 :                 if (!id)
     710           0 :                         return isl_space_free(space);
     711             :         }
     712             : 
     713           0 :         for (i = 0; i < 2; ++i) {
     714           0 :                 if (!space->tuple_id[i])
     715           0 :                         continue;
     716           0 :                 if (!isl_id_get_user(space->tuple_id[i]))
     717           0 :                         continue;
     718           0 :                 space = isl_space_cow(space);
     719           0 :                 if (!space)
     720           0 :                         return NULL;
     721           0 :                 name = isl_id_get_name(space->tuple_id[i]);
     722           0 :                 id = isl_id_alloc(ctx, name, NULL);
     723           0 :                 isl_id_free(space->tuple_id[i]);
     724           0 :                 space->tuple_id[i] = id;
     725           0 :                 if (!id)
     726           0 :                         return isl_space_free(space);
     727             :         }
     728             : 
     729           0 :         for (i = 0; i < 2; ++i) {
     730           0 :                 if (!space->nested[i])
     731           0 :                         continue;
     732           0 :                 space = isl_space_cow(space);
     733           0 :                 if (!space)
     734           0 :                         return NULL;
     735           0 :                 space->nested[i] = isl_space_reset_user(space->nested[i]);
     736           0 :                 if (!space->nested[i])
     737           0 :                         return isl_space_free(space);
     738             :         }
     739             : 
     740           0 :         return space;
     741             : }
     742             : 
     743 95347803678 : static __isl_keep isl_id *tuple_id(__isl_keep isl_space *dim,
     744             :         enum isl_dim_type type)
     745             : {
     746 95347803678 :         if (!dim)
     747           0 :                 return NULL;
     748 95347803678 :         if (type == isl_dim_in)
     749 32552049754 :                 return dim->tuple_id[0];
     750 62795753924 :         if (type == isl_dim_out)
     751 30111769536 :                 return dim->tuple_id[1];
     752 32683984388 :         return NULL;
     753             : }
     754             : 
     755 93664691270 : static __isl_keep isl_space *nested(__isl_keep isl_space *dim,
     756             :         enum isl_dim_type type)
     757             : {
     758 93664691270 :         if (!dim)
     759           0 :                 return NULL;
     760 93664691270 :         if (type == isl_dim_in)
     761 30868937346 :                 return dim->nested[0];
     762 62795753924 :         if (type == isl_dim_out)
     763 30111769536 :                 return dim->nested[1];
     764 32683984388 :         return NULL;
     765             : }
     766             : 
     767             : /* Are the two spaces the same, apart from positions and names of parameters?
     768             :  */
     769 16242816667 : isl_bool isl_space_has_equal_tuples(__isl_keep isl_space *space1,
     770             :         __isl_keep isl_space *space2)
     771             : {
     772 16242816667 :         if (!space1 || !space2)
     773           0 :                 return isl_bool_error;
     774 16242816667 :         if (space1 == space2)
     775           0 :                 return isl_bool_true;
     776 31265493225 :         return isl_space_tuple_is_equal(space1, isl_dim_in,
     777 15401260463 :                                         space2, isl_dim_in) &&
     778 15401260463 :                isl_space_tuple_is_equal(space1, isl_dim_out,
     779             :                                         space2, isl_dim_out);
     780             : }
     781             : 
     782             : /* Check if the tuple of type "type1" of "space1" is the same as
     783             :  * the tuple of type "type2" of "space2".
     784             :  *
     785             :  * That is, check if the tuples have the same identifier, the same dimension
     786             :  * and the same internal structure.
     787             :  * The identifiers of the dimensions inside the tuples do not affect the result.
     788             :  *
     789             :  * Note that this function only checks the tuples themselves.
     790             :  * If nested tuples are involved, then we need to be careful not
     791             :  * to have result affected by possibly differing parameters
     792             :  * in those nested tuples.
     793             :  */
     794 47961761607 : isl_bool isl_space_tuple_is_equal(__isl_keep isl_space *space1,
     795             :         enum isl_dim_type type1, __isl_keep isl_space *space2,
     796             :         enum isl_dim_type type2)
     797             : {
     798             :         isl_id *id1, *id2;
     799             :         isl_space *nested1, *nested2;
     800             : 
     801 47961761607 :         if (!space1 || !space2)
     802           0 :                 return isl_bool_error;
     803             : 
     804 47961761607 :         if (space1 == space2 && type1 == type2)
     805     4250640 :                 return isl_bool_true;
     806             : 
     807 47957510967 :         if (n(space1, type1) != n(space2, type2))
     808   378583905 :                 return isl_bool_false;
     809 47578927062 :         id1 = tuple_id(space1, type1);
     810 47578927062 :         id2 = tuple_id(space2, type2);
     811 47578927062 :         if (!id1 ^ !id2)
     812   841556204 :                 return isl_bool_false;
     813 46737370858 :         if (id1 && id1 != id2)
     814           0 :                 return isl_bool_false;
     815 46737370858 :         nested1 = nested(space1, type1);
     816 46737370858 :         nested2 = nested(space2, type2);
     817 46737370858 :         if (!nested1 ^ !nested2)
     818           0 :                 return isl_bool_false;
     819 46737370858 :         if (nested1 && !isl_space_has_equal_tuples(nested1, nested2))
     820           0 :                 return isl_bool_false;
     821 46737370858 :         return isl_bool_true;
     822             : }
     823             : 
     824 17704252030 : static isl_bool match(__isl_keep isl_space *space1, enum isl_dim_type type1,
     825             :         __isl_keep isl_space *space2, enum isl_dim_type type2)
     826             : {
     827             :         int i;
     828             : 
     829 17704252030 :         if (space1 == space2 && type1 == type2)
     830  1391127141 :                 return isl_bool_true;
     831             : 
     832 16313124889 :         if (!isl_space_tuple_is_equal(space1, type1, space2, type2))
     833           0 :                 return isl_bool_false;
     834             : 
     835 16313124889 :         if (!space1->ids && !space2->ids)
     836 16313124889 :                 return isl_bool_true;
     837             : 
     838           0 :         for (i = 0; i < n(space1, type1); ++i) {
     839           0 :                 if (get_id(space1, type1, i) != get_id(space2, type2, i))
     840           0 :                         return isl_bool_false;
     841             :         }
     842           0 :         return isl_bool_true;
     843             : }
     844             : 
     845             : /* Do "space1" and "space2" have the same parameters?
     846             :  */
     847 16408135040 : isl_bool isl_space_has_equal_params(__isl_keep isl_space *space1,
     848             :         __isl_keep isl_space *space2)
     849             : {
     850 16408135040 :         if (!space1 || !space2)
     851           0 :                 return isl_bool_error;
     852             : 
     853 16408135040 :         return match(space1, isl_dim_param, space2, isl_dim_param);
     854             : }
     855             : 
     856             : /* Do "space1" and "space2" have the same identifiers for all
     857             :  * the tuple variables?
     858             :  */
     859   648058495 : isl_bool isl_space_has_equal_ids(__isl_keep isl_space *space1,
     860             :         __isl_keep isl_space *space2)
     861             : {
     862             :         isl_bool equal;
     863             : 
     864   648058495 :         if (!space1 || !space2)
     865           0 :                 return isl_bool_error;
     866             : 
     867   648058495 :         equal = match(space1, isl_dim_in, space2, isl_dim_in);
     868   648058495 :         if (equal < 0 || !equal)
     869           0 :                 return equal;
     870   648058495 :         return match(space1, isl_dim_out, space2, isl_dim_out);
     871             : }
     872             : 
     873           0 : isl_bool isl_space_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
     874             :         __isl_keep isl_space *space2, enum isl_dim_type type2)
     875             : {
     876           0 :         if (!space1 || !space2)
     877           0 :                 return isl_bool_error;
     878             : 
     879           0 :         return match(space1, type1, space2, type2);
     880             : }
     881             : 
     882           0 : static void get_ids(__isl_keep isl_space *dim, enum isl_dim_type type,
     883             :         unsigned first, unsigned n, __isl_keep isl_id **ids)
     884             : {
     885             :         int i;
     886             : 
     887           0 :         for (i = 0; i < n ; ++i)
     888           0 :                 ids[i] = get_id(dim, type, first + i);
     889           0 : }
     890             : 
     891      129106 : static __isl_give isl_space *space_extend(__isl_take isl_space *space,
     892             :                         unsigned nparam, unsigned n_in, unsigned n_out)
     893             : {
     894      129106 :         isl_id **ids = NULL;
     895             : 
     896      129106 :         if (!space)
     897           0 :                 return NULL;
     898      258212 :         if (space->nparam == nparam &&
     899      258212 :             space->n_in == n_in && space->n_out == n_out)
     900           0 :                 return space;
     901             : 
     902      129106 :         isl_assert(space->ctx, space->nparam <= nparam, goto error);
     903      129106 :         isl_assert(space->ctx, space->n_in <= n_in, goto error);
     904      129106 :         isl_assert(space->ctx, space->n_out <= n_out, goto error);
     905             : 
     906      129106 :         space = isl_space_cow(space);
     907      129106 :         if (!space)
     908           0 :                 goto error;
     909             : 
     910      129106 :         if (space->ids) {
     911             :                 unsigned n;
     912           0 :                 n = nparam + n_in + n_out;
     913           0 :                 if (n < nparam || n < n_in || n < n_out)
     914           0 :                         isl_die(isl_space_get_ctx(space), isl_error_invalid,
     915             :                                 "overflow in total number of dimensions",
     916             :                                 goto error);
     917           0 :                 ids = isl_calloc_array(space->ctx, isl_id *, n);
     918           0 :                 if (!ids)
     919           0 :                         goto error;
     920           0 :                 get_ids(space, isl_dim_param, 0, space->nparam, ids);
     921           0 :                 get_ids(space, isl_dim_in, 0, space->n_in, ids + nparam);
     922           0 :                 get_ids(space, isl_dim_out, 0, space->n_out,
     923           0 :                         ids + nparam + n_in);
     924           0 :                 free(space->ids);
     925           0 :                 space->ids = ids;
     926           0 :                 space->n_id = nparam + n_in + n_out;
     927             :         }
     928      129106 :         space->nparam = nparam;
     929      129106 :         space->n_in = n_in;
     930      129106 :         space->n_out = n_out;
     931             : 
     932      129106 :         return space;
     933             : error:
     934           0 :         free(ids);
     935           0 :         isl_space_free(space);
     936           0 :         return NULL;
     937             : }
     938             : 
     939           0 : __isl_give isl_space *isl_space_extend(__isl_take isl_space *space,
     940             :         unsigned nparam, unsigned n_in, unsigned n_out)
     941             : {
     942           0 :         return space_extend(space, nparam, n_in, n_out);
     943             : }
     944             : 
     945      129106 : __isl_give isl_space *isl_space_add_dims(__isl_take isl_space *space,
     946             :         enum isl_dim_type type, unsigned n)
     947             : {
     948      129106 :         space = isl_space_reset(space, type);
     949      129106 :         if (!space)
     950           0 :                 return NULL;
     951      129106 :         switch (type) {
     952             :         case isl_dim_param:
     953           0 :                 space = space_extend(space,
     954           0 :                                 space->nparam + n, space->n_in, space->n_out);
     955           0 :                 if (space && space->nested[0] &&
     956           0 :                     !(space->nested[0] = isl_space_add_dims(space->nested[0],
     957             :                                                     isl_dim_param, n)))
     958           0 :                         goto error;
     959           0 :                 if (space && space->nested[1] &&
     960           0 :                     !(space->nested[1] = isl_space_add_dims(space->nested[1],
     961             :                                                     isl_dim_param, n)))
     962           0 :                         goto error;
     963           0 :                 return space;
     964             :         case isl_dim_in:
     965           0 :                 return space_extend(space,
     966           0 :                                 space->nparam, space->n_in + n, space->n_out);
     967             :         case isl_dim_out:
     968      129106 :                 return space_extend(space,
     969      129106 :                                 space->nparam, space->n_in, space->n_out + n);
     970             :         default:
     971           0 :                 isl_die(space->ctx, isl_error_invalid,
     972             :                         "cannot add dimensions of specified type", goto error);
     973             :         }
     974             : error:
     975           0 :         isl_space_free(space);
     976           0 :         return NULL;
     977             : }
     978             : 
     979             : /* Add a parameter with identifier "id" to "space", provided
     980             :  * it does not already appear in "space".
     981             :  */
     982           0 : __isl_give isl_space *isl_space_add_param_id(__isl_take isl_space *space,
     983             :         __isl_take isl_id *id)
     984             : {
     985             :         int pos;
     986             : 
     987           0 :         if (!space || !id)
     988             :                 goto error;
     989             : 
     990           0 :         if (isl_space_find_dim_by_id(space, isl_dim_param, id) >= 0) {
     991           0 :                 isl_id_free(id);
     992           0 :                 return space;
     993             :         }
     994             : 
     995           0 :         pos = isl_space_dim(space, isl_dim_param);
     996           0 :         space = isl_space_add_dims(space, isl_dim_param, 1);
     997           0 :         space = isl_space_set_dim_id(space, isl_dim_param, pos, id);
     998             : 
     999           0 :         return space;
    1000             : error:
    1001           0 :         isl_space_free(space);
    1002           0 :         isl_id_free(id);
    1003           0 :         return NULL;
    1004             : }
    1005             : 
    1006    17167917 : static int valid_dim_type(enum isl_dim_type type)
    1007             : {
    1008    17167917 :         switch (type) {
    1009             :         case isl_dim_param:
    1010             :         case isl_dim_in:
    1011             :         case isl_dim_out:
    1012    17167917 :                 return 1;
    1013             :         default:
    1014           0 :                 return 0;
    1015             :         }
    1016             : }
    1017             : 
    1018             : /* Insert "n" dimensions of type "type" at position "pos".
    1019             :  * If we are inserting parameters, then they are also inserted in
    1020             :  * any nested spaces.
    1021             :  */
    1022           0 : __isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *space,
    1023             :         enum isl_dim_type type, unsigned pos, unsigned n)
    1024             : {
    1025             :         isl_ctx *ctx;
    1026           0 :         isl_id **ids = NULL;
    1027             :         unsigned total;
    1028             : 
    1029           0 :         if (!space)
    1030           0 :                 return NULL;
    1031           0 :         if (n == 0)
    1032           0 :                 return isl_space_reset(space, type);
    1033             : 
    1034           0 :         ctx = isl_space_get_ctx(space);
    1035           0 :         if (!valid_dim_type(type))
    1036           0 :                 isl_die(ctx, isl_error_invalid,
    1037             :                         "cannot insert dimensions of specified type",
    1038             :                         goto error);
    1039             : 
    1040           0 :         total = isl_space_dim(space, isl_dim_all);
    1041           0 :         if (total + n < total)
    1042           0 :                 isl_die(ctx, isl_error_invalid,
    1043             :                         "overflow in total number of dimensions",
    1044             :                         return isl_space_free(space));
    1045           0 :         isl_assert(ctx, pos <= isl_space_dim(space, type), goto error);
    1046             : 
    1047           0 :         space = isl_space_cow(space);
    1048           0 :         if (!space)
    1049           0 :                 return NULL;
    1050             : 
    1051           0 :         if (space->ids) {
    1052           0 :                 enum isl_dim_type t, o = isl_dim_param;
    1053             :                 int off;
    1054             :                 int s[3];
    1055           0 :                 ids = isl_calloc_array(ctx, isl_id *,
    1056             :                              space->nparam + space->n_in + space->n_out + n);
    1057           0 :                 if (!ids)
    1058           0 :                         goto error;
    1059           0 :                 off = 0;
    1060           0 :                 s[isl_dim_param - o] = space->nparam;
    1061           0 :                 s[isl_dim_in - o] = space->n_in;
    1062           0 :                 s[isl_dim_out - o] = space->n_out;
    1063           0 :                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
    1064           0 :                         if (t != type) {
    1065           0 :                                 get_ids(space, t, 0, s[t - o], ids + off);
    1066           0 :                                 off += s[t - o];
    1067             :                         } else {
    1068           0 :                                 get_ids(space, t, 0, pos, ids + off);
    1069           0 :                                 off += pos + n;
    1070           0 :                                 get_ids(space, t, pos, s[t - o] - pos,
    1071           0 :                                         ids + off);
    1072           0 :                                 off += s[t - o] - pos;
    1073             :                         }
    1074             :                 }
    1075           0 :                 free(space->ids);
    1076           0 :                 space->ids = ids;
    1077           0 :                 space->n_id = space->nparam + space->n_in + space->n_out + n;
    1078             :         }
    1079           0 :         switch (type) {
    1080           0 :         case isl_dim_param:     space->nparam += n; break;
    1081           0 :         case isl_dim_in:        space->n_in += n; break;
    1082           0 :         case isl_dim_out:       space->n_out += n; break;
    1083             :         default:                ;
    1084             :         }
    1085           0 :         space = isl_space_reset(space, type);
    1086             : 
    1087           0 :         if (type == isl_dim_param) {
    1088           0 :                 if (space && space->nested[0] &&
    1089           0 :                     !(space->nested[0] = isl_space_insert_dims(space->nested[0],
    1090             :                                                     isl_dim_param, pos, n)))
    1091           0 :                         goto error;
    1092           0 :                 if (space && space->nested[1] &&
    1093           0 :                     !(space->nested[1] = isl_space_insert_dims(space->nested[1],
    1094             :                                                     isl_dim_param, pos, n)))
    1095           0 :                         goto error;
    1096             :         }
    1097             : 
    1098           0 :         return space;
    1099             : error:
    1100           0 :         isl_space_free(space);
    1101           0 :         return NULL;
    1102             : }
    1103             : 
    1104           0 : __isl_give isl_space *isl_space_move_dims(__isl_take isl_space *space,
    1105             :         enum isl_dim_type dst_type, unsigned dst_pos,
    1106             :         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
    1107             : {
    1108             :         int i;
    1109             : 
    1110           0 :         space = isl_space_reset(space, src_type);
    1111           0 :         space = isl_space_reset(space, dst_type);
    1112           0 :         if (!space)
    1113           0 :                 return NULL;
    1114           0 :         if (n == 0)
    1115           0 :                 return space;
    1116             : 
    1117           0 :         isl_assert(space->ctx, src_pos + n <= isl_space_dim(space, src_type),
    1118             :                 goto error);
    1119             : 
    1120           0 :         if (dst_type == src_type && dst_pos == src_pos)
    1121           0 :                 return space;
    1122             : 
    1123           0 :         isl_assert(space->ctx, dst_type != src_type, goto error);
    1124             : 
    1125           0 :         space = isl_space_cow(space);
    1126           0 :         if (!space)
    1127           0 :                 return NULL;
    1128             : 
    1129           0 :         if (space->ids) {
    1130             :                 isl_id **ids;
    1131           0 :                 enum isl_dim_type t, o = isl_dim_param;
    1132             :                 int off;
    1133             :                 int s[3];
    1134           0 :                 ids = isl_calloc_array(space->ctx, isl_id *,
    1135             :                                  space->nparam + space->n_in + space->n_out);
    1136           0 :                 if (!ids)
    1137           0 :                         goto error;
    1138           0 :                 off = 0;
    1139           0 :                 s[isl_dim_param - o] = space->nparam;
    1140           0 :                 s[isl_dim_in - o] = space->n_in;
    1141           0 :                 s[isl_dim_out - o] = space->n_out;
    1142           0 :                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
    1143           0 :                         if (t == dst_type) {
    1144           0 :                                 get_ids(space, t, 0, dst_pos, ids + off);
    1145           0 :                                 off += dst_pos;
    1146           0 :                                 get_ids(space, src_type, src_pos, n, ids + off);
    1147           0 :                                 off += n;
    1148           0 :                                 get_ids(space, t, dst_pos, s[t - o] - dst_pos,
    1149           0 :                                                 ids + off);
    1150           0 :                                 off += s[t - o] - dst_pos;
    1151           0 :                         } else if (t == src_type) {
    1152           0 :                                 get_ids(space, t, 0, src_pos, ids + off);
    1153           0 :                                 off += src_pos;
    1154           0 :                                 get_ids(space, t, src_pos + n,
    1155           0 :                                             s[t - o] - src_pos - n, ids + off);
    1156           0 :                                 off += s[t - o] - src_pos - n;
    1157             :                         } else {
    1158           0 :                                 get_ids(space, t, 0, s[t - o], ids + off);
    1159           0 :                                 off += s[t - o];
    1160             :                         }
    1161             :                 }
    1162           0 :                 free(space->ids);
    1163           0 :                 space->ids = ids;
    1164           0 :                 space->n_id = space->nparam + space->n_in + space->n_out;
    1165             :         }
    1166             : 
    1167           0 :         switch (dst_type) {
    1168           0 :         case isl_dim_param:     space->nparam += n; break;
    1169           0 :         case isl_dim_in:        space->n_in += n; break;
    1170           0 :         case isl_dim_out:       space->n_out += n; break;
    1171             :         default:                ;
    1172             :         }
    1173             : 
    1174           0 :         switch (src_type) {
    1175           0 :         case isl_dim_param:     space->nparam -= n; break;
    1176           0 :         case isl_dim_in:        space->n_in -= n; break;
    1177           0 :         case isl_dim_out:       space->n_out -= n; break;
    1178             :         default:                ;
    1179             :         }
    1180             : 
    1181           0 :         if (dst_type != isl_dim_param && src_type != isl_dim_param)
    1182           0 :                 return space;
    1183             : 
    1184           0 :         for (i = 0; i < 2; ++i) {
    1185           0 :                 if (!space->nested[i])
    1186           0 :                         continue;
    1187           0 :                 space->nested[i] = isl_space_replace_params(space->nested[i],
    1188             :                                                              space);
    1189           0 :                 if (!space->nested[i])
    1190           0 :                         goto error;
    1191             :         }
    1192             : 
    1193           0 :         return space;
    1194             : error:
    1195           0 :         isl_space_free(space);
    1196           0 :         return NULL;
    1197             : }
    1198             : 
    1199             : /* Check that "space1" and "space2" have the same parameters,
    1200             :  * reporting an error if they do not.
    1201             :  */
    1202           0 : isl_stat isl_space_check_equal_params(__isl_keep isl_space *space1,
    1203             :         __isl_keep isl_space *space2)
    1204             : {
    1205             :         isl_bool equal;
    1206             : 
    1207           0 :         equal = isl_space_has_equal_params(space1, space2);
    1208           0 :         if (equal < 0)
    1209           0 :                 return isl_stat_error;
    1210           0 :         if (!equal)
    1211           0 :                 isl_die(isl_space_get_ctx(space1), isl_error_invalid,
    1212             :                         "parameters need to match", return isl_stat_error);
    1213           0 :         return isl_stat_ok;
    1214             : }
    1215             : 
    1216           0 : __isl_give isl_space *isl_space_join(__isl_take isl_space *left,
    1217             :         __isl_take isl_space *right)
    1218             : {
    1219             :         isl_space *dim;
    1220             : 
    1221           0 :         if (isl_space_check_equal_params(left, right) < 0)
    1222           0 :                 goto error;
    1223             : 
    1224           0 :         isl_assert(left->ctx,
    1225             :                 isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_in),
    1226             :                 goto error);
    1227             : 
    1228           0 :         dim = isl_space_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
    1229           0 :         if (!dim)
    1230           0 :                 goto error;
    1231             : 
    1232           0 :         dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param);
    1233           0 :         dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in);
    1234           0 :         dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out);
    1235             : 
    1236           0 :         if (dim && left->tuple_id[0] &&
    1237           0 :             !(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
    1238           0 :                 goto error;
    1239           0 :         if (dim && right->tuple_id[1] &&
    1240           0 :             !(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
    1241           0 :                 goto error;
    1242           0 :         if (dim && left->nested[0] &&
    1243           0 :             !(dim->nested[0] = isl_space_copy(left->nested[0])))
    1244           0 :                 goto error;
    1245           0 :         if (dim && right->nested[1] &&
    1246           0 :             !(dim->nested[1] = isl_space_copy(right->nested[1])))
    1247           0 :                 goto error;
    1248             : 
    1249           0 :         isl_space_free(left);
    1250           0 :         isl_space_free(right);
    1251             : 
    1252           0 :         return dim;
    1253             : error:
    1254           0 :         isl_space_free(left);
    1255           0 :         isl_space_free(right);
    1256           0 :         return NULL;
    1257             : }
    1258             : 
    1259             : /* Given two map spaces { A -> C } and { B -> D }, construct the space
    1260             :  * { [A -> B] -> [C -> D] }.
    1261             :  * Given two set spaces { A } and { B }, construct the space { [A -> B] }.
    1262             :  */
    1263           0 : __isl_give isl_space *isl_space_product(__isl_take isl_space *left,
    1264             :         __isl_take isl_space *right)
    1265             : {
    1266             :         isl_space *dom1, *dom2, *nest1, *nest2;
    1267             :         int is_set;
    1268             : 
    1269           0 :         if (!left || !right)
    1270             :                 goto error;
    1271             : 
    1272           0 :         is_set = isl_space_is_set(left);
    1273           0 :         if (is_set != isl_space_is_set(right))
    1274           0 :                 isl_die(isl_space_get_ctx(left), isl_error_invalid,
    1275             :                         "expecting either two set spaces or two map spaces",
    1276             :                         goto error);
    1277           0 :         if (is_set)
    1278           0 :                 return isl_space_range_product(left, right);
    1279             : 
    1280           0 :         if (isl_space_check_equal_params(left, right) < 0)
    1281           0 :                 goto error;
    1282             : 
    1283           0 :         dom1 = isl_space_domain(isl_space_copy(left));
    1284           0 :         dom2 = isl_space_domain(isl_space_copy(right));
    1285           0 :         nest1 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
    1286             : 
    1287           0 :         dom1 = isl_space_range(left);
    1288           0 :         dom2 = isl_space_range(right);
    1289           0 :         nest2 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
    1290             : 
    1291           0 :         return isl_space_join(isl_space_reverse(nest1), nest2);
    1292             : error:
    1293           0 :         isl_space_free(left);
    1294           0 :         isl_space_free(right);
    1295           0 :         return NULL;
    1296             : }
    1297             : 
    1298             : /* Given two spaces { A -> C } and { B -> C }, construct the space
    1299             :  * { [A -> B] -> C }
    1300             :  */
    1301           0 : __isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left,
    1302             :         __isl_take isl_space *right)
    1303             : {
    1304             :         isl_space *ran, *dom1, *dom2, *nest;
    1305             : 
    1306           0 :         if (isl_space_check_equal_params(left, right) < 0)
    1307           0 :                 goto error;
    1308             : 
    1309           0 :         if (!isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_out))
    1310           0 :                 isl_die(left->ctx, isl_error_invalid,
    1311             :                         "ranges need to match", goto error);
    1312             : 
    1313           0 :         ran = isl_space_range(isl_space_copy(left));
    1314             : 
    1315           0 :         dom1 = isl_space_domain(left);
    1316           0 :         dom2 = isl_space_domain(right);
    1317           0 :         nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
    1318             : 
    1319           0 :         return isl_space_join(isl_space_reverse(nest), ran);
    1320             : error:
    1321           0 :         isl_space_free(left);
    1322           0 :         isl_space_free(right);
    1323           0 :         return NULL;
    1324             : }
    1325             : 
    1326           0 : __isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
    1327             :         __isl_take isl_space *right)
    1328             : {
    1329             :         isl_space *dom, *ran1, *ran2, *nest;
    1330             : 
    1331           0 :         if (isl_space_check_equal_params(left, right) < 0)
    1332           0 :                 goto error;
    1333             : 
    1334           0 :         if (!isl_space_tuple_is_equal(left, isl_dim_in, right, isl_dim_in))
    1335           0 :                 isl_die(left->ctx, isl_error_invalid,
    1336             :                         "domains need to match", goto error);
    1337             : 
    1338           0 :         dom = isl_space_domain(isl_space_copy(left));
    1339             : 
    1340           0 :         ran1 = isl_space_range(left);
    1341           0 :         ran2 = isl_space_range(right);
    1342           0 :         nest = isl_space_wrap(isl_space_join(isl_space_reverse(ran1), ran2));
    1343             : 
    1344           0 :         return isl_space_join(isl_space_reverse(dom), nest);
    1345             : error:
    1346           0 :         isl_space_free(left);
    1347           0 :         isl_space_free(right);
    1348           0 :         return NULL;
    1349             : }
    1350             : 
    1351             : /* Given a space of the form [A -> B] -> C, return the space A -> C.
    1352             :  */
    1353           0 : __isl_give isl_space *isl_space_domain_factor_domain(
    1354             :         __isl_take isl_space *space)
    1355             : {
    1356             :         isl_space *nested;
    1357             :         isl_space *domain;
    1358             : 
    1359           0 :         if (!space)
    1360           0 :                 return NULL;
    1361           0 :         if (!isl_space_domain_is_wrapping(space))
    1362           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    1363             :                         "domain not a product", return isl_space_free(space));
    1364             : 
    1365           0 :         nested = space->nested[0];
    1366           0 :         domain = isl_space_copy(space);
    1367           0 :         domain = isl_space_drop_dims(domain, isl_dim_in,
    1368             :                                         nested->n_in, nested->n_out);
    1369           0 :         if (!domain)
    1370           0 :                 return isl_space_free(space);
    1371           0 :         if (nested->tuple_id[0]) {
    1372           0 :                 domain->tuple_id[0] = isl_id_copy(nested->tuple_id[0]);
    1373           0 :                 if (!domain->tuple_id[0])
    1374           0 :                         goto error;
    1375             :         }
    1376           0 :         if (nested->nested[0]) {
    1377           0 :                 domain->nested[0] = isl_space_copy(nested->nested[0]);
    1378           0 :                 if (!domain->nested[0])
    1379           0 :                         goto error;
    1380             :         }
    1381             : 
    1382           0 :         isl_space_free(space);
    1383           0 :         return domain;
    1384             : error:
    1385           0 :         isl_space_free(space);
    1386           0 :         isl_space_free(domain);
    1387           0 :         return NULL;
    1388             : }
    1389             : 
    1390             : /* Given a space of the form [A -> B] -> C, return the space B -> C.
    1391             :  */
    1392           0 : __isl_give isl_space *isl_space_domain_factor_range(
    1393             :         __isl_take isl_space *space)
    1394             : {
    1395             :         isl_space *nested;
    1396             :         isl_space *range;
    1397             : 
    1398           0 :         if (!space)
    1399           0 :                 return NULL;
    1400           0 :         if (!isl_space_domain_is_wrapping(space))
    1401           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    1402             :                         "domain not a product", return isl_space_free(space));
    1403             : 
    1404           0 :         nested = space->nested[0];
    1405           0 :         range = isl_space_copy(space);
    1406           0 :         range = isl_space_drop_dims(range, isl_dim_in, 0, nested->n_in);
    1407           0 :         if (!range)
    1408           0 :                 return isl_space_free(space);
    1409           0 :         if (nested->tuple_id[1]) {
    1410           0 :                 range->tuple_id[0] = isl_id_copy(nested->tuple_id[1]);
    1411           0 :                 if (!range->tuple_id[0])
    1412           0 :                         goto error;
    1413             :         }
    1414           0 :         if (nested->nested[1]) {
    1415           0 :                 range->nested[0] = isl_space_copy(nested->nested[1]);
    1416           0 :                 if (!range->nested[0])
    1417           0 :                         goto error;
    1418             :         }
    1419             : 
    1420           0 :         isl_space_free(space);
    1421           0 :         return range;
    1422             : error:
    1423           0 :         isl_space_free(space);
    1424           0 :         isl_space_free(range);
    1425           0 :         return NULL;
    1426             : }
    1427             : 
    1428             : /* Internal function that selects the domain of the map that is
    1429             :  * embedded in either a set space or the range of a map space.
    1430             :  * In particular, given a space of the form [A -> B], return the space A.
    1431             :  * Given a space of the form A -> [B -> C], return the space A -> B.
    1432             :  */
    1433           0 : static __isl_give isl_space *range_factor_domain(__isl_take isl_space *space)
    1434             : {
    1435             :         isl_space *nested;
    1436             :         isl_space *domain;
    1437             : 
    1438           0 :         if (!space)
    1439           0 :                 return NULL;
    1440             : 
    1441           0 :         nested = space->nested[1];
    1442           0 :         domain = isl_space_copy(space);
    1443           0 :         domain = isl_space_drop_dims(domain, isl_dim_out,
    1444             :                                         nested->n_in, nested->n_out);
    1445           0 :         if (!domain)
    1446           0 :                 return isl_space_free(space);
    1447           0 :         if (nested->tuple_id[0]) {
    1448           0 :                 domain->tuple_id[1] = isl_id_copy(nested->tuple_id[0]);
    1449           0 :                 if (!domain->tuple_id[1])
    1450           0 :                         goto error;
    1451             :         }
    1452           0 :         if (nested->nested[0]) {
    1453           0 :                 domain->nested[1] = isl_space_copy(nested->nested[0]);
    1454           0 :                 if (!domain->nested[1])
    1455           0 :                         goto error;
    1456             :         }
    1457             : 
    1458           0 :         isl_space_free(space);
    1459           0 :         return domain;
    1460             : error:
    1461           0 :         isl_space_free(space);
    1462           0 :         isl_space_free(domain);
    1463           0 :         return NULL;
    1464             : }
    1465             : 
    1466             : /* Given a space of the form A -> [B -> C], return the space A -> B.
    1467             :  */
    1468           0 : __isl_give isl_space *isl_space_range_factor_domain(
    1469             :         __isl_take isl_space *space)
    1470             : {
    1471           0 :         if (!space)
    1472           0 :                 return NULL;
    1473           0 :         if (!isl_space_range_is_wrapping(space))
    1474           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    1475             :                         "range not a product", return isl_space_free(space));
    1476             : 
    1477           0 :         return range_factor_domain(space);
    1478             : }
    1479             : 
    1480             : /* Given a space of the form [A -> B], return the space A.
    1481             :  */
    1482           0 : static __isl_give isl_space *set_factor_domain(__isl_take isl_space *space)
    1483             : {
    1484           0 :         if (!space)
    1485           0 :                 return NULL;
    1486           0 :         if (!isl_space_is_wrapping(space))
    1487           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    1488             :                         "not a product", return isl_space_free(space));
    1489             : 
    1490           0 :         return range_factor_domain(space);
    1491             : }
    1492             : 
    1493             : /* Given a space of the form [A -> B] -> [C -> D], return the space A -> C.
    1494             :  * Given a space of the form [A -> B], return the space A.
    1495             :  */
    1496           0 : __isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space)
    1497             : {
    1498           0 :         if (!space)
    1499           0 :                 return NULL;
    1500           0 :         if (isl_space_is_set(space))
    1501           0 :                 return set_factor_domain(space);
    1502           0 :         space = isl_space_domain_factor_domain(space);
    1503           0 :         space = isl_space_range_factor_domain(space);
    1504           0 :         return space;
    1505             : }
    1506             : 
    1507             : /* Internal function that selects the range of the map that is
    1508             :  * embedded in either a set space or the range of a map space.
    1509             :  * In particular, given a space of the form [A -> B], return the space B.
    1510             :  * Given a space of the form A -> [B -> C], return the space A -> C.
    1511             :  */
    1512           0 : static __isl_give isl_space *range_factor_range(__isl_take isl_space *space)
    1513             : {
    1514             :         isl_space *nested;
    1515             :         isl_space *range;
    1516             : 
    1517           0 :         if (!space)
    1518           0 :                 return NULL;
    1519             : 
    1520           0 :         nested = space->nested[1];
    1521           0 :         range = isl_space_copy(space);
    1522           0 :         range = isl_space_drop_dims(range, isl_dim_out, 0, nested->n_in);
    1523           0 :         if (!range)
    1524           0 :                 return isl_space_free(space);
    1525           0 :         if (nested->tuple_id[1]) {
    1526           0 :                 range->tuple_id[1] = isl_id_copy(nested->tuple_id[1]);
    1527           0 :                 if (!range->tuple_id[1])
    1528           0 :                         goto error;
    1529             :         }
    1530           0 :         if (nested->nested[1]) {
    1531           0 :                 range->nested[1] = isl_space_copy(nested->nested[1]);
    1532           0 :                 if (!range->nested[1])
    1533           0 :                         goto error;
    1534             :         }
    1535             : 
    1536           0 :         isl_space_free(space);
    1537           0 :         return range;
    1538             : error:
    1539           0 :         isl_space_free(space);
    1540           0 :         isl_space_free(range);
    1541           0 :         return NULL;
    1542             : }
    1543             : 
    1544             : /* Given a space of the form A -> [B -> C], return the space A -> C.
    1545             :  */
    1546           0 : __isl_give isl_space *isl_space_range_factor_range(
    1547             :         __isl_take isl_space *space)
    1548             : {
    1549           0 :         if (!space)
    1550           0 :                 return NULL;
    1551           0 :         if (!isl_space_range_is_wrapping(space))
    1552           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    1553             :                         "range not a product", return isl_space_free(space));
    1554             : 
    1555           0 :         return range_factor_range(space);
    1556             : }
    1557             : 
    1558             : /* Given a space of the form [A -> B], return the space B.
    1559             :  */
    1560           0 : static __isl_give isl_space *set_factor_range(__isl_take isl_space *space)
    1561             : {
    1562           0 :         if (!space)
    1563           0 :                 return NULL;
    1564           0 :         if (!isl_space_is_wrapping(space))
    1565           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    1566             :                         "not a product", return isl_space_free(space));
    1567             : 
    1568           0 :         return range_factor_range(space);
    1569             : }
    1570             : 
    1571             : /* Given a space of the form [A -> B] -> [C -> D], return the space B -> D.
    1572             :  * Given a space of the form [A -> B], return the space B.
    1573             :  */
    1574           0 : __isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space)
    1575             : {
    1576           0 :         if (!space)
    1577           0 :                 return NULL;
    1578           0 :         if (isl_space_is_set(space))
    1579           0 :                 return set_factor_range(space);
    1580           0 :         space = isl_space_domain_factor_range(space);
    1581           0 :         space = isl_space_range_factor_range(space);
    1582           0 :         return space;
    1583             : }
    1584             : 
    1585           0 : __isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *space)
    1586             : {
    1587             :         isl_ctx *ctx;
    1588           0 :         isl_id **ids = NULL;
    1589             :         int n_id;
    1590             : 
    1591           0 :         if (!space)
    1592           0 :                 return NULL;
    1593           0 :         ctx = isl_space_get_ctx(space);
    1594           0 :         if (!isl_space_is_set(space))
    1595           0 :                 isl_die(ctx, isl_error_invalid, "not a set space", goto error);
    1596           0 :         space = isl_space_cow(space);
    1597           0 :         if (!space)
    1598           0 :                 return NULL;
    1599           0 :         n_id = space->nparam + space->n_out + space->n_out;
    1600           0 :         if (n_id > 0 && space->ids) {
    1601           0 :                 ids = isl_calloc_array(space->ctx, isl_id *, n_id);
    1602           0 :                 if (!ids)
    1603           0 :                         goto error;
    1604           0 :                 get_ids(space, isl_dim_param, 0, space->nparam, ids);
    1605           0 :                 get_ids(space, isl_dim_out, 0, space->n_out,
    1606           0 :                         ids + space->nparam);
    1607             :         }
    1608           0 :         space->n_in = space->n_out;
    1609           0 :         if (ids) {
    1610           0 :                 free(space->ids);
    1611           0 :                 space->ids = ids;
    1612           0 :                 space->n_id = n_id;
    1613           0 :                 space = copy_ids(space, isl_dim_out, 0, space, isl_dim_in);
    1614             :         }
    1615           0 :         isl_id_free(space->tuple_id[0]);
    1616           0 :         space->tuple_id[0] = isl_id_copy(space->tuple_id[1]);
    1617           0 :         isl_space_free(space->nested[0]);
    1618           0 :         space->nested[0] = isl_space_copy(space->nested[1]);
    1619           0 :         return space;
    1620             : error:
    1621           0 :         isl_space_free(space);
    1622           0 :         return NULL;
    1623             : }
    1624             : 
    1625           0 : __isl_give isl_space *isl_space_map_from_domain_and_range(
    1626             :         __isl_take isl_space *domain, __isl_take isl_space *range)
    1627             : {
    1628           0 :         if (!domain || !range)
    1629             :                 goto error;
    1630           0 :         if (!isl_space_is_set(domain))
    1631           0 :                 isl_die(isl_space_get_ctx(domain), isl_error_invalid,
    1632             :                         "domain is not a set space", goto error);
    1633           0 :         if (!isl_space_is_set(range))
    1634           0 :                 isl_die(isl_space_get_ctx(range), isl_error_invalid,
    1635             :                         "range is not a set space", goto error);
    1636           0 :         return isl_space_join(isl_space_reverse(domain), range);
    1637             : error:
    1638           0 :         isl_space_free(domain);
    1639           0 :         isl_space_free(range);
    1640           0 :         return NULL;
    1641             : }
    1642             : 
    1643           0 : static __isl_give isl_space *set_ids(__isl_take isl_space *dim,
    1644             :         enum isl_dim_type type,
    1645             :         unsigned first, unsigned n, __isl_take isl_id **ids)
    1646             : {
    1647             :         int i;
    1648             : 
    1649           0 :         for (i = 0; i < n ; ++i)
    1650           0 :                 dim = set_id(dim, type, first + i, ids[i]);
    1651             : 
    1652           0 :         return dim;
    1653             : }
    1654             : 
    1655           0 : __isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim)
    1656             : {
    1657             :         unsigned t;
    1658             :         isl_space *nested;
    1659           0 :         isl_id **ids = NULL;
    1660             :         isl_id *id;
    1661             : 
    1662           0 :         if (!dim)
    1663           0 :                 return NULL;
    1664           0 :         if (match(dim, isl_dim_in, dim, isl_dim_out))
    1665           0 :                 return dim;
    1666             : 
    1667           0 :         dim = isl_space_cow(dim);
    1668           0 :         if (!dim)
    1669           0 :                 return NULL;
    1670             : 
    1671           0 :         id = dim->tuple_id[0];
    1672           0 :         dim->tuple_id[0] = dim->tuple_id[1];
    1673           0 :         dim->tuple_id[1] = id;
    1674             : 
    1675           0 :         nested = dim->nested[0];
    1676           0 :         dim->nested[0] = dim->nested[1];
    1677           0 :         dim->nested[1] = nested;
    1678             : 
    1679           0 :         if (dim->ids) {
    1680           0 :                 int n_id = dim->n_in + dim->n_out;
    1681           0 :                 ids = isl_alloc_array(dim->ctx, isl_id *, n_id);
    1682           0 :                 if (n_id && !ids)
    1683           0 :                         goto error;
    1684           0 :                 get_ids(dim, isl_dim_in, 0, dim->n_in, ids);
    1685           0 :                 get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in);
    1686             :         }
    1687             : 
    1688           0 :         t = dim->n_in;
    1689           0 :         dim->n_in = dim->n_out;
    1690           0 :         dim->n_out = t;
    1691             : 
    1692           0 :         if (dim->ids) {
    1693           0 :                 dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids);
    1694           0 :                 dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out);
    1695           0 :                 free(ids);
    1696             :         }
    1697             : 
    1698           0 :         return dim;
    1699             : error:
    1700           0 :         free(ids);
    1701           0 :         isl_space_free(dim);
    1702           0 :         return NULL;
    1703             : }
    1704             : 
    1705    17167917 : __isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
    1706             :         enum isl_dim_type type, unsigned first, unsigned num)
    1707             : {
    1708             :         int i;
    1709             : 
    1710    17167917 :         if (!dim)
    1711           0 :                 return NULL;
    1712             : 
    1713    17167917 :         if (num == 0)
    1714           0 :                 return isl_space_reset(dim, type);
    1715             : 
    1716    17167917 :         if (!valid_dim_type(type))
    1717           0 :                 isl_die(dim->ctx, isl_error_invalid,
    1718             :                         "cannot drop dimensions of specified type", goto error);
    1719             : 
    1720    17167917 :         if (first + num > n(dim, type) || first + num < first)
    1721           0 :                 isl_die(isl_space_get_ctx(dim), isl_error_invalid,
    1722             :                         "index out of bounds", return isl_space_free(dim));
    1723    17167917 :         dim = isl_space_cow(dim);
    1724    17167917 :         if (!dim)
    1725           0 :                 goto error;
    1726    17167917 :         if (dim->ids) {
    1727           0 :                 dim = extend_ids(dim);
    1728           0 :                 if (!dim)
    1729           0 :                         goto error;
    1730           0 :                 for (i = 0; i < num; ++i)
    1731           0 :                         isl_id_free(get_id(dim, type, first + i));
    1732           0 :                 for (i = first+num; i < n(dim, type); ++i)
    1733           0 :                         set_id(dim, type, i - num, get_id(dim, type, i));
    1734           0 :                 switch (type) {
    1735             :                 case isl_dim_param:
    1736           0 :                         get_ids(dim, isl_dim_in, 0, dim->n_in,
    1737           0 :                                 dim->ids + offset(dim, isl_dim_in) - num);
    1738             :                 case isl_dim_in:
    1739           0 :                         get_ids(dim, isl_dim_out, 0, dim->n_out,
    1740           0 :                                 dim->ids + offset(dim, isl_dim_out) - num);
    1741             :                 default:
    1742             :                         ;
    1743             :                 }
    1744           0 :                 dim->n_id -= num;
    1745             :         }
    1746    17167917 :         switch (type) {
    1747           0 :         case isl_dim_param:     dim->nparam -= num; break;
    1748           0 :         case isl_dim_in:        dim->n_in -= num; break;
    1749    17167917 :         case isl_dim_out:       dim->n_out -= num; break;
    1750             :         default:                ;
    1751             :         }
    1752    17167917 :         dim = isl_space_reset(dim, type);
    1753    17167917 :         if (type == isl_dim_param) {
    1754           0 :                 if (dim && dim->nested[0] &&
    1755           0 :                     !(dim->nested[0] = isl_space_drop_dims(dim->nested[0],
    1756             :                                                     isl_dim_param, first, num)))
    1757           0 :                         goto error;
    1758           0 :                 if (dim && dim->nested[1] &&
    1759           0 :                     !(dim->nested[1] = isl_space_drop_dims(dim->nested[1],
    1760             :                                                     isl_dim_param, first, num)))
    1761           0 :                         goto error;
    1762             :         }
    1763    17167917 :         return dim;
    1764             : error:
    1765           0 :         isl_space_free(dim);
    1766           0 :         return NULL;
    1767             : }
    1768             : 
    1769           0 : __isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
    1770             :                 unsigned first, unsigned n)
    1771             : {
    1772           0 :         if (!dim)
    1773           0 :                 return NULL;
    1774           0 :         return isl_space_drop_dims(dim, isl_dim_in, first, n);
    1775             : }
    1776             : 
    1777           0 : __isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
    1778             :                 unsigned first, unsigned n)
    1779             : {
    1780           0 :         if (!dim)
    1781           0 :                 return NULL;
    1782           0 :         return isl_space_drop_dims(dim, isl_dim_out, first, n);
    1783             : }
    1784             : 
    1785           0 : __isl_give isl_space *isl_space_domain(__isl_take isl_space *space)
    1786             : {
    1787           0 :         if (!space)
    1788           0 :                 return NULL;
    1789           0 :         space = isl_space_drop_dims(space, isl_dim_out, 0, space->n_out);
    1790           0 :         space = isl_space_reverse(space);
    1791           0 :         space = mark_as_set(space);
    1792           0 :         return space;
    1793             : }
    1794             : 
    1795           0 : __isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim)
    1796             : {
    1797           0 :         if (!dim)
    1798           0 :                 return NULL;
    1799           0 :         if (!isl_space_is_set(dim))
    1800           0 :                 isl_die(isl_space_get_ctx(dim), isl_error_invalid,
    1801             :                         "not a set space", goto error);
    1802           0 :         dim = isl_space_reverse(dim);
    1803           0 :         dim = isl_space_reset(dim, isl_dim_out);
    1804           0 :         return dim;
    1805             : error:
    1806           0 :         isl_space_free(dim);
    1807           0 :         return NULL;
    1808             : }
    1809             : 
    1810           0 : __isl_give isl_space *isl_space_range(__isl_take isl_space *space)
    1811             : {
    1812           0 :         if (!space)
    1813           0 :                 return NULL;
    1814           0 :         space = isl_space_drop_dims(space, isl_dim_in, 0, space->n_in);
    1815           0 :         space = mark_as_set(space);
    1816           0 :         return space;
    1817             : }
    1818             : 
    1819           0 : __isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim)
    1820             : {
    1821           0 :         if (!dim)
    1822           0 :                 return NULL;
    1823           0 :         if (!isl_space_is_set(dim))
    1824           0 :                 isl_die(isl_space_get_ctx(dim), isl_error_invalid,
    1825             :                         "not a set space", goto error);
    1826           0 :         return isl_space_reset(dim, isl_dim_in);
    1827             : error:
    1828           0 :         isl_space_free(dim);
    1829           0 :         return NULL;
    1830             : }
    1831             : 
    1832             : /* Given a map space A -> B, return the map space [A -> B] -> A.
    1833             :  */
    1834           0 : __isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space)
    1835             : {
    1836             :         isl_space *domain;
    1837             : 
    1838           0 :         domain = isl_space_from_range(isl_space_domain(isl_space_copy(space)));
    1839           0 :         space = isl_space_from_domain(isl_space_wrap(space));
    1840           0 :         space = isl_space_join(space, domain);
    1841             : 
    1842           0 :         return space;
    1843             : }
    1844             : 
    1845             : /* Given a map space A -> B, return the map space [A -> B] -> B.
    1846             :  */
    1847           0 : __isl_give isl_space *isl_space_range_map(__isl_take isl_space *space)
    1848             : {
    1849             :         isl_space *range;
    1850             : 
    1851           0 :         range = isl_space_from_range(isl_space_range(isl_space_copy(space)));
    1852           0 :         space = isl_space_from_domain(isl_space_wrap(space));
    1853           0 :         space = isl_space_join(space, range);
    1854             : 
    1855           0 :         return space;
    1856             : }
    1857             : 
    1858           0 : __isl_give isl_space *isl_space_params(__isl_take isl_space *space)
    1859             : {
    1860           0 :         if (isl_space_is_params(space))
    1861           0 :                 return space;
    1862           0 :         space = isl_space_drop_dims(space,
    1863             :                             isl_dim_in, 0, isl_space_dim(space, isl_dim_in));
    1864           0 :         space = isl_space_drop_dims(space,
    1865             :                             isl_dim_out, 0, isl_space_dim(space, isl_dim_out));
    1866           0 :         space = mark_as_params(space);
    1867           0 :         return space;
    1868             : }
    1869             : 
    1870           0 : __isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space)
    1871             : {
    1872           0 :         if (!space)
    1873           0 :                 return NULL;
    1874           0 :         if (!isl_space_is_params(space))
    1875           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    1876             :                         "not a parameter space", goto error);
    1877           0 :         return isl_space_reset(space, isl_dim_set);
    1878             : error:
    1879           0 :         isl_space_free(space);
    1880           0 :         return NULL;
    1881             : }
    1882             : 
    1883    57730041 : __isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
    1884             :         unsigned n_div)
    1885             : {
    1886             :         int i;
    1887             : 
    1888    57730041 :         if (!dim)
    1889           0 :                 return NULL;
    1890   115460082 :         if (n_div == 0 &&
    1891   115460082 :             dim->nparam == 0 && dim->n_in == 0 && dim->n_id == 0)
    1892    57730041 :                 return isl_space_reset(isl_space_reset(dim, isl_dim_in), isl_dim_out);
    1893           0 :         dim = isl_space_cow(dim);
    1894           0 :         if (!dim)
    1895           0 :                 return NULL;
    1896           0 :         dim->n_out += dim->nparam + dim->n_in + n_div;
    1897           0 :         dim->nparam = 0;
    1898           0 :         dim->n_in = 0;
    1899             : 
    1900           0 :         for (i = 0; i < dim->n_id; ++i)
    1901           0 :                 isl_id_free(get_id(dim, isl_dim_out, i));
    1902           0 :         dim->n_id = 0;
    1903           0 :         dim = isl_space_reset(dim, isl_dim_in);
    1904           0 :         dim = isl_space_reset(dim, isl_dim_out);
    1905             : 
    1906           0 :         return dim;
    1907             : }
    1908             : 
    1909             : /* Are the two spaces the same, including positions and names of parameters?
    1910             :  */
    1911 23886361851 : isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
    1912             :         __isl_keep isl_space *space2)
    1913             : {
    1914             :         isl_bool equal;
    1915             : 
    1916 23886361851 :         if (!space1 || !space2)
    1917           0 :                 return isl_bool_error;
    1918 23886361851 :         if (space1 == space2)
    1919  7643545184 :                 return isl_bool_true;
    1920 16242816667 :         equal = isl_space_has_equal_params(space1, space2);
    1921 16242816667 :         if (equal < 0 || !equal)
    1922           0 :                 return equal;
    1923 16242816667 :         return isl_space_has_equal_tuples(space1, space2);
    1924             : }
    1925             : 
    1926             : /* Do the tuples of "space1" correspond to those of the domain of "space2"?
    1927             :  * That is, is "space1" eqaul to the domain of "space2", ignoring parameters.
    1928             :  *
    1929             :  * "space2" is allowed to be a set space, in which case "space1"
    1930             :  * should be a parameter space.
    1931             :  */
    1932           0 : isl_bool isl_space_has_domain_tuples(__isl_keep isl_space *space1,
    1933             :         __isl_keep isl_space *space2)
    1934             : {
    1935             :         isl_bool is_set;
    1936             : 
    1937           0 :         is_set = isl_space_is_set(space1);
    1938           0 :         if (is_set < 0 || !is_set)
    1939           0 :                 return is_set;
    1940           0 :         return isl_space_tuple_is_equal(space1, isl_dim_set,
    1941             :                                         space2, isl_dim_in);
    1942             : }
    1943             : 
    1944             : /* Is space1 equal to the domain of space2?
    1945             :  *
    1946             :  * In the internal version we also allow space2 to be the space of a set,
    1947             :  * provided space1 is a parameter space.
    1948             :  */
    1949           0 : isl_bool isl_space_is_domain_internal(__isl_keep isl_space *space1,
    1950             :         __isl_keep isl_space *space2)
    1951             : {
    1952             :         isl_bool equal_params;
    1953             : 
    1954           0 :         if (!space1 || !space2)
    1955           0 :                 return isl_bool_error;
    1956           0 :         equal_params = isl_space_has_equal_params(space1, space2);
    1957           0 :         if (equal_params < 0 || !equal_params)
    1958           0 :                 return equal_params;
    1959           0 :         return isl_space_has_domain_tuples(space1, space2);
    1960             : }
    1961             : 
    1962             : /* Is space1 equal to the domain of space2?
    1963             :  */
    1964           0 : isl_bool isl_space_is_domain(__isl_keep isl_space *space1,
    1965             :         __isl_keep isl_space *space2)
    1966             : {
    1967           0 :         if (!space2)
    1968           0 :                 return isl_bool_error;
    1969           0 :         if (!isl_space_is_map(space2))
    1970           0 :                 return isl_bool_false;
    1971           0 :         return isl_space_is_domain_internal(space1, space2);
    1972             : }
    1973             : 
    1974             : /* Is space1 equal to the range of space2?
    1975             :  *
    1976             :  * In the internal version, space2 is allowed to be the space of a set,
    1977             :  * in which case it should be equal to space1.
    1978             :  */
    1979           0 : isl_bool isl_space_is_range_internal(__isl_keep isl_space *space1,
    1980             :         __isl_keep isl_space *space2)
    1981             : {
    1982             :         isl_bool equal_params;
    1983             : 
    1984           0 :         if (!space1 || !space2)
    1985           0 :                 return isl_bool_error;
    1986           0 :         if (!isl_space_is_set(space1))
    1987           0 :                 return isl_bool_false;
    1988           0 :         equal_params = isl_space_has_equal_params(space1, space2);
    1989           0 :         if (equal_params < 0 || !equal_params)
    1990           0 :                 return equal_params;
    1991           0 :         return isl_space_tuple_is_equal(space1, isl_dim_set,
    1992             :                                         space2, isl_dim_out);
    1993             : }
    1994             : 
    1995             : /* Is space1 equal to the range of space2?
    1996             :  */
    1997           0 : isl_bool isl_space_is_range(__isl_keep isl_space *space1,
    1998             :         __isl_keep isl_space *space2)
    1999             : {
    2000           0 :         if (!space2)
    2001           0 :                 return isl_bool_error;
    2002           0 :         if (!isl_space_is_map(space2))
    2003           0 :                 return isl_bool_false;
    2004           0 :         return isl_space_is_range_internal(space1, space2);
    2005             : }
    2006             : 
    2007             : /* Update "hash" by hashing in the parameters of "space".
    2008             :  */
    2009           0 : static uint32_t isl_hash_params(uint32_t hash, __isl_keep isl_space *space)
    2010             : {
    2011             :         int i;
    2012             :         isl_id *id;
    2013             : 
    2014           0 :         if (!space)
    2015           0 :                 return hash;
    2016             : 
    2017           0 :         isl_hash_byte(hash, space->nparam % 256);
    2018             : 
    2019           0 :         for (i = 0; i < space->nparam; ++i) {
    2020           0 :                 id = get_id(space, isl_dim_param, i);
    2021           0 :                 hash = isl_hash_id(hash, id);
    2022             :         }
    2023             : 
    2024           0 :         return hash;
    2025             : }
    2026             : 
    2027             : /* Update "hash" by hashing in the tuples of "space".
    2028             :  * Changes in this function should be reflected in isl_hash_tuples_domain.
    2029             :  */
    2030           0 : static uint32_t isl_hash_tuples(uint32_t hash, __isl_keep isl_space *space)
    2031             : {
    2032             :         isl_id *id;
    2033             : 
    2034           0 :         if (!space)
    2035           0 :                 return hash;
    2036             : 
    2037           0 :         isl_hash_byte(hash, space->n_in % 256);
    2038           0 :         isl_hash_byte(hash, space->n_out % 256);
    2039             : 
    2040           0 :         id = tuple_id(space, isl_dim_in);
    2041           0 :         hash = isl_hash_id(hash, id);
    2042           0 :         id = tuple_id(space, isl_dim_out);
    2043           0 :         hash = isl_hash_id(hash, id);
    2044             : 
    2045           0 :         hash = isl_hash_tuples(hash, space->nested[0]);
    2046           0 :         hash = isl_hash_tuples(hash, space->nested[1]);
    2047             : 
    2048           0 :         return hash;
    2049             : }
    2050             : 
    2051             : /* Update "hash" by hashing in the domain tuple of "space".
    2052             :  * The result of this function is equal to the result of applying
    2053             :  * isl_hash_tuples to the domain of "space".
    2054             :  */
    2055           0 : static uint32_t isl_hash_tuples_domain(uint32_t hash,
    2056             :         __isl_keep isl_space *space)
    2057             : {
    2058             :         isl_id *id;
    2059             : 
    2060           0 :         if (!space)
    2061           0 :                 return hash;
    2062             : 
    2063           0 :         isl_hash_byte(hash, 0);
    2064           0 :         isl_hash_byte(hash, space->n_in % 256);
    2065             : 
    2066           0 :         hash = isl_hash_id(hash, &isl_id_none);
    2067           0 :         id = tuple_id(space, isl_dim_in);
    2068           0 :         hash = isl_hash_id(hash, id);
    2069             : 
    2070           0 :         hash = isl_hash_tuples(hash, space->nested[0]);
    2071             : 
    2072           0 :         return hash;
    2073             : }
    2074             : 
    2075             : /* Return a hash value that digests the tuples of "space",
    2076             :  * i.e., that ignores the parameters.
    2077             :  */
    2078           0 : uint32_t isl_space_get_tuple_hash(__isl_keep isl_space *space)
    2079             : {
    2080             :         uint32_t hash;
    2081             : 
    2082           0 :         if (!space)
    2083           0 :                 return 0;
    2084             : 
    2085           0 :         hash = isl_hash_init();
    2086           0 :         hash = isl_hash_tuples(hash, space);
    2087             : 
    2088           0 :         return hash;
    2089             : }
    2090             : 
    2091           0 : uint32_t isl_space_get_hash(__isl_keep isl_space *space)
    2092             : {
    2093             :         uint32_t hash;
    2094             : 
    2095           0 :         if (!space)
    2096           0 :                 return 0;
    2097             : 
    2098           0 :         hash = isl_hash_init();
    2099           0 :         hash = isl_hash_params(hash, space);
    2100           0 :         hash = isl_hash_tuples(hash, space);
    2101             : 
    2102           0 :         return hash;
    2103             : }
    2104             : 
    2105             : /* Return the hash value of the domain of "space".
    2106             :  * That is, isl_space_get_domain_hash(space) is equal to
    2107             :  * isl_space_get_hash(isl_space_domain(space)).
    2108             :  */
    2109           0 : uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space)
    2110             : {
    2111             :         uint32_t hash;
    2112             : 
    2113           0 :         if (!space)
    2114           0 :                 return 0;
    2115             : 
    2116           0 :         hash = isl_hash_init();
    2117           0 :         hash = isl_hash_params(hash, space);
    2118           0 :         hash = isl_hash_tuples_domain(hash, space);
    2119             : 
    2120           0 :         return hash;
    2121             : }
    2122             : 
    2123           0 : isl_bool isl_space_is_wrapping(__isl_keep isl_space *dim)
    2124             : {
    2125           0 :         if (!dim)
    2126           0 :                 return isl_bool_error;
    2127             : 
    2128           0 :         if (!isl_space_is_set(dim))
    2129           0 :                 return isl_bool_false;
    2130             : 
    2131           0 :         return dim->nested[1] != NULL;
    2132             : }
    2133             : 
    2134             : /* Is "space" the space of a map where the domain is a wrapped map space?
    2135             :  */
    2136           0 : isl_bool isl_space_domain_is_wrapping(__isl_keep isl_space *space)
    2137             : {
    2138           0 :         if (!space)
    2139           0 :                 return isl_bool_error;
    2140             : 
    2141           0 :         if (isl_space_is_set(space))
    2142           0 :                 return isl_bool_false;
    2143             : 
    2144           0 :         return space->nested[0] != NULL;
    2145             : }
    2146             : 
    2147             : /* Is "space" the space of a map where the range is a wrapped map space?
    2148             :  */
    2149           0 : isl_bool isl_space_range_is_wrapping(__isl_keep isl_space *space)
    2150             : {
    2151           0 :         if (!space)
    2152           0 :                 return isl_bool_error;
    2153             : 
    2154           0 :         if (isl_space_is_set(space))
    2155           0 :                 return isl_bool_false;
    2156             : 
    2157           0 :         return space->nested[1] != NULL;
    2158             : }
    2159             : 
    2160             : /* Is "space" a product of two spaces?
    2161             :  * That is, is it a wrapping set space or a map space
    2162             :  * with wrapping domain and range?
    2163             :  */
    2164           0 : isl_bool isl_space_is_product(__isl_keep isl_space *space)
    2165             : {
    2166             :         isl_bool is_set;
    2167             :         isl_bool is_product;
    2168             : 
    2169           0 :         is_set = isl_space_is_set(space);
    2170           0 :         if (is_set < 0)
    2171           0 :                 return isl_bool_error;
    2172           0 :         if (is_set)
    2173           0 :                 return isl_space_is_wrapping(space);
    2174           0 :         is_product = isl_space_domain_is_wrapping(space);
    2175           0 :         if (is_product < 0 || !is_product)
    2176           0 :                 return is_product;
    2177           0 :         return isl_space_range_is_wrapping(space);
    2178             : }
    2179             : 
    2180           0 : __isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim)
    2181             : {
    2182             :         isl_space *wrap;
    2183             : 
    2184           0 :         if (!dim)
    2185           0 :                 return NULL;
    2186             : 
    2187           0 :         wrap = isl_space_set_alloc(dim->ctx,
    2188           0 :                                     dim->nparam, dim->n_in + dim->n_out);
    2189             : 
    2190           0 :         wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param);
    2191           0 :         wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in);
    2192           0 :         wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
    2193             : 
    2194           0 :         if (!wrap)
    2195           0 :                 goto error;
    2196             : 
    2197           0 :         wrap->nested[1] = dim;
    2198             : 
    2199           0 :         return wrap;
    2200             : error:
    2201           0 :         isl_space_free(dim);
    2202           0 :         return NULL;
    2203             : }
    2204             : 
    2205           0 : __isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim)
    2206             : {
    2207             :         isl_space *unwrap;
    2208             : 
    2209           0 :         if (!dim)
    2210           0 :                 return NULL;
    2211             : 
    2212           0 :         if (!isl_space_is_wrapping(dim))
    2213           0 :                 isl_die(dim->ctx, isl_error_invalid, "not a wrapping space",
    2214             :                         goto error);
    2215             : 
    2216           0 :         unwrap = isl_space_copy(dim->nested[1]);
    2217           0 :         isl_space_free(dim);
    2218             : 
    2219           0 :         return unwrap;
    2220             : error:
    2221           0 :         isl_space_free(dim);
    2222           0 :         return NULL;
    2223             : }
    2224             : 
    2225  2578034203 : isl_bool isl_space_is_named_or_nested(__isl_keep isl_space *space,
    2226             :         enum isl_dim_type type)
    2227             : {
    2228  2578034203 :         if (type != isl_dim_in && type != isl_dim_out)
    2229           0 :                 return isl_bool_false;
    2230  2578034203 :         if (!space)
    2231           0 :                 return isl_bool_error;
    2232  2578034203 :         if (space->tuple_id[type - isl_dim_in])
    2233   115460082 :                 return isl_bool_true;
    2234  2462574121 :         if (space->nested[type - isl_dim_in])
    2235           0 :                 return isl_bool_true;
    2236  2462574121 :         return isl_bool_false;
    2237             : }
    2238             : 
    2239           0 : isl_bool isl_space_may_be_set(__isl_keep isl_space *space)
    2240             : {
    2241             :         isl_bool nested;
    2242             : 
    2243           0 :         if (!space)
    2244           0 :                 return isl_bool_error;
    2245           0 :         if (isl_space_is_set(space))
    2246           0 :                 return isl_bool_true;
    2247           0 :         if (isl_space_dim(space, isl_dim_in) != 0)
    2248           0 :                 return isl_bool_false;
    2249           0 :         nested = isl_space_is_named_or_nested(space, isl_dim_in);
    2250           0 :         if (nested < 0 || nested)
    2251           0 :                 return isl_bool_not(nested);
    2252           0 :         return isl_bool_true;
    2253             : }
    2254             : 
    2255   132757105 : __isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
    2256             :         enum isl_dim_type type)
    2257             : {
    2258   132757105 :         if (!isl_space_is_named_or_nested(dim, type))
    2259    75027064 :                 return dim;
    2260             : 
    2261    57730041 :         dim = isl_space_cow(dim);
    2262    57730041 :         if (!dim)
    2263           0 :                 return NULL;
    2264             : 
    2265    57730041 :         isl_id_free(dim->tuple_id[type - isl_dim_in]);
    2266    57730041 :         dim->tuple_id[type - isl_dim_in] = NULL;
    2267    57730041 :         isl_space_free(dim->nested[type - isl_dim_in]);
    2268    57730041 :         dim->nested[type - isl_dim_in] = NULL;
    2269             : 
    2270    57730041 :         return dim;
    2271             : }
    2272             : 
    2273           0 : __isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim)
    2274             : {
    2275           0 :         if (!dim)
    2276           0 :                 return NULL;
    2277           0 :         if (!dim->nested[0] && !dim->nested[1])
    2278           0 :                 return dim;
    2279             : 
    2280           0 :         if (dim->nested[0])
    2281           0 :                 dim = isl_space_reset(dim, isl_dim_in);
    2282           0 :         if (dim && dim->nested[1])
    2283           0 :                 dim = isl_space_reset(dim, isl_dim_out);
    2284             : 
    2285           0 :         return dim;
    2286             : }
    2287             : 
    2288           0 : __isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *space)
    2289             : {
    2290           0 :         if (!space)
    2291           0 :                 return NULL;
    2292           0 :         if (!space->nested[0])
    2293           0 :                 return space;
    2294             : 
    2295           0 :         return isl_space_reset(space, isl_dim_in);
    2296             : }
    2297             : 
    2298           0 : __isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *space)
    2299             : {
    2300           0 :         if (!space)
    2301           0 :                 return NULL;
    2302           0 :         if (!space->nested[1])
    2303           0 :                 return space;
    2304             : 
    2305           0 :         return isl_space_reset(space, isl_dim_out);
    2306             : }
    2307             : 
    2308             : /* Replace the parameters of dst by those of src.
    2309             :  */
    2310           0 : __isl_give isl_space *isl_space_replace_params(__isl_take isl_space *dst,
    2311             :         __isl_keep isl_space *src)
    2312             : {
    2313             :         isl_bool equal_params;
    2314           0 :         enum isl_dim_type type = isl_dim_param;
    2315             : 
    2316           0 :         equal_params = isl_space_has_equal_params(dst, src);
    2317           0 :         if (equal_params < 0)
    2318           0 :                 return isl_space_free(dst);
    2319           0 :         if (equal_params)
    2320           0 :                 return dst;
    2321             : 
    2322           0 :         dst = isl_space_cow(dst);
    2323             : 
    2324           0 :         if (!dst || !src)
    2325             :                 goto error;
    2326             : 
    2327           0 :         dst = isl_space_drop_dims(dst, type, 0, isl_space_dim(dst, type));
    2328           0 :         dst = isl_space_add_dims(dst, type, isl_space_dim(src, type));
    2329           0 :         dst = copy_ids(dst, type, 0, src, type);
    2330             : 
    2331           0 :         if (dst) {
    2332             :                 int i;
    2333           0 :                 for (i = 0; i <= 1; ++i) {
    2334           0 :                         if (!dst->nested[i])
    2335           0 :                                 continue;
    2336           0 :                         dst->nested[i] = isl_space_replace_params(
    2337             :                                                         dst->nested[i], src);
    2338           0 :                         if (!dst->nested[i])
    2339           0 :                                 goto error;
    2340             :                 }
    2341             :         }
    2342             : 
    2343           0 :         return dst;
    2344             : error:
    2345           0 :         isl_space_free(dst);
    2346           0 :         return NULL;
    2347             : }
    2348             : 
    2349             : /* Given a dimension specification "dim" of a set, create a dimension
    2350             :  * specification for the lift of the set.  In particular, the result
    2351             :  * is of the form [dim -> local[..]], with n_local variables in the
    2352             :  * range of the wrapped map.
    2353             :  */
    2354           0 : __isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local)
    2355             : {
    2356             :         isl_space *local_dim;
    2357             : 
    2358           0 :         if (!dim)
    2359           0 :                 return NULL;
    2360             : 
    2361           0 :         local_dim = isl_space_dup(dim);
    2362           0 :         local_dim = isl_space_drop_dims(local_dim, isl_dim_set, 0, dim->n_out);
    2363           0 :         local_dim = isl_space_add_dims(local_dim, isl_dim_set, n_local);
    2364           0 :         local_dim = isl_space_set_tuple_name(local_dim, isl_dim_set, "local");
    2365           0 :         dim = isl_space_join(isl_space_from_domain(dim),
    2366             :                             isl_space_from_range(local_dim));
    2367           0 :         dim = isl_space_wrap(dim);
    2368           0 :         dim = isl_space_set_tuple_name(dim, isl_dim_set, "lifted");
    2369             : 
    2370           0 :         return dim;
    2371             : }
    2372             : 
    2373           0 : isl_bool isl_space_can_zip(__isl_keep isl_space *space)
    2374             : {
    2375             :         isl_bool is_set;
    2376             : 
    2377           0 :         is_set = isl_space_is_set(space);
    2378           0 :         if (is_set < 0)
    2379           0 :                 return isl_bool_error;
    2380           0 :         if (is_set)
    2381           0 :                 return isl_bool_false;
    2382           0 :         return isl_space_is_product(space);
    2383             : }
    2384             : 
    2385           0 : __isl_give isl_space *isl_space_zip(__isl_take isl_space *dim)
    2386             : {
    2387             :         isl_space *dom, *ran;
    2388             :         isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran;
    2389             : 
    2390           0 :         if (!isl_space_can_zip(dim))
    2391           0 :                 isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped",
    2392             :                         goto error);
    2393             : 
    2394           0 :         if (!dim)
    2395           0 :                 return NULL;
    2396           0 :         dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim)));
    2397           0 :         ran = isl_space_unwrap(isl_space_range(dim));
    2398           0 :         dom_dom = isl_space_domain(isl_space_copy(dom));
    2399           0 :         dom_ran = isl_space_range(dom);
    2400           0 :         ran_dom = isl_space_domain(isl_space_copy(ran));
    2401           0 :         ran_ran = isl_space_range(ran);
    2402           0 :         dom = isl_space_join(isl_space_from_domain(dom_dom),
    2403             :                            isl_space_from_range(ran_dom));
    2404           0 :         ran = isl_space_join(isl_space_from_domain(dom_ran),
    2405             :                            isl_space_from_range(ran_ran));
    2406           0 :         return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
    2407             :                             isl_space_from_range(isl_space_wrap(ran)));
    2408             : error:
    2409           0 :         isl_space_free(dim);
    2410           0 :         return NULL;
    2411             : }
    2412             : 
    2413             : /* Can we apply isl_space_curry to "space"?
    2414             :  * That is, does it have a nested relation in its domain?
    2415             :  */
    2416           0 : isl_bool isl_space_can_curry(__isl_keep isl_space *space)
    2417             : {
    2418           0 :         if (!space)
    2419           0 :                 return isl_bool_error;
    2420             : 
    2421           0 :         return !!space->nested[0];
    2422             : }
    2423             : 
    2424             : /* Given a space (A -> B) -> C, return the corresponding space
    2425             :  * A -> (B -> C).
    2426             :  */
    2427           0 : __isl_give isl_space *isl_space_curry(__isl_take isl_space *space)
    2428             : {
    2429             :         isl_space *dom, *ran;
    2430             :         isl_space *dom_dom, *dom_ran;
    2431             : 
    2432           0 :         if (!space)
    2433           0 :                 return NULL;
    2434             : 
    2435           0 :         if (!isl_space_can_curry(space))
    2436           0 :                 isl_die(space->ctx, isl_error_invalid,
    2437             :                         "space cannot be curried", goto error);
    2438             : 
    2439           0 :         dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
    2440           0 :         ran = isl_space_range(space);
    2441           0 :         dom_dom = isl_space_domain(isl_space_copy(dom));
    2442           0 :         dom_ran = isl_space_range(dom);
    2443           0 :         ran = isl_space_join(isl_space_from_domain(dom_ran),
    2444             :                            isl_space_from_range(ran));
    2445           0 :         return isl_space_join(isl_space_from_domain(dom_dom),
    2446             :                             isl_space_from_range(isl_space_wrap(ran)));
    2447             : error:
    2448           0 :         isl_space_free(space);
    2449           0 :         return NULL;
    2450             : }
    2451             : 
    2452             : /* Can isl_space_range_curry be applied to "space"?
    2453             :  * That is, does it have a nested relation in its range,
    2454             :  * the domain of which is itself a nested relation?
    2455             :  */
    2456           0 : isl_bool isl_space_can_range_curry(__isl_keep isl_space *space)
    2457             : {
    2458             :         isl_bool can;
    2459             : 
    2460           0 :         if (!space)
    2461           0 :                 return isl_bool_error;
    2462           0 :         can = isl_space_range_is_wrapping(space);
    2463           0 :         if (can < 0 || !can)
    2464           0 :                 return can;
    2465           0 :         return isl_space_can_curry(space->nested[1]);
    2466             : }
    2467             : 
    2468             : /* Given a space A -> ((B -> C) -> D), return the corresponding space
    2469             :  * A -> (B -> (C -> D)).
    2470             :  */
    2471           0 : __isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
    2472             : {
    2473           0 :         if (!space)
    2474           0 :                 return NULL;
    2475             : 
    2476           0 :         if (!isl_space_can_range_curry(space))
    2477           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    2478             :                         "space range cannot be curried",
    2479             :                         return isl_space_free(space));
    2480             : 
    2481           0 :         space = isl_space_cow(space);
    2482           0 :         if (!space)
    2483           0 :                 return NULL;
    2484           0 :         space->nested[1] = isl_space_curry(space->nested[1]);
    2485           0 :         if (!space->nested[1])
    2486           0 :                 return isl_space_free(space);
    2487             : 
    2488           0 :         return space;
    2489             : }
    2490             : 
    2491             : /* Can we apply isl_space_uncurry to "space"?
    2492             :  * That is, does it have a nested relation in its range?
    2493             :  */
    2494           0 : isl_bool isl_space_can_uncurry(__isl_keep isl_space *space)
    2495             : {
    2496           0 :         if (!space)
    2497           0 :                 return isl_bool_error;
    2498             : 
    2499           0 :         return !!space->nested[1];
    2500             : }
    2501             : 
    2502             : /* Given a space A -> (B -> C), return the corresponding space
    2503             :  * (A -> B) -> C.
    2504             :  */
    2505           0 : __isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space)
    2506             : {
    2507             :         isl_space *dom, *ran;
    2508             :         isl_space *ran_dom, *ran_ran;
    2509             : 
    2510           0 :         if (!space)
    2511           0 :                 return NULL;
    2512             : 
    2513           0 :         if (!isl_space_can_uncurry(space))
    2514           0 :                 isl_die(space->ctx, isl_error_invalid,
    2515             :                         "space cannot be uncurried",
    2516             :                         return isl_space_free(space));
    2517             : 
    2518           0 :         dom = isl_space_domain(isl_space_copy(space));
    2519           0 :         ran = isl_space_unwrap(isl_space_range(space));
    2520           0 :         ran_dom = isl_space_domain(isl_space_copy(ran));
    2521           0 :         ran_ran = isl_space_range(ran);
    2522           0 :         dom = isl_space_join(isl_space_from_domain(dom),
    2523             :                            isl_space_from_range(ran_dom));
    2524           0 :         return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
    2525             :                             isl_space_from_range(ran_ran));
    2526             : }
    2527             : 
    2528           0 : isl_bool isl_space_has_named_params(__isl_keep isl_space *space)
    2529             : {
    2530             :         int i;
    2531             :         unsigned off;
    2532             : 
    2533           0 :         if (!space)
    2534           0 :                 return isl_bool_error;
    2535           0 :         if (space->nparam == 0)
    2536           0 :                 return isl_bool_true;
    2537           0 :         off = isl_space_offset(space, isl_dim_param);
    2538           0 :         if (off + space->nparam > space->n_id)
    2539           0 :                 return isl_bool_false;
    2540           0 :         for (i = 0; i < space->nparam; ++i)
    2541           0 :                 if (!space->ids[off + i])
    2542           0 :                         return isl_bool_false;
    2543           0 :         return isl_bool_true;
    2544             : }
    2545             : 
    2546             : /* Check that "space" has only named parameters, reporting an error
    2547             :  * if it does not.
    2548             :  */
    2549           0 : isl_stat isl_space_check_named_params(__isl_keep isl_space *space)
    2550             : {
    2551             :         isl_bool named;
    2552             : 
    2553           0 :         named = isl_space_has_named_params(space);
    2554           0 :         if (named < 0)
    2555           0 :                 return isl_stat_error;
    2556           0 :         if (!named)
    2557           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
    2558             :                         "unexpected unnamed parameters", return isl_stat_error);
    2559             : 
    2560           0 :         return isl_stat_ok;
    2561             : }
    2562             : 
    2563             : /* Align the initial parameters of space1 to match the order in space2.
    2564             :  */
    2565           0 : __isl_give isl_space *isl_space_align_params(__isl_take isl_space *space1,
    2566             :         __isl_take isl_space *space2)
    2567             : {
    2568             :         isl_reordering *exp;
    2569             : 
    2570           0 :         if (isl_space_check_named_params(space1) < 0 ||
    2571           0 :             isl_space_check_named_params(space2) < 0)
    2572             :                 goto error;
    2573             : 
    2574           0 :         exp = isl_parameter_alignment_reordering(space1, space2);
    2575           0 :         exp = isl_reordering_extend_space(exp, space1);
    2576           0 :         isl_space_free(space2);
    2577           0 :         space1 = isl_reordering_get_space(exp);
    2578           0 :         isl_reordering_free(exp);
    2579           0 :         return space1;
    2580             : error:
    2581           0 :         isl_space_free(space1);
    2582           0 :         isl_space_free(space2);
    2583           0 :         return NULL;
    2584             : }
    2585             : 
    2586             : /* Given the space of set (domain), construct a space for a map
    2587             :  * with as domain the given space and as range the range of "model".
    2588             :  */
    2589           0 : __isl_give isl_space *isl_space_extend_domain_with_range(
    2590             :         __isl_take isl_space *space, __isl_take isl_space *model)
    2591             : {
    2592           0 :         if (!model)
    2593           0 :                 goto error;
    2594             : 
    2595           0 :         space = isl_space_from_domain(space);
    2596           0 :         space = isl_space_add_dims(space, isl_dim_out,
    2597             :                                     isl_space_dim(model, isl_dim_out));
    2598           0 :         if (isl_space_has_tuple_id(model, isl_dim_out))
    2599           0 :                 space = isl_space_set_tuple_id(space, isl_dim_out,
    2600             :                                 isl_space_get_tuple_id(model, isl_dim_out));
    2601           0 :         if (!space)
    2602           0 :                 goto error;
    2603           0 :         if (model->nested[1]) {
    2604           0 :                 isl_space *nested = isl_space_copy(model->nested[1]);
    2605             :                 int n_nested, n_space;
    2606           0 :                 nested = isl_space_align_params(nested, isl_space_copy(space));
    2607           0 :                 n_nested = isl_space_dim(nested, isl_dim_param);
    2608           0 :                 n_space = isl_space_dim(space, isl_dim_param);
    2609           0 :                 if (n_nested > n_space)
    2610           0 :                         nested = isl_space_drop_dims(nested, isl_dim_param,
    2611           0 :                                                 n_space, n_nested - n_space);
    2612           0 :                 if (!nested)
    2613           0 :                         goto error;
    2614           0 :                 space->nested[1] = nested;
    2615             :         }
    2616           0 :         isl_space_free(model);
    2617           0 :         return space;
    2618             : error:
    2619           0 :         isl_space_free(model);
    2620           0 :         isl_space_free(space);
    2621           0 :         return NULL;
    2622             : }
    2623             : 
    2624             : /* Compare the "type" dimensions of two isl_spaces.
    2625             :  *
    2626             :  * The order is fairly arbitrary.
    2627             :  */
    2628    94974777 : static int isl_space_cmp_type(__isl_keep isl_space *space1,
    2629             :         __isl_keep isl_space *space2, enum isl_dim_type type)
    2630             : {
    2631             :         int cmp;
    2632             :         isl_space *nested1, *nested2;
    2633             : 
    2634    94974777 :         if (isl_space_dim(space1, type) != isl_space_dim(space2, type))
    2635           0 :                 return isl_space_dim(space1, type) -
    2636           0 :                         isl_space_dim(space2, type);
    2637             : 
    2638    94974777 :         cmp = isl_id_cmp(tuple_id(space1, type), tuple_id(space2, type));
    2639    94974777 :         if (cmp != 0)
    2640           0 :                 return cmp;
    2641             : 
    2642    94974777 :         nested1 = nested(space1, type);
    2643    94974777 :         nested2 = nested(space2, type);
    2644    94974777 :         if (!nested1 != !nested2)
    2645           0 :                 return !nested1 - !nested2;
    2646             : 
    2647    94974777 :         if (nested1)
    2648           0 :                 return isl_space_cmp(nested1, nested2);
    2649             : 
    2650    94974777 :         return 0;
    2651             : }
    2652             : 
    2653             : /* Compare two isl_spaces.
    2654             :  *
    2655             :  * The order is fairly arbitrary.
    2656             :  */
    2657   732451979 : int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2)
    2658             : {
    2659             :         int i;
    2660             :         int cmp;
    2661             : 
    2662   732451979 :         if (space1 == space2)
    2663   700793720 :                 return 0;
    2664    31658259 :         if (!space1)
    2665           0 :                 return -1;
    2666    31658259 :         if (!space2)
    2667           0 :                 return 1;
    2668             : 
    2669    31658259 :         cmp = isl_space_cmp_type(space1, space2, isl_dim_param);
    2670    31658259 :         if (cmp != 0)
    2671           0 :                 return cmp;
    2672    31658259 :         cmp = isl_space_cmp_type(space1, space2, isl_dim_in);
    2673    31658259 :         if (cmp != 0)
    2674           0 :                 return cmp;
    2675    31658259 :         cmp = isl_space_cmp_type(space1, space2, isl_dim_out);
    2676    31658259 :         if (cmp != 0)
    2677           0 :                 return cmp;
    2678             : 
    2679    31658259 :         if (!space1->ids && !space2->ids)
    2680    31658259 :                 return 0;
    2681             : 
    2682           0 :         for (i = 0; i < n(space1, isl_dim_param); ++i) {
    2683           0 :                 cmp = isl_id_cmp(get_id(space1, isl_dim_param, i),
    2684             :                                  get_id(space2, isl_dim_param, i));
    2685           0 :                 if (cmp != 0)
    2686           0 :                         return cmp;
    2687             :         }
    2688             : 
    2689           0 :         return 0;
    2690             : }

Generated by: LCOV version 1.12