1 /******************************************************************************
2 * PIP : Parametric Integer Programming *
3 ******************************************************************************
5 * Copyright Paul Feautrier, 1988, 1993, 1994, 1996 *
7 * This is free software; you can redistribute it and/or modify it under the *
8 * terms of the GNU General Public License as published by the Free Software *
9 * Foundation; either version 2 of the License, or (at your option) any later *
12 * This software is distributed in the hope that it will be useful, but *
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
17 * You should have received a copy of the GNU General Public License along *
18 * with software; if not, write to the Free Software Foundation, Inc., *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
21 * Written by Paul Feautrier and Cedric Bastoul *
23 ******************************************************************************/
29 #include <piplib/piplib.h>
31 extern long int cross_product
, limit
;
37 Entier param1
, param2
;
50 struct S sol_space
[SOL_SIZE
];
53 Entier
mod(Entier
, Entier
);
55 Entier
pgcd(Entier x
, Entier y
)
62 return(x
>= 0? x
: -x
);
78 if(p
<0 || p
>=SOL_SIZE
)
79 {fprintf(stderr
, "Syserr : sol_reset : Memory allocation error\n");
85 struct S
*sol_alloc(void)
87 r
= sol_space
+ sol_free
;
89 r
->param1
= r
->param2
= 0;
91 if(sol_free
>= SOL_SIZE
)
92 {fprintf(stderr
, "The solution is too complex! : sol\n");
104 {fprintf(dump
, "\nNil");
109 void sol_error(int c
)
116 fprintf(dump
, "Erreur %d\n", c
);
124 return(sol_space
[p
].flags
!= Nil
);
133 fprintf(dump
, "\nIf ");
145 fprintf(dump
, "\nList %d ", n
);
158 fprintf(dump
, "\nForme %d ", l
);
171 fprintf(dump
, "New %d ", k
);
182 fprintf(dump
, "Div ");
196 fprintf(dump
, "val(");
197 fprintf(dump
, FORMAT
, n
);
199 fprintf(dump
, FORMAT
, d
);
207 /* a` partir d'un point de la solution, sauter un objet
208 bien forme' ainsi qu'un e'ventuel New et pointer sur l'objet
213 if(sol_space
[i
].flags
!= New
) return i
;
214 i
= skip(i
+1); /* sauter le Div */
217 /* au lancement, i indexe une cellule qui est la te^te d'un objet.
218 la valeur retourne'e est la te^te de l'objet qui suit. Les
219 objets de type New sont e'limine's */
223 while((f
= sol_space
[i
].flags
) == Free
|| f
== Error
) i
++;
224 switch (sol_space
[i
].flags
) {
225 case Nil
: case Val
: i
++; break;
226 case New
: i
= skip_New(i
); break;
227 case If
: i
= skip(i
+1); /* sauter le pre'dicat */
228 i
= skip(i
); /* sauter le vrai */
229 i
= skip(i
); break; /* sauter le faux */
230 case List
: case Form
: n
= sol_space
[i
].param1
;
232 while(n
--) i
= skip(i
);
234 case Div
: i
= skip(i
+1); /* sauter la forme */
235 i
= skip(i
); /* sauter le diviseur */
237 default : fprintf(stderr
,
238 "Syserr : skip : unknown %d\n", sol_space
[i
].flags
);
242 /* simplification de la solution : e'limination des constructions
243 (if p () ()). N'est en service qu'en pre'sence de l'option -z */
245 void sol_simplify(int i
)
247 if(sol_space
[i
].flags
== If
) {
248 j
= skip(i
+1); /* j : de'but de la partie vraie */
249 k
= skip(j
); /* k : d‚but de la partie fausse */
252 if(sol_space
[j
].flags
== Nil
&& sol_space
[k
].flags
== Nil
) {
253 sol_space
[i
].flags
= Nil
;
254 if(k
>= sol_free
- 1) sol_free
= i
+1;
255 else for(l
= i
+1; l
<=k
; l
++) sol_space
[l
].flags
= Free
;
260 /* e'dition de la solution */
262 int sol_edit(FILE *foo
, int i
)
268 if(p
->flags
== Free
) {
273 if(p
->flags
== New
) {
275 fprintf(foo
, "(newparm %d ", n
);
276 if(verbose
>0)fprintf(dump
, "(newparm %d ", n
);
277 i
= sol_edit(foo
, ++i
);
280 if(verbose
>0)fprintf(dump
, ")\n");
286 case Nil
: fprintf(foo
, "()\n");
287 if(verbose
>0)fprintf(dump
, "()\n");
289 case Error
: fprintf(foo
, "Error %d\n", p
->param1
);
290 if(verbose
>0)fprintf(dump
, "Error %d\n", p
->param1
);
292 case If
: fprintf(foo
, "(if ");
293 if(verbose
>0)fprintf(dump
, "(if ");
294 i
= sol_edit(foo
, ++i
);
295 i
= sol_edit(foo
, i
);
296 i
= sol_edit(foo
, i
);
298 if(verbose
>0)fprintf(dump
, ")\n");
300 case List
: fprintf(foo
, "(list ");
301 if(verbose
>0)fprintf(dump
, "(list ");
304 while(n
--) i
= sol_edit(foo
, i
);
306 if(verbose
>0)fprintf(dump
, ")\n");
308 case Form
: fprintf(foo
, "#[");
309 if(verbose
>0)fprintf(dump
, "#[");
311 for(j
= 0; j
<n
; j
++){
313 N
= p
->param1
; D
= p
->param2
;
317 fprintf(foo
, FORMAT
, N
/d
);
320 fprintf(dump
, FORMAT
, N
/d
);
325 fprintf(foo
,FORMAT
,N
/d
);
327 fprintf(foo
,FORMAT
, D
/d
);
330 fprintf(dump
,FORMAT
,N
/d
);
332 fprintf(dump
,FORMAT
, D
/d
);
337 if(verbose
>0)fprintf(dump
, "]\n");
340 case Div
: fprintf(foo
, "(div ");
341 if(verbose
>0)fprintf(dump
, "(div ");
342 i
= sol_edit(foo
, ++i
);
343 i
= sol_edit(foo
, i
);
345 if(verbose
>0)fprintf(dump
, ")\n");
347 case Val
: N
= p
->param1
; D
= p
->param2
;
349 if(d
== D
){putc(' ', foo
);
350 fprintf(foo
, FORMAT
, N
/d
);
353 fprintf(dump
, FORMAT
, N
/d
);
357 fprintf(foo
, FORMAT
, N
/d
);
359 fprintf(foo
, FORMAT
, D
/d
);
362 fprintf(dump
, FORMAT
, N
/d
);
364 fprintf(dump
, FORMAT
, D
/d
);
369 default : fprintf(foo
, "Inconnu : sol\n");
370 if(verbose
>0)fprintf(dump
, "Inconnu : sol\n");
376 /* Fonction sol_vector_edit :
377 * Cette fonction a pour but de placer les informations correspondant
378 * a un Vector dans la grammaire dans une structure de type PipVector. Elle
379 * prend en parametre un pointeur vers une case memoire contenant le
380 * numero de cellule du tableau sol_space a partir de laquelle on doit
381 * commencer la lecture des informations. Elle retourne un pointeur vers
382 * une structure de type PipVector contenant les informations de ce Vector.
383 * Premiere version : Ced. 20 juillet 2001.
385 PipVector
* sol_vector_edit(int * i
)
391 vector
= (PipVector
*)malloc(sizeof(PipVector
)) ;
393 { fprintf(stderr
, "Memory Overflow.\n") ;
396 p
= sol_space
+ (*i
) ;
398 vector
->nb_elements
= n
;
399 vector
->the_vector
= (Entier
*)malloc(sizeof(Entier
)*n
) ;
400 if (vector
->the_vector
== NULL
)
401 { fprintf(stderr
, "Memory Overflow.\n") ;
404 vector
->the_deno
= (Entier
*)malloc(sizeof(Entier
)*n
) ;
405 if (vector
->the_deno
== NULL
)
406 { fprintf(stderr
, "Memory Overflow.\n") ;
417 vector
->the_vector
[j
] = N
/d
;
419 vector
->the_deno
[j
] = UN
;
421 vector
->the_deno
[j
] = D
/d
;
429 /* Fonction sol_newparm_edit :
430 * Cette fonction a pour but de placer les informations correspondant
431 * a un Newparm dans la grammaire dans une structure de type PipNewparm. Elle
432 * prend en parametre un pointeur vers une case memoire contenant le
433 * numero de cellule du tableau sol_space a partir de laquelle on doit
434 * commencer la lecture des informations. Elle retourne un pointeur vers
435 * une structure de type PipNewparm contenant les informations de ce Newparm.
436 * Premiere version : Ced. 18 octobre 2001.
438 PipNewparm
* sol_newparm_edit(int * i
)
440 PipNewparm
* newparm
, * newparm_new
, * newparm_now
;
442 /* On place p au lieu de lecture. */
443 p
= sol_space
+ (*i
) ;
444 /* On passe le New et le Div pour aller a Form et lire le VECTOR. */
447 newparm
= (PipNewparm
*)malloc(sizeof(PipNewparm
)) ;
449 { fprintf(stderr
, "Memory Overflow.\n") ;
452 newparm
->vector
= sol_vector_edit(i
) ;
453 newparm
->rank
= p
->param1
;
454 /* On met p a jour pour lire le denominateur (un Val de param2 UN). */
455 p
= sol_space
+ (*i
) ;
456 newparm
->deno
= p
->param1
;
457 newparm
->next
= NULL
;
459 newparm_now
= newparm
;
461 { fprintf(dump
,"\n(newparm ") ;
462 fprintf(dump
,FORMAT
,newparm
->rank
) ;
463 fprintf(dump
," (div ") ;
464 pip_vector_print(dump
,newparm
->vector
) ;
466 fprintf(dump
,FORMAT
,newparm
->deno
) ;
470 /* On passe aux elements suivants. */
472 p
= sol_space
+ (*i
) ;
473 while (p
->flags
== New
)
475 newparm_new
= (PipNewparm
*)malloc(sizeof(PipNewparm
)) ;
476 if (newparm_new
== NULL
)
477 { fprintf(stderr
, "Memory Overflow.\n") ;
480 newparm_new
->vector
= sol_vector_edit(i
) ;
481 newparm_new
->rank
= p
->param1
;
482 p
= sol_space
+ (*i
) ;
483 newparm_new
->deno
= p
->param1
;
484 newparm_new
->next
= NULL
;
486 newparm_now
->next
= newparm_new
;
487 newparm_now
= newparm_now
->next
;
489 { fprintf(dump
,"\n(newparm ") ;
490 fprintf(dump
,FORMAT
,newparm_new
->rank
) ;
491 fprintf(dump
," (div ") ;
492 pip_vector_print(dump
,newparm_new
->vector
) ;
494 fprintf(dump
,FORMAT
,newparm_new
->deno
) ;
498 p
= sol_space
+ (*i
) ;
504 /* Fonction sol_list_edit :
505 * Cette fonction a pour but de placer les informations correspondant
506 * a une List dans la grammaire dans une structure de type PipList. Elle
507 * prend en parametre un pointeur vers une case memoire contenant le
508 * numero de cellule du tableau sol_space a partir de laquelle on doit
509 * commencer la lecture des informations. Elle retourne un pointeur vers
510 * une structure de type PipList contenant les informations de cette List.
511 * Premiere version : Ced. 18 octobre 2001.
513 PipList
* sol_list_edit(int * i
, int nb_elements
)
514 { PipList
* list
, * list_new
, * list_now
;
516 /* Pour le premier element. */
517 list
= (PipList
*)malloc(sizeof(PipList
)) ;
519 { fprintf(stderr
, "Memory Overflow.\n") ;
522 list
->vector
= sol_vector_edit(i
) ;
527 { fprintf(dump
,"\n(list ") ;
528 pip_vector_print(dump
,list
->vector
) ;
532 /* Pour les elements suivants. */
533 while (nb_elements
--)
534 { list_new
= (PipList
*)malloc(sizeof(PipList
)) ;
535 if (list_new
== NULL
)
536 { fprintf(stderr
, "Memory Overflow.\n") ;
539 list_new
->vector
= sol_vector_edit(i
) ;
540 list_new
->next
= NULL
;
543 { fprintf(dump
,"\n") ;
544 pip_vector_print(dump
,list_new
->vector
) ;
546 list_now
->next
= list_new
;
547 list_now
= list_now
->next
;
550 fprintf(dump
,"\n)") ;
556 /* Fonction sol_quast_edit :
557 * Cette fonction a pour but de placer les informations de la solution
558 * (qui sont contenues dans le tableau sol_space) dans une structure de
559 * type PipQuast en vue d'une utilisation directe de la solution par une
560 * application exterieure. Elle prend en parametre un pointeur vers une
561 * case memoire contenant le numero de cellule du tableau sol_space
562 * a partir de laquelle on doit commencer la lecture des informations. Elle
563 * recoit aussi l'adresse du PipQuast qui l'a appelle (pour le champ father).
564 * Elle retourne un pointeur vers une structure de type PipQuast qui
565 * contient toutes les informations sur la solution (sous forme d'arbre).
566 * Remarques : cette fonction lit les informations comme elles doivent
567 * se presenter a la fin du traitement. Elle respecte scrupuleusement
568 * la grammaire attendue et n'accepte de passer des cellules a Free
569 * qu'entre une des trois grandes formes (if, list ou suite de newparm).
570 * 20 juillet 2001 : Premiere version, Ced.
571 * 31 juillet 2001 : Ajout du traitement de l'option verbose = code*2 :0(
572 * 18 octobre 2001 : Grands changements dus a l'eclatement de la structure
573 * PipVector en PipVector, PipNewparm et PipList, et
574 * eclatement de la fonction avec sol_newparm_edit et
577 PipQuast
* sol_quast_edit(int * i
, PipQuast
* father
)
580 PipQuast
* solution
;
581 PipList
* list_new
, * list_now
;
582 PipNewparm
* newparm_new
, * newparm_now
;
584 /* On place p au lieu de lecture. */
585 p
= sol_space
+ (*i
) ;
586 /* En cas d'utilisation de l'option de simplification, une plage de
587 * structures S peut avoir les flags a Free. On doit alors les passer.
589 while (p
->flags
== Free
)
594 solution
= (PipQuast
*)malloc(sizeof(PipQuast
)) ;
595 if (solution
== NULL
)
596 { fprintf(stderr
, "Memory Overflow.\n") ;
599 solution
->newparm
= NULL
;
600 solution
->list
= NULL
;
601 solution
->condition
= NULL
;
602 solution
->next_then
= NULL
;
603 solution
->next_else
= NULL
;
604 solution
->father
= father
;
606 /* On peut commencer par une chaine de nouveaux parametres... */
608 { solution
->newparm
= sol_newparm_edit(i
) ;
609 p
= sol_space
+ (*i
) ;
612 /* ...ensuite soit par une liste (vide ou non) soit par un if. */
613 (*i
)++ ; /* Factorise de List, Nil et If. */
615 { case List
: if ((nb_elements
= p
->param1
) != 0)
616 solution
->list
= sol_list_edit(i
,nb_elements
) ;
618 case Nil
: if (verbose
)
619 fprintf(dump
,"\n()") ;
621 case If
: solution
->condition
= sol_vector_edit(i
) ;
623 { fprintf(dump
,"\n(if ") ;
624 pip_vector_print(dump
,solution
->condition
) ;
626 solution
->next_then
= sol_quast_edit(i
,solution
) ;
627 solution
->next_else
= sol_quast_edit(i
,solution
) ;
629 fprintf(dump
,"\n)") ;
631 default : fprintf(stderr
,"\nAie !!! Flag %d inattendu.\n",p
->flags
) ;
633 fprintf(dump
,"\nAie !!! Flag %d inattendu.\n",p
->flags
) ;