4 #include "ev_operations.h"
6 void evalue_set_si(evalue
*ev
, int n
, int d
) {
7 value_set_si(ev
->d
, d
);
9 value_set_si(ev
->x
.n
, n
);
12 void evalue_set(evalue
*ev
, Value n
, Value d
) {
13 value_assign(ev
->d
, d
);
15 value_assign(ev
->x
.n
, n
);
18 void aep_evalue(evalue
*e
, int *ref
) {
23 if (value_notzero_p(e
->d
))
24 return; /* a rational number, its already reduced */
26 return; /* hum... an overflow probably occured */
28 /* First check the components of p */
29 for (i
=0;i
<p
->size
;i
++)
30 aep_evalue(&p
->arr
[i
],ref
);
33 if (p
->type
!= modulo
)
34 p
->pos
= ref
[p
->pos
-1]+1;
39 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
45 if (value_notzero_p(e
->d
))
46 return; /* a rational number, its already reduced */
48 return; /* hum... an overflow probably occured */
51 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
52 for(i
=0;i
<CT
->NbRows
-1;i
++)
53 for(j
=0;j
<CT
->NbColumns
;j
++)
54 if(value_notzero_p(CT
->p
[i
][j
])) {
59 /* Transform the references in e, using ref */
63 } /* addeliminatedparams_evalue */
65 void reduce_evalue (evalue
*e
) {
70 if (value_notzero_p(e
->d
))
71 return; /* a rational number, its already reduced */
73 return; /* hum... an overflow probably occured */
75 /* First reduce the components of p */
76 for (i
=0; i
<p
->size
; i
++)
77 reduce_evalue(&p
->arr
[i
]);
79 if (p
->type
==periodic
) {
81 /* Try to reduce the period */
82 for (i
=1; i
<=(p
->size
)/2; i
++) {
83 if ((p
->size
% i
)==0) {
85 /* Can we reduce the size to i ? */
87 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
88 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
91 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
95 you_lose
: /* OK, lets not do it */
100 /* Try to reduce its strength */
103 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
107 else if (p
->type
==polynomial
) {
109 /* Try to reduce the degree */
110 for (i
=p
->size
-1;i
>=1;i
--) {
111 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
113 /* Zero coefficient */
114 free_evalue_refs(&(p
->arr
[i
]));
119 /* Try to reduce its strength */
122 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
126 else if (p
->type
==modulo
) {
128 /* Try to reduce the degree */
129 for (i
=p
->size
-1;i
>=2;i
--) {
130 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
132 /* Zero coefficient */
133 free_evalue_refs(&(p
->arr
[i
]));
138 /* Try to reduce its strength */
141 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
142 free_evalue_refs(&(p
->arr
[0]));
146 } /* reduce_evalue */
148 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
150 if(value_notzero_p(e
->d
)) {
151 if(value_notone_p(e
->d
)) {
152 value_print(DST
,VALUE_FMT
,e
->x
.n
);
154 value_print(DST
,VALUE_FMT
,e
->d
);
157 value_print(DST
,VALUE_FMT
,e
->x
.n
);
161 print_enode(DST
,e
->x
.p
,pname
);
165 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
170 fprintf(DST
, "NULL");
176 for (i
=0; i
<p
->size
; i
++) {
177 print_evalue(DST
, &p
->arr
[i
], pname
);
181 fprintf(DST
, " }\n");
185 for (i
=p
->size
-1; i
>=0; i
--) {
186 print_evalue(DST
, &p
->arr
[i
], pname
);
187 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
189 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
191 fprintf(DST
, " )\n");
195 for (i
=0; i
<p
->size
; i
++) {
196 print_evalue(DST
, &p
->arr
[i
], pname
);
197 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
199 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
203 for (i
=p
->size
-1; i
>=1; i
--) {
204 print_evalue(DST
, &p
->arr
[i
], pname
);
210 print_evalue(DST
, &p
->arr
[0], pname
);
211 fprintf(DST
, ") mod %d", p
->pos
);
213 fprintf(DST
, ")^%d + ", i
-1);
215 fprintf(DST
, " + ", i
-1);
218 fprintf(DST
, " )\n");
222 print_evalue(DST
, &p
->arr
[0], pname
);
223 fprintf(DST
, "= 0 ] * \n");
224 print_evalue(DST
, &p
->arr
[1], pname
);
227 for (i
=0; i
<p
->size
/2; i
++) {
228 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
229 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
238 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
240 if (value_notzero_p(e1
->d
)) {
241 if (value_zero_p(e2
->d
))
243 return value_lt(e1
->x
.n
, e2
->x
.n
);
245 if (value_notzero_p(e2
->d
))
247 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
249 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
252 return mod_term_smaller(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
255 static void eadd_rev(evalue
*e1
, evalue
*res
)
259 evalue_copy(&ev
, e1
);
261 free_evalue_refs(res
);
265 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
269 evalue_copy(&ev
, e1
);
270 eadd(res
, &ev
.x
.p
->arr
[ev
.x
.p
->type
==modulo
]);
271 free_evalue_refs(res
);
275 struct section
{ Polyhedron
* D
; evalue E
; };
277 void eadd_partitions (evalue
*e1
,evalue
*res
)
282 s
= (struct section
*)
283 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
284 sizeof(struct section
));
288 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
289 assert(res
->x
.p
->size
>= 2);
290 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
291 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
293 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
295 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
304 value_init(s
[n
].E
.d
);
305 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
309 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
310 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
311 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
313 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
314 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
320 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
321 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
323 value_init(s
[n
].E
.d
);
324 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
325 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
330 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
334 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
335 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
336 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
337 value_clear(res
->x
.p
->arr
[2*i
].d
);
341 res
->x
.p
= new_enode(partition
, 2*n
, -1);
342 for (j
= 0; j
< n
; ++j
) {
343 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
344 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
345 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
351 void eadd(evalue
*e1
,evalue
*res
) {
354 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
355 /* Add two rational numbers */
361 value_multiply(m1
,e1
->x
.n
,res
->d
);
362 value_multiply(m2
,res
->x
.n
,e1
->d
);
363 value_addto(res
->x
.n
,m1
,m2
);
364 value_multiply(res
->d
,e1
->d
,res
->d
);
365 Gcd(res
->x
.n
,res
->d
,&g
);
366 if (value_notone_p(g
)) {
367 value_division(res
->d
,res
->d
,g
);
368 value_division(res
->x
.n
,res
->x
.n
,g
);
370 value_clear(g
); value_clear(m1
); value_clear(m2
);
373 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
374 switch (res
->x
.p
->type
) {
376 /* Add the constant to the constant term of a polynomial*/
377 eadd(e1
, &res
->x
.p
->arr
[0]);
380 /* Add the constant to all elements of a periodic number */
381 for (i
=0; i
<res
->x
.p
->size
; i
++) {
382 eadd(e1
, &res
->x
.p
->arr
[i
]);
386 fprintf(stderr
, "eadd: cannot add const with vector\n");
389 eadd(e1
, &res
->x
.p
->arr
[1]);
392 assert(EVALUE_IS_ZERO(*e1
));
393 break; /* Do nothing */
395 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
396 eadd(e1
, &res
->x
.p
->arr
[i
]);
402 /* add polynomial or periodic to constant
403 * you have to exchange e1 and res, before doing addition */
405 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
409 else { // ((e1->d==0) && (res->d==0))
410 assert(!((e1
->x
.p
->type
== partition
) ^
411 (res
->x
.p
->type
== partition
)));
412 if (e1
->x
.p
->type
== partition
) {
413 eadd_partitions(e1
, res
);
416 if (e1
->x
.p
->type
== relation
) {
420 if (res
->x
.p
->type
== relation
) {
421 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
422 eadd(e1
, &res
->x
.p
->arr
[i
]);
425 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
426 /* adding to evalues of different type. two cases are possible
427 * res is periodic and e1 is polynomial, you have to exchange
428 * e1 and res then to add e1 to the constant term of res */
429 if (e1
->x
.p
->type
== polynomial
) {
430 eadd_rev_cst(e1
, res
);
432 else if (res
->x
.p
->type
== polynomial
) {
433 /* res is polynomial and e1 is periodic,
434 add e1 to the constant term of res */
436 eadd(e1
,&res
->x
.p
->arr
[0]);
442 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
443 (res
->x
.p
->type
== modulo
&&
444 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
445 /* adding evalues of different position (i.e function of different unknowns
446 * to case are possible */
448 switch (res
->x
.p
->type
) {
450 if(mod_term_smaller(res
, e1
))
451 eadd(e1
,&res
->x
.p
->arr
[1]);
453 eadd_rev_cst(e1
, res
);
455 case polynomial
: // res and e1 are polynomials
456 // add e1 to the constant term of res
458 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
459 eadd(e1
,&res
->x
.p
->arr
[0]);
461 eadd_rev_cst(e1
, res
);
462 // value_clear(g); value_clear(m1); value_clear(m2);
464 case periodic
: // res and e1 are pointers to periodic numbers
465 //add e1 to all elements of res
467 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
468 for (i
=0;i
<res
->x
.p
->size
;i
++) {
469 eadd(e1
,&res
->x
.p
->arr
[i
]);
478 //same type , same pos and same size
479 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
480 // add any element in e1 to the corresponding element in res
481 if (res
->x
.p
->type
== modulo
)
482 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
483 i
= res
->x
.p
->type
== modulo
? 1 : 0;
484 for (; i
<res
->x
.p
->size
; i
++) {
485 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
490 /* Sizes are different */
491 switch(res
->x
.p
->type
) {
494 /* VIN100: if e1-size > res-size you have to copy e1 in a */
495 /* new enode and add res to that new node. If you do not do */
496 /* that, you lose the the upper weight part of e1 ! */
498 if(e1
->x
.p
->size
> res
->x
.p
->size
)
502 if (res
->x
.p
->type
== modulo
)
503 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
504 i
= res
->x
.p
->type
== modulo
? 1 : 0;
505 for (; i
<e1
->x
.p
->size
; i
++) {
506 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
513 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
516 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
517 of the sizes of e1 and res, then to copy res periodicaly in ne, after
518 to add periodicaly elements of e1 to elements of ne, and finaly to
523 value_init(ex
); value_init(ey
);value_init(ep
);
526 value_set_si(ex
,e1
->x
.p
->size
);
527 value_set_si(ey
,res
->x
.p
->size
);
528 value_assign (ep
,*Lcm(ex
,ey
));
529 p
=(int)mpz_get_si(ep
);
530 ne
= (evalue
*) malloc (sizeof(evalue
));
532 value_set_si( ne
->d
,0);
534 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
536 value_assign(ne
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%y
].d
);
537 if (value_notzero_p(ne
->x
.p
->arr
[i
].d
)) {
538 value_init(ne
->x
.p
->arr
[i
].x
.n
);
539 value_assign(ne
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%y
].x
.n
);
542 ne
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%y
].x
.p
);
546 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
549 value_assign(res
->d
, ne
->d
);
555 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
562 static void emul_rev (evalue
*e1
, evalue
*res
)
566 evalue_copy(&ev
, e1
);
568 free_evalue_refs(res
);
572 static void emul_poly (evalue
*e1
, evalue
*res
)
574 int i
, j
, o
= res
->x
.p
->type
== modulo
;
576 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
578 value_set_si(tmp
.d
,0);
579 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
581 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
582 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
583 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
584 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
587 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
588 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
589 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
592 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
593 emul(&res
->x
.p
->arr
[i
], &ev
);
594 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
595 free_evalue_refs(&ev
);
597 free_evalue_refs(res
);
601 void emul_partitions (evalue
*e1
,evalue
*res
)
606 s
= (struct section
*)
607 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
608 sizeof(struct section
));
612 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
613 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
614 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
615 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
621 /* This code is only needed because the partitions
622 are not true partitions.
624 for (k
= 0; k
< n
; ++k
) {
625 if (DomainIncludes(s
[k
].D
, d
))
627 if (DomainIncludes(d
, s
[k
].D
)) {
629 free_evalue_refs(&s
[k
].E
);
640 value_init(s
[n
].E
.d
);
641 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
642 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
646 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
647 value_clear(res
->x
.p
->arr
[2*i
].d
);
648 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
652 res
->x
.p
= new_enode(partition
, 2*n
, -1);
653 for (j
= 0; j
< n
; ++j
) {
654 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
655 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
656 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
662 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
663 * do a copy of "res" befor calling this function if you nead it after. The vector type of
664 * evalues is not treated here */
666 void emul (evalue
*e1
, evalue
*res
){
669 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
670 fprintf(stderr
, "emul: do not proced on evector type !\n");
674 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
675 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
676 emul_partitions(e1
, res
);
679 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
680 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
681 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
683 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
)
684 emul(e1
, &res
->x
.p
->arr
[1]);
686 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
687 switch(e1
->x
.p
->type
) {
689 switch(res
->x
.p
->type
) {
691 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
692 /* Product of two polynomials of the same variable */
697 /* Product of two polynomials of different variables */
699 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
700 for( i
=0; i
<res
->x
.p
->size
; i
++)
701 emul(e1
, &res
->x
.p
->arr
[i
]);
709 /* Product of a polynomial and a periodic or modulo */
714 switch(res
->x
.p
->type
) {
716 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
717 /* Product of two periodics of the same parameter and period */
719 for(i
=0; i
<res
->x
.p
->size
;i
++)
720 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
725 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
726 /* Product of two periodics of the same parameter and different periods */
730 value_init(x
); value_init(y
);value_init(z
);
733 value_set_si(x
,e1
->x
.p
->size
);
734 value_set_si(y
,res
->x
.p
->size
);
735 value_assign (z
,*Lcm(x
,y
));
736 lcm
=(int)mpz_get_si(z
);
737 newp
= (evalue
*) malloc (sizeof(evalue
));
739 value_set_si( newp
->d
,0);
740 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
742 value_assign(newp
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%iy
].d
);
743 if (value_notzero_p(newp
->x
.p
->arr
[i
].d
)) {
744 value_assign(newp
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%iy
].x
.n
);
747 newp
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%iy
].x
.p
);
752 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
754 value_assign(res
->d
,newp
->d
);
757 value_clear(x
); value_clear(y
);value_clear(z
);
761 /* Product of two periodics of different parameters */
763 for(i
=0; i
<res
->x
.p
->size
; i
++)
764 emul(e1
, &(res
->x
.p
->arr
[i
]));
770 /* Product of a periodic and a polynomial */
772 for(i
=0; i
<res
->x
.p
->size
; i
++)
773 emul(e1
, &(res
->x
.p
->arr
[i
]));
779 switch(res
->x
.p
->type
) {
781 for(i
=0; i
<res
->x
.p
->size
; i
++)
782 emul(e1
, &(res
->x
.p
->arr
[i
]));
787 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
788 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
789 if (e1
->x
.p
->pos
!= 2)
793 /* x mod 2 == (x mod 2)^2 */
794 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1) (x mod 2) */
795 assert(e1
->x
.p
->size
== 3);
796 assert(res
->x
.p
->size
== 3);
798 evalue_copy(&tmp
, &res
->x
.p
->arr
[1]);
799 eadd(&res
->x
.p
->arr
[2], &tmp
);
800 emul(&e1
->x
.p
->arr
[2], &tmp
);
801 emul(&e1
->x
.p
->arr
[1], res
);
802 eadd(&tmp
, &res
->x
.p
->arr
[2]);
803 free_evalue_refs(&tmp
);
806 if(mod_term_smaller(res
, e1
))
807 for(i
=1; i
<res
->x
.p
->size
; i
++)
808 emul(e1
, &(res
->x
.p
->arr
[i
]));
823 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
824 /* Product of two rational numbers */
828 value_multiply(res
->d
,e1
->d
,res
->d
);
829 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
830 Gcd(res
->x
.n
, res
->d
,&g
);
831 if (value_notone_p(g
)) {
832 value_division(res
->d
,res
->d
,g
);
833 value_division(res
->x
.n
,res
->x
.n
,g
);
839 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
840 /* Product of an expression (polynomial or peririodic) and a rational number */
846 /* Product of a rationel number and an expression (polynomial or peririodic) */
848 i
= res
->x
.p
->type
== modulo
? 1 : 0;
849 for (; i
<res
->x
.p
->size
; i
++)
850 emul(e1
, &res
->x
.p
->arr
[i
]);
861 void emask(evalue
*mask
, evalue
*res
) {
867 assert(mask
->x
.p
->type
== partition
);
868 assert(res
->x
.p
->type
== partition
);
870 s
= (struct section
*)
871 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
872 sizeof(struct section
));
876 evalue_set_si(&mone
, -1, 1);
879 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
880 assert(mask
->x
.p
->size
>= 2);
881 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
882 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
884 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
886 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
895 value_init(s
[n
].E
.d
);
896 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
900 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
901 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
902 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
903 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
904 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
906 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
907 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
913 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
914 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
916 value_init(s
[n
].E
.d
);
917 evalue_copy(&s
[n
].E
, &mask
->x
.p
->arr
[2*i
+1]);
918 emul(&res
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
923 assert(0); // We don't allow this.
927 free_evalue_refs(&mone
);
928 free_evalue_refs(mask
);
929 free_evalue_refs(res
);
931 res
->x
.p
= new_enode(partition
, 2*n
, -1);
932 for (j
= 0; j
< n
; ++j
) {
933 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
934 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
935 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
941 void evalue_copy(evalue
*dst
, evalue
*src
)
943 value_assign(dst
->d
, src
->d
);
944 if(value_notzero_p(src
->d
)) {
945 value_init(dst
->x
.n
);
946 value_assign(dst
->x
.n
, src
->x
.n
);
948 dst
->x
.p
= ecopy(src
->x
.p
);
951 enode
*new_enode(enode_type type
,int size
,int pos
) {
957 fprintf(stderr
, "Allocating enode of size 0 !\n" );
960 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
964 for(i
=0; i
<size
; i
++) {
965 value_init(res
->arr
[i
].d
);
966 value_set_si(res
->arr
[i
].d
,0);
972 enode
*ecopy(enode
*e
) {
977 res
= new_enode(e
->type
,e
->size
,e
->pos
);
978 for(i
=0;i
<e
->size
;++i
) {
979 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
980 if(value_zero_p(res
->arr
[i
].d
))
981 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
982 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
983 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
985 value_init(res
->arr
[i
].x
.n
);
986 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
992 int eequal(evalue
*e1
,evalue
*e2
) {
997 if (value_ne(e1
->d
,e2
->d
))
1000 /* e1->d == e2->d */
1001 if (value_notzero_p(e1
->d
)) {
1002 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1005 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1009 /* e1->d == e2->d == 0 */
1012 if (p1
->type
!= p2
->type
) return 0;
1013 if (p1
->size
!= p2
->size
) return 0;
1014 if (p1
->pos
!= p2
->pos
) return 0;
1015 for (i
=0; i
<p1
->size
; i
++)
1016 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1021 void free_evalue_refs(evalue
*e
) {
1026 if (EVALUE_IS_DOMAIN(*e
)) {
1027 Domain_Free(EVALUE_DOMAIN(*e
));
1030 } else if (value_pos_p(e
->d
)) {
1032 /* 'e' stores a constant */
1034 value_clear(e
->x
.n
);
1037 assert(value_zero_p(e
->d
));
1040 if (!p
) return; /* null pointer */
1041 for (i
=0; i
<p
->size
; i
++) {
1042 free_evalue_refs(&(p
->arr
[i
]));
1046 } /* free_evalue_refs */
1048 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1049 Vector
* val
, evalue
*res
)
1051 unsigned nparam
= periods
->Size
;
1054 double d
= compute_evalue(e
, val
->p
);
1059 value_set_si(res
->d
, 1);
1060 value_init(res
->x
.n
);
1061 value_set_double(res
->x
.n
, d
);
1062 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1065 if (value_one_p(periods
->p
[p
]))
1066 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1071 value_assign(tmp
, periods
->p
[p
]);
1072 value_set_si(res
->d
, 0);
1073 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1075 value_decrement(tmp
, tmp
);
1076 value_assign(val
->p
[p
], tmp
);
1077 mod2table_r(e
, periods
, m
, p
+1, val
,
1078 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1079 } while (value_pos_p(tmp
));
1085 void evalue_mod2table(evalue
*e
, int nparam
)
1090 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1093 for (i
=0; i
<p
->size
; i
++) {
1094 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1096 if (p
->type
== modulo
) {
1097 Vector
*periods
= Vector_Alloc(nparam
);
1098 Vector
*val
= Vector_Alloc(nparam
);
1104 value_set_si(tmp
, p
->pos
);
1105 Vector_Set(periods
->p
, 1, nparam
);
1106 Vector_Set(val
->p
, 0, nparam
);
1107 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1110 assert(p
->type
== polynomial
);
1111 assert(p
->size
== 2);
1112 assert(value_one_p(p
->arr
[1].d
));
1113 Gcd(tmp
, p
->arr
[1].x
.n
, &periods
->p
[p
->pos
-1]);
1114 value_division(periods
->p
[p
->pos
-1], tmp
, periods
->p
[p
->pos
-1]);
1116 value_set_si(tmp
, p
->pos
);
1118 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1121 evalue_set_si(&res
, 0, 1);
1122 /* Compute the polynomial using Horner's rule */
1123 for (i
=p
->size
-1;i
>1;i
--) {
1124 eadd(&p
->arr
[i
], &res
);
1127 eadd(&p
->arr
[1], &res
);
1129 free_evalue_refs(e
);
1130 free_evalue_refs(&EP
);
1135 Vector_Free(periods
);
1137 } /* evalue_mod2table */
1139 /********************************************************/
1140 /* function in domain */
1141 /* check if the parameters in list_args */
1142 /* verifies the constraints of Domain P */
1143 /********************************************************/
1144 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1147 Value v
; /* value of the constraint of a row when
1148 parameters are instanciated*/
1154 /*P->Constraint constraint matrice of polyhedron P*/
1155 for(row
=0;row
<P
->NbConstraints
;row
++) {
1156 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1157 for(col
=1;col
<P
->Dimension
+1;col
++) {
1158 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1159 value_addto(v
,v
,tmp
);
1161 if (value_notzero_p(P
->Constraint
[row
][0])) {
1163 /*if v is not >=0 then this constraint is not respected */
1164 if (value_neg_p(v
)) {
1168 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1173 /*if v is not = 0 then this constraint is not respected */
1174 if (value_notzero_p(v
))
1179 /*if not return before this point => all
1180 the constraints are respected */
1186 /****************************************************/
1187 /* function compute enode */
1188 /* compute the value of enode p with parameters */
1189 /* list "list_args */
1190 /* compute the polynomial or the periodic */
1191 /****************************************************/
1193 static double compute_enode(enode
*p
, Value
*list_args
) {
1205 if (p
->type
== polynomial
) {
1207 value_assign(param
,list_args
[p
->pos
-1]);
1209 /* Compute the polynomial using Horner's rule */
1210 for (i
=p
->size
-1;i
>0;i
--) {
1211 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1212 res
*=VALUE_TO_DOUBLE(param
);
1214 res
+=compute_evalue(&p
->arr
[0],list_args
);
1216 else if (p
->type
== modulo
) {
1217 double d
= compute_evalue(&p
->arr
[0], list_args
);
1222 value_set_double(param
, d
);
1223 value_set_si(m
, p
->pos
);
1224 mpz_fdiv_r(param
, param
, m
);
1226 /* Compute the polynomial using Horner's rule */
1227 for (i
=p
->size
-1;i
>1;i
--) {
1228 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1229 res
*=VALUE_TO_DOUBLE(param
);
1231 res
+=compute_evalue(&p
->arr
[1],list_args
);
1233 else if (p
->type
== periodic
) {
1234 value_assign(param
,list_args
[p
->pos
-1]);
1236 /* Choose the right element of the periodic */
1237 value_absolute(m
,param
);
1238 value_set_si(param
,p
->size
);
1239 value_modulus(m
,m
,param
);
1240 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
1242 else if (p
->type
== relation
) {
1243 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 0.5)
1244 res
= compute_evalue(&p
->arr
[1], list_args
);
1249 } /* compute_enode */
1251 /*************************************************/
1252 /* return the value of Ehrhart Polynomial */
1253 /* It returns a double, because since it is */
1254 /* a recursive function, some intermediate value */
1255 /* might not be integral */
1256 /*************************************************/
1258 double compute_evalue(evalue
*e
,Value
*list_args
) {
1262 if (value_notzero_p(e
->d
)) {
1263 if (value_notone_p(e
->d
))
1264 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
1266 res
= VALUE_TO_DOUBLE(e
->x
.n
);
1269 res
= compute_enode(e
->x
.p
,list_args
);
1271 } /* compute_evalue */
1274 /****************************************************/
1275 /* function compute_poly : */
1276 /* Check for the good validity domain */
1277 /* return the number of point in the Polyhedron */
1278 /* in allocated memory */
1279 /* Using the Ehrhart pseudo-polynomial */
1280 /****************************************************/
1281 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
1284 /* double d; int i; */
1286 tmp
= (Value
*) malloc (sizeof(Value
));
1287 assert(tmp
!= NULL
);
1289 value_set_si(*tmp
,0);
1292 return(tmp
); /* no ehrhart polynomial */
1293 if(en
->ValidityDomain
) {
1294 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
1295 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1300 return(tmp
); /* no Validity Domain */
1302 if(in_domain(en
->ValidityDomain
,list_args
)) {
1304 #ifdef EVAL_EHRHART_DEBUG
1305 Print_Domain(stdout
,en
->ValidityDomain
);
1306 print_evalue(stdout
,&en
->EP
);
1309 /* d = compute_evalue(&en->EP,list_args);
1311 printf("(double)%lf = %d\n", d, i ); */
1312 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1318 value_set_si(*tmp
,0);
1319 return(tmp
); /* no compatible domain with the arguments */
1320 } /* compute_poly */