1 /******************************************************************************
2 * PIP : Parametric Integer Programming *
3 ******************************************************************************
5 ******************************************************************************
7 * Copyright Paul Feautrier, 1988, 1993, 1994, 1996, 2002 *
9 * This is free software; you can redistribute it and/or modify it under the *
10 * terms of the GNU General Public License as published by the Free Software *
11 * Foundation; either version 2 of the License, or (at your option) any later *
14 * This software is distributed in the hope that it will be useful, but *
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
19 * You should have received a copy of the GNU General Public License along *
20 * with software; if not, write to the Free Software Foundation, Inc., *
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
23 * Written by Paul Feautrier and Cedric Bastoul *
25 *****************************************************************************/
31 #include <piplib/piplib.h>
33 #define TAB_CHUNK 4096*sizeof(Entier)
35 static char *tab_free
, *tab_top
;
36 static struct A
*tab_base
;
38 extern int allocation
;
39 extern long int cross_product
, limit
;
40 static int chunk_count
;
43 #if defined(LINEAR_VALUE_IS_MP)
44 int dscanf(FILE *, Entier
);
46 int dscanf(FILE *, Entier
*);
53 tab_free
= malloc(sizeof (struct A
));
55 {fprintf(stderr
, "Your computer doesn't have enough memory\n");
59 tab_top
= tab_free
+ sizeof (struct A
);
60 tab_base
= (struct A
*)tab_free
;
61 tab_free
+= sizeof(struct A
);
62 tab_base
->precedent
= NULL
;
63 tab_base
->bout
= tab_top
;
64 tab_base
->free
= tab_free
;
71 if (tab_base
) free(tab_base
);
75 struct high_water_mark
tab_hwm(void)
76 {struct high_water_mark p
;
77 p
.chunk
= chunk_count
;
83 #if defined(LINEAR_VALUE_IS_MP)
84 /* the clear_tab routine clears the GMP objects which may be referenced
87 void tab_clear(Tableau
*tp
)
90 /* clear the determinant */
91 mpz_clear(tp
->determinant
);
93 for(i
=0; i
<tp
->height
; i
++){
94 /* clear the denominator */
95 mpz_clear(Denom(tp
, i
));
96 if((Flag(tp
, i
) & Unit
) == 0)
97 for(j
=0; j
<tp
->width
; j
++)
98 mpz_clear(Index(tp
,i
,j
));
103 void tab_reset(struct high_water_mark by_the_mark
)
107 while(chunk_count
> by_the_mark
.chunk
)
109 g
= tab_base
->precedent
;
111 #if defined(LINEAR_VALUE_IS_MP)
112 /* Before actually freeing the memory, one has to clear the
113 * included Tableaux. If this is not done, the GMP objects
114 * referenced in the Tableaux will be orphaned.
117 /* Enumerate the included tableaux. */
118 p
= (char *)tab_base
+ sizeof(struct A
);
119 while(p
< tab_base
->free
){
129 tab_top
= tab_base
->bout
;
132 if(chunk_count
> 0) {
133 #if defined(LINEAR_VALUE_IS_MP)
134 /* Do not forget to clear the tables in the current chunk above the
136 p
= (char *)by_the_mark
.top
;
137 while(p
< tab_base
->free
) {
144 tab_free
= by_the_mark
.top
;
145 tab_base
->free
= tab_free
;
148 fprintf(stderr
, "Syserr: tab_reset : error in memory allocation\n");
153 Tableau
* tab_alloc(int h
, int w
, int n
)
155 /* h : le nombre de ligne reelles;
156 n : le nombre de lignes virtuelles
159 char *p
; Tableau
*tp
;
161 unsigned long taille
;
163 taille
= sizeof(struct T
) + (h
+n
-1) * sizeof (struct L
)
164 + h
* w
* sizeof (Entier
);
165 if(tab_free
+ taille
>= tab_top
)
168 d
= taille
+ sizeof(struct A
);
169 if(d
< TAB_CHUNK
) d
= TAB_CHUNK
;
170 tab_free
= malloc(d
);
172 {printf("Memory overflow\n");
176 g
= (struct A
*)tab_free
;
177 g
->precedent
= tab_base
;
178 tab_top
= tab_free
+ d
;
179 tab_free
+= sizeof(struct A
);
185 tab_base
->free
= tab_free
;
187 q
= (Entier
*)(p
+ sizeof(struct T
) + (h
+n
-1) * sizeof (struct L
));
188 #if defined(LINEAR_VALUE_IS_MP)
189 mpz_init_set_ui(tp
->determinant
,1);
191 tp
->determinant
[0] = (Entier
) 1;
192 tp
->l_determinant
= 1;
194 for(i
= 0; i
<n
; i
++){
195 tp
->row
[i
].flags
= Unit
;
196 tp
->row
[i
].objet
.unit
= i
;
197 #if defined(LINEAR_VALUE_IS_MP)
198 mpz_init_set_ui(Denom(tp
, i
), 1);
203 for(i
= n
; i
< (h
+n
); i
++){
204 tp
->row
[i
].flags
= 0;
205 tp
->row
[i
].objet
.val
= q
;
206 for(j
= 0; j
< w
; j
++)
207 #if defined(LINEAR_VALUE_IS_MP)
208 mpz_init_set_ui(*q
++, 0); /* loop body. */
209 mpz_init_set_ui(Denom(tp
, i
), 0);
211 *q
++ = 0; /* loop body. */
212 Denom(tp
, i
) = ZERO
;
215 tp
->height
= h
+ n
; tp
->width
= w
;
216 #if defined(LINEAR_VALUE_IS_MP)
217 tp
->taille
= taille
;
223 Tableau
* tab_get(foo
, h
, w
, n
)
230 #if defined(LINEAR_VALUE_IS_MP)
234 p
= tab_alloc(h
, w
, n
);
235 while((c
= dgetc(foo
)) != EOF
)
237 for(i
= n
; i
<h
+n
; i
++)
238 {p
->row
[i
].flags
= Unknown
;
239 #if defined(LINEAR_VALUE_IS_MP)
240 mpz_set_ui(Denom(p
, i
), 1);
244 while((c
= dgetc(foo
)) != EOF
)if(c
== '[')break;
245 for(j
= 0; j
<w
; j
++){
246 #if defined(LINEAR_VALUE_IS_MP)
247 if(dscanf(foo
, x
) < 0)
250 mpz_set(p
->row
[i
].objet
.val
[j
], x
);
252 if(dscanf(foo
, &x
) < 0)
255 p
->row
[i
].objet
.val
[j
] = x
;
259 while((c
= dgetc(foo
)) != EOF
)if(c
== ']')break;
261 #if defined(LINEAR_VALUE_IS_MP)
269 /* Fonction tab_Matrix2Tableau :
270 * Cette fonction effectue la conversion du format de matrice de la polylib
271 * vers le format de traitement de Pip. matrix est la matrice a convertir.
272 * Nineq est le nombre d'inequations necessaires (dans le format de la
273 * polylib, le premier element d'une ligne indique si l'equation decrite
274 * est une inequation ou une egalite. Pip ne gere que les inequations. On
275 * compte donc le nombre d'inequations total pour reserver la place
276 * necessaire, et on scinde toute egalite p(x)=0 en p(x)>=0 et -p(x)>=0).
277 * Nv est le nombre de variables dans la premiere serie de variables (c'est
278 * a dire que si les premiers coefficients dans les lignes de la matrice
279 * sont ceux des inconnues, Nv est le nombre d'inconnues, resp. parametres).
280 * n est le nombre de lignes 'virtuelles' contenues dans la matrice (c'est
281 * a dire en fait le nombre d'inconnues). Si Max vaut 0, on va rechercher
282 * le minimum lexicographique, sinon on recherche le maximum. La fonction
283 * met alors en place le bignum s'il n'y est pas deja et prepare les
284 * contraintes au calcul du maximum lexicographique.
285 * 27 juillet 2001 : Premiere version, Ced.
286 * 30 juillet 2001 : Nombreuses modifications. Le calcul du nombre total
287 * d'inequations (Nineq) se fait a present a l'exterieur.
288 * 3 octobre 2001 : Pas mal d'ameliorations.
289 * 18 octobre 2003 : Mise en place de la possibilite de calculer le
290 * maximum lexicographique (parties 'if (Max)').
292 Tableau
* tab_Matrix2Tableau(matrix
, Nineq
, Nv
, n
, Max
, Bg
)
294 int Nineq
, Nv
, n
, Max
, Bg
;
296 unsigned i
, j
, end
, current
, new, nb_columns
, decal
=0, bignum_is_new
;
297 Entier
* entier
, inequality
, bignum
;
299 #if defined(LINEAR_VALUE_IS_MP)
300 mpz_init(inequality
) ;
303 nb_columns
= matrix
->NbColumns
- 1 ;
304 /* S'il faut un BigNum et qu'il n'existe pas, on lui reserve sa place. */
305 if ((Max
) && (bignum_is_new
= (Bg
> (matrix
->NbColumns
- 2))))
308 p
= tab_alloc(Nineq
,nb_columns
,n
) ;
310 /* La variable decal sert a prendre en compte les lignes supplementaires
311 * issues des egalites.
313 end
= matrix
->NbRows
+ n
;
315 { current
= i
+ decal
;
316 Flag(p
,current
) = Unknown
;
317 #if defined(LINEAR_VALUE_IS_MP)
318 mpz_set_ui(Denom(p
,current
),1) ;
320 mpz_set_ui(bignum
,0) ;
322 Denom(p
,current
) = UN
;
326 entier
= *(matrix
->p
+ i
- n
) ;
327 /* Pour passer l'indicateur d'egalite/inegalite. */
328 #if defined(LINEAR_VALUE_IS_MP)
329 mpz_set(inequality
,*entier
) ;
331 inequality
= *entier
;
335 /* Dans le format de la polylib, l'element constant est place en
336 * dernier. Dans le format de Pip, il se trouve apres la premiere
337 * serie de variables (inconnues ou parametres). On remet donc les
338 * choses dans l'ordre de Pip. Ici pour p(x) >= 0.
343 #if defined(LINEAR_VALUE_IS_MP)
344 mpz_add(bignum
,bignum
,*entier
) ;
345 mpz_neg(*(p
->row
[current
].objet
.val
+ j
),*entier
++) ;
348 *(p
->row
[current
].objet
.val
+ j
) = -(*entier
++) ;
352 for (j
=Nv
+1;j
<Bg
;j
++)
353 #if defined(LINEAR_VALUE_IS_MP)
354 mpz_set(*(p
->row
[current
].objet
.val
+ j
),*entier
++) ;
356 *(p
->row
[current
].objet
.val
+ j
) = *entier
++ ;
360 #if defined(LINEAR_VALUE_IS_MP)
361 mpz_set(*(p
->row
[current
].objet
.val
+ Bg
),bignum
) ;
363 { mpz_add(*(p
->row
[current
].objet
.val
+ Bg
),bignum
,*entier
++) ;
364 for (j
=Bg
+1;j
<nb_columns
;j
++)
365 mpz_set(*(p
->row
[current
].objet
.val
+ j
),*entier
++) ;
368 *(p
->row
[current
].objet
.val
+ Bg
) = bignum
;
370 { *(p
->row
[current
].objet
.val
+ Bg
) = bignum
+ *entier
++ ;
371 for (j
=Bg
+1;j
<nb_columns
;j
++)
372 *(p
->row
[current
].objet
.val
+ j
) = *entier
++ ;
376 #if defined(LINEAR_VALUE_IS_MP)
377 mpz_set(*(p
->row
[current
].objet
.val
+ Nv
),*entier
) ;
379 *(p
->row
[current
].objet
.val
+ Nv
) = *entier
;
384 #if defined(LINEAR_VALUE_IS_MP)
385 mpz_set(*(p
->row
[current
].objet
.val
+ j
),*entier
++) ;
387 *(p
->row
[current
].objet
.val
+ j
) = *entier
++ ;
389 for (j
=Nv
+1;j
<nb_columns
;j
++)
390 #if defined(LINEAR_VALUE_IS_MP)
391 mpz_set(*(p
->row
[current
].objet
.val
+ j
),*entier
++) ;
392 mpz_set(*(p
->row
[current
].objet
.val
+ Nv
),*entier
) ;
394 *(p
->row
[current
].objet
.val
+ j
) = *entier
++ ;
395 *(p
->row
[current
].objet
.val
+ Nv
) = *entier
;
399 /* Et ici lors de l'ajout de -p(x) >= 0 quand on traite une egalite. */
400 #if defined(LINEAR_VALUE_IS_MP)
401 if (mpz_sgn(inequality
) == 0)
407 Flag(p
,new)= Unknown
;
408 #if defined(LINEAR_VALUE_IS_MP)
409 mpz_set(Denom(p
,new),UN
) ;
414 for (j
=0;j
<nb_columns
;j
++)
415 #if defined(LINEAR_VALUE_IS_MP)
416 mpz_neg(*(p
->row
[new].objet
.val
+ j
),*(p
->row
[current
].objet
.val
+ j
)) ;
418 *(p
->row
[new].objet
.val
+ j
) = -(*(p
->row
[current
].objet
.val
+ j
)) ;
422 #if defined(LINEAR_VALUE_IS_MP)
423 mpz_clear(inequality
);
431 char *Attr
[] = {"Unit", "+", "-", "0", "*", "?"};
433 void tab_display(p
, foo
)
438 int i
, j
, ff
, fff
, n
;
440 #if defined(LINEAR_VALUE_IS_MP)
444 fprintf(foo
, "%ld/[%d * %d]\n", cross_product
, p
->height
, p
->width
);
445 for(i
= 0; i
<p
->height
; i
++){
446 fff
= ff
= p
->row
[i
].flags
;
447 /* if(fff ==0) continue; */
448 #if defined(LINEAR_VALUE_IS_MP)
449 mpz_set(d
, Denom(p
, i
));
455 if(fff
& 1) fprintf(foo
, "%s ",Attr
[n
]);
458 fprintf(foo
, "%f #[", p
->row
[i
].size
);
460 for(j
= 0; j
<p
->width
; j
++)
461 fprintf(foo
, " /%d/",(j
== p
->row
[i
].objet
.unit
)? 1: 0);
463 for(j
= 0; j
<p
->width
; j
++){
464 #if defined(LINEAR_VALUE_IS_MP)
465 mpz_out_str(foo
, 10, Index(p
, i
, j
));
469 fprintf(foo
, FORMAT
, x
);
474 #if defined(LINEAR_VALUE_IS_MP)
475 mpz_out_str(foo
, 10, d
);
477 fprintf(foo
, "%d", (int)d
);
481 #if defined(LINEAR_VALUE_IS_MP)