LCOV - code coverage report
Current view: top level - metalib_isl - isl_multi_templ.c (source / functions) Hit Total Coverage
Test: 2018-10-31_point_maint_greina16.lcov Lines: 0 693 0.0 %
Date: 2018-11-01 11:27:00 Functions: 0 252 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011      Sven Verdoolaege
       3             :  * Copyright 2012-2013 Ecole Normale Superieure
       4             :  *
       5             :  * Use of this software is governed by the MIT license
       6             :  *
       7             :  * Written by Sven Verdoolaege,
       8             :  * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
       9             :  */
      10             : 
      11             : #include <isl/id.h>
      12             : #include <isl_space_private.h>
      13             : #include <isl_val_private.h>
      14             : #include <isl/set.h>
      15             : #include <isl_reordering.h>
      16             : 
      17             : #include <isl_multi_macro.h>
      18             : 
      19             : #define MULTI_NAME(BASE) "isl_multi_" #BASE
      20             : #define xLIST(EL) EL ## _list
      21             : #define LIST(EL) xLIST(EL)
      22             : 
      23           0 : isl_ctx *FN(MULTI(BASE),get_ctx)(__isl_keep MULTI(BASE) *multi)
      24             : {
      25           0 :         return multi ? isl_space_get_ctx(multi->space) : NULL;
      26             : }
      27             : 
      28             : /* Return the space of "multi".
      29             :  */
      30           0 : __isl_keep isl_space *FN(MULTI(BASE),peek_space)(__isl_keep MULTI(BASE) *multi)
      31             : {
      32           0 :         return multi ? multi->space : NULL;
      33             : }
      34             : 
      35           0 : __isl_give isl_space *FN(MULTI(BASE),get_space)(__isl_keep MULTI(BASE) *multi)
      36             : {
      37           0 :         return isl_space_copy(FN(MULTI(BASE),peek_space)(multi));
      38             : }
      39             : 
      40             : /* Return the position of the dimension of the given type and name
      41             :  * in "multi".
      42             :  * Return -1 if no such dimension can be found.
      43             :  */
      44           0 : int FN(MULTI(BASE),find_dim_by_name)(__isl_keep MULTI(BASE) *multi,
      45             :         enum isl_dim_type type, const char *name)
      46             : {
      47           0 :         if (!multi)
      48           0 :                 return -1;
      49           0 :         return isl_space_find_dim_by_name(multi->space, type, name);
      50             : }
      51             : 
      52           0 : __isl_give isl_space *FN(MULTI(BASE),get_domain_space)(
      53             :         __isl_keep MULTI(BASE) *multi)
      54             : {
      55           0 :         return multi ? isl_space_domain(isl_space_copy(multi->space)) : NULL;
      56             : }
      57             : 
      58             : /* Allocate a multi expression living in "space".
      59             :  *
      60             :  * If the number of base expressions is zero, then make sure
      61             :  * there is enough room in the structure for the explicit domain,
      62             :  * in case the type supports such an explicit domain.
      63             :  */
      64           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),alloc)(__isl_take isl_space *space)
      65             : {
      66             :         isl_ctx *ctx;
      67             :         int n;
      68             :         MULTI(BASE) *multi;
      69             : 
      70           0 :         if (!space)
      71           0 :                 return NULL;
      72             : 
      73           0 :         ctx = isl_space_get_ctx(space);
      74           0 :         n = isl_space_dim(space, isl_dim_out);
      75           0 :         if (n > 0)
      76           0 :                 multi = isl_calloc(ctx, MULTI(BASE),
      77             :                          sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *));
      78             :         else
      79           0 :                 multi = isl_calloc(ctx, MULTI(BASE), sizeof(MULTI(BASE)));
      80           0 :         if (!multi)
      81           0 :                 goto error;
      82             : 
      83           0 :         multi->space = space;
      84           0 :         multi->n = n;
      85           0 :         multi->ref = 1;
      86           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi))
      87           0 :                 multi = FN(MULTI(BASE),init_explicit_domain)(multi);
      88           0 :         return multi;
      89             : error:
      90           0 :         isl_space_free(space);
      91           0 :         return NULL;
      92             : }
      93             : 
      94           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),dup)(__isl_keep MULTI(BASE) *multi)
      95             : {
      96             :         int i;
      97             :         MULTI(BASE) *dup;
      98             : 
      99           0 :         if (!multi)
     100           0 :                 return NULL;
     101             : 
     102           0 :         dup = FN(MULTI(BASE),alloc)(isl_space_copy(multi->space));
     103           0 :         if (!dup)
     104           0 :                 return NULL;
     105             : 
     106           0 :         for (i = 0; i < multi->n; ++i)
     107           0 :                 dup = FN(FN(MULTI(BASE),set),BASE)(dup, i,
     108             :                                                     FN(EL,copy)(multi->u.p[i]));
     109           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi))
     110           0 :                 dup = FN(MULTI(BASE),copy_explicit_domain)(dup, multi);
     111             : 
     112           0 :         return dup;
     113             : }
     114             : 
     115           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi)
     116             : {
     117           0 :         if (!multi)
     118           0 :                 return NULL;
     119             : 
     120           0 :         if (multi->ref == 1)
     121           0 :                 return multi;
     122             : 
     123           0 :         multi->ref--;
     124           0 :         return FN(MULTI(BASE),dup)(multi);
     125             : }
     126             : 
     127           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),copy)(__isl_keep MULTI(BASE) *multi)
     128             : {
     129           0 :         if (!multi)
     130           0 :                 return NULL;
     131             : 
     132           0 :         multi->ref++;
     133           0 :         return multi;
     134             : }
     135             : 
     136           0 : __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
     137             : {
     138             :         int i;
     139             : 
     140           0 :         if (!multi)
     141           0 :                 return NULL;
     142             : 
     143           0 :         if (--multi->ref > 0)
     144           0 :                 return NULL;
     145             : 
     146           0 :         isl_space_free(multi->space);
     147           0 :         for (i = 0; i < multi->n; ++i)
     148           0 :                 FN(EL,free)(multi->u.p[i]);
     149           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi))
     150           0 :                 FN(MULTI(BASE),free_explicit_domain)(multi);
     151           0 :         free(multi);
     152             : 
     153           0 :         return NULL;
     154             : }
     155             : 
     156           0 : unsigned FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi,
     157             :         enum isl_dim_type type)
     158             : {
     159           0 :         return multi ? isl_space_dim(multi->space, type) : 0;
     160             : }
     161             : 
     162             : /* Return the position of the first dimension of "type" with id "id".
     163             :  * Return -1 if there is no such dimension.
     164             :  */
     165           0 : int FN(MULTI(BASE),find_dim_by_id)(__isl_keep MULTI(BASE) *multi,
     166             :         enum isl_dim_type type, __isl_keep isl_id *id)
     167             : {
     168           0 :         if (!multi)
     169           0 :                 return -1;
     170           0 :         return isl_space_find_dim_by_id(multi->space, type, id);
     171             : }
     172             : 
     173             : /* Return the id of the given dimension.
     174             :  */
     175           0 : __isl_give isl_id *FN(MULTI(BASE),get_dim_id)(__isl_keep MULTI(BASE) *multi,
     176             :         enum isl_dim_type type, unsigned pos)
     177             : {
     178           0 :         return multi ? isl_space_get_dim_id(multi->space, type, pos) : NULL;
     179             : }
     180             : 
     181           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_name)(
     182             :         __isl_take MULTI(BASE) *multi,
     183             :         enum isl_dim_type type, unsigned pos, const char *s)
     184             : {
     185             :         int i;
     186             : 
     187           0 :         multi = FN(MULTI(BASE),cow)(multi);
     188           0 :         if (!multi)
     189           0 :                 return NULL;
     190             : 
     191           0 :         multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
     192           0 :         if (!multi->space)
     193           0 :                 return FN(MULTI(BASE),free)(multi);
     194             : 
     195           0 :         if (type == isl_dim_out)
     196           0 :                 return multi;
     197           0 :         for (i = 0; i < multi->n; ++i) {
     198           0 :                 multi->u.p[i] = FN(EL,set_dim_name)(multi->u.p[i],
     199             :                                                         type, pos, s);
     200           0 :                 if (!multi->u.p[i])
     201           0 :                         return FN(MULTI(BASE),free)(multi);
     202             :         }
     203             : 
     204           0 :         return multi;
     205             : }
     206             : 
     207           0 : const char *FN(MULTI(BASE),get_tuple_name)(__isl_keep MULTI(BASE) *multi,
     208             :         enum isl_dim_type type)
     209             : {
     210           0 :         return multi ? isl_space_get_tuple_name(multi->space, type) : NULL;
     211             : }
     212             : 
     213             : /* Does the specified tuple have an id?
     214             :  */
     215           0 : isl_bool FN(MULTI(BASE),has_tuple_id)(__isl_keep MULTI(BASE) *multi,
     216             :         enum isl_dim_type type)
     217             : {
     218           0 :         if (!multi)
     219           0 :                 return isl_bool_error;
     220           0 :         return isl_space_has_tuple_id(multi->space, type);
     221             : }
     222             : 
     223             : /* Return the id of the specified tuple.
     224             :  */
     225           0 : __isl_give isl_id *FN(MULTI(BASE),get_tuple_id)(__isl_keep MULTI(BASE) *multi,
     226             :         enum isl_dim_type type)
     227             : {
     228           0 :         return multi ? isl_space_get_tuple_id(multi->space, type) : NULL;
     229             : }
     230             : 
     231           0 : __isl_give EL *FN(FN(MULTI(BASE),get),BASE)(__isl_keep MULTI(BASE) *multi,
     232             :         int pos)
     233             : {
     234             :         isl_ctx *ctx;
     235             : 
     236           0 :         if (!multi)
     237           0 :                 return NULL;
     238           0 :         ctx = FN(MULTI(BASE),get_ctx)(multi);
     239           0 :         if (pos < 0 || pos >= multi->n)
     240           0 :                 isl_die(ctx, isl_error_invalid,
     241             :                         "index out of bounds", return NULL);
     242           0 :         return FN(EL,copy)(multi->u.p[pos]);
     243             : }
     244             : 
     245             : /* Set the element at position "pos" of "multi" to "el",
     246             :  * where the position may be empty if "multi" has only a single reference.
     247             :  */
     248           0 : static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore)(
     249             :         __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
     250             : {
     251           0 :         multi = FN(MULTI(BASE),cow)(multi);
     252           0 :         if (!multi || !el)
     253             :                 goto error;
     254             : 
     255           0 :         if (pos < 0 || pos >= multi->n)
     256           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
     257             :                         "index out of bounds", goto error);
     258             : 
     259           0 :         FN(EL,free)(multi->u.p[pos]);
     260           0 :         multi->u.p[pos] = el;
     261             : 
     262           0 :         return multi;
     263             : error:
     264           0 :         FN(MULTI(BASE),free)(multi);
     265           0 :         FN(EL,free)(el);
     266           0 :         return NULL;
     267             : }
     268             : 
     269             : /* Set the element at position "pos" of "multi" to "el",
     270             :  * where the position may be empty if "multi" has only a single reference.
     271             :  * However, the space of "multi" is available and is checked
     272             :  * for compatibility with "el".
     273             :  */
     274           0 : static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_check_space)(
     275             :         __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
     276             : {
     277             :         isl_space *space;
     278             : 
     279           0 :         space = FN(MULTI(BASE),peek_space)(multi);
     280           0 :         if (FN(EL,check_match_domain_space)(el, space) < 0)
     281           0 :                 multi = FN(MULTI(BASE),free)(multi);
     282           0 :         return FN(MULTI(BASE),restore)(multi, pos, el);
     283             : }
     284             : 
     285           0 : __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),set),BASE)(
     286             :         __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
     287             : {
     288           0 :         isl_space *multi_space = NULL;
     289           0 :         isl_space *el_space = NULL;
     290             :         isl_bool match;
     291             : 
     292           0 :         multi_space = FN(MULTI(BASE),get_space)(multi);
     293           0 :         match = FN(EL,matching_params)(el, multi_space);
     294           0 :         if (match < 0)
     295           0 :                 goto error;
     296           0 :         if (!match) {
     297           0 :                 multi = FN(MULTI(BASE),align_params)(multi,
     298             :                                                     FN(EL,get_space)(el));
     299           0 :                 isl_space_free(multi_space);
     300           0 :                 multi_space = FN(MULTI(BASE),get_space)(multi);
     301           0 :                 el = FN(EL,align_params)(el, isl_space_copy(multi_space));
     302             :         }
     303             : 
     304           0 :         multi = FN(MULTI(BASE),restore_check_space)(multi, pos, el);
     305             : 
     306           0 :         isl_space_free(multi_space);
     307           0 :         isl_space_free(el_space);
     308             : 
     309           0 :         return multi;
     310             : error:
     311           0 :         FN(MULTI(BASE),free)(multi);
     312           0 :         FN(EL,free)(el);
     313           0 :         isl_space_free(multi_space);
     314           0 :         isl_space_free(el_space);
     315           0 :         return NULL;
     316             : }
     317             : 
     318             : /* Reset the space of "multi".  This function is called from isl_pw_templ.c
     319             :  * and doesn't know if the space of an element object is represented
     320             :  * directly or through its domain.  It therefore passes along both,
     321             :  * which we pass along to the element function since we don't know how
     322             :  * that is represented either.
     323             :  *
     324             :  * If "multi" has an explicit domain, then the caller is expected
     325             :  * to make sure that any modification that would change the dimensions
     326             :  * of the explicit domain has bee applied before this function is called.
     327             :  */
     328           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space_and_domain)(
     329             :         __isl_take MULTI(BASE) *multi, __isl_take isl_space *space,
     330             :         __isl_take isl_space *domain)
     331             : {
     332             :         int i;
     333             : 
     334           0 :         multi = FN(MULTI(BASE),cow)(multi);
     335           0 :         if (!multi || !space || !domain)
     336             :                 goto error;
     337             : 
     338           0 :         for (i = 0; i < multi->n; ++i) {
     339           0 :                 multi->u.p[i] = FN(EL,reset_domain_space)(multi->u.p[i],
     340             :                                  isl_space_copy(domain));
     341           0 :                 if (!multi->u.p[i])
     342           0 :                         goto error;
     343             :         }
     344           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
     345           0 :                 multi = FN(MULTI(BASE),reset_explicit_domain_space)(multi,
     346             :                                                         isl_space_copy(domain));
     347           0 :                 if (!multi)
     348           0 :                         goto error;
     349             :         }
     350           0 :         isl_space_free(domain);
     351           0 :         isl_space_free(multi->space);
     352           0 :         multi->space = space;
     353             : 
     354           0 :         return multi;
     355             : error:
     356           0 :         isl_space_free(domain);
     357           0 :         isl_space_free(space);
     358           0 :         FN(MULTI(BASE),free)(multi);
     359           0 :         return NULL;
     360             : }
     361             : 
     362           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_domain_space)(
     363             :         __isl_take MULTI(BASE) *multi, __isl_take isl_space *domain)
     364             : {
     365             :         isl_space *space;
     366             : 
     367           0 :         space = isl_space_extend_domain_with_range(isl_space_copy(domain),
     368             :                                                 isl_space_copy(multi->space));
     369           0 :         return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
     370             : }
     371             : 
     372           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space)(
     373             :         __isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
     374             : {
     375             :         isl_space *domain;
     376             : 
     377           0 :         domain = isl_space_domain(isl_space_copy(space));
     378           0 :         return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
     379             : }
     380             : 
     381             : /* Set the id of the given dimension of "multi" to "id".
     382             :  */
     383           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_id)(
     384             :         __isl_take MULTI(BASE) *multi,
     385             :         enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
     386             : {
     387             :         isl_space *space;
     388             : 
     389           0 :         multi = FN(MULTI(BASE),cow)(multi);
     390           0 :         if (!multi || !id)
     391             :                 goto error;
     392             : 
     393           0 :         space = FN(MULTI(BASE),get_space)(multi);
     394           0 :         space = isl_space_set_dim_id(space, type, pos, id);
     395             : 
     396           0 :         return FN(MULTI(BASE),reset_space)(multi, space);
     397             : error:
     398           0 :         isl_id_free(id);
     399           0 :         FN(MULTI(BASE),free)(multi);
     400           0 :         return NULL;
     401             : }
     402             : 
     403           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_name)(
     404             :         __isl_keep MULTI(BASE) *multi, enum isl_dim_type type,
     405             :         const char *s)
     406             : {
     407             :         isl_space *space;
     408             : 
     409           0 :         multi = FN(MULTI(BASE),cow)(multi);
     410           0 :         if (!multi)
     411           0 :                 return NULL;
     412             : 
     413           0 :         space = FN(MULTI(BASE),get_space)(multi);
     414           0 :         space = isl_space_set_tuple_name(space, type, s);
     415             : 
     416           0 :         return FN(MULTI(BASE),reset_space)(multi, space);
     417             : }
     418             : 
     419           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_id)(
     420             :         __isl_take MULTI(BASE) *multi, enum isl_dim_type type,
     421             :         __isl_take isl_id *id)
     422             : {
     423             :         isl_space *space;
     424             : 
     425           0 :         multi = FN(MULTI(BASE),cow)(multi);
     426           0 :         if (!multi)
     427           0 :                 goto error;
     428             : 
     429           0 :         space = FN(MULTI(BASE),get_space)(multi);
     430           0 :         space = isl_space_set_tuple_id(space, type, id);
     431             : 
     432           0 :         return FN(MULTI(BASE),reset_space)(multi, space);
     433             : error:
     434           0 :         isl_id_free(id);
     435           0 :         return NULL;
     436             : }
     437             : 
     438             : /* Drop the id on the specified tuple.
     439             :  */
     440           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_tuple_id)(
     441             :         __isl_take MULTI(BASE) *multi, enum isl_dim_type type)
     442             : {
     443             :         isl_space *space;
     444             : 
     445           0 :         if (!multi)
     446           0 :                 return NULL;
     447           0 :         if (!FN(MULTI(BASE),has_tuple_id)(multi, type))
     448           0 :                 return multi;
     449             : 
     450           0 :         multi = FN(MULTI(BASE),cow)(multi);
     451           0 :         if (!multi)
     452           0 :                 return NULL;
     453             : 
     454           0 :         space = FN(MULTI(BASE),get_space)(multi);
     455           0 :         space = isl_space_reset_tuple_id(space, type);
     456             : 
     457           0 :         return FN(MULTI(BASE),reset_space)(multi, space);
     458             : }
     459             : 
     460             : /* Reset the user pointer on all identifiers of parameters and tuples
     461             :  * of the space of "multi".
     462             :  */
     463           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_user)(
     464             :         __isl_take MULTI(BASE) *multi)
     465             : {
     466             :         isl_space *space;
     467             : 
     468           0 :         space = FN(MULTI(BASE),get_space)(multi);
     469           0 :         space = isl_space_reset_user(space);
     470             : 
     471           0 :         return FN(MULTI(BASE),reset_space)(multi, space);
     472             : }
     473             : 
     474           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),realign_domain)(
     475             :         __isl_take MULTI(BASE) *multi, __isl_take isl_reordering *exp)
     476             : {
     477             :         int i;
     478             :         isl_space *space;
     479             : 
     480           0 :         multi = FN(MULTI(BASE),cow)(multi);
     481           0 :         if (!multi || !exp)
     482             :                 goto error;
     483             : 
     484           0 :         for (i = 0; i < multi->n; ++i) {
     485           0 :                 multi->u.p[i] = FN(EL,realign_domain)(multi->u.p[i],
     486             :                                                 isl_reordering_copy(exp));
     487           0 :                 if (!multi->u.p[i])
     488           0 :                         goto error;
     489             :         }
     490             : 
     491           0 :         space = isl_reordering_get_space(exp);
     492           0 :         multi = FN(MULTI(BASE),reset_domain_space)(multi, space);
     493             : 
     494           0 :         isl_reordering_free(exp);
     495           0 :         return multi;
     496             : error:
     497           0 :         isl_reordering_free(exp);
     498           0 :         FN(MULTI(BASE),free)(multi);
     499           0 :         return NULL;
     500             : }
     501             : 
     502             : /* Align the parameters of "multi" to those of "model".
     503             :  *
     504             :  * If "multi" has an explicit domain, then align the parameters
     505             :  * of the domain first.
     506             :  */
     507           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)(
     508             :         __isl_take MULTI(BASE) *multi, __isl_take isl_space *model)
     509             : {
     510             :         isl_ctx *ctx;
     511             :         isl_bool equal_params;
     512             :         isl_reordering *exp;
     513             : 
     514           0 :         if (!multi || !model)
     515             :                 goto error;
     516             : 
     517           0 :         equal_params = isl_space_has_equal_params(multi->space, model);
     518           0 :         if (equal_params < 0)
     519           0 :                 goto error;
     520           0 :         if (equal_params) {
     521           0 :                 isl_space_free(model);
     522           0 :                 return multi;
     523             :         }
     524             : 
     525           0 :         ctx = isl_space_get_ctx(model);
     526           0 :         if (!isl_space_has_named_params(model))
     527           0 :                 isl_die(ctx, isl_error_invalid,
     528             :                         "model has unnamed parameters", goto error);
     529           0 :         if (!isl_space_has_named_params(multi->space))
     530           0 :                 isl_die(ctx, isl_error_invalid,
     531             :                         "input has unnamed parameters", goto error);
     532             : 
     533           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
     534           0 :                 multi = FN(MULTI(BASE),align_explicit_domain_params)(multi,
     535             :                                                         isl_space_copy(model));
     536           0 :                 if (!multi)
     537           0 :                         goto error;
     538             :         }
     539           0 :         exp = isl_parameter_alignment_reordering(multi->space, model);
     540           0 :         exp = isl_reordering_extend_space(exp,
     541             :                                     FN(MULTI(BASE),get_domain_space)(multi));
     542           0 :         multi = FN(MULTI(BASE),realign_domain)(multi, exp);
     543             : 
     544           0 :         isl_space_free(model);
     545           0 :         return multi;
     546             : error:
     547           0 :         isl_space_free(model);
     548           0 :         FN(MULTI(BASE),free)(multi);
     549           0 :         return NULL;
     550             : }
     551             : 
     552             : /* Create a multi expression in the given space with the elements of "list"
     553             :  * as base expressions.
     554             :  *
     555             :  * Since isl_multi_*_restore_* assumes that the element and
     556             :  * the multi expression have matching spaces, the alignment
     557             :  * (if any) needs to be performed beforehand.
     558             :  */
     559           0 : __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))(
     560             :         __isl_take isl_space *space, __isl_take LIST(EL) *list)
     561             : {
     562             :         int i;
     563             :         int n;
     564             :         isl_ctx *ctx;
     565             :         MULTI(BASE) *multi;
     566             : 
     567           0 :         if (!space || !list)
     568             :                 goto error;
     569             : 
     570           0 :         ctx = isl_space_get_ctx(space);
     571           0 :         n = FN(FN(LIST(EL),n),BASE)(list);
     572           0 :         if (n != isl_space_dim(space, isl_dim_out))
     573           0 :                 isl_die(ctx, isl_error_invalid,
     574             :                         "invalid number of elements in list", goto error);
     575             : 
     576           0 :         for (i = 0; i < n; ++i) {
     577           0 :                 EL *el = FN(LIST(EL),peek)(list, i);
     578           0 :                 space = isl_space_align_params(space, FN(EL,get_space)(el));
     579             :         }
     580           0 :         multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
     581           0 :         for (i = 0; i < n; ++i) {
     582           0 :                 EL *el = FN(FN(LIST(EL),get),BASE)(list, i);
     583           0 :                 el = FN(EL,align_params)(el, isl_space_copy(space));
     584           0 :                 multi = FN(MULTI(BASE),restore_check_space)(multi, i, el);
     585             :         }
     586             : 
     587           0 :         isl_space_free(space);
     588           0 :         FN(LIST(EL),free)(list);
     589           0 :         return multi;
     590             : error:
     591           0 :         isl_space_free(space);
     592           0 :         FN(LIST(EL),free)(list);
     593           0 :         return NULL;
     594             : }
     595             : 
     596             : #ifndef NO_IDENTITY
     597             : /* Create a multi expression in the given space that maps each
     598             :  * input dimension to the corresponding output dimension.
     599             :  */
     600           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),identity)(__isl_take isl_space *space)
     601             : {
     602             :         int i, n;
     603             :         isl_local_space *ls;
     604             :         MULTI(BASE) *multi;
     605             : 
     606           0 :         if (!space)
     607           0 :                 return NULL;
     608             : 
     609           0 :         if (isl_space_is_set(space))
     610           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
     611             :                         "expecting map space", goto error);
     612             : 
     613           0 :         n = isl_space_dim(space, isl_dim_out);
     614           0 :         if (n != isl_space_dim(space, isl_dim_in))
     615           0 :                 isl_die(isl_space_get_ctx(space), isl_error_invalid,
     616             :                         "number of input and output dimensions needs to be "
     617             :                         "the same", goto error);
     618             : 
     619           0 :         multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
     620             : 
     621           0 :         if (!n) {
     622           0 :                 isl_space_free(space);
     623           0 :                 return multi;
     624             :         }
     625             : 
     626           0 :         space = isl_space_domain(space);
     627           0 :         ls = isl_local_space_from_space(space);
     628             : 
     629           0 :         for (i = 0; i < n; ++i) {
     630             :                 EL *el;
     631           0 :                 el = FN(EL,var_on_domain)(isl_local_space_copy(ls),
     632             :                                                 isl_dim_set, i);
     633           0 :                 multi = FN(FN(MULTI(BASE),set),BASE)(multi, i, el);
     634             :         }
     635             : 
     636           0 :         isl_local_space_free(ls);
     637             : 
     638           0 :         return multi;
     639             : error:
     640           0 :         isl_space_free(space);
     641           0 :         return NULL;
     642             : }
     643             : #endif
     644             : 
     645             : #ifndef NO_ZERO
     646             : /* Construct a multi expression in the given space with value zero in
     647             :  * each of the output dimensions.
     648             :  */
     649           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),zero)(__isl_take isl_space *space)
     650             : {
     651             :         int n;
     652             :         MULTI(BASE) *multi;
     653             : 
     654           0 :         if (!space)
     655           0 :                 return NULL;
     656             : 
     657           0 :         n = isl_space_dim(space , isl_dim_out);
     658           0 :         multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
     659             : 
     660           0 :         if (!n)
     661           0 :                 isl_space_free(space);
     662             :         else {
     663             :                 int i;
     664             :                 isl_local_space *ls;
     665             :                 EL *el;
     666             : 
     667           0 :                 space = isl_space_domain(space);
     668           0 :                 ls = isl_local_space_from_space(space);
     669           0 :                 el = FN(EL,zero_on_domain)(ls);
     670             : 
     671           0 :                 for (i = 0; i < n; ++i)
     672           0 :                         multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
     673             :                                                             FN(EL,copy)(el));
     674             : 
     675           0 :                 FN(EL,free)(el);
     676             :         }
     677             : 
     678           0 :         return multi;
     679             : }
     680             : #endif
     681             : 
     682             : #ifndef NO_FROM_BASE
     683             : /* Create a multiple expression with a single output/set dimension
     684             :  * equal to "el".
     685             :  * For most multiple expression types, the base type has a single
     686             :  * output/set dimension and the space of the result is therefore
     687             :  * the same as the space of the input.
     688             :  * In the case of isl_multi_union_pw_aff, however, the base type
     689             :  * lives in a parameter space and we therefore need to add
     690             :  * a single set dimension.
     691             :  */
     692           0 : __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
     693             : {
     694             :         isl_space *space;
     695             :         MULTI(BASE) *multi;
     696             : 
     697           0 :         space = FN(EL,get_space(el));
     698           0 :         if (isl_space_is_params(space)) {
     699           0 :                 space = isl_space_set_from_params(space);
     700           0 :                 space = isl_space_add_dims(space, isl_dim_set, 1);
     701             :         }
     702           0 :         multi = FN(MULTI(BASE),alloc)(space);
     703           0 :         multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
     704             : 
     705           0 :         return multi;
     706             : }
     707             : #endif
     708             : 
     709           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
     710             :         __isl_take MULTI(BASE) *multi,
     711             :         enum isl_dim_type type, unsigned first, unsigned n)
     712             : {
     713             :         int i;
     714             :         unsigned dim;
     715             : 
     716           0 :         multi = FN(MULTI(BASE),cow)(multi);
     717           0 :         if (!multi)
     718           0 :                 return NULL;
     719             : 
     720           0 :         dim = FN(MULTI(BASE),dim)(multi, type);
     721           0 :         if (first + n > dim || first + n < first)
     722           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
     723             :                         "index out of bounds",
     724             :                         return FN(MULTI(BASE),free)(multi));
     725             : 
     726           0 :         multi->space = isl_space_drop_dims(multi->space, type, first, n);
     727           0 :         if (!multi->space)
     728           0 :                 return FN(MULTI(BASE),free)(multi);
     729             : 
     730           0 :         if (type == isl_dim_out) {
     731           0 :                 for (i = 0; i < n; ++i)
     732           0 :                         FN(EL,free)(multi->u.p[first + i]);
     733           0 :                 for (i = first; i + n < multi->n; ++i)
     734           0 :                         multi->u.p[i] = multi->u.p[i + n];
     735           0 :                 multi->n -= n;
     736           0 :                 if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi))
     737           0 :                         multi = FN(MULTI(BASE),init_explicit_domain)(multi);
     738             : 
     739           0 :                 return multi;
     740             :         }
     741             : 
     742           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi))
     743           0 :                 multi = FN(MULTI(BASE),drop_explicit_domain_dims)(multi,
     744             :                                                                 type, first, n);
     745           0 :         if (!multi)
     746           0 :                 return NULL;
     747             : 
     748           0 :         for (i = 0; i < multi->n; ++i) {
     749           0 :                 multi->u.p[i] = FN(EL,drop_dims)(multi->u.p[i], type, first, n);
     750           0 :                 if (!multi->u.p[i])
     751           0 :                         return FN(MULTI(BASE),free)(multi);
     752             :         }
     753             : 
     754           0 :         return multi;
     755             : }
     756             : 
     757             : /* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
     758             :  */
     759           0 : static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_multi_and)(
     760             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
     761             :         __isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi1,
     762             :                 __isl_take MULTI(BASE) *multi2))
     763             : {
     764             :         isl_ctx *ctx;
     765             :         isl_bool equal_params;
     766             : 
     767           0 :         if (!multi1 || !multi2)
     768             :                 goto error;
     769           0 :         equal_params = isl_space_has_equal_params(multi1->space, multi2->space);
     770           0 :         if (equal_params < 0)
     771           0 :                 goto error;
     772           0 :         if (equal_params)
     773           0 :                 return fn(multi1, multi2);
     774           0 :         ctx = FN(MULTI(BASE),get_ctx)(multi1);
     775           0 :         if (!isl_space_has_named_params(multi1->space) ||
     776           0 :             !isl_space_has_named_params(multi2->space))
     777           0 :                 isl_die(ctx, isl_error_invalid,
     778             :                         "unaligned unnamed parameters", goto error);
     779           0 :         multi1 = FN(MULTI(BASE),align_params)(multi1,
     780             :                                             FN(MULTI(BASE),get_space)(multi2));
     781           0 :         multi2 = FN(MULTI(BASE),align_params)(multi2,
     782             :                                             FN(MULTI(BASE),get_space)(multi1));
     783           0 :         return fn(multi1, multi2);
     784             : error:
     785           0 :         FN(MULTI(BASE),free)(multi1);
     786           0 :         FN(MULTI(BASE),free)(multi2);
     787           0 :         return NULL;
     788             : }
     789             : 
     790             : /* Given two MULTI(BASE)s A -> B and C -> D,
     791             :  * construct a MULTI(BASE) (A * C) -> [B -> D].
     792             :  *
     793             :  * The parameters are assumed to have been aligned.
     794             :  *
     795             :  * If "multi1" and/or "multi2" has an explicit domain, then
     796             :  * intersect the domain of the result with these explicit domains.
     797             :  */
     798           0 : static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
     799             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
     800             : {
     801             :         int i, n1, n2;
     802             :         EL *el;
     803             :         isl_space *space;
     804             :         MULTI(BASE) *res;
     805             : 
     806           0 :         if (!multi1 || !multi2)
     807             :                 goto error;
     808             : 
     809           0 :         space = isl_space_range_product(FN(MULTI(BASE),get_space)(multi1),
     810             :                                         FN(MULTI(BASE),get_space)(multi2));
     811           0 :         res = FN(MULTI(BASE),alloc)(space);
     812             : 
     813           0 :         n1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
     814           0 :         n2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
     815             : 
     816           0 :         for (i = 0; i < n1; ++i) {
     817           0 :                 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
     818           0 :                 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
     819             :         }
     820             : 
     821           0 :         for (i = 0; i < n2; ++i) {
     822           0 :                 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
     823           0 :                 res = FN(FN(MULTI(BASE),set),BASE)(res, n1 + i, el);
     824             :         }
     825             : 
     826           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi1))
     827           0 :                 res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi1);
     828           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi2))
     829           0 :                 res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi2);
     830             : 
     831           0 :         FN(MULTI(BASE),free)(multi1);
     832           0 :         FN(MULTI(BASE),free)(multi2);
     833           0 :         return res;
     834             : error:
     835           0 :         FN(MULTI(BASE),free)(multi1);
     836           0 :         FN(MULTI(BASE),free)(multi2);
     837           0 :         return NULL;
     838             : }
     839             : 
     840             : /* Given two MULTI(BASE)s A -> B and C -> D,
     841             :  * construct a MULTI(BASE) (A * C) -> [B -> D].
     842             :  */
     843           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)(
     844             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
     845             : {
     846           0 :         return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
     847             :                                         &FN(MULTI(BASE),range_product_aligned));
     848             : }
     849             : 
     850             : /* Is the range of "multi" a wrapped relation?
     851             :  */
     852           0 : isl_bool FN(MULTI(BASE),range_is_wrapping)(__isl_keep MULTI(BASE) *multi)
     853             : {
     854           0 :         if (!multi)
     855           0 :                 return isl_bool_error;
     856           0 :         return isl_space_range_is_wrapping(multi->space);
     857             : }
     858             : 
     859             : /* Given a function A -> [B -> C], extract the function A -> B.
     860             :  */
     861           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_domain)(
     862             :         __isl_take MULTI(BASE) *multi)
     863             : {
     864             :         isl_space *space;
     865             :         int total, keep;
     866             : 
     867           0 :         if (!multi)
     868           0 :                 return NULL;
     869           0 :         if (!isl_space_range_is_wrapping(multi->space))
     870           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
     871             :                         "range is not a product",
     872             :                         return FN(MULTI(BASE),free)(multi));
     873             : 
     874           0 :         space = FN(MULTI(BASE),get_space)(multi);
     875           0 :         total = isl_space_dim(space, isl_dim_out);
     876           0 :         space = isl_space_range_factor_domain(space);
     877           0 :         keep = isl_space_dim(space, isl_dim_out);
     878           0 :         multi = FN(MULTI(BASE),drop_dims)(multi,
     879           0 :                                         isl_dim_out, keep, total - keep);
     880           0 :         multi = FN(MULTI(BASE),reset_space)(multi, space);
     881             : 
     882           0 :         return multi;
     883             : }
     884             : 
     885             : /* Given a function A -> [B -> C], extract the function A -> C.
     886             :  */
     887           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)(
     888             :         __isl_take MULTI(BASE) *multi)
     889             : {
     890             :         isl_space *space;
     891             :         int total, keep;
     892             : 
     893           0 :         if (!multi)
     894           0 :                 return NULL;
     895           0 :         if (!isl_space_range_is_wrapping(multi->space))
     896           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
     897             :                         "range is not a product",
     898             :                         return FN(MULTI(BASE),free)(multi));
     899             : 
     900           0 :         space = FN(MULTI(BASE),get_space)(multi);
     901           0 :         total = isl_space_dim(space, isl_dim_out);
     902           0 :         space = isl_space_range_factor_range(space);
     903           0 :         keep = isl_space_dim(space, isl_dim_out);
     904           0 :         multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
     905           0 :         multi = FN(MULTI(BASE),reset_space)(multi, space);
     906             : 
     907           0 :         return multi;
     908             : }
     909             : 
     910             : /* Given a function [B -> C], extract the function C.
     911             :  */
     912           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
     913             :         __isl_take MULTI(BASE) *multi)
     914             : {
     915             :         isl_space *space;
     916             :         int total, keep;
     917             : 
     918           0 :         if (!multi)
     919           0 :                 return NULL;
     920           0 :         if (!isl_space_is_wrapping(multi->space))
     921           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
     922             :                         "not a product", return FN(MULTI(BASE),free)(multi));
     923             : 
     924           0 :         space = FN(MULTI(BASE),get_space)(multi);
     925           0 :         total = isl_space_dim(space, isl_dim_out);
     926           0 :         space = isl_space_factor_range(space);
     927           0 :         keep = isl_space_dim(space, isl_dim_out);
     928           0 :         multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep);
     929           0 :         multi = FN(MULTI(BASE),reset_space)(multi, space);
     930             : 
     931           0 :         return multi;
     932             : }
     933             : 
     934             : #ifndef NO_PRODUCT
     935             : /* Given two MULTI(BASE)s A -> B and C -> D,
     936             :  * construct a MULTI(BASE) [A -> C] -> [B -> D].
     937             :  *
     938             :  * The parameters are assumed to have been aligned.
     939             :  *
     940             :  * If "multi1" and/or "multi2" has an explicit domain, then
     941             :  * intersect the domain of the result with these explicit domains.
     942             :  */
     943           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
     944             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
     945             : {
     946             :         int i;
     947             :         EL *el;
     948             :         isl_space *space;
     949             :         MULTI(BASE) *res;
     950             :         int in1, in2, out1, out2;
     951             : 
     952           0 :         in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
     953           0 :         in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
     954           0 :         out1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
     955           0 :         out2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
     956           0 :         space = isl_space_product(FN(MULTI(BASE),get_space)(multi1),
     957             :                                   FN(MULTI(BASE),get_space)(multi2));
     958           0 :         res = FN(MULTI(BASE),alloc)(isl_space_copy(space));
     959           0 :         space = isl_space_domain(space);
     960             : 
     961           0 :         for (i = 0; i < out1; ++i) {
     962           0 :                 el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
     963           0 :                 el = FN(EL,insert_dims)(el, isl_dim_in, in1, in2);
     964           0 :                 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
     965           0 :                 res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
     966             :         }
     967             : 
     968           0 :         for (i = 0; i < out2; ++i) {
     969           0 :                 el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
     970           0 :                 el = FN(EL,insert_dims)(el, isl_dim_in, 0, in1);
     971           0 :                 el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
     972           0 :                 res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
     973             :         }
     974             : 
     975           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
     976           0 :             FN(MULTI(BASE),has_explicit_domain)(multi2))
     977           0 :                 res = FN(MULTI(BASE),intersect_explicit_domain_product)(res,
     978             :                                                                 multi1, multi2);
     979             : 
     980           0 :         isl_space_free(space);
     981           0 :         FN(MULTI(BASE),free)(multi1);
     982           0 :         FN(MULTI(BASE),free)(multi2);
     983           0 :         return res;
     984             : }
     985             : 
     986             : /* Given two MULTI(BASE)s A -> B and C -> D,
     987             :  * construct a MULTI(BASE) [A -> C] -> [B -> D].
     988             :  */
     989           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),product)(
     990             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
     991             : {
     992           0 :         return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
     993             :                                         &FN(MULTI(BASE),product_aligned));
     994             : }
     995             : #endif
     996             : 
     997           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
     998             :         __isl_take MULTI(BASE) *multi)
     999             : {
    1000           0 :         if (!multi)
    1001           0 :                 return NULL;
    1002             : 
    1003           0 :         if (!multi->space->nested[1])
    1004           0 :                 return multi;
    1005             : 
    1006           0 :         multi = FN(MULTI(BASE),cow)(multi);
    1007           0 :         if (!multi)
    1008           0 :                 return NULL;
    1009             : 
    1010           0 :         multi->space = isl_space_flatten_range(multi->space);
    1011           0 :         if (!multi->space)
    1012           0 :                 return FN(MULTI(BASE),free)(multi);
    1013             : 
    1014           0 :         return multi;
    1015             : }
    1016             : 
    1017             : /* Given two MULTI(BASE)s A -> B and C -> D,
    1018             :  * construct a MULTI(BASE) (A * C) -> (B, D).
    1019             :  */
    1020           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),flat_range_product)(
    1021             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
    1022             : {
    1023             :         MULTI(BASE) *multi;
    1024             : 
    1025           0 :         multi = FN(MULTI(BASE),range_product)(multi1, multi2);
    1026           0 :         multi = FN(MULTI(BASE),flatten_range)(multi);
    1027           0 :         return multi;
    1028             : }
    1029             : 
    1030             : /* Given two multi expressions, "multi1"
    1031             :  *
    1032             :  *      [A] -> [B1 B2]
    1033             :  *
    1034             :  * where B2 starts at position "pos", and "multi2"
    1035             :  *
    1036             :  *      [A] -> [D]
    1037             :  *
    1038             :  * return the multi expression
    1039             :  *
    1040             :  *      [A] -> [B1 D B2]
    1041             :  */
    1042           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
    1043             :         __isl_take MULTI(BASE) *multi1, unsigned pos,
    1044             :         __isl_take MULTI(BASE) *multi2)
    1045             : {
    1046             :         MULTI(BASE) *res;
    1047             :         unsigned dim;
    1048             : 
    1049           0 :         if (!multi1 || !multi2)
    1050             :                 goto error;
    1051             : 
    1052           0 :         dim = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
    1053           0 :         if (pos > dim)
    1054           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
    1055             :                         "index out of bounds", goto error);
    1056             : 
    1057           0 :         res = FN(MULTI(BASE),copy)(multi1);
    1058           0 :         res = FN(MULTI(BASE),drop_dims)(res, isl_dim_out, pos, dim - pos);
    1059           0 :         multi1 = FN(MULTI(BASE),drop_dims)(multi1, isl_dim_out, 0, pos);
    1060             : 
    1061           0 :         res = FN(MULTI(BASE),flat_range_product)(res, multi2);
    1062           0 :         res = FN(MULTI(BASE),flat_range_product)(res, multi1);
    1063             : 
    1064           0 :         return res;
    1065             : error:
    1066           0 :         FN(MULTI(BASE),free)(multi1);
    1067           0 :         FN(MULTI(BASE),free)(multi2);
    1068           0 :         return NULL;
    1069             : }
    1070             : 
    1071             : #ifndef NO_SPLICE
    1072             : /* Given two multi expressions, "multi1"
    1073             :  *
    1074             :  *      [A1 A2] -> [B1 B2]
    1075             :  *
    1076             :  * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
    1077             :  * and "multi2"
    1078             :  *
    1079             :  *      [C] -> [D]
    1080             :  *
    1081             :  * return the multi expression
    1082             :  *
    1083             :  *      [A1 C A2] -> [B1 D B2]
    1084             :  *
    1085             :  * We first insert input dimensions to obtain
    1086             :  *
    1087             :  *      [A1 C A2] -> [B1 B2]
    1088             :  *
    1089             :  * and
    1090             :  *
    1091             :  *      [A1 C A2] -> [D]
    1092             :  *
    1093             :  * and then apply range_splice.
    1094             :  */
    1095           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),splice)(
    1096             :         __isl_take MULTI(BASE) *multi1, unsigned in_pos, unsigned out_pos,
    1097             :         __isl_take MULTI(BASE) *multi2)
    1098             : {
    1099             :         unsigned n_in1;
    1100             :         unsigned n_in2;
    1101             : 
    1102           0 :         if (!multi1 || !multi2)
    1103             :                 goto error;
    1104             : 
    1105           0 :         n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
    1106           0 :         if (in_pos > n_in1)
    1107           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
    1108             :                         "index out of bounds", goto error);
    1109             : 
    1110           0 :         n_in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
    1111             : 
    1112           0 :         multi1 = FN(MULTI(BASE),insert_dims)(multi1, isl_dim_in, in_pos, n_in2);
    1113           0 :         multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, n_in2,
    1114             :                                                 n_in1 - in_pos);
    1115           0 :         multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, 0, in_pos);
    1116             : 
    1117           0 :         return FN(MULTI(BASE),range_splice)(multi1, out_pos, multi2);
    1118             : error:
    1119           0 :         FN(MULTI(BASE),free)(multi1);
    1120           0 :         FN(MULTI(BASE),free)(multi2);
    1121           0 :         return NULL;
    1122             : }
    1123             : #endif
    1124             : 
    1125             : /* Check that "multi1" and "multi2" live in the same space,
    1126             :  * reporting an error if they do not.
    1127             :  */
    1128           0 : static isl_stat FN(MULTI(BASE),check_equal_space)(
    1129             :         __isl_keep MULTI(BASE) *multi1, __isl_keep MULTI(BASE) *multi2)
    1130             : {
    1131             :         isl_bool equal;
    1132             : 
    1133           0 :         if (!multi1 || !multi2)
    1134           0 :                 return isl_stat_error;
    1135             : 
    1136           0 :         equal = isl_space_is_equal(multi1->space, multi2->space);
    1137           0 :         if (equal < 0)
    1138           0 :                 return isl_stat_error;
    1139           0 :         if (!equal)
    1140           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
    1141             :                         "spaces don't match", return isl_stat_error);
    1142             : 
    1143           0 :         return isl_stat_ok;
    1144             : }
    1145             : 
    1146             : /* This function is currently only used from isl_aff.c
    1147             :  */
    1148             : static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
    1149             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
    1150             :         __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
    1151             :         __attribute__ ((unused));
    1152             : 
    1153             : /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
    1154             :  * return the result.
    1155             :  *
    1156             :  * If "multi2" has an explicit domain, then
    1157             :  * intersect the domain of the result with this explicit domain.
    1158             :  */
    1159           0 : static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
    1160             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
    1161             :         __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
    1162             : {
    1163             :         int i;
    1164             : 
    1165           0 :         multi1 = FN(MULTI(BASE),cow)(multi1);
    1166           0 :         if (FN(MULTI(BASE),check_equal_space)(multi1, multi2) < 0)
    1167           0 :                 goto error;
    1168             : 
    1169           0 :         for (i = 0; i < multi1->n; ++i) {
    1170           0 :                 multi1->u.p[i] = fn(multi1->u.p[i],
    1171             :                                                 FN(EL,copy)(multi2->u.p[i]));
    1172           0 :                 if (!multi1->u.p[i])
    1173           0 :                         goto error;
    1174             :         }
    1175             : 
    1176           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi2))
    1177           0 :                 multi1 = FN(MULTI(BASE),intersect_explicit_domain)(multi1,
    1178             :                                                                     multi2);
    1179             : 
    1180           0 :         FN(MULTI(BASE),free)(multi2);
    1181           0 :         return multi1;
    1182             : error:
    1183           0 :         FN(MULTI(BASE),free)(multi1);
    1184           0 :         FN(MULTI(BASE),free)(multi2);
    1185           0 :         return NULL;
    1186             : }
    1187             : 
    1188             : /* Add "multi2" from "multi1" and return the result.
    1189             :  *
    1190             :  * The parameters of "multi1" and "multi2" are assumed to have been aligned.
    1191             :  */
    1192           0 : static __isl_give MULTI(BASE) *FN(MULTI(BASE),add_aligned)(
    1193             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
    1194             : {
    1195           0 :         return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,add));
    1196             : }
    1197             : 
    1198             : /* Add "multi2" from "multi1" and return the result.
    1199             :  */
    1200           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),add)(__isl_take MULTI(BASE) *multi1,
    1201             :         __isl_take MULTI(BASE) *multi2)
    1202             : {
    1203           0 :         return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
    1204             :                                                 &FN(MULTI(BASE),add_aligned));
    1205             : }
    1206             : 
    1207             : /* Subtract "multi2" from "multi1" and return the result.
    1208             :  *
    1209             :  * The parameters of "multi1" and "multi2" are assumed to have been aligned.
    1210             :  */
    1211           0 : static __isl_give MULTI(BASE) *FN(MULTI(BASE),sub_aligned)(
    1212             :         __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
    1213             : {
    1214           0 :         return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
    1215             : }
    1216             : 
    1217             : /* Subtract "multi2" from "multi1" and return the result.
    1218             :  */
    1219           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
    1220             :         __isl_take MULTI(BASE) *multi2)
    1221             : {
    1222           0 :         return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
    1223             :                                                 &FN(MULTI(BASE),sub_aligned));
    1224             : }
    1225             : 
    1226             : /* Multiply the elements of "multi" by "v" and return the result.
    1227             :  */
    1228           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
    1229             :         __isl_take isl_val *v)
    1230             : {
    1231             :         int i;
    1232             : 
    1233           0 :         if (!multi || !v)
    1234             :                 goto error;
    1235             : 
    1236           0 :         if (isl_val_is_one(v)) {
    1237           0 :                 isl_val_free(v);
    1238           0 :                 return multi;
    1239             :         }
    1240             : 
    1241           0 :         if (!isl_val_is_rat(v))
    1242           0 :                 isl_die(isl_val_get_ctx(v), isl_error_invalid,
    1243             :                         "expecting rational factor", goto error);
    1244             : 
    1245           0 :         multi = FN(MULTI(BASE),cow)(multi);
    1246           0 :         if (!multi)
    1247           0 :                 return NULL;
    1248             : 
    1249           0 :         for (i = 0; i < multi->n; ++i) {
    1250           0 :                 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i],
    1251             :                                                 isl_val_copy(v));
    1252           0 :                 if (!multi->u.p[i])
    1253           0 :                         goto error;
    1254             :         }
    1255             : 
    1256           0 :         isl_val_free(v);
    1257           0 :         return multi;
    1258             : error:
    1259           0 :         isl_val_free(v);
    1260           0 :         return FN(MULTI(BASE),free)(multi);
    1261             : }
    1262             : 
    1263             : /* Divide the elements of "multi" by "v" and return the result.
    1264             :  */
    1265           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
    1266             :         __isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
    1267             : {
    1268             :         int i;
    1269             : 
    1270           0 :         if (!multi || !v)
    1271             :                 goto error;
    1272             : 
    1273           0 :         if (isl_val_is_one(v)) {
    1274           0 :                 isl_val_free(v);
    1275           0 :                 return multi;
    1276             :         }
    1277             : 
    1278           0 :         if (!isl_val_is_rat(v))
    1279           0 :                 isl_die(isl_val_get_ctx(v), isl_error_invalid,
    1280             :                         "expecting rational factor", goto error);
    1281           0 :         if (isl_val_is_zero(v))
    1282           0 :                 isl_die(isl_val_get_ctx(v), isl_error_invalid,
    1283             :                         "cannot scale down by zero", goto error);
    1284             : 
    1285           0 :         multi = FN(MULTI(BASE),cow)(multi);
    1286           0 :         if (!multi)
    1287           0 :                 return NULL;
    1288             : 
    1289           0 :         for (i = 0; i < multi->n; ++i) {
    1290           0 :                 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i],
    1291             :                                                     isl_val_copy(v));
    1292           0 :                 if (!multi->u.p[i])
    1293           0 :                         goto error;
    1294             :         }
    1295             : 
    1296           0 :         isl_val_free(v);
    1297           0 :         return multi;
    1298             : error:
    1299           0 :         isl_val_free(v);
    1300           0 :         return FN(MULTI(BASE),free)(multi);
    1301             : }
    1302             : 
    1303             : /* Multiply the elements of "multi" by the corresponding element of "mv"
    1304             :  * and return the result.
    1305             :  */
    1306           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
    1307             :         __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
    1308             : {
    1309             :         int i;
    1310             : 
    1311           0 :         if (!multi || !mv)
    1312             :                 goto error;
    1313             : 
    1314           0 :         if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
    1315             :                                         mv->space, isl_dim_set))
    1316           0 :                 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
    1317             :                         "spaces don't match", goto error);
    1318             : 
    1319           0 :         multi = FN(MULTI(BASE),cow)(multi);
    1320           0 :         if (!multi)
    1321           0 :                 goto error;
    1322             : 
    1323           0 :         for (i = 0; i < multi->n; ++i) {
    1324             :                 isl_val *v;
    1325             : 
    1326           0 :                 v = isl_multi_val_get_val(mv, i);
    1327           0 :                 multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i], v);
    1328           0 :                 if (!multi->u.p[i])
    1329           0 :                         goto error;
    1330             :         }
    1331             : 
    1332           0 :         isl_multi_val_free(mv);
    1333           0 :         return multi;
    1334             : error:
    1335           0 :         isl_multi_val_free(mv);
    1336           0 :         return FN(MULTI(BASE),free)(multi);
    1337             : }
    1338             : 
    1339             : /* Divide the elements of "multi" by the corresponding element of "mv"
    1340             :  * and return the result.
    1341             :  */
    1342           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
    1343             :         __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
    1344             : {
    1345             :         int i;
    1346             : 
    1347           0 :         if (!multi || !mv)
    1348             :                 goto error;
    1349             : 
    1350           0 :         if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
    1351             :                                         mv->space, isl_dim_set))
    1352           0 :                 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
    1353             :                         "spaces don't match", goto error);
    1354             : 
    1355           0 :         multi = FN(MULTI(BASE),cow)(multi);
    1356           0 :         if (!multi)
    1357           0 :                 return NULL;
    1358             : 
    1359           0 :         for (i = 0; i < multi->n; ++i) {
    1360             :                 isl_val *v;
    1361             : 
    1362           0 :                 v = isl_multi_val_get_val(mv, i);
    1363           0 :                 multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i], v);
    1364           0 :                 if (!multi->u.p[i])
    1365           0 :                         goto error;
    1366             :         }
    1367             : 
    1368           0 :         isl_multi_val_free(mv);
    1369           0 :         return multi;
    1370             : error:
    1371           0 :         isl_multi_val_free(mv);
    1372           0 :         return FN(MULTI(BASE),free)(multi);
    1373             : }
    1374             : 
    1375             : /* Compute the residues of the elements of "multi" modulo
    1376             :  * the corresponding element of "mv" and return the result.
    1377             :  */
    1378           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
    1379             :         __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
    1380             : {
    1381             :         int i;
    1382             : 
    1383           0 :         if (!multi || !mv)
    1384             :                 goto error;
    1385             : 
    1386           0 :         if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
    1387             :                                         mv->space, isl_dim_set))
    1388           0 :                 isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
    1389             :                         "spaces don't match", goto error);
    1390             : 
    1391           0 :         multi = FN(MULTI(BASE),cow)(multi);
    1392           0 :         if (!multi)
    1393           0 :                 goto error;
    1394             : 
    1395           0 :         for (i = 0; i < multi->n; ++i) {
    1396             :                 isl_val *v;
    1397             : 
    1398           0 :                 v = isl_multi_val_get_val(mv, i);
    1399           0 :                 multi->u.p[i] = FN(EL,mod_val)(multi->u.p[i], v);
    1400           0 :                 if (!multi->u.p[i])
    1401           0 :                         goto error;
    1402             :         }
    1403             : 
    1404           0 :         isl_multi_val_free(mv);
    1405           0 :         return multi;
    1406             : error:
    1407           0 :         isl_multi_val_free(mv);
    1408           0 :         return FN(MULTI(BASE),free)(multi);
    1409             : }
    1410             : 
    1411             : #ifndef NO_MOVE_DIMS
    1412             : /* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
    1413             :  * to dimensions of "dst_type" at "dst_pos".
    1414             :  *
    1415             :  * We only support moving input dimensions to parameters and vice versa.
    1416             :  */
    1417           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
    1418             :         enum isl_dim_type dst_type, unsigned dst_pos,
    1419             :         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
    1420             : {
    1421             :         int i;
    1422             : 
    1423           0 :         if (!multi)
    1424           0 :                 return NULL;
    1425             : 
    1426           0 :         if (n == 0 &&
    1427           0 :             !isl_space_is_named_or_nested(multi->space, src_type) &&
    1428           0 :             !isl_space_is_named_or_nested(multi->space, dst_type))
    1429           0 :                 return multi;
    1430             : 
    1431           0 :         if (dst_type == isl_dim_out || src_type == isl_dim_out)
    1432           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
    1433             :                         "cannot move output/set dimension",
    1434             :                         return FN(MULTI(BASE),free)(multi));
    1435           0 :         if (dst_type == isl_dim_div || src_type == isl_dim_div)
    1436           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
    1437             :                         "cannot move divs",
    1438             :                         return FN(MULTI(BASE),free)(multi));
    1439           0 :         if (src_pos + n > isl_space_dim(multi->space, src_type))
    1440           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
    1441             :                         "range out of bounds",
    1442             :                         return FN(MULTI(BASE),free)(multi));
    1443           0 :         if (dst_type == src_type)
    1444           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_unsupported,
    1445             :                         "moving dims within the same type not supported",
    1446             :                         return FN(MULTI(BASE),free)(multi));
    1447             : 
    1448           0 :         multi = FN(MULTI(BASE),cow)(multi);
    1449           0 :         if (!multi)
    1450           0 :                 return NULL;
    1451             : 
    1452           0 :         multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
    1453             :                                                 src_type, src_pos, n);
    1454           0 :         if (!multi->space)
    1455           0 :                 return FN(MULTI(BASE),free)(multi);
    1456           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi))
    1457           0 :                 multi = FN(MULTI(BASE),move_explicit_domain_dims)(multi,
    1458             :                                 dst_type, dst_pos, src_type, src_pos, n);
    1459           0 :         if (!multi)
    1460           0 :                 return NULL;
    1461             : 
    1462           0 :         for (i = 0; i < multi->n; ++i) {
    1463           0 :                 multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
    1464             :                                                 dst_type, dst_pos,
    1465             :                                                 src_type, src_pos, n);
    1466           0 :                 if (!multi->u.p[i])
    1467           0 :                         return FN(MULTI(BASE),free)(multi);
    1468             :         }
    1469             : 
    1470           0 :         return multi;
    1471             : }
    1472             : #endif
    1473             : 
    1474             : /* Convert a multiple expression defined over a parameter domain
    1475             :  * into one that is defined over a zero-dimensional set.
    1476             :  */
    1477           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),from_range)(
    1478             :         __isl_take MULTI(BASE) *multi)
    1479             : {
    1480             :         isl_space *space;
    1481             : 
    1482           0 :         if (!multi)
    1483           0 :                 return NULL;
    1484           0 :         if (!isl_space_is_set(multi->space))
    1485           0 :                 isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
    1486             :                         "not living in a set space",
    1487             :                         return FN(MULTI(BASE),free)(multi));
    1488             : 
    1489           0 :         space = FN(MULTI(BASE),get_space)(multi);
    1490           0 :         space = isl_space_from_range(space);
    1491           0 :         multi = FN(MULTI(BASE),reset_space)(multi, space);
    1492             : 
    1493           0 :         return multi;
    1494             : }
    1495             : 
    1496             : /* Are "multi1" and "multi2" obviously equal?
    1497             :  */
    1498           0 : isl_bool FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1,
    1499             :         __isl_keep MULTI(BASE) *multi2)
    1500             : {
    1501             :         int i;
    1502             :         isl_bool equal;
    1503             : 
    1504           0 :         if (!multi1 || !multi2)
    1505           0 :                 return isl_bool_error;
    1506           0 :         if (multi1->n != multi2->n)
    1507           0 :                 return isl_bool_false;
    1508           0 :         equal = isl_space_is_equal(multi1->space, multi2->space);
    1509           0 :         if (equal < 0 || !equal)
    1510           0 :                 return equal;
    1511             : 
    1512           0 :         for (i = 0; i < multi1->n; ++i) {
    1513           0 :                 equal = FN(EL,plain_is_equal)(multi1->u.p[i], multi2->u.p[i]);
    1514           0 :                 if (equal < 0 || !equal)
    1515           0 :                         return equal;
    1516             :         }
    1517             : 
    1518           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
    1519           0 :             FN(MULTI(BASE),has_explicit_domain)(multi2)) {
    1520           0 :                 equal = FN(MULTI(BASE),equal_explicit_domain)(multi1, multi2);
    1521           0 :                 if (equal < 0 || !equal)
    1522           0 :                         return equal;
    1523             :         }
    1524             : 
    1525           0 :         return isl_bool_true;
    1526             : }
    1527             : 
    1528             : /* Does "multi" involve any NaNs?
    1529             :  */
    1530           0 : isl_bool FN(MULTI(BASE),involves_nan)(__isl_keep MULTI(BASE) *multi)
    1531             : {
    1532             :         int i;
    1533             : 
    1534           0 :         if (!multi)
    1535           0 :                 return isl_bool_error;
    1536           0 :         if (multi->n == 0)
    1537           0 :                 return isl_bool_false;
    1538             : 
    1539           0 :         for (i = 0; i < multi->n; ++i) {
    1540           0 :                 isl_bool has_nan = FN(EL,involves_nan)(multi->u.p[i]);
    1541           0 :                 if (has_nan < 0 || has_nan)
    1542           0 :                         return has_nan;
    1543             :         }
    1544             : 
    1545           0 :         return isl_bool_false;
    1546             : }
    1547             : 
    1548             : #ifndef NO_DOMAIN
    1549             : /* Return the shared domain of the elements of "multi".
    1550             :  *
    1551             :  * If "multi" has an explicit domain, then return this domain.
    1552             :  */
    1553           0 : __isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
    1554             : {
    1555             :         int i;
    1556             :         isl_set *dom;
    1557             : 
    1558           0 :         if (!multi)
    1559           0 :                 return NULL;
    1560             : 
    1561           0 :         if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
    1562           0 :                 dom = FN(MULTI(BASE),get_explicit_domain)(multi);
    1563           0 :                 FN(MULTI(BASE),free)(multi);
    1564           0 :                 return dom;
    1565             :         }
    1566             : 
    1567           0 :         dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
    1568           0 :         for (i = 0; i < multi->n; ++i) {
    1569             :                 isl_set *dom_i;
    1570             : 
    1571           0 :                 dom_i = FN(EL,domain)(FN(FN(MULTI(BASE),get),BASE)(multi, i));
    1572           0 :                 dom = isl_set_intersect(dom, dom_i);
    1573             :         }
    1574             : 
    1575           0 :         FN(MULTI(BASE),free)(multi);
    1576           0 :         return dom;
    1577             : }
    1578             : #endif
    1579             : 
    1580             : #ifndef NO_NEG
    1581             : /* Return the opposite of "multi".
    1582             :  */
    1583           0 : __isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
    1584             : {
    1585             :         int i;
    1586             : 
    1587           0 :         multi = FN(MULTI(BASE),cow)(multi);
    1588           0 :         if (!multi)
    1589           0 :                 return NULL;
    1590             : 
    1591           0 :         for (i = 0; i < multi->n; ++i) {
    1592           0 :                 multi->u.p[i] = FN(EL,neg)(multi->u.p[i]);
    1593           0 :                 if (!multi->u.p[i])
    1594           0 :                         return FN(MULTI(BASE),free)(multi);
    1595             :         }
    1596             : 
    1597           0 :         return multi;
    1598             : }
    1599             : #endif

Generated by: LCOV version 1.12