polylib 5.22.8
ext_ehrhart.c
Go to the documentation of this file.
1#include <polylib/polylib.h>
2#include <stdlib.h>
3#define WS 200
4
5/* #define UE_DEBUG */
6
7typedef struct _Polyhedron_union {
11
12static int ppcm1(int a, int b);
14
15/**** ker.c ****/
16
17static void Soustraire_ligne(Matrix *R, int l1, int l2, int piv);
18static int existepivot(Matrix *R, int l);
19static void swap_line(Matrix *R, int l1, int l2);
20
21/* Caclule une base du noyau de l'application definie
22par la matrice _carree_ R (completee par des 0..0) */
23
24/* /!\ R est alteree par cette fonction. */
25
27 Matrix *B /*,*BTran*/; /* matrice des vect. de la base */
28 int i, j;
29 Value p;
30 int l; /* ligne en cours de `pivotage' */
31 int lnn;
32 int dimbase;
33 int u; /* vecteur util en cours de calcul */
34 Value som;
35 int c;
36 /* diagonalisation de R : algo du pivot */
37 /* avec conservation des pivots nuls */
38 for (l = 0; l < R->NbRows; ++l) {
39 /* cherche le prochain pivot non nul */
40 if ((lnn = existepivot(R, l)) != -1) {
41 swap_line(R, l, lnn);
42
43 /* met la colonne dessous a 0 */
44 for (j = l + 1; j < R->NbRows; ++j)
45 if (value_notzero_p(R->p[j][l]))
46 Soustraire_ligne(R, l, j, l);
47
48 /* et celle dessus aussi */
49 for (j = 0; j < l; ++j)
50 if (value_notzero_p(R->p[j][l]))
51 Soustraire_ligne(R, l, j, l);
52 }
53 /* s'ils sont tous nuls on passe au suivant */
54 /* en laissant cette ligne inchangee. */
55 }
56
57 dimbase = 0;
58 for (l = 0; l < R->NbRows; ++l)
59 if (value_zero_p(R->p[l][l]))
60 ++dimbase; /* = nb de 0 dans la diagonale */
61
62 B = Matrix_Alloc(dimbase, R->NbRows);
63
64 l = 0;
65 for (u = 0; u < dimbase; ++u) {
66 while (value_notzero_p(R->p[l][l]))
67 ++l;
68
69 /* calcul effectif de ce vecteur : chaque coord en commencant par le bas */
70 for (i = R->NbRows - 1; i > l; --i)
71 value_set_si(B->p[u][i], 0);
72 value_set_si(B->p[u][l], 1);
73 for (i = l - 1; i >= 0; --i) /* i=chaque coord du vecteur */
74 {
75 if (value_zero_p(R->p[i][i]))
76 /* on a deux 0... un seul dans */
77 /* ce vect util suffit */
78 value_set_si(B->p[u][i], 0);
79 else {
80 /* somme des coef deja calcules * coef dans la matrice */
81 value_set_si(som, 0);
82 for (c = l; c > i; --c) {
83 value_addmul(som, R->p[i][c], B->p[u][c]);
84 value_multiply(B->p[u][c], B->p[u][c], R->p[i][i]);
85 }
86 value_oppose(B->p[u][i], som);
87 }
88 }
89 /* reste a faire le pgcd du vecteur et a l'orienter */
90 value_set_si(p, 0);
91 for (i = 0; i < R->NbRows; ++i)
92 value_gcd(p, p, B->p[u][i]);
93 if (value_zero_p(p))
94 value_set_si(p, 1);
95 for (i = 0; i < R->NbRows && value_zero_p(B->p[u][i]); ++i)
96 ;
97 if (i < R->NbRows)
98 if (value_neg_p(B->p[u][i]))
99 value_oppose(p, p);
100
101 for (i = 0; i < R->NbRows; ++i)
102 value_divexact(B->p[u][i], B->p[u][i], p);
103
104 /* incrementer le compteur de lignes */
105 ++l;
106 }
107 return B;
108}
109
110/* fonction qui calcule les vect generateurs de l'espace vectoriel
111 contenant le polyhedre P */
112/*
113Matrix *CalcPolyhedronBase( Polyhedron *P )
114{
115 Matrix *R;
116 Matrix *B;
117 int n, lines;
118
119 if( emptyQ(P) )
120 return( Matrix_Alloc( 0, P->Dimension ) ); */
121/* pas de vect. gen */ /*
122
123R = Matrix_Alloc( P->Dimension, P->Dimension );
124
125*/
126/* recopie le 'lineality space' du polyedre dans la matrice R */ /*
127for( lines=0,n=0 ; n<P->NbConstraints ; ++n )
128{
129 if( P->Constraint[n][0]==0 )
130 */
131/* c'est une direction definissant un ss-espace */ /*
132 {
133 memcpy( &R->p[lines][0], &P->Constraint[n][1],
134 sizeof(int)*P->Dimension );
135 ++lines;
136 }
137 }
138 */
139/* remplit le reste de 0..0 */ /*
140 for( ; lines<R->NbRows ; ++lines )
141 memset( &R->p[lines][0], 0, sizeof(int)*P->Dimension );
142
143 B = CalcBase( R );
144 Matrix_Free( R );
145
146 return( B );
147 }*/
148
149/* fonction qui calcule l'espace vectoriel non parametre de dimension dim
150 contenant le polyhedre parametre P */
151/* les _egalites_ sont stockees par la polylib sous forme triangulaire
152superieure donc il suffit de prendre les premieres. */
153
154/*Matrix *CalcEVPolyhedronNP( Polyhedron *P, int dim )
155{
156 Matrix *R;
157 Matrix *B;
158 int n, lines;
159
160 if( emptyQ(P) ) */
161/* pas de vect. gen */ /*
162 {
163 B = Matrix_Alloc( 1, dim ); */
164/* on ne peut pas allouer 0 lignes ! */ /*
165B->NbRows = 0;
166return( B );
167}
168
169R = Matrix_Alloc( dim, dim );
170
171*/
172/* recopie le 'lineality space' du polyedre dans la matrice R */ /*
173 for( lines=0,n=0 ; n<P->NbConstraints && lines<dim ; ++n )
174 {
175 if( P->Constraint[n][0]==0 )
176 */
177/* c'est une direction definissant un ss-espace */ /*
178 {
179 memcpy( &R->p[lines][0], &P->Constraint[n][1],
180 sizeof(int)*P->Dimension );
181 ++lines;
182 }
183 }
184*/
185/* remplit le reste de 0..0 */ /*
186 for( ; lines<R->NbRows ; ++lines )
187 memset( &R->p[lines][0], 0, sizeof(int)*dim );
188
189 B = CalcBase( R );
190 Matrix_Free( R );
191
192 return( B );
193 }*/
194
195/* renvoie la ligne sur laquelle on a trouve un coef non nul */
196/* pareil mais cherche dans toutes les lignes */
197/* et -1 s'il n'y en a pas. */
198static int existepivot(Matrix *R, int l) {
199 int j, c;
200
201 for (j = l; j < R->NbRows; ++j)
202 if (value_notzero_p(R->p[j][l]))
203 return (j);
204
205 /* on ne l'a pas trouve pour l'instant... on cherche au dessus */
206 /* les lignes ayant que des 0 jusqu'a la position l */
207 for (j = 0; j < l; ++j) {
208 for (c = 0; c < l && value_zero_p(R->p[j][c]); c++)
209 ;
210 if (c == l && value_notzero_p(R->p[j][l]))
211 return (j);
212 }
213
214 return (-1);
215}
216
217/* echange les lignes l1 et l2 dans la matrice R */
218static void swap_line(Matrix *R, int l1, int l2) {
219 int i;
220 Value tmp;
221
222 if (l1 != l2)
223 for (i = 0; i < R->NbColumns; i++) {
224 value_assign(tmp, R->p[l1][i]);
225 value_assign(R->p[l1][i], R->p[l2][i]);
226 value_assign(R->p[l2][i], tmp);
227 }
228}
229
230int pgcd1(int a, int b) {
231 int r;
232 if (a == 0)
233 return (abs(b));
234 if (b == 0)
235 return (abs(a));
236 do {
237 r = a % b;
238 a = b;
239 b = r;
240 } while (r != 0);
241 return (abs(a));
242}
243
244/* Soustraire la ligne l1 de l2 */
245/* On effectue l2 = (l1[piv]/pgcd)*l2 - l1 * (l2[piv]/pgcd) */
246static void Soustraire_ligne(Matrix *R, int l1, int l2, int piv) {
247 int i;
248 Value a, b, p, t;
249 /* l2 = a*l2 - b*l1 */
250
251 if (value_zero_p(R->p[l2][piv])) /* c'est deja fait ! */
252 return;
253
254 value_init(a);
255 value_init(b);
256 value_init(p);
257 value_init(t);
258
259 value_gcd(p, R->p[l1][piv], R->p[l2][piv]);
260 value_divexact(a, R->p[l1][piv], p);
261 value_divexact(b, R->p[l2][piv], p);
262
263 value_set_si(R->p[l2][piv], 0);
264 value_set_si(p, 0);
265 for (i = piv + 1; i < R->NbColumns; i++) {
266 value_multiply(t, b, R->p[l1][i]);
267 value_multiply(R->p[l2][i], a, R->p[l2][i]);
268 value_subtract(R->p[l2][i], R->p[l2][i], t);
269 value_gcd(p, p, R->p[l2][i]);
270 }
271 /* Simplification par le pgcd de toute la ligne */
272 for (i = piv + 1; i < R->NbColumns && value_notzero_p(p); i++)
273 value_divexact(R->p[l2][i], R->p[l2][i], p);
274
275 value_clear(a);
276 value_clear(b);
277 value_clear(p);
278 value_clear(t);
279}
280
281/*** ext_ehrhart.c ****/
282
283void new_eadd(evalue *e1, evalue *res) {
284 int i, p, x, y;
285
286 evalue *ne;
287 Value g, m1, m2;
288
289 value_init(g);
290 value_init(m1);
291 value_init(m2);
292 if (value_notzero_p(e1->d) && value_notzero_p(res->d)) {
293 /* Add two rational numbers*/
294 value_multiply(m1, e1->x.n, res->d);
295 value_multiply(m2, res->x.n, e1->d);
296 value_addto(res->x.n, m1, m2);
297 value_multiply(res->d, e1->d, res->d);
298 value_gcd(g, res->x.n, res->d);
299 if (value_notone_p(g)) {
300 value_divexact(res->d, res->d, g);
301 value_divexact(res->x.n, res->x.n, g);
302 }
303 value_clear(g);
304 value_clear(m1);
305 value_clear(m2);
306 return;
307 } else if (value_notzero_p(e1->d) && value_zero_p(res->d)) {
308 if (res->x.p->type == polynomial) {
309 /* Add the constant to the constant term of a polynomial*/
310 new_eadd(e1, &res->x.p->arr[0]);
311 value_clear(g);
312 value_clear(m1);
313 value_clear(m2);
314 return;
315 } else if (res->x.p->type == periodic) {
316 /* Add the constant to all elements of a periodic number */
317 for (i = 0; i < res->x.p->size; i++) {
318 new_eadd(e1, &res->x.p->arr[i]);
319 }
320 value_clear(g);
321 value_clear(m1);
322 value_clear(m2);
323
324 return;
325 } else {
326 fprintf(stderr, "eadd: cannot add const with vector\n");
327 value_clear(g);
328 value_clear(m1);
329 value_clear(m2);
330
331 return;
332 }
333 }
334 /* ######### add polynomial or periodic to constant #############
335 you have to exchange e1 and res, before doing addition */
336
337 else if (value_zero_p(e1->d) && value_notzero_p(res->d)) {
338 enode *tmp;
339 evalue x;
340 x = *res;
341 tmp = ecopy(e1->x.p);
342 value_init(res->d);
343 value_set_si(res->d, 0);
344 res->x.p = tmp;
345
346 new_eadd(&x, res);
347 value_clear(g);
348 value_clear(m1);
349 value_clear(m2);
350 return;
351 } else { /* ((e1->d==0) && (res->d==0)) */
352 if ((e1->x.p->type != res->x.p->type)) {
353 /* ##### adding to evalues of different type. two cases are possible ####
354
355 #### res is periodic and e1 is polynomial, you have to exchange
356 e1 and res then to add e1 to the constant term of res #### */
357 if ((res->x.p->type == periodic) && (e1->x.p->type == polynomial)) {
358
359 evalue eval;
360 value_set_si(eval.d, 0);
361 eval.x.p = ecopy(res->x.p);
362 res->x.p = ecopy(e1->x.p);
363 new_eadd(&eval, &res->x.p->arr[0]);
364
365 } else if ((res->x.p->type == polynomial) &&
366 (e1->x.p->type == periodic)) {
367 /* #### res is polynomial and e1 is periodic,
368 add e1 to the constant term of res #### */
369
370 new_eadd(e1, &res->x.p->arr[0]);
371 }
372
373 value_clear(g);
374 value_clear(m1);
375 value_clear(m2);
376 return;
377 } else if (e1->x.p->pos != res->x.p->pos) {
378 /* ### adding evalues of different position (i.e function of different
379 unknowns to case are possible ### */
380
381 if (res->x.p->type ==
382 polynomial) { /* ### res and e1 are polynomials
383 add e1 to the constant term of res */
384
385 new_eadd(e1, &res->x.p->arr[0]);
386 value_clear(g);
387 value_clear(m1);
388 value_clear(m2);
389 return;
390 } else { /* ### res and e1 are pointers to periodic numbers
391 add e1 to all elements of res */
392
393 for (i = 0; i < res->x.p->size; i++) {
394 new_eadd(e1, &res->x.p->arr[i]);
395 }
396 value_clear(g);
397 value_clear(m1);
398 value_clear(m2);
399 return;
400 }
401
402 } /* ### */
403
404 /* same type , same pos and same size */
405 if (e1->x.p->size == res->x.p->size) {
406 /* add any element in e1 to the corresponding element in res */
407 for (i = 0; i < res->x.p->size; i++) {
408 new_eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
409 }
410 value_clear(g);
411 value_clear(m1);
412 value_clear(m2);
413 return;
414 }
415
416 /* Sizes are different */
417 if (res->x.p->type == polynomial) {
418 /* VIN100: if e1-size > res-size you have to copy e1 in a */
419 /* new enode and add res to that new node. If you do not do */
420 /* that, you lose the the upper weight part of e1 ! */
421
422 if (e1->x.p->size > res->x.p->size) {
423 enode *tmp;
424 tmp = ecopy(e1->x.p);
425 for (i = 0; i < res->x.p->size; ++i) {
426 new_eadd(&res->x.p->arr[i], &tmp->arr[i]);
427 /* free_evalue_refs(&res->x.p->arr[i]); */
428 }
429 res->x.p = tmp;
430
431 } else {
432
433 for (i = 0; i < e1->x.p->size; i++) {
434 new_eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
435 }
436 value_clear(g);
437 value_clear(m1);
438 value_clear(m2);
439
440 return;
441 }
442 }
443
444 /* ### add two periodics of the same pos (unknown) but whith different sizes
445 (periods) ### */
446 else if (res->x.p->type == periodic) {
447 /* you have to create a new evalue 'ne' in whitch size equals to the scm
448 of the sizes of e1 and res, then to copy res periodicaly in ne, after
449 to add periodicaly elements of e1 to elements of ne, and finaly to
450 return ne. */
451
452 x = e1->x.p->size;
453 y = res->x.p->size;
454 p = ppcm1(x, y);
455 ne = (evalue *)malloc(sizeof(evalue));
456 value_init(ne->d);
457 value_set_si(ne->d, 0);
458
459 ne->x.p = new_enode(res->x.p->type, p, res->x.p->pos);
460 for (i = 0; i < p; i++) {
461 value_assign(ne->x.p->arr[i].d, res->x.p->arr[i % y].d);
462 if (value_notzero_p(ne->x.p->arr[i].d)) {
463 value_init(ne->x.p->arr[i].x.n);
464 value_assign(ne->x.p->arr[i].x.n, res->x.p->arr[i % y].x.n);
465 } else {
466 ne->x.p->arr[i].x.p = ecopy(res->x.p->arr[i % y].x.p);
467 }
468 }
469 for (i = 0; i < p; i++) {
470 new_eadd(&e1->x.p->arr[i % x], &ne->x.p->arr[i]);
471 }
472
473 res = ne;
474
475 value_clear(g);
476 value_clear(m1);
477 value_clear(m2);
478 return;
479 } else { /* evector */
480 fprintf(stderr, "eadd: ?cannot add vectors of different length\n");
481 value_clear(g);
482 value_clear(m1);
483 value_clear(m2);
484 return;
485 }
486 }
487 value_clear(g);
488 value_clear(m1);
489 value_clear(m2);
490 return;
491} /* new_eadd */
492
493/* remove the last row and the last column of a matrix Mat */
495 int i;
496 Value *p;
497 p = *(Mat->p + (Mat->NbRows - 1));
498 for (i = 0; i < Mat->NbColumns; i++) {
499 value_clear(*p++);
500 }
501 for (i = 0; i < Mat->NbRows - 1; i++) {
502 p = *(Mat->p + i);
503 value_clear(*(p + (Mat->NbColumns - 1)));
504 }
505 Mat->NbRows--;
506 Mat->NbColumns--;
507 return Mat;
508} /* Reduce_Matrix */
509
510/* Computes the scalar product (in euclidien space) of two vectors */
511
512void Scalar_product(Value *p1, Value *p2, unsigned length, Value *r) {
513 Value *cp1, *cp2;
514
515 int i;
516 cp1 = p1;
517 cp2 = p2;
518 value_set_si(*r, 0);
519 for (i = 0; i < length; i++) {
520 value_addmul(*r, *cp1, *cp2);
521 cp1++;
522 cp2++;
523 }
524} /* Scalar_product */
525
526/* computes the scm of two integrals */
527
528int ppcm1(int a, int b) {
529 int t;
530 t = (a * b) / pgcd1(a, b);
531 return t;
532} /* ppcm1 */
533
535 Matrix *OrthMat;
536 Value a, b, c, d;
537 Vector *q, *p, *f;
538 unsigned length;
539 int i, j, k;
540 value_init(a);
541 value_init(b);
542 value_init(c);
543 value_init(d);
544 OrthMat = Matrix_Alloc(Mat->NbRows, Mat->NbColumns);
545 length = Mat->NbColumns;
546 for (k = 0; k < length; k++) {
547 value_assign(OrthMat->p[0][k], Mat->p[0][k]);
548 }
549 f = Vector_Alloc(length);
550 p = Vector_Alloc(length);
551 q = Vector_Alloc(length);
552 for (i = 1; i < Mat->NbRows; i++) {
553 for (k = 0; k < length; k++) {
554 value_assign(f->p[k], Mat->p[i][k]);
555 value_assign(q->p[k], Mat->p[i][k]);
556 }
557 value_set_si(d, 1);
558 for (j = 0; j < i; j++) {
559 for (k = 0; k < length; k++) {
560 value_assign(p->p[k], OrthMat->p[j][k]);
561 }
562
563 Scalar_product(p->p, f->p, length, &a);
564 Scalar_product(p->p, p->p, length, &b);
565 value_gcd(c, a, b);
566 value_divexact(a, a, c);
567 value_divexact(b, b, c);
568 for (k = 0; k < length; k++) {
569 value_multiply(p->p[k], p->p[k], a);
570 }
571
572 if (value_notone_p(d) | value_notone_p(b)) {
573 value_lcm(c, d, b);
574 value_divexact(a, c, b);
575 value_divexact(b, c, d);
576 value_assign(d, c);
577 for (k = 0; k < length; k++) {
578 value_multiply(p->p[k], p->p[k], a);
579 value_multiply(q->p[k], q->p[k], b);
580 }
581 }
582
583 for (k = 0; k < length; k++) {
584 value_subtract(q->p[k], q->p[k], p->p[k]);
585 }
586 }
587 Vector_Gcd(q->p, length, &c);
588 Vector_AntiScale(q->p, OrthMat->p[i], c, length);
589 }
590 value_clear(a);
591 value_clear(b);
592 value_clear(c);
593 value_clear(d);
594 return OrthMat;
595} /* Orthogonal_Base */
596
597/* Remove an element of a list */
599 if (en == *re) {
600 *re = (*re)->next;
601 } else {
602 prev->next = en->next;
603 }
604} /* Remove_Element */
605
606/* Remove validite domains and correspending ehrhart polynomials whitch are
607 redundant after the enumeration of a polyhedron */
608
610 Enumeration *ren1, *ren2, *previous = NULL;
611 int red;
612 for (ren1 = *Ures; ren1; ren1 = ren1->next) {
613 red = 0;
614 for (ren2 = *Ures; ren2; ren2 = ren2->next) {
615 if (ren1 != ren2) {
616
618 red = 1;
619 break;
620 }
621 }
622 }
623 if (red) {
624 Remove_Element(ren1, Ures, previous);
625 }
626 previous = ren1;
627 }
628} /*Remove_RedendentDomains */
629
630int IncludeInRes(Polyhedron *p, Enumeration *e, unsigned MR) {
631 Enumeration *en;
632 for (en = e; en; en = en->next) {
633
635 return 1;
636 }
637 return 0;
638}
639
640Polyhedron *DMUnion(Enumeration *en, unsigned MR) {
641 Enumeration *e1;
642 Polyhedron *d;
643 e1 = en;
644 d = e1->ValidityDomain;
645 for (e1 = en->next; e1; e1 = e1->next) {
646 d = DomainUnion(d, e1->ValidityDomain, MR);
647 }
648 return d;
649}
650
652 Polyhedron *p;
653
654 for (p = Poldisj; p; p = p->next) {
656 printf("\n");
657 }
658}
660 if (value_notzero_p(en->EP.d)) {
661
662 if (value_mone_p(en->EP.x.n)) {
663 return 1;
664 }
665 }
666 return 0;
667}
668
669/* Enumeration of a domain D */
670
672 const char **pn) {
673 Polyhedron_union *Polun, *pu;
674 Polyhedron *lp, *lp1, *lp1next;
675 Polyhedron *d1, *d2, *d;
676 Enumeration *e, *pr, *en, *en1, *en2, *tmp, *res, *sen;
677 Polun = NULL;
678
679 for (d = D; d; d = d->next) {
682 }
685
686 lp = Disjoint_Domain(D, 0, MAXRAYS);
687
688#ifdef UE_DEBUG
689 printf("##############################################################\n");
690 printf("\n###### DISJOINT UNION ######\n\n");
691 AffConstraints(lp);
692 printf("##############################################################\n");
693#endif
694
695 for (lp1 = lp; lp1; lp1 = lp1->next) {
696 Enumeration *enext;
697 lp1next = lp1->next;
698 lp1->next = NULL;
699 en = Polyhedron_Enumerate(lp1, C, MAXRAYS, NULL);
700 lp1->next = lp1next;
701 sen = NULL;
702 for (e = en; e; e = enext) {
703 enext = e->next;
704 if (!Degenerate(e)) {
705 e->next = sen;
706 sen = e;
707 } else {
708 free_evalue_refs(&e->EP);
710 free(e);
711 }
712 }
713
714 if (sen != NULL) {
715 pu = (Polyhedron_union *)malloc(sizeof(Polyhedron_union));
716 pu->pt = sen;
717 pu->next = Polun;
718 Polun = pu;
719 }
720 }
721 if (!Polun) {
722#ifdef UE_DEBUG
723 fprintf(stdout, "Empty Polun\n");
724#endif
725 return ((Enumeration *)0);
726 }
727
728 while (Polun->next != NULL) {
729 Enumeration *enext;
730 res = NULL;
731 en1 = Polun->pt;
732 en2 = (Polun->next)->pt;
733
734 d1 = DMUnion(en1, MAXRAYS);
735 d2 = DMUnion(en2, MAXRAYS);
736
737 for (en1 = Polun->pt; en1; en1 = enext) {
738 enext = en1->next;
739 for (en2 = (Polun->next)->pt; en2; en2 = en2->next) {
741 MAXRAYS);
742 if (d && !emptyQ(d) && !IncludeInRes(d, res, MAXRAYS)) {
743 tmp = (Enumeration *)malloc(sizeof(Enumeration));
744 value_init(tmp->EP.d);
745 value_assign(tmp->EP.d, en2->EP.d);
746 if (value_zero_p(tmp->EP.d))
747 tmp->EP.x.p = ecopy(en2->EP.x.p);
748 else {
749 value_init(tmp->EP.x.n);
750 value_assign(tmp->EP.x.n, en2->EP.x.n);
751 }
752
753 new_eadd(&en1->EP, &tmp->EP);
754 tmp->ValidityDomain = d;
755 tmp->next = res;
756 res = tmp;
757 }
758 }
760 if (d && !emptyQ(d) && !IncludeInRes(d, res, MAXRAYS)) {
761 en1->ValidityDomain = d;
762 en1->next = res;
763 res = en1;
764 } else {
765 free_evalue_refs(&en1->EP);
766 free(en1);
767 }
768 }
769 for (en2 = (Polun->next)->pt; en2; en2 = enext) {
770 enext = en2->next;
772 if (d && !emptyQ(d) && !IncludeInRes(d, res, MAXRAYS)) {
773 en2->ValidityDomain = d;
774 en2->next = res;
775 res = en2;
776 } else {
777 free_evalue_refs(&en2->EP);
778 free(en2);
779 }
780 }
781 Domain_Free(d1);
782 Domain_Free(d2);
783
784 Polun->pt = res;
785
786 Polun->next = (Polun->next)->next;
787 }
788 res = Polun->pt;
789
791 return (res);
792}
793
794/**********
795 DO NOT USE THE FOLLOWING FUNCTION IT'S NOT WORKING PROPERLY YET.
796 **********/
797
798/* Enumeration of the image by T of domain D */
800 unsigned MAXRAYS,
801 const char **par_name) {
802 Polyhedron *polun, *pol;
803 Enumeration *ee;
804 Matrix *TCopy, *Tred, *d1, *d;
805 Vector *v1, *v2;
806 Value h;
807 int i, j, k;
808
813
814 value_init(h);
815 if (!D) {
816 fprintf(stdout, " Error: in reading input domain \n");
817 value_clear(h);
818 return ((Enumeration *)0);
819 } else {
820 printf(
821 "\n ################ INPUT POLYHEDRON #######################\n\n");
823 }
824
825#ifdef DOMAIN_IMAGE
826 fpol = DomainImage(D, T, MAXRAYS);
827 printf("\n $$$$$$$$$$$$$ THE DOMAIN IMAGE $$$$$$$$$$$$$\n\n");
828 AffConstraints(fpol);
829 if (emptyQ(fpol)) {
830 value_clear(h);
831 return ((Enumeration *)0);
832 }
833 ee = Domain_Enumerate(fpol, C, MAXRAYS, par_name);
834 value_clear(h);
835 return (ee);
836#endif
837
838 TCopy = Matrix_Copy(T);
839 Tred = Reduce_Matrix(TCopy);
840 printf("\n ################## INPUT REDUCED TRANSFORMATION MATRIX "
841 "##################\n");
842 Matrix_Print(stdout, P_VALUE_FMT, Tred);
843
844 if (Tred->NbRows < Tred->NbColumns) {
845 d1 = (Matrix *)Matrix_Alloc(Tred->NbColumns, Tred->NbColumns);
846 for (i = 0; i < Tred->NbRows; i++) {
847 for (j = 0; j < Tred->NbColumns; j++) {
848 value_assign(d1->p[i][j], Tred->p[i][j]);
849 }
850 }
851 for (i = Tred->NbRows; i < Tred->NbColumns; i++) {
852 for (j = 0; j < Tred->NbColumns; j++) {
853 value_set_si(d1->p[i][j], 0);
854 }
855 }
856 d = (Matrix *)CalcBase(d1);
857 Matrix_Free(Tred);
858 Matrix_Free(d1);
859
860 } else {
861 d = (Matrix *)CalcBase(Tred);
862 Matrix_Free(Tred);
863 }
864 if (d->NbRows == 0) {
865 if (emptyQ(D)) {
866 value_clear(h);
867 return ((Enumeration *)0);
868 } else {
869 printf(" Ker(A)=0 implys directly Enumeration on input "
870 "polyhedron\n\n");
871 ee = Domain_Enumerate(D, C, MAXRAYS, par_name);
872 value_clear(h);
873 return ee;
874 }
875 }
876
877 d1 = Transpose(d);
878 Matrix_Free(d);
879
880 if (d1->NbRows != D->Dimension) {
881 fprintf(stdout, " \n Error: incompatible dimension \n");
882 value_clear(h);
883 return ((Enumeration *)0);
884 }
885 if (d1->NbColumns > 1) {
886 fprintf(stdout, " \n Error: Can not compute integral points : More then "
887 "vector in ker(A)! \n");
888 value_clear(h);
889 return ((Enumeration *)0);
890 }
891 printf(
892 " \n Ker(A)=1 implys adding constraints befor Enumeration\n");
893 v1 = Vector_Alloc(d1->NbRows);
894 v2 = Vector_Alloc(d1->NbRows);
895
896 polun = (Polyhedron *)NULL;
897 for (k = 0; k < d1->NbRows; k++) {
898 value_assign(v1->p[k], d1->p[k][0]);
899 }
900 /* adding a new constraint for all constraints of D in which the scalar
901 * product of the*/
902 /* normal whith vector v1 is greter then zero*/
903
904 for (j = 0; j < D->NbConstraints; j++) {
905 for (k = 0; k <= D->Dimension - 1; k++) {
906 value_assign(v2->p[k], D->Constraint[j][k + 1]);
907 }
908 Scalar_product(v1->p, v2->p, D->Dimension, &h);
909
910 if (value_pos_p(h) && !value_zero_p(D->Constraint[j][0])) {
911 Vector *NCont;
912 Value val;
913 value_init(val);
914 /* Create a new contraint whitch is added to the polyhedron*/
915
916 NCont = Vector_Alloc(d1->NbRows + 2);
917 value_set_si(NCont->p[0], 1); /* the constraint is an inequality */
918
919 for (k = 1; k <= D->Dimension; k++) {
920 value_oppose(NCont->p[k], D->Constraint[j][k]);
921 }
922 value_decrement(val, h);
923 value_subtract(val, val, D->Constraint[j][D->Dimension + 1]);
924 value_assign(NCont->p[D->Dimension + 1], val);
925 value_clear(val);
926 /* add the new constraint to polyhedron D */
927 pol = AddConstraints(NCont->p, 1, D, MAXRAYS);
929 polun = AddPolyToDomain(Polyhedron_Copy(pol), polun);
930 Polyhedron_Free(pol);
931 Vector_Free(NCont);
932 value_clear(val);
933 }
934 }
935 if (polun == NULL) { /* No constraint is added to input polyhedron */
936 if (emptyQ(D)) {
937 value_clear(h);
938 return ((Enumeration *)0);
939 } else {
940 ee = Domain_Enumerate(D, C, MAXRAYS, par_name);
941 }
942 } else { /* some constraintes are added to input polyhedron */
943 if (emptyQ(polun)) {
944 value_clear(h);
945 return ((Enumeration *)0);
946 } else {
947 printf(
948 "\n "
949 "##################################################################");
950 printf("\n ****** THE RESULT OF ADDING CONSTRAINTS TO THE INPUT "
951 "POLYHEDRON ****** \n");
952 AffConstraints(polun);
953 ee = Domain_Enumerate(polun, C, MAXRAYS, par_name);
954 value_clear(h);
955 return (ee);
956 }
957 }
958
959 return (NULL);
960}
Matrix * Transpose(Matrix *A)
Definition: Matop.c:83
Matrix * Matrix_Copy(Matrix const *Src)
Definition: Matop.c:98
#define value_pos_p(val)
Definition: arithmetique.h:571
#define value_mone_p(val)
Definition: arithmetique.h:579
#define value_oppose(ref, val)
Definition: arithmetique.h:552
#define value_notzero_p(val)
Definition: arithmetique.h:576
#define value_divexact(ref, val1, val2)
Definition: arithmetique.h:548
#define value_gcd(ref, val1, val2)
Definition: arithmetique.h:556
#define value_notone_p(val)
Definition: arithmetique.h:578
#define value_lcm(ref, val1, val2)
Definition: arithmetique.h:557
#define value_decrement(ref, val)
Definition: arithmetique.h:546
#define value_zero_p(val)
Definition: arithmetique.h:575
#define value_assign(v1, v2)
Definition: arithmetique.h:482
#define value_set_si(val, i)
Definition: arithmetique.h:483
#define value_addmul(ref, val1, val2)
Definition: arithmetique.h:539
#define value_clear(val)
Definition: arithmetique.h:485
#define value_multiply(ref, val1, val2)
Definition: arithmetique.h:543
#define value_subtract(ref, val1, val2)
Definition: arithmetique.h:544
#define value_addto(ref, val1, val2)
Definition: arithmetique.h:537
#define value_neg_p(val)
Definition: arithmetique.h:572
#define value_init(val)
Definition: arithmetique.h:481
Enumeration * Polyhedron_Enumerate(Polyhedron *Pi, Polyhedron *C, unsigned MAXRAYS, const char **param_name)
Procedure to count points in a parameterized polytope.
Definition: ehrhart.c:1870
enode * new_enode(enode_type type, int size, int pos)
EHRHART POLYNOMIAL SYMBOLIC ALGEBRA SYSTEM.
Definition: ehrhart.c:90
void free_evalue_refs(evalue *e)
releases all memory referenced by e.
Definition: ehrhart.c:115
enode * ecopy(enode *e)
Definition: ehrhart.c:144
void new_eadd(evalue *e1, evalue *res)
Definition: ext_ehrhart.c:283
int pgcd1(int a, int b)
Definition: ext_ehrhart.c:230
void AffConstraints(Polyhedron *Poldisj)
Definition: ext_ehrhart.c:651
Matrix * CalcBase(Matrix *R)
Definition: ext_ehrhart.c:26
void Scalar_product(Value *p1, Value *p2, unsigned length, Value *r)
Definition: ext_ehrhart.c:512
static int existepivot(Matrix *R, int l)
Definition: ext_ehrhart.c:198
int Degenerate(Enumeration *en)
Definition: ext_ehrhart.c:659
static void Soustraire_ligne(Matrix *R, int l1, int l2, int piv)
Definition: ext_ehrhart.c:246
Polyhedron * DMUnion(Enumeration *en, unsigned MR)
Definition: ext_ehrhart.c:640
int IncludeInRes(Polyhedron *p, Enumeration *e, unsigned MR)
Definition: ext_ehrhart.c:630
static int ppcm1(int a, int b)
Definition: ext_ehrhart.c:528
Enumeration * Polyhedron_Image_Enumerate(Polyhedron *D, Polyhedron *C, Matrix *T, unsigned MAXRAYS, const char **par_name)
Definition: ext_ehrhart.c:799
Enumeration * Domain_Enumerate(Polyhedron *D, Polyhedron *C, unsigned MAXRAYS, const char **pn)
Definition: ext_ehrhart.c:671
static void swap_line(Matrix *R, int l1, int l2)
Definition: ext_ehrhart.c:218
void Remove_RedundantDomains(Enumeration **Ures)
Definition: ext_ehrhart.c:609
Matrix * Reduce_Matrix(Matrix *Mat)
Definition: ext_ehrhart.c:494
void Remove_Element(Enumeration *en, Enumeration **re, Enumeration *prev)
Definition: ext_ehrhart.c:598
struct _Polyhedron_union Polyhedron_union
Matrix * Orthogonal_Base(Matrix *Mat)
Definition: ext_ehrhart.c:534
Matrix * Matrix_Alloc(unsigned NbRows, unsigned NbColumns)
Definition: matrix.c:24
void Matrix_Print(FILE *Dst, const char *Format, Matrix *Mat)
Definition: matrix.c:115
void Matrix_Free(Matrix *Mat)
Definition: matrix.c:71
int PolyhedronIncludes(Polyhedron *Pol1, Polyhedron *Pol2)
Definition: polyhedron.c:2404
Polyhedron * Disjoint_Domain(Polyhedron *P, int flag, unsigned NbMaxRays)
Definition: polyhedron.c:4540
void Polyhedron_PrintConstraints(FILE *Dst, const char *Format, Polyhedron *Pol)
Definition: polyhedron.c:4739
void Polyhedron_Free(Polyhedron *Pol)
Definition: polyhedron.c:1614
Polyhedron * DomainDifference(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:3694
Polyhedron * AddPolyToDomain(Polyhedron *Pol, Polyhedron *PolDomain)
Definition: polyhedron.c:2449
Polyhedron * DomainIntersection(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Return the intersection of two polyhedral domains 'Pol1' and 'Pol2'.
Definition: polyhedron.c:2637
Polyhedron * Polyhedron_Copy(Polyhedron *Pol)
Definition: polyhedron.c:2840
Polyhedron * DomainUnion(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays)
Definition: polyhedron.c:3585
Polyhedron * DomainImage(Polyhedron *Pol, Matrix *Func, unsigned NbMaxConstrs)
Definition: polyhedron.c:4303
Polyhedron * AddConstraints(Value *Con, unsigned NbConstraints, Polyhedron *Pol, unsigned NbMaxRays)
Definition: polyhedron.c:2303
void Domain_Free(Polyhedron *Pol)
Definition: polyhedron.c:1626
#define POL_ENSURE_VERTICES(P)
Definition: polyhedron.h:17
#define POL_ENSURE_FACETS(P)
Definition: polyhedron.h:13
Definition: types.h:70
Value * p
Definition: types.h:72
Enumeration * pt
Definition: ext_ehrhart.c:8
struct _Polyhedron_union * next
Definition: ext_ehrhart.c:9
Definition: types.h:182
evalue arr[1]
Definition: types.h:186
Polyhedron * ValidityDomain
Definition: types.h:191
evalue EP
Definition: types.h:192
struct _enumeration * next
Definition: types.h:193
Definition: types.h:173
Value d
Definition: types.h:174
Definition: types.h:75
unsigned NbRows
Definition: types.h:76
Value ** p
Definition: types.h:77
unsigned NbColumns
Definition: types.h:76
unsigned Dimension
Definition: types.h:94
unsigned NbConstraints
Definition: types.h:94
struct polyhedron * next
Definition: types.h:99
Value ** Constraint
Definition: types.h:95
@ periodic
Definition: types.h:165
@ polynomial
Definition: types.h:165
#define emptyQ(P)
Definition: types.h:118
#define P_VALUE_FMT
Definition: types.h:39
void Vector_Free(Vector *vector)
Definition: vector.c:162
void Vector_Gcd(Value *p, unsigned length, Value *min)
Definition: vector.c:485
void Vector_AntiScale(Value *p1, Value *p2, Value lambda, unsigned length)
Definition: vector.c:356
Vector * Vector_Alloc(unsigned length)
Definition: vector.c:137
#define MAXRAYS
Definition: verif_ehrhart.c:20