1 /*--------------------------------------------------------------------*/
2 /* T R A I T E R . C */
3 /* Copyright Paul Feautrier, 1988, 1993, 1994, 1996 */
4 /* This file is part of the PIP software */
5 /* PIP is NOT public domain. It can be */
6 /* used freely for research and teaching */
7 /* but NOT for commercial advantage. */
8 /*--------------------------------------------------------------------*/
13 #include <polylib/arithmetique.h>
14 #include <polylib/polylib.h>
20 #define MAX_BUFFER 1024
22 extern long int cross_product
, limit
;
25 extern int profondeur
;
27 extern int compa_count
;
31 while(x
) x
>>= 1, n
++;
35 int chercher(Tableau
*p
, int masque
, int n
)
38 if(p
->row
[i
].flags
& masque
) break;
42 /* il est convenu que traiter ne doit modifier ni le tableau, ni le contexte;
43 le tableau peut grandir en cas de coupure (+1 en hauteur et +1 en largeur
44 si nparm != 0) et en cas de partage (+1 en hauteur)(seulement si nparm != 0).
45 le contexte peut grandir en cas de coupure (+2 en hauteur et +1 en largeur)
46 (seulement si nparm !=0) et en cas de partage (+1 en hauteur)(nparm !=0).
47 On estime le nombre de coupures a llog(D) et le nombre de partages a
51 Tableau
*expanser(Tableau
*tp
, int virt
, int reel
, int ncol
,
52 int off
, int dh
, int dw
)
58 rp
= tab_alloc(reel
+dh
, ncol
+dw
, virt
);
59 q
= (char *)rp
+ 2 * sizeof(int) + (virt
+ reel
+ dh
) * sizeof(struct L
);
61 for(i
= off
; i
<virt
+ reel
; i
++)
62 {ff
= Flag(rp
, i
) = Flag(tp
, i
-off
);
63 Denom(rp
, i
) = Denom(tp
, i
-off
);
64 if(ff
& Unit
) rp
->row
[i
].objet
.unit
= tp
->row
[i
-off
].objet
.unit
;
66 rp
->row
[i
].objet
.val
= pq
;
68 pp
= tp
->row
[i
-off
].objet
.val
;
69 qq
= rp
->row
[i
].objet
.val
;
70 for(j
= 0; j
<ncol
; j
++) *qq
++ = *pp
++;
76 int exam_coef(Tableau
*tp
, int nvar
, int ncol
, int bigparm
)
80 for(i
= 0; i
<tp
->height
; i
++)
84 {if(bigparm
>= 0 && (x
= Index(tp
,i
, bigparm
)))
85 {if(x
<0) {Flag(tp
, i
) = Minus
;
88 else Flag(tp
, i
) = Plus
;
92 p
= tp
->row
[i
].objet
.val
+nvar
+1;
93 for(j
= nvar
+1; j
<ncol
; j
++)
96 else if (x
>0) fff
= Plus
;
98 if(fff
!= Zero
&& fff
!= ff
) {
99 if(ff
== Zero
) ff
= fff
;
104 /* bug de'tecte' par [paf], 16/2/93 !
105 Si tous les coefficients des parame`tres sont ne'gatifs
106 et si le terme constant est nul, le signe est inconnu!!
107 On traite donc spe'cialement le terme constant. */
108 x
= Index(tp
, i
, nvar
);
110 else if(x
>0) fff
= Plus
;
112 /* ici on a le signe du terme constant */
114 /* le signe est inconnu si les coefficients sont positifs et
115 le terme constant ne'gatif */
116 case Plus
: if(fff
== Minus
) ff
= Unknown
; break;
117 /* si les coefficients sont tous nuls, le signe est celui
119 case Zero
: ff
= fff
; break;
120 /* le signe est inconnu si les coefficients sont ne'gatifs,
121 sauf si le terme constant est ‚galement n‚gatif. */
122 case Minus
: if(fff
!= Minus
) ff
= Unknown
; break;
123 /* enfin, il n'y a rien a` dire si le signe des coefficients est inconnu */
126 if(ff
== Minus
) return(i
);
132 void compa_test(Tableau
*tp
, Tableau
*context
,
133 int ni
, int nvar
, int nparm
, int nc
)
135 Entier discr
[MAXPARM
];
138 int cPlus
, cMinus
, isCritic
;
140 Tableau
*tPlus
, *tMinus
;
142 struct high_water_mark q
;
144 if(nparm
== 0) return;
145 if(nparm
>= MAXPARM
) {
146 fprintf(stderr
, "Too much parameters : %d\n", nparm
);
150 for(i
= 0; i
<ni
+ nvar
; i
++)
152 if(ff
& (Critic
| Unknown
))
154 for(j
= 0; j
<nvar
; j
++) if(Index(tp
, i
, j
) > 0)
159 for(j
= 0; j
< nparm
; j
++) discr
[j
] = Index(tp
, i
, j
+nvar
+1);
160 discr
[nparm
] = Index(tp
, i
, nvar
)- (isCritic
? 0 : 1);
161 tPlus
= expanser(context
, nparm
, nc
, nparm
+1, nparm
, 1, 0);
162 Flag(tPlus
, nparm
+nc
) = Unknown
;
163 for(j
= 0; j
<=nparm
; j
++)Index(tPlus
, nparm
+nc
, j
) = discr
[j
];
164 Denom(tPlus
, nparm
+nc
) = UN
;
165 verbold
= verbose
; verbose
= 0;
166 if(verbold
&& limit
<= compa_count
&& compa_count
<= limit
+10) {
167 tab_display(tPlus
, dump
);
170 traiter(tPlus
, NULL
, True
, UN
, nparm
, 0, nc
+1, 0, -1);
171 cPlus
= is_not_Nil(p
);
173 for(j
= 0; j
<nparm
+1; j
++) discr
[j
] = -discr
[j
];
174 discr
[nparm
] = discr
[nparm
] - (isCritic
? 1 : 2);
175 tMinus
= expanser(context
, nparm
, nc
, nparm
+1, nparm
, 1, 0);
176 Flag(tMinus
, nparm
+nc
) = Unknown
;
177 for(j
= 0; j
<= nparm
; j
++)Index(tMinus
, nparm
+nc
, j
) = discr
[j
];
178 Denom(tMinus
, nparm
+nc
) = UN
;
179 if(verbold
&& limit
<= compa_count
&& compa_count
<= limit
+10) {
180 tab_display(tMinus
, dump
);
182 traiter(tMinus
, NULL
, True
, UN
, nparm
, 0, nc
+1, 0, -1);
183 cMinus
= is_not_Nil(p
);
186 if (cPlus
&& cMinus
) {
187 Flag(tp
,i
) = isCritic
? Critic
: Unknown
;
194 Flag(tp
,i
) = cPlus
? Plus
: Zero
;
202 Entier
valeur(Tableau
*tp
, int i
, int j
, Entier D
)
204 if(Flag(tp
, i
) & Unit
)
205 return(tp
->row
[i
].objet
.unit
== j
? Denom(tp
,i
) : 0);
206 else return(Index(tp
, i
, j
));
209 void solution(Tableau
*tp
, int nvar
, int nparm
, Entier D
)
211 int ncol
= nvar
+ nparm
+ 1;
213 for(i
= 0; i
<nvar
; i
++)
215 for(j
= nvar
+1; j
<ncol
; j
++)
216 sol_val(valeur(tp
, i
, j
, D
), Denom(tp
,i
));
217 sol_val(valeur(tp
, i
, nvar
, D
), Denom(tp
,i
));
221 int choisir_piv(Tableau
*tp
, int pivi
, int nvar
, int nligne
, Entier D
)
226 for(j
= 0; j
<nvar
; j
++)
227 {if((foo
= Index(tp
, pivi
, j
)) <= 0) continue;
233 for(k
= 0; k
<nligne
; k
++)
234 {x
= pivot
* valeur(tp
, k
, j
, D
) - valeur(tp
, k
, pivj
, D
) * foo
;
246 Entier
pivoter(Tableau
*tp
, int pivi
, Entier D
, int nvar
,
247 int nparm
, int ni
, int iq
)
249 int ncol
= nvar
+ nparm
+ 1;
250 int nligne
= nvar
+ ni
;
252 Entier x
, d
, gcd
, dpiv
;
254 Entier pivot
, foo
, z
;
255 Entier
new[MAXCOL
], *p
, *q
;
258 fprintf(stderr
, "Too much variables\n");
261 if(0 > pivi
|| pivi
>= nligne
|| Flag(tp
, pivi
) == Unit
) {
262 fprintf(stderr
, "Syserr : pivoter : wrong pivot row\n");
265 pivj
= choisir_piv(tp
, pivi
, nvar
, nligne
, D
);
266 if(pivj
< 0) return(-1);
268 fprintf(stderr
, "Syserr : pivoter : wrong pivot\n");
271 pivot
= Index(tp
, pivi
, pivj
);
272 dpiv
= Denom(tp
, pivi
);
274 char format
[MAX_BUFFER
];
275 sprintf(format
,"Integer overflow : %s\n",FORMAT
);
276 fprintf(stderr
, format
, D
);
277 tab_display(tp
, stdout
);
281 for(j
= 0; j
<ncol
; j
++)
282 new[j
] = (j
== pivj
? dpiv
: -Index(tp
, pivi
, j
));
283 for(k
= 0; k
<nligne
; k
++)
285 if(Flag(tp
,k
) & Unit
)continue;
286 if(k
== pivi
)continue;
287 foo
= Index(tp
, k
, pivj
);
288 d
= pgcd_entier(pivot
, foo
);
294 p
= tp
->row
[k
].objet
.val
;
295 q
= tp
->row
[pivi
].objet
.val
;
296 for(j
= 0; j
<ncol
; j
++)
300 z
= (*p
) * lpiv
- (*q
) * foo
;
304 if(gcd
!= 1) gcd
= pgcd_entier(gcd
, z
);
307 p
= tp
->row
[k
].objet
.val
;
308 for(j
= 0; j
<ncol
; j
++)
311 Denom(tp
,k
) = Denom(tp
,k
)/gcd
;
313 p
= tp
->row
[pivi
].objet
.val
;
314 for(k
= 0; k
<nligne
; k
++)
315 if((Flag(tp
, k
) & Unit
) && tp
->row
[k
].objet
.unit
== pivj
) break;
317 tp
->row
[k
].objet
.val
= p
;
318 for(j
= 0; j
<ncol
; j
++)
320 Denom(tp
, k
) = pivot
;
321 Flag(tp
, pivi
) = Unit
| Zero
;
322 Denom(tp
, pivi
) = UN
;
323 tp
->row
[pivi
].objet
.unit
= pivj
;
325 for(k
= 0; k
<nligne
; k
++)
327 if(ff
& Unit
) continue;
328 x
= Index(tp
, k
, pivj
);
329 if(x
< 0) fff
= Minus
;
330 else if(x
== 0) fff
= Zero
;
332 if(fff
!= Zero
&& fff
!= ff
) {
333 if(ff
== Zero
) ff
= (fff
== Minus
? Unknown
: fff
);
340 /* dans cette version, "traiter" modifie ineq; par contre
341 le contexte est immediatement recopie' */
343 static Entier discr
[MAXPARM
];
345 Entier
traiter(tp
, ctxt
, iq
, D
, nvar
, nparm
, ni
, nc
, bigparm
)
347 int iq
, nvar
, nparm
, ni
, nc
, bigparm
;
351 int pivi
, nligne
, ncol
;
352 struct high_water_mark x
;
359 context
= expanser(ctxt
, 0, nc
, nparm
+1, 0, dch
, dcw
);
361 nligne
= nvar
+ni
; ncol
= nvar
+nparm
+1;
362 if(nligne
> tp
->height
|| ncol
> tp
->width
) {
363 fprintf(stderr
, "Syserr : traiter : tableau too small\n");
366 pivi
= chercher(tp
, Minus
, nligne
);
367 if(pivi
< nligne
) goto pirouette
; /* There is a negative row */
369 pivi
= exam_coef(tp
, nvar
, ncol
, bigparm
);
370 if(pivi
< nligne
) goto pirouette
;
371 /* There is a row whose coefficients are negative */
372 compa_test(tp
, context
, ni
, nvar
, nparm
, nc
);
373 pivi
= chercher(tp
, Minus
, nligne
);
374 if(pivi
< nligne
) goto pirouette
;
375 /* The compatibility test has found a negative row */
376 pivi
= chercher(tp
, Critic
, nligne
);
377 if(pivi
>= nligne
)pivi
= chercher(tp
, Unknown
, nligne
);
378 /* Here, the problem tree splits */
382 struct high_water_mark q
;
383 if(nc
>= context
->height
) {
386 context
= expanser(context
, 0, nc
, nparm
+1, 0, dch
, dcw
);
388 if(nparm
>= MAXPARM
) {
389 char format
[MAX_BUFFER
];
390 sprintf(format
,"Too much parameters : %s\n",FORMAT
);
391 fprintf(stderr
, format
, nparm
);
396 char format
[MAX_BUFFER
];
397 sprintf(format
,"profondeur %s %%lx\n",FORMAT
);
398 fprintf(dump
,format
, profondeur
, q
.top
);
400 ntp
= expanser(tp
, nvar
, ni
, ncol
, 0, 0, 0);
404 for(j
= 0; j
<nparm
; j
++) {
405 discr
[j
] = Index(tp
, pivi
, j
+ nvar
+1);
406 com_dem
= pgcd_entier(com_dem
, discr
[j
]);
408 discr
[nparm
] = Index(tp
, pivi
, nvar
);
409 com_dem
= pgcd_entier(com_dem
, discr
[nparm
]);
410 for(j
= 0; j
<=nparm
; j
++) {
412 Index(context
, nc
, j
) = discr
[j
];
413 sol_val(discr
[j
], UN
);
415 Flag(context
, nc
) = Unknown
;
416 Denom(context
, nc
) = UN
;
417 Flag(ntp
, pivi
) = Plus
;
419 traiter(ntp
, context
, iq
, D
, nvar
, nparm
, ni
, nc
+1, bigparm
);
423 char format
[MAX_BUFFER
];
424 sprintf(format
,"descente %s %%lx\n",FORMAT
);
425 fprintf(dump
, format
, profondeur
, tab_hwm().top
);
427 for(j
= 0; j
<nparm
; j
++)
428 Index(context
, nc
, j
) = - Index(context
, nc
, j
);
429 Index(context
, nc
, nparm
) = - Index(context
, nc
, nparm
) -1;
430 Flag(tp
, pivi
) = Minus
;
431 Denom(context
, nc
) = UN
;
435 /* Here, all rows are positive. Do we need an integral solution? */
437 solution(tp
, nvar
, nparm
, D
);
441 pivi
= integrer(&tp
, &context
, D
, &nvar
, &nparm
, &ni
, &nc
);
442 if(pivi
> 0) goto pirouette
;
443 /* A cut has been inserted and is always negative */
444 /* Here, either there is an integral solution, */
445 if(pivi
== 0) solution(tp
, nvar
, nparm
, D
);
446 /* or no solution exists */
450 /* Here, a negative row has been found. The call to <<pivoter>> executes
454 if((D
= pivoter(tp
, pivi
, D
, nvar
, nparm
, ni
, iq
)) < 0) {
459 /* Danger : a premature return would induce memory leaks */