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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011      INRIA Saclay
       3             :  * Copyright 2012      Ecole Normale Superieure
       4             :  *
       5             :  * Use of this software is governed by the MIT license
       6             :  *
       7             :  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
       8             :  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
       9             :  * 91893 Orsay, France
      10             :  * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
      11             :  */
      12             : 
      13             : #include <isl_pw_macro.h>
      14             : 
      15             : /* Given a function "cmp" that returns the set of elements where
      16             :  * "el1" is "better" than "el2", return this set.
      17             :  */
      18           0 : static __isl_give isl_set *FN(PW,better)(__isl_keep EL *el1, __isl_keep EL *el2,
      19             :         __isl_give isl_set *(*cmp)(__isl_take EL *el1, __isl_take EL *el2))
      20             : {
      21           0 :         return cmp(FN(EL,copy)(el1), FN(EL,copy)(el2));
      22             : }
      23             : 
      24             : /* Return a list containing the domains of the pieces of "pw".
      25             :  */
      26           0 : static __isl_give isl_set_list *FN(PW,extract_domains)(__isl_keep PW *pw)
      27             : {
      28             :         int i;
      29             :         isl_ctx *ctx;
      30             :         isl_set_list *list;
      31             : 
      32           0 :         if (!pw)
      33           0 :                 return NULL;
      34           0 :         ctx = FN(PW,get_ctx)(pw);
      35           0 :         list = isl_set_list_alloc(ctx, pw->n);
      36           0 :         for (i = 0; i < pw->n; ++i)
      37           0 :                 list = isl_set_list_add(list, isl_set_copy(pw->p[i].set));
      38             : 
      39           0 :         return list;
      40             : }
      41             : 
      42             : /* Given sets B ("set"), C ("better") and A' ("out"), return
      43             :  *
      44             :  *      (B \cap C) \cup ((B \setminus C) \setminus A')
      45             :  */
      46           0 : static __isl_give isl_set *FN(PW,better_or_out)(__isl_take isl_set *set,
      47             :         __isl_take isl_set *better, __isl_take isl_set *out)
      48             : {
      49             :         isl_set *set_better, *set_out;
      50             : 
      51           0 :         set_better = isl_set_intersect(isl_set_copy(set), isl_set_copy(better));
      52           0 :         set_out = isl_set_subtract(isl_set_subtract(set, better), out);
      53             : 
      54           0 :         return isl_set_union(set_better, set_out);
      55             : }
      56             : 
      57             : /* Given sets A ("set"), C ("better") and B' ("out"), return
      58             :  *
      59             :  *      (A \setminus C) \cup ((A \cap C) \setminus B')
      60             :  */
      61           0 : static __isl_give isl_set *FN(PW,worse_or_out)(__isl_take isl_set *set,
      62             :         __isl_take isl_set *better, __isl_take isl_set *out)
      63             : {
      64             :         isl_set *set_worse, *set_out;
      65             : 
      66           0 :         set_worse = isl_set_subtract(isl_set_copy(set), isl_set_copy(better));
      67           0 :         set_out = isl_set_subtract(isl_set_intersect(set, better), out);
      68             : 
      69           0 :         return isl_set_union(set_worse, set_out);
      70             : }
      71             : 
      72             : /* Given two piecewise expressions "pw1" and "pw2", replace their domains
      73             :  * by the sets in "list1" and "list2" and combine the results into
      74             :  * a single piecewise expression.
      75             :  * The pieces of "pw1" and "pw2" are assumed to have been sorted
      76             :  * according to the function value expressions.
      77             :  * The pieces of the result are also sorted in this way.
      78             :  *
      79             :  * Run through the pieces of "pw1" and "pw2" in order until they
      80             :  * have both been exhausted, picking the piece from "pw1" or "pw2"
      81             :  * depending on which should come first, together with the corresponding
      82             :  * domain from "list1" or "list2".  In cases where the next pieces
      83             :  * in both "pw1" and "pw2" have the same function value expression,
      84             :  * construct only a single piece in the result with as domain
      85             :  * the union of the domains in "list1" and "list2".
      86             :  */
      87           0 : static __isl_give PW *FN(PW,merge)(__isl_take PW *pw1, __isl_take PW *pw2,
      88             :         __isl_take isl_set_list *list1, __isl_take isl_set_list *list2)
      89             : {
      90             :         int i, j;
      91             :         PW *res;
      92             : 
      93           0 :         if (!pw1 || !pw2)
      94             :                 goto error;
      95             : 
      96           0 :         res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), pw1->n + pw2->n);
      97             : 
      98           0 :         i = 0; j = 0;
      99           0 :         while (i < pw1->n || j < pw2->n) {
     100             :                 int cmp;
     101             :                 isl_set *set;
     102             :                 EL *el;
     103             : 
     104           0 :                 if (i < pw1->n && j < pw2->n)
     105           0 :                         cmp = FN(EL,plain_cmp)(pw1->p[i].FIELD,
     106           0 :                                                 pw2->p[j].FIELD);
     107             :                 else
     108           0 :                         cmp = i < pw1->n ? -1 : 1;
     109             : 
     110           0 :                 if (cmp < 0) {
     111           0 :                         set = isl_set_list_get_set(list1, i);
     112           0 :                         el = FN(EL,copy)(pw1->p[i].FIELD);
     113           0 :                         ++i;
     114           0 :                 } else if (cmp > 0) {
     115           0 :                         set = isl_set_list_get_set(list2, j);
     116           0 :                         el = FN(EL,copy)(pw2->p[j].FIELD);
     117           0 :                         ++j;
     118             :                 } else {
     119           0 :                         set = isl_set_union(isl_set_list_get_set(list1, i),
     120           0 :                                             isl_set_list_get_set(list2, j));
     121           0 :                         el = FN(EL,copy)(pw1->p[i].FIELD);
     122           0 :                         ++i;
     123           0 :                         ++j;
     124             :                 }
     125           0 :                 res = FN(PW,add_piece)(res, set, el);
     126             :         }
     127             : 
     128           0 :         isl_set_list_free(list1);
     129           0 :         isl_set_list_free(list2);
     130           0 :         FN(PW,free)(pw1);
     131           0 :         FN(PW,free)(pw2);
     132           0 :         return res;
     133             : error:
     134           0 :         isl_set_list_free(list1);
     135           0 :         isl_set_list_free(list2);
     136           0 :         FN(PW,free)(pw1);
     137           0 :         FN(PW,free)(pw2);
     138           0 :         return NULL;
     139             : }
     140             : 
     141             : /* Given a function "cmp" that returns the set of elements where
     142             :  * "el1" is "better" than "el2", return a piecewise
     143             :  * expression defined on the union of the definition domains
     144             :  * of "pw1" and "pw2" that maps to the "best" of "pw1" and
     145             :  * "pw2" on each cell.  If only one of the two input functions
     146             :  * is defined on a given cell, then it is considered the best.
     147             :  *
     148             :  * Run through all pairs of pieces in "pw1" and "pw2".
     149             :  * If the domains of these pieces intersect, then the intersection
     150             :  * needs to be distributed over the two pieces based on "cmp".
     151             :  * Let C be the set where the piece from "pw2" is better (according to "cmp")
     152             :  * than the piece from "pw1".  Let A be the domain of the piece from "pw1" and
     153             :  * B the domain of the piece from "pw2".
     154             :  *
     155             :  * The elements in C need to be removed from A, except for those parts
     156             :  * that lie outside of B.  That is,
     157             :  *
     158             :  *      A <- (A \setminus C) \cup ((A \cap C) \setminus B')
     159             :  *
     160             :  * Conversely, the elements in B need to be restricted to C, except
     161             :  * for those parts that lie outside of A.  That is
     162             :  *
     163             :  *      B <- (B \cap C) \cup ((B \setminus C) \setminus A')
     164             :  *
     165             :  * Since all pairs of pieces are considered, the domains are updated
     166             :  * several times.  A and B refer to these updated domains
     167             :  * (kept track of in "list1" and "list2"), while A' and B' refer
     168             :  * to the original domains of the pieces.  It is safe to use these
     169             :  * original domains because the difference between, say, A' and A is
     170             :  * the domains of pw2-pieces that have been removed before and
     171             :  * those domains are disjoint from B.  A' is used instead of A
     172             :  * because the continued updating of A may result in this domain
     173             :  * getting broken up into more disjuncts.
     174             :  *
     175             :  * After the updated domains have been computed, the result is constructed
     176             :  * from "pw1", "pw2", "list1" and "list2".  If there are any pieces
     177             :  * in "pw1" and "pw2" with the same function value expression, then
     178             :  * they are combined into a single piece in the result.
     179             :  * In order to be able to do this efficiently, the pieces of "pw1" and
     180             :  * "pw2" are first sorted according to their function value expressions.
     181             :  */
     182           0 : static __isl_give PW *FN(PW,union_opt_cmp)(
     183             :         __isl_take PW *pw1, __isl_take PW *pw2,
     184             :         __isl_give isl_set *(*cmp)(__isl_take EL *el1, __isl_take EL *el2))
     185             : {
     186             :         int i, j;
     187           0 :         PW *res = NULL;
     188             :         isl_ctx *ctx;
     189           0 :         isl_set *set = NULL;
     190           0 :         isl_set_list *list1 = NULL, *list2 = NULL;
     191             : 
     192           0 :         if (!pw1 || !pw2)
     193             :                 goto error;
     194             : 
     195           0 :         ctx = isl_space_get_ctx(pw1->dim);
     196           0 :         if (!isl_space_is_equal(pw1->dim, pw2->dim))
     197           0 :                 isl_die(ctx, isl_error_invalid,
     198             :                         "arguments should live in the same space", goto error);
     199             : 
     200           0 :         if (FN(PW,is_empty)(pw1)) {
     201           0 :                 FN(PW,free)(pw1);
     202           0 :                 return pw2;
     203             :         }
     204             : 
     205           0 :         if (FN(PW,is_empty)(pw2)) {
     206           0 :                 FN(PW,free)(pw2);
     207           0 :                 return pw1;
     208             :         }
     209             : 
     210           0 :         pw1 = FN(PW,sort)(pw1);
     211           0 :         pw2 = FN(PW,sort)(pw2);
     212           0 :         if (!pw1 || !pw2)
     213             :                 goto error;
     214             : 
     215           0 :         list1 = FN(PW,extract_domains)(pw1);
     216           0 :         list2 = FN(PW,extract_domains)(pw2);
     217             : 
     218           0 :         for (i = 0; i < pw1->n; ++i) {
     219           0 :                 for (j = 0; j < pw2->n; ++j) {
     220             :                         isl_bool disjoint;
     221             :                         isl_set *better, *set_i, *set_j;
     222             : 
     223           0 :                         disjoint = isl_set_is_disjoint(pw1->p[i].set,
     224           0 :                                                         pw2->p[j].set);
     225           0 :                         if (disjoint < 0)
     226           0 :                                 goto error;
     227           0 :                         if (disjoint)
     228           0 :                                 continue;
     229           0 :                         better = FN(PW,better)(pw2->p[j].FIELD,
     230           0 :                                                 pw1->p[i].FIELD, cmp);
     231           0 :                         set_i = isl_set_list_get_set(list1, i);
     232           0 :                         set_j = isl_set_copy(pw2->p[j].set);
     233           0 :                         set_i = FN(PW,worse_or_out)(set_i,
     234             :                                                 isl_set_copy(better), set_j);
     235           0 :                         list1 = isl_set_list_set_set(list1, i, set_i);
     236           0 :                         set_i = isl_set_copy(pw1->p[i].set);
     237           0 :                         set_j = isl_set_list_get_set(list2, j);
     238           0 :                         set_j = FN(PW,better_or_out)(set_j, better, set_i);
     239           0 :                         list2 = isl_set_list_set_set(list2, j, set_j);
     240             :                 }
     241             :         }
     242             : 
     243           0 :         res = FN(PW,merge)(pw1, pw2, list1, list2);
     244             : 
     245           0 :         return res;
     246             : error:
     247           0 :         isl_set_list_free(list1);
     248           0 :         isl_set_list_free(list2);
     249           0 :         FN(PW,free)(pw1);
     250           0 :         FN(PW,free)(pw2);
     251           0 :         isl_set_free(set);
     252           0 :         return FN(PW,free)(res);
     253             : }

Generated by: LCOV version 1.12