PIPS
sc_transformation.c
Go to the documentation of this file.
1 /*
2 
3  $Id: sc_transformation.c 1641 2016-03-02 08:20:19Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of Linear/C3 Library.
8 
9  Linear/C3 Library is free software: you can redistribute it and/or modify it
10  under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  Linear/C3 Library is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with Linear/C3 Library. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 /* Package sc
26  */
27 
28 #ifdef HAVE_CONFIG_H
29  #include "config.h"
30 #endif
31 
32 #include <string.h>
33 #include <stdio.h>
34 
35 #include "boolean.h"
36 #include "arithmetique.h"
37 #include "vecteur.h"
38 #include "contrainte.h"
39 #include "sc.h"
40 
41 /* Transform each equality in two inequalities
42  */
43 
45 Psysteme sc;
46 {
47 
48  Pcontrainte eg,pc1,pc2;
49 
50  for (eg = sc->egalites;
52  eg=eg->succ)
53  {
54  pc1 = contrainte_dup(eg);
55  pc2 = contrainte_dup(eg);
56  vect_chg_sgn(pc2->vecteur);
57  sc_add_ineg(sc,pc1);
58  sc_add_ineg(sc,pc2);
59  }
60 
61  sc->egalites = contraintes_free(sc->egalites);
62  sc->nb_eq = 0;
63 
64  sc = sc_elim_db_constraints(sc);
65 }
66 
67 
68 /* Transform the two constraints A.x <= b and -A.x <= -b of system sc into
69  * an equality A.x == b.
70  */
72 Psysteme sc;
73 {
74  Pcontrainte pc1, pc2, pc1_succ, c_tmp;
75  bool found;
76 
77  for (pc1 = sc->inegalites, pc1_succ = (pc1==NULL ? NULL : pc1->succ);
79  pc1 = pc1_succ, pc1_succ = (pc1==NULL ? NULL : pc1->succ))
80  {
81  for (pc2 = pc1->succ, found=false;
82  !CONTRAINTE_UNDEFINED_P(pc2) && !found;
83  pc2 = pc2->succ)
84  {
85  Pvecteur pv = vect_add(pc1->vecteur, pc2->vecteur);
86 
87  if (VECTEUR_NUL_P(pv)) /* True if the constraints are opposed. */
88  {
89  c_tmp = contrainte_dup(pc1);
90 
91  sc_add_eg(sc, c_tmp);
92  eq_set_vect_nul(pc2);
93  eq_set_vect_nul(pc1);
94  found = true;
95  }
96 
97  vect_rm(pv);
98  }
99  }
100 
102  /* ??? humm, the result is *not* returned */
103 }
104 
105 /* sc_find_equalities(Psysteme * ps)
106  *
107  * what: updates *ps to an equivalent system with more/better equalities.
108  * in/out: *ps
109  * how: (1) Maslov PLDI'92; (2) (a <= x <= a) => (x == a)
110  *
111  * (1) Inspired by Vadim Maslov, PLDI'92 "delinearization". It is based on
112  * the following property (a 1 page theorem and proof in his paper):
113  *
114  * Prop: forall a,n,m in Z, a>0, |m|<a, (an+m=0 <=> n=0, m=0)
115  * Proof: [<=] trivial; [=>] a|n|=|m|<a => |n|<1 => n=0 => m=0;
116  *
117  * From this property, typical of dependence tests on linearized accesses,
118  * two simple equations are derived from a bigger one and inequalities.
119  * Our purpose is to identify the simpler equalities and to substitute
120  * them in the system, not to perform an actual dependence test.
121  *
122  * The issue is to identify candidates n and m in equalities, so as to test
123  * the bounds on m and match the property conditions. We will not assume
124  * cartesian constraints on the variables, but rather compute it by projection.
125  * We will use the gcd condition before projecting to find m bounds.
126  * By doing so, we may lose some instances if a variable is in fact a constant.
127  *
128  * FC, Apr 09 1997.
129  */
130 static int abscmp(Pvecteur * pv1, Pvecteur * pv2)
131 {
132  Value v1 = value_abs(val_of(*pv1)), v2 = value_abs(val_of(*pv2));
133  return value_compare(v1, v2);
134 }
135 
137 {
138  Variable vtmp = (Variable) "local temporary variable";
139  Pcontrainte eq;
140 
142 
143  /* FOR EACH EQUALITY
144  */
145  for (eq = sc_egalites(*ps); eq; eq = eq->succ)
146  {
147  Pvecteur m, an;
148  Value c, a;
149 
151  m = vect_new(vtmp, VALUE_MONE);
152 
153  c = vect_coeff(TCST, an);
154  vect_erase_var(&an, TCST);
155 
156  /* the vector is sorted by increassing absolute coeffs.
157  * the the m/an separation is performed on a per-abs(coeff) basis.
158  */
160 
161  /* BUILD POSSIBLE AN AND M (AN + M + C == 0)
162  */
163  while (!VECTEUR_NUL_P(an))
164  {
165  Value refc, coeff, vmin, vmax, d, r, dp, rp, delta, ma;
166  Psysteme ns;
167 
168  /* accumulate next absolute coeff in m
169  */
170  refc = value_abs(val_of(an));
171 
172  do
173  {
174  Pvecteur v = m; /* insert head(an) in front of m */
175  m = an;
176  an = an->succ;
177  m->succ = v;
178  coeff = VECTEUR_NUL_P(an)? VALUE_ZERO: value_abs(val_of(an));
179  }
180  while (value_eq(coeff, refc));
181 
182  /* WITH AN, COMPUTES A AND CHECK A "GCD" CONDITION ???
183  */
184  if (VECTEUR_NUL_P(an))
185  continue; /* break... */
186 
187  a = vect_pgcd_all(an);
188  if (value_ge(refc, a))
189  continue; /* to WHILE(an) */
190 
191  /* COMPUTE M BOUNDS, IF ANY
192  */
193  ns = sc_dup(*ps);
195  base_rm(sc_base(ns));
196  sc_creer_base(ns);
197 
198  if (!sc_minmax_of_variable(ns, vtmp, &vmin, &vmax)) /* kills ns */
199  {
200  /* the system is not feasible. */
201  vect_rm(m);
202  vect_rm(an);
203  sc_rm(*ps);
204  *ps = sc_empty(BASE_NULLE);
205  return;
206  }
207 
208  if (value_min_p(vmin) || value_max_p(vmax))
209  {
210  /* well, if m is not bounded, the larger m won't be either,
211  * thus we can shorten the an loop...
212  */
213  vect_rm(an), an = VECTEUR_NUL;
214  vect_rm(m), m = VECTEUR_NUL;
215  continue; /* break... */
216  }
217 
218  /* now, we must compute the shifts...
219  *
220  * an + m + c == 0, vmin <= m <= vmax ;
221  * c = a d + r, 0 <= r < a,
222  * a (n+d) + (m+r) == 0, vmin+r <= m+r <= vmax+r,
223  * (vmax+r) = a d' + r', 0 <= r' < a,
224  * vmin+r-ad' <= (m+r-ad') <= r' < a
225  *
226  * question: -a < vmin+r-ad ?
227  * if YES: m+r-ad'==0 and n+d+d'==0
228  * assert: vmin+r-ad<=0 (or not feasible!)
229  */
230 
231  /* c = a d + r
232  */
233  d = value_pdiv(c, a);
234  r = value_pmod(c, a);
235 
236  value_addto(vmax, r);
237  value_addto(vmin, r);
238 
239  /* vmax' = a dp + rp
240  */
241  dp = value_pdiv(vmax, a);
242  rp = value_pmod(vmax, a);
243 
244  /* delta = -ad'
245  */
246  delta = value_minus(rp, vmax);
247  vmax = rp;
248  value_addto(vmin, delta);
249  ma = value_uminus(a);
250 
251  if (value_lt(ma, vmin)) /* CONDITION |m|<a */
252  {
253  Value n_shift, m_shift;
254 
255  Pvecteur n = vect_div(an, a); /* an modified */
256  n_shift = value_plus(d,dp);
257  vect_add_elem(&n, TCST, n_shift);
258 
259  vect_erase_var(&m, vtmp);
260  m_shift = value_plus(r, delta);
261  vect_add_elem(&m, TCST, m_shift);
262 
263  /* INSERT m==0 [ahead] and n==0 [in place of the old one]
264  */
265  sc_add_egalite(*ps, contrainte_make(m)); /* m pointed to */
266 
269 
270  /* KEEPS ON WITH N AND resetted M
271  */
272  m = vect_new(vtmp, VALUE_MONE);
273  an = n;
274  }
275  }
276 
277  /* an == VECTEUR_NUL */
278  vect_rm(m), m=VECTEUR_NUL;
279  }
280 }
281 
282 /* that is all
283  */
#define VALUE_ZERO
#define value_minus(v1, v2)
#define value_pdiv(v1, v2)
#define value_uminus(val)
unary operators on values
#define VALUE_MONE
#define value_pmod(v1, v2)
#define value_min_p(val)
#define value_compare(v1, v2)
int Value
#define value_addto(ref, val)
#define value_eq(v1, v2)
bool operators on values
#define value_max_p(val)
#define value_plus(v1, v2)
binary operators on values
#define value_abs(val)
#define value_lt(v1, v2)
#define value_ge(v1, v2)
#define CONTRAINTE_UNDEFINED_P(c)
#define contrainte_vecteur(c)
passage au champ vecteur d'une contrainte "a la Newgen"
Pcontrainte contraintes_free(Pcontrainte pc)
Pcontrainte contraintes_free(Pcontrainte pc): desallocation de toutes les contraintes de la liste pc.
Definition: alloc.c:226
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
Pcontrainte contrainte_dup(Pcontrainte c_in)
Pcontrainte contrainte_dup(Pcontrainte c_in): allocation d'une contrainte c_out prenant la valeur de ...
Definition: alloc.c:132
void eq_set_vect_nul(Pcontrainte)
void_eq_set_vect_nul(Pcontrainte c): transformation d'une contrainte en une contrainte triviale 0 == ...
Definition: unaires.c:84
Value vect_pgcd_all(Pvecteur v)
Value vect_pgcd(Pvecteur v): calcul du pgcd de tous les coefficients non nul d'un vecteur v.
Definition: reductions.c:108
Psysteme sc_empty(Pbase b)
Psysteme sc_empty(Pbase b): build a Psysteme with one unfeasible constraint to define the empty subsp...
Definition: sc_alloc.c:319
void sc_creer_base(Psysteme ps)
void sc_creer_base(Psysteme ps): initialisation des parametres dimension et base d'un systeme lineair...
Definition: sc_alloc.c:129
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
void sc_add_egalite(Psysteme p, Pcontrainte e)
void sc_add_egalite(Psysteme p, Pcontrainte e): macro ajoutant une egalite e a un systeme p; la base ...
Definition: sc_alloc.c:389
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
Psysteme sc_elim_double_constraints(Psysteme ps)
Psysteme sc_elim_double_constraints(Psysteme ps): elimination des egalites et des inegalites identiqu...
Psysteme sc_elim_db_constraints(Psysteme ps)
Psysteme sc_elim_db_constraints(Psysteme ps): elimination des egalites et des inegalites identiques o...
bool sc_minmax_of_variable(Psysteme ps, Variable var, Value *pmin, Value *pmax)
void sc_minmax_of_variable(Psysteme ps, Variable var, Value *pmin, *pmax): examine un systeme pour tr...
Definition: sc_eval.c:143
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
void sc_find_equalities(Psysteme *ps)
void sc_transform_ineg_in_eg(Psysteme sc)
Transform the two constraints A.x <= b and -A.x <= -b of system sc into an equality A....
void sc_transform_eg_in_ineg(Psysteme sc)
Package sc.
static int abscmp(Pvecteur *pv1, Pvecteur *pv2)
sc_find_equalities(Psysteme * ps)
void vect_chg_sgn(Pvecteur v)
void vect_chg_sgn(Pvecteur v): multiplie v par -1
Definition: scalaires.c:151
Pvecteur vect_div(Pvecteur v, Value x)
Pvecteur vect_div(Pvecteur v, Value x): division du vecteur v par le scalaire x, si x est different d...
Definition: scalaires.c:52
Pvecteur vecteur
struct Scontrainte * succ
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
struct Svecteur * succ
Definition: vecteur-local.h:92
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define val_of(varval)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
#define VECTEUR_NUL_P(v)
#define base_rm(b)
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
#define BASE_NULLE
MACROS SUR LES BASES.
Pvecteur vect_dup(Pvecteur v_in)
Pvecteur vect_dup(Pvecteur v_in): duplication du vecteur v_in; allocation de et copie dans v_out;.
Definition: alloc.c:51
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
Pvecteur vect_add(Pvecteur v1, Pvecteur v2)
package vecteur - operations binaires
Definition: binaires.c:53
void vect_erase_var(Pvecteur *ppv, Variable v)
void vect_erase_var(Pvecteur * ppv, Variable v): projection du vecteur *ppv selon la direction v (i....
Definition: unaires.c:106
void vect_add_elem(Pvecteur *pvect, Variable var, Value val)
void vect_add_elem(Pvecteur * pvect, Variable var, Value val): addition d'un vecteur colineaire au ve...
Definition: unaires.c:72
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228
void vect_sort_in_place(Pvecteur *pv, int *compare)
void vect_sort_in_place(pv, compare) Pvecteur *pv; int (*compare)(Pvecteur *, Pvecteur *);
Definition: unaires.c:290