PIPS
traiter.c
Go to the documentation of this file.
1 /*
2 
3  $Id: traiter.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS 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 General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 
28 #ifndef lint
29 static char vcid_pip_traiter[] = "$Id: traiter.c 23065 2016-03-02 09:05:50Z coelho $";
30 #endif /* lint */
31 
32 #include <stdio.h>
33 #include "pip__type.h"
34 #include "pip__sol.h"
35 #include "pip__tab.h"
36 
38 
39 int llog(x)
40 Entier x;
41 {int n = 0;
42  while(x) x >>= 1, n++;
43  return(n);
44 }
45 
46 int chercher(p, masque, n)
47 Tableau *p;
48 int masque, n;
49 {int i;
50  for(i = 0; i<n; i++)
51  if(p->row[i].flags & masque) break;
52  return(i);
53 }
54 
55 /* il est convenu que traiter ne doit modifier ni le tableau, ni le contexte;
56  le tableau peut grandir en cas de coupure (+1 en hauteur et +1 en largeur
57  si nparm != 0) et en cas de partage (+1 en hauteur)(seulement si nparm != 0).
58  le contexte peut grandir en cas de coupure (+2 en hauteur et +1 en largeur)
59  (seulement si nparm !=0) et en cas de partage (+1 en hauteur)(nparm !=0).
60  On estime le nombre de coupures a llog(D) et le nombre de partages a
61  ni.
62 */
63 
64 Tableau *expanser(tp, virt, reel, ncol, off, dh, dw)
65 Tableau *tp;
66 int virt, reel, ncol, off, dh, dw;
67 {
68  int i, j, ff;
69  char *q; Entier *pq;
70  Tableau *rp;
71  rp = tab_alloc(reel+dh, ncol+dw, virt);
72  q = (char *)rp + 2 * sizeof(int) + (virt + reel + dh) * sizeof(struct L);
73  pq = (Entier *) q;
74  for(i = off; i<virt + reel; i++)
75  {ff = Flag(rp, i) = Flag(tp, i-off);
76  if(ff & Unit) rp->row[i].objet.unit = tp->row[i-off].objet.unit;
77  else{rp->row[i].objet.val = pq;
78  pq +=(ncol + dw);
79  for(j = 0; j<ncol; j++) Index(rp,i,j) = Index(tp,i-off,j);
80  for(j = ncol; j<ncol+dw; j++)Index(rp,i,j) = 0;
81  }
82  }
83  return(rp);
84 }
85 
86 int exam_coef(tp, nvar, ncol, bigparm)
87 Tableau *tp;
88 int nvar, ncol, bigparm;
89 {int i, j;
90  int ff, fff;
91  Entier x;
92  for(i = 0; i<tp->height; i++)
93  {ff = Flag(tp,i);
94  if(ff == 0) break;
95  if(ff == Unknown)
96  {if(bigparm >= 0 && (x = Index(tp,i, bigparm)))
97  {if(x<0) {Flag(tp, i) = Minus;
98  return(i);
99  }
100  else Flag(tp, i) = Plus;
101  continue;
102  }
103  ff = Zero;
104  for(j = nvar; j<ncol; j++)
105  {x = Index(tp, i, j);
106  if(x<0) fff = Minus;
107  else if (x>0) fff = Plus;
108  else fff = Zero;
109  if(fff != Zero && fff != ff)
110  if(ff == Zero) ff = fff;
111  else {ff = Unknown;
112  break;
113  }
114  }
115  Flag(tp, i) = ff;
116  if(ff == Minus) return(i);
117  }
118  }
119  return(i);
120 }
121 
122 void traiter();
123 
124 void compa_test(tp, context, ni, nvar, nparm, nc)
125 Tableau *tp, *context;
126 int ni, nvar, nparm, nc;
127 {
128  int i, j;
129  int ff;
130  int cPlus, cMinus, isCritic;
131  Tableau *tPlus, *tMinus;
132  Entier discr[MAXPARM];
133  int p; char *q;
134  if(nparm == 0) return;
135  if(nparm >= MAXPARM) {
136  fprintf(stderr, "Trop de parametres : %d\n", nparm);
137  exit(1);
138  }
139  q = tab_hwm();
140  for(i = 0; i<ni + nvar; i++)
141  {ff = Flag(tp,i);
142  if(ff & (Critic | Unknown))
143  {isCritic = True;
144  for(j = 0; j<nvar; j++) if(Index(tp, i, j) > 0)
145  {isCritic = False;
146  break;
147  }
148  for(j = 0; j < nparm; j++) discr[j] = Index(tp, i, j+nvar+1);
149  discr[nparm] = Index(tp, i, nvar)- (isCritic ? 0 : 1);
150  tPlus = expanser(context, nparm, nc, nparm+1, nparm, 1, 0);
151  Flag(tPlus, nparm+nc) = Unknown;
152  for(j = 0; j<=nparm; j++)Index(tPlus, nparm+nc, j) = discr[j];
153  p = sol_hwm();
154  traiter(tPlus, NULL, True, UN, nparm, 0, nc+1, 0, -1);
155  cPlus = is_not_Nil(p);
156  sol_reset(p);
157  for(j = 0; j<nparm+1; j++) discr[j] = -discr[j];
158  discr[nparm] = discr[nparm] - (isCritic ? 1 : 2);
159  tMinus = expanser(context, nparm, nc, nparm+1, nparm, 1, 0);
160  Flag(tMinus, nparm+nc) = Unknown;
161  for(j = 0; j<= nparm; j++)Index(tMinus, nparm+nc, j) = discr[j];
162  traiter(tMinus, NULL, True, UN, nparm, 0, nc+1, 0, -1);
163  cMinus = is_not_Nil(p);
164  sol_reset(p);
165  if (cPlus && cMinus)
166  Flag(tp,i) = isCritic ? Critic : Unknown;
167  else if (cMinus)
168  {Flag(tp,i) = Minus;
169  break;
170  }
171  else Flag(tp,i) = cPlus ? Plus : Zero;
172  }
173  }
174  tab_reset(q);
175  return;
176 }
177 
178 Entier valeur(tp, i, j, D)
179 Tableau *tp;
180 int i, j;
181 Entier D;
182 {
183  if(Flag(tp, i) & Unit)
184  return(tp->row[i].objet.unit == j ? D : 0);
185  else return(Index(tp, i, j));
186 }
187 
188 void solution(tp, nvar, nparm, D)
189 Tableau *tp;
190 int nvar, nparm;
191 Entier D;
192 {int i, j;
193  int ncol = nvar + nparm + 1;
194  sol_list(nvar);
195  for(i = 0; i<nvar; i++)
196  {sol_forme(nparm+1);
197  for(j = nvar+1; j<ncol; j++)
198  sol_val(valeur(tp, i, j, D), D);
199  sol_val(valeur(tp, i, nvar, D), D);
200  }
201 }
202 
203 int choisir_piv(tp, pivi, nvar, nligne, D)
204 Tableau *tp;
205 int pivi, nvar, nligne;
206 Entier D;
207 {
208  int j, k;
209  long pivot, foo, x;
210  int pivj = -1;
211  for(j = 0; j<nvar; j++)
212  {if((foo = Index(tp, pivi, j)) <= 0) continue;
213  if(pivj < 0)
214  {pivj = j;
215  pivot = foo;
216  continue;
217  }
218  for(k = 0; k<nligne; k++)
219  {x = pivot * valeur(tp, k, j, D) - valeur(tp, k, pivj, D) * foo;
220  cross_product++;
221  if(x) break;
222  }
223  if(x < 0)
224  {pivj = j;
225  pivot = foo;
226  }
227  }
228 /* fprintf(stderr, "%d ", pivj); */
229  return(pivj);
230 }
231 
232 int pivoter(tp, pivi, D, nvar, nparm, ni)
233 Tableau *tp;
234 int pivi;
235 Entier D;
236 int nvar, nparm, ni;
237 {int pivj;
238  int ncol = nvar + nparm + 1;
239  int nligne = nvar + ni;
240  int j, k;
241  int x;
242  int ff, fff;
243  long int pivot, foo, z;
244  Entier new[MAXCOL], *p;
245  if(ncol >= MAXCOL) {
246  fprintf(stderr, "Trop de colonnes : %d\n", ncol);
247  exit(1);
248  }
249  if(verbose >0)
250  tab_display(tp, dump);
251  pivj = choisir_piv(tp, pivi, nvar, nligne, D);
252  if(pivj < 0) return(-1);
253  pivot = Index(tp, pivi, pivj);
254  for(j = 0; j<ncol; j++) new[j] = (j == pivj ? D : -Index(tp, pivi, j));
255  for(k = 0; k<nligne; k++)
256  {if(Flag(tp,k) & Unit)continue;
257  if(k == pivi)continue;
258  foo = Index(tp, k, pivj);
259  for(j = 0; j<ncol; j++)
260  {if(j == pivj) continue;
261  cross_product++;
262  z = Index(tp, k, j) * pivot - Index(tp, pivi, j) * foo;
263  if(z%D || z > 32767L * D)
264  {fprintf(stderr, "%ld/Catastrophe en li %d co %d "
265  ,cross_product, k, j);
266  fprintf(stderr, "%ld", z);
267  fprintf(stderr, FORMAT, D);
268  fprintf(stderr, "\n");
269  exit(30);
270  }
271  Index(tp, k, j) = z/D;
272  }
273  }
274  p = tp->row[pivi].objet.val;
275  for(k = 0; k<nligne; k++)
276  if((Flag(tp, k) & Unit) && tp->row[k].objet.unit == pivj) break;
277  Flag(tp, k) = Plus;
278  tp->row[k].objet.val = p;
279  for(j = 0; j<ncol; j++) *p++ = new[j];
280  Flag(tp, pivi) = Unit | Zero;
281  tp->row[pivi].objet.unit = pivj;
282 
283  for(k = 0; k<nligne; k++)
284  {ff = Flag(tp, k);
285  if(ff & Unit) continue;
286  x = Index(tp, k, pivj);
287  if(x < 0) fff = Minus;
288  else if(x == 0) fff = Zero;
289  else fff = Plus;
290  if(fff != Zero && fff != ff)
291  if(ff == Zero) ff = (fff == Minus ? Unknown : fff);
292  else ff = Unknown;
293  Flag(tp, k) = ff;
294  }
295 /* if((cross_product % 10000) == 0)
296  fprintf(stderr,"%ld pivotements\n\r", cross_product); */
297  return((Entier) pivot);
298 }
299 
300 /* dans cette version, "traiter" modifie ineq; par contre
301  le contexte est immediatement recopie' */
302 
303 void traiter(tp, ctxt, iq, D, nvar, nparm, ni, nc, bigparm)
304 Tableau *tp, *ctxt;
305 int iq, nvar, nparm, ni, nc, bigparm;
306 Entier D;
307 {
308  int j;
309  int pivi, nligne, ncol;
310  char *x;
311  Tableau *context;
312  int dch, dcw;
313  dcw = llog(D);
314  dch = 2 * dcw + 1;
315  x = tab_hwm();
316  context = expanser(ctxt, 0, nc, nparm+1, 0, dch, dcw);
317  for(;;)
318  {nligne = nvar+ni; ncol = nvar+nparm+1;
319  if(nligne > tp->height || ncol > tp->width)
320  {fprintf(stderr, "%ld/Explosion ! :trt\n", cross_product);
321  exit(69);
322  }
323  pivi = chercher(tp, Minus, nligne);
324  if(pivi < nligne) goto pirouette; /* il y a une ligne connue
325  negative */
326  pivi = exam_coef(tp, nvar, ncol, bigparm);
327  if(pivi < nligne) goto pirouette; /* il y a une ligne ou tous
328  les coefficients sont
329  negatif */
330  compa_test(tp, context, ni, nvar, nparm, nc);
331  pivi = chercher(tp, Minus, nligne);
332  if(pivi < nligne) goto pirouette; /* on trouve une ligne negative
333  apres test de compatibilite'*/
334  pivi = chercher(tp, Critic, nligne);
335  if(pivi >= nligne)pivi = chercher(tp, Unknown, nligne);
336  if(pivi < nligne)
337  { /* on a trouve' une ligne de signe indetermine',
338  et donc on divise le probleme en deux */
339  Tableau * ntp;
340  Entier discr[MAXPARM], com_dem;
341  char *q;
342  if(nc >= context->height)
343  {dcw = llog(D);
344  dch = 2 * dcw + 1;
345  context = expanser(context, 0, nc, nparm+1, 0, dch, dcw);
346  }
347  if(nparm >= MAXPARM) {
348  fprintf(stderr, "Trop de parametres : %d\n", nparm);
349  exit(2);
350  }
351  q = tab_hwm();
352  ntp = expanser(tp, nvar, ni, ncol, 0, 0, 0);
353  sol_if();
354  sol_forme(nparm+1);
355  com_dem = 0;
356  for(j = 0; j<nparm; j++)
357  {discr[j] = Index(tp, pivi, j + nvar +1);
358  com_dem = sol_pgcd(com_dem, discr[j]);
359  }
360  discr[nparm] = Index(tp, pivi, nvar);
361  com_dem = sol_pgcd(com_dem, discr[nparm]);
362  if(com_dem < 0)
363  {printf("pgcd negatif ! %d : trt\n", com_dem);
364  exit(88);
365  }
366  for(j = 0; j<=nparm; j++)
367  {discr[j] /= com_dem;
368  Index(context, nc, j) = discr[j];
369  sol_val(discr[j], UN);
370  }
371  Flag(context, nc) = Unknown;
372  Flag(ntp, pivi) = Plus;
373  traiter(ntp, context, iq, D, nvar, nparm, ni, nc+1, bigparm);
374  tab_reset(q);
375  for(j = 0; j<nparm; j++) discr[j] = -discr[j];
376  discr[nparm] = -discr[nparm] - 1;
377  Flag(tp, pivi) = Minus;
378  for(j = 0; j<=nparm; j++)
379  Index(context, nc, j) = discr[j];
380  nc++;
381  goto pirouette;
382  }
383 /* Ici, on a trouve' une solution. Est-elle entiere ? */
384 
385 /* if(non_borne(tp, nvar, D, bigparm))
386  {
387  sol_nil();
388  break;
389  } */
390 
391  if(iq){pivi = integrer(&tp, &context, D,
392  &nvar, &nparm, &ni, &nc);
393  if(pivi >= 0) goto pirouette;
394  }
395 
396 /* Oui, elle est entiere, ou bien on s'en fiche (iq == 0) */
397 
398  solution(tp, nvar, nparm, D);
399  break;
400 
401 /* dans tout les cas ou on a trouve' une ligne ne'gative, on vient ici
402  pour effectuer l'echange variable dependante <-> variable independante */
403 
404 pirouette :
405  if((D = pivoter(tp, pivi, D, nvar, nparm, ni)) < 0)
406  {
407  sol_nil();
408  break;
409  }
410  }
411  tab_reset(x);
412 }
#define D(A)
Definition: iabrev.h:56
int integrer(Tableau **ptp, Tableau **pcontext, int D, int *pnvar, int *pnparm, int *pni, int *pnc)
Definition: integrer.c:56
int verbose
Definition: maind.c:45
FILE * dump
Should not be used : put here for Pip copatibility.
Definition: pip.c:97
long int cross_product
Definition: pip.c:91
#define exit(code)
Definition: misc-local.h:54
int sol_hwm()
Definition: sol.c:75
void sol_if()
Definition: sol.c:118
void sol_reset()
void sol_list()
void sol_val()
int is_not_Nil()
void sol_nil()
Definition: sol.c:101
#define Critic
Definition: pip__tab.h:40
Tableau * tab_alloc()
#define Index(p, i, j)
Definition: pip__tab.h:45
char * tab_hwm()
Definition: tab.c:92
void tab_reset()
#define Unknown
Definition: pip__tab.h:41
#define Flag(p, i)
Definition: pip__tab.h:46
#define Unit
Definition: pip__tab.h:36
void tab_display()
#define Minus
Definition: pip__tab.h:38
#define Plus
Definition: pip__tab.h:37
#define Zero
Definition: pip__tab.h:39
#define Entier
Definition: pip__type.h:24
#define MAXPARM
Definition: pip__type.h:42
#define False
Definition: pip__type.h:33
#define UN
Definition: pip__type.h:26
#define FORMAT
Definition: pip__type.h:25
#define True
Definition: pip__type.h:32
#define MAXCOL
Definition: pip__type.h:41
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
int printf()
void pivot(frac *X, frac A, frac B, frac C, frac D, bool ofl_ctrl)
void sol_forme(int l)
Definition: sol.c:133
static char * x
Definition: split_file.c:159
Definition: pip__tab.h:30
int unit
Definition: pip__tab.h:31
Entier * val
Definition: pip__tab.h:32
union L::@15 objet
Definition: pip__tab.h:48
struct L row[1]
Definition: pip__tab.h:49
Definition: delay.c:253
int pivoter(Tableau *tp, int pivi, Entier D, int nvar, int nparm, int ni)
Definition: traiter.c:232
void solution(Tableau *tp, int nvar, int nparm, Entier D)
Definition: traiter.c:188
Tableau * expanser(Tableau *tp, int virt, int reel, int ncol, int off, int dh, int dw)
il est convenu que traiter ne doit modifier ni le tableau, ni le contexte; le tableau peut grandir en...
Definition: traiter.c:64
int choisir_piv(Tableau *tp, int pivi, int nvar, int nligne, Entier D)
Definition: traiter.c:203
int llog(Entier x)
Definition: traiter.c:39
Entier valeur(Tableau *tp, int i, int j, Entier D)
Definition: traiter.c:178
static char vcid_pip_traiter[]
Definition: traiter.c:29
int exam_coef(Tableau *tp, int nvar, int ncol, int bigparm)
Definition: traiter.c:86
void compa_test(Tableau *tp, Tableau *context, int ni, int nvar, int nparm, int nc)
Definition: traiter.c:124
Entier sol_pgcd()
lint
void traiter()
int chercher(Tableau *p, int masque, int n)
Definition: traiter.c:46