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
);
226 fprintf(DST
, " +\n [ ");
227 print_evalue(DST
, &p
->arr
[0], pname
);
228 fprintf(DST
, "!= 0 ] * \n");
229 print_evalue(DST
, &p
->arr
[2], pname
);
233 for (i
=0; i
<p
->size
/2; i
++) {
234 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
235 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
244 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
246 if (value_notzero_p(e1
->d
)) {
247 if (value_zero_p(e2
->d
))
249 return value_lt(e1
->x
.n
, e2
->x
.n
);
251 if (value_notzero_p(e2
->d
))
253 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
255 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
258 return mod_term_smaller(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
261 static void eadd_rev(evalue
*e1
, evalue
*res
)
265 evalue_copy(&ev
, e1
);
267 free_evalue_refs(res
);
271 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
275 evalue_copy(&ev
, e1
);
276 eadd(res
, &ev
.x
.p
->arr
[ev
.x
.p
->type
==modulo
]);
277 free_evalue_refs(res
);
281 struct section
{ Polyhedron
* D
; evalue E
; };
283 void eadd_partitions (evalue
*e1
,evalue
*res
)
288 s
= (struct section
*)
289 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
290 sizeof(struct section
));
294 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
295 assert(res
->x
.p
->size
>= 2);
296 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
297 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
299 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
301 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
310 value_init(s
[n
].E
.d
);
311 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
315 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
316 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
317 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
319 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
320 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
326 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
327 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
329 value_init(s
[n
].E
.d
);
330 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
331 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
336 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
340 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
341 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
342 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
343 value_clear(res
->x
.p
->arr
[2*i
].d
);
347 res
->x
.p
= new_enode(partition
, 2*n
, -1);
348 for (j
= 0; j
< n
; ++j
) {
349 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
350 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
351 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
357 static void explicit_complement(evalue
*res
)
359 enode
*rel
= new_enode(relation
, 3, 0);
361 value_clear(rel
->arr
[0].d
);
362 rel
->arr
[0] = res
->x
.p
->arr
[0];
363 value_clear(rel
->arr
[1].d
);
364 rel
->arr
[1] = res
->x
.p
->arr
[1];
365 value_set_si(rel
->arr
[2].d
, 1);
366 value_init(rel
->arr
[2].x
.n
);
367 value_set_si(rel
->arr
[2].x
.n
, 0);
372 void eadd(evalue
*e1
,evalue
*res
) {
375 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
376 /* Add two rational numbers */
382 value_multiply(m1
,e1
->x
.n
,res
->d
);
383 value_multiply(m2
,res
->x
.n
,e1
->d
);
384 value_addto(res
->x
.n
,m1
,m2
);
385 value_multiply(res
->d
,e1
->d
,res
->d
);
386 Gcd(res
->x
.n
,res
->d
,&g
);
387 if (value_notone_p(g
)) {
388 value_division(res
->d
,res
->d
,g
);
389 value_division(res
->x
.n
,res
->x
.n
,g
);
391 value_clear(g
); value_clear(m1
); value_clear(m2
);
394 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
395 switch (res
->x
.p
->type
) {
397 /* Add the constant to the constant term of a polynomial*/
398 eadd(e1
, &res
->x
.p
->arr
[0]);
401 /* Add the constant to all elements of a periodic number */
402 for (i
=0; i
<res
->x
.p
->size
; i
++) {
403 eadd(e1
, &res
->x
.p
->arr
[i
]);
407 fprintf(stderr
, "eadd: cannot add const with vector\n");
410 eadd(e1
, &res
->x
.p
->arr
[1]);
413 assert(EVALUE_IS_ZERO(*e1
));
414 break; /* Do nothing */
416 /* Create (zero) complement if needed */
417 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
418 explicit_complement(res
);
419 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
420 eadd(e1
, &res
->x
.p
->arr
[i
]);
426 /* add polynomial or periodic to constant
427 * you have to exchange e1 and res, before doing addition */
429 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
433 else { // ((e1->d==0) && (res->d==0))
434 assert(!((e1
->x
.p
->type
== partition
) ^
435 (res
->x
.p
->type
== partition
)));
436 if (e1
->x
.p
->type
== partition
) {
437 eadd_partitions(e1
, res
);
440 if (e1
->x
.p
->type
== relation
&&
441 (res
->x
.p
->type
!= relation
||
442 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
446 if (res
->x
.p
->type
== relation
) {
447 if (e1
->x
.p
->type
== relation
&&
448 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
449 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
450 explicit_complement(res
);
451 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
452 explicit_complement(e1
);
453 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
454 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
457 if (res
->x
.p
->size
< 3)
458 explicit_complement(res
);
459 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
460 eadd(e1
, &res
->x
.p
->arr
[i
]);
463 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
464 /* adding to evalues of different type. two cases are possible
465 * res is periodic and e1 is polynomial, you have to exchange
466 * e1 and res then to add e1 to the constant term of res */
467 if (e1
->x
.p
->type
== polynomial
) {
468 eadd_rev_cst(e1
, res
);
470 else if (res
->x
.p
->type
== polynomial
) {
471 /* res is polynomial and e1 is periodic,
472 add e1 to the constant term of res */
474 eadd(e1
,&res
->x
.p
->arr
[0]);
480 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
481 (res
->x
.p
->type
== modulo
&&
482 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
483 /* adding evalues of different position (i.e function of different unknowns
484 * to case are possible */
486 switch (res
->x
.p
->type
) {
488 if(mod_term_smaller(res
, e1
))
489 eadd(e1
,&res
->x
.p
->arr
[1]);
491 eadd_rev_cst(e1
, res
);
493 case polynomial
: // res and e1 are polynomials
494 // add e1 to the constant term of res
496 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
497 eadd(e1
,&res
->x
.p
->arr
[0]);
499 eadd_rev_cst(e1
, res
);
500 // value_clear(g); value_clear(m1); value_clear(m2);
502 case periodic
: // res and e1 are pointers to periodic numbers
503 //add e1 to all elements of res
505 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
506 for (i
=0;i
<res
->x
.p
->size
;i
++) {
507 eadd(e1
,&res
->x
.p
->arr
[i
]);
516 //same type , same pos and same size
517 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
518 // add any element in e1 to the corresponding element in res
519 if (res
->x
.p
->type
== modulo
)
520 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
521 i
= res
->x
.p
->type
== modulo
? 1 : 0;
522 for (; i
<res
->x
.p
->size
; i
++) {
523 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
528 /* Sizes are different */
529 switch(res
->x
.p
->type
) {
532 /* VIN100: if e1-size > res-size you have to copy e1 in a */
533 /* new enode and add res to that new node. If you do not do */
534 /* that, you lose the the upper weight part of e1 ! */
536 if(e1
->x
.p
->size
> res
->x
.p
->size
)
540 if (res
->x
.p
->type
== modulo
)
541 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
542 i
= res
->x
.p
->type
== modulo
? 1 : 0;
543 for (; i
<e1
->x
.p
->size
; i
++) {
544 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
551 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
554 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
555 of the sizes of e1 and res, then to copy res periodicaly in ne, after
556 to add periodicaly elements of e1 to elements of ne, and finaly to
561 value_init(ex
); value_init(ey
);value_init(ep
);
564 value_set_si(ex
,e1
->x
.p
->size
);
565 value_set_si(ey
,res
->x
.p
->size
);
566 value_assign (ep
,*Lcm(ex
,ey
));
567 p
=(int)mpz_get_si(ep
);
568 ne
= (evalue
*) malloc (sizeof(evalue
));
570 value_set_si( ne
->d
,0);
572 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
574 value_assign(ne
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%y
].d
);
575 if (value_notzero_p(ne
->x
.p
->arr
[i
].d
)) {
576 value_init(ne
->x
.p
->arr
[i
].x
.n
);
577 value_assign(ne
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%y
].x
.n
);
580 ne
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%y
].x
.p
);
584 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
587 value_assign(res
->d
, ne
->d
);
593 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
600 static void emul_rev (evalue
*e1
, evalue
*res
)
604 evalue_copy(&ev
, e1
);
606 free_evalue_refs(res
);
610 static void emul_poly (evalue
*e1
, evalue
*res
)
612 int i
, j
, o
= res
->x
.p
->type
== modulo
;
614 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
616 value_set_si(tmp
.d
,0);
617 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
619 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
620 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
621 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
622 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
625 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
626 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
627 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
630 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
631 emul(&res
->x
.p
->arr
[i
], &ev
);
632 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
633 free_evalue_refs(&ev
);
635 free_evalue_refs(res
);
639 void emul_partitions (evalue
*e1
,evalue
*res
)
644 s
= (struct section
*)
645 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
646 sizeof(struct section
));
650 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
651 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
652 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
653 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
659 /* This code is only needed because the partitions
660 are not true partitions.
662 for (k
= 0; k
< n
; ++k
) {
663 if (DomainIncludes(s
[k
].D
, d
))
665 if (DomainIncludes(d
, s
[k
].D
)) {
667 free_evalue_refs(&s
[k
].E
);
678 value_init(s
[n
].E
.d
);
679 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
680 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
684 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
685 value_clear(res
->x
.p
->arr
[2*i
].d
);
686 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
690 res
->x
.p
= new_enode(partition
, 2*n
, -1);
691 for (j
= 0; j
< n
; ++j
) {
692 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
693 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
694 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
700 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
701 * do a copy of "res" befor calling this function if you nead it after. The vector type of
702 * evalues is not treated here */
704 void emul (evalue
*e1
, evalue
*res
){
707 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
708 fprintf(stderr
, "emul: do not proced on evector type !\n");
712 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
713 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
714 emul_partitions(e1
, res
);
717 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
718 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
719 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
721 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
722 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
723 emul(e1
, &res
->x
.p
->arr
[i
]);
725 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
726 switch(e1
->x
.p
->type
) {
728 switch(res
->x
.p
->type
) {
730 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
731 /* Product of two polynomials of the same variable */
736 /* Product of two polynomials of different variables */
738 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
739 for( i
=0; i
<res
->x
.p
->size
; i
++)
740 emul(e1
, &res
->x
.p
->arr
[i
]);
748 /* Product of a polynomial and a periodic or modulo */
753 switch(res
->x
.p
->type
) {
755 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
756 /* Product of two periodics of the same parameter and period */
758 for(i
=0; i
<res
->x
.p
->size
;i
++)
759 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
764 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
765 /* Product of two periodics of the same parameter and different periods */
769 value_init(x
); value_init(y
);value_init(z
);
772 value_set_si(x
,e1
->x
.p
->size
);
773 value_set_si(y
,res
->x
.p
->size
);
774 value_assign (z
,*Lcm(x
,y
));
775 lcm
=(int)mpz_get_si(z
);
776 newp
= (evalue
*) malloc (sizeof(evalue
));
778 value_set_si( newp
->d
,0);
779 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
781 value_assign(newp
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%iy
].d
);
782 if (value_notzero_p(newp
->x
.p
->arr
[i
].d
)) {
783 value_assign(newp
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%iy
].x
.n
);
786 newp
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%iy
].x
.p
);
791 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
793 value_assign(res
->d
,newp
->d
);
796 value_clear(x
); value_clear(y
);value_clear(z
);
800 /* Product of two periodics of different parameters */
802 for(i
=0; i
<res
->x
.p
->size
; i
++)
803 emul(e1
, &(res
->x
.p
->arr
[i
]));
809 /* Product of a periodic and a polynomial */
811 for(i
=0; i
<res
->x
.p
->size
; i
++)
812 emul(e1
, &(res
->x
.p
->arr
[i
]));
818 switch(res
->x
.p
->type
) {
820 for(i
=0; i
<res
->x
.p
->size
; i
++)
821 emul(e1
, &(res
->x
.p
->arr
[i
]));
826 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
827 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
828 if (e1
->x
.p
->pos
!= 2)
832 /* x mod 2 == (x mod 2)^2 */
833 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1) (x mod 2) */
834 assert(e1
->x
.p
->size
== 3);
835 assert(res
->x
.p
->size
== 3);
837 evalue_copy(&tmp
, &res
->x
.p
->arr
[1]);
838 eadd(&res
->x
.p
->arr
[2], &tmp
);
839 emul(&e1
->x
.p
->arr
[2], &tmp
);
840 emul(&e1
->x
.p
->arr
[1], res
);
841 eadd(&tmp
, &res
->x
.p
->arr
[2]);
842 free_evalue_refs(&tmp
);
845 if(mod_term_smaller(res
, e1
))
846 for(i
=1; i
<res
->x
.p
->size
; i
++)
847 emul(e1
, &(res
->x
.p
->arr
[i
]));
862 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
863 /* Product of two rational numbers */
867 value_multiply(res
->d
,e1
->d
,res
->d
);
868 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
869 Gcd(res
->x
.n
, res
->d
,&g
);
870 if (value_notone_p(g
)) {
871 value_division(res
->d
,res
->d
,g
);
872 value_division(res
->x
.n
,res
->x
.n
,g
);
878 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
879 /* Product of an expression (polynomial or peririodic) and a rational number */
885 /* Product of a rationel number and an expression (polynomial or peririodic) */
887 i
= res
->x
.p
->type
== modulo
? 1 : 0;
888 for (; i
<res
->x
.p
->size
; i
++)
889 emul(e1
, &res
->x
.p
->arr
[i
]);
900 void emask(evalue
*mask
, evalue
*res
) {
906 assert(mask
->x
.p
->type
== partition
);
907 assert(res
->x
.p
->type
== partition
);
909 s
= (struct section
*)
910 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
911 sizeof(struct section
));
915 evalue_set_si(&mone
, -1, 1);
918 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
919 assert(mask
->x
.p
->size
>= 2);
920 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
921 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
923 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
925 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
934 value_init(s
[n
].E
.d
);
935 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
939 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
940 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
941 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
942 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
943 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
945 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
946 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
952 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
953 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
955 value_init(s
[n
].E
.d
);
956 evalue_copy(&s
[n
].E
, &mask
->x
.p
->arr
[2*i
+1]);
957 emul(&res
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
962 assert(0); // We don't allow this.
966 free_evalue_refs(&mone
);
967 free_evalue_refs(mask
);
968 free_evalue_refs(res
);
970 res
->x
.p
= new_enode(partition
, 2*n
, -1);
971 for (j
= 0; j
< n
; ++j
) {
972 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
973 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
974 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
980 void evalue_copy(evalue
*dst
, evalue
*src
)
982 value_assign(dst
->d
, src
->d
);
983 if(value_notzero_p(src
->d
)) {
984 value_init(dst
->x
.n
);
985 value_assign(dst
->x
.n
, src
->x
.n
);
987 dst
->x
.p
= ecopy(src
->x
.p
);
990 enode
*new_enode(enode_type type
,int size
,int pos
) {
996 fprintf(stderr
, "Allocating enode of size 0 !\n" );
999 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1003 for(i
=0; i
<size
; i
++) {
1004 value_init(res
->arr
[i
].d
);
1005 value_set_si(res
->arr
[i
].d
,0);
1006 res
->arr
[i
].x
.p
= 0;
1011 enode
*ecopy(enode
*e
) {
1016 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1017 for(i
=0;i
<e
->size
;++i
) {
1018 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1019 if(value_zero_p(res
->arr
[i
].d
))
1020 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1021 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1022 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1024 value_init(res
->arr
[i
].x
.n
);
1025 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1031 int eequal(evalue
*e1
,evalue
*e2
) {
1036 if (value_ne(e1
->d
,e2
->d
))
1039 /* e1->d == e2->d */
1040 if (value_notzero_p(e1
->d
)) {
1041 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1044 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1048 /* e1->d == e2->d == 0 */
1051 if (p1
->type
!= p2
->type
) return 0;
1052 if (p1
->size
!= p2
->size
) return 0;
1053 if (p1
->pos
!= p2
->pos
) return 0;
1054 for (i
=0; i
<p1
->size
; i
++)
1055 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1060 void free_evalue_refs(evalue
*e
) {
1065 if (EVALUE_IS_DOMAIN(*e
)) {
1066 Domain_Free(EVALUE_DOMAIN(*e
));
1069 } else if (value_pos_p(e
->d
)) {
1071 /* 'e' stores a constant */
1073 value_clear(e
->x
.n
);
1076 assert(value_zero_p(e
->d
));
1079 if (!p
) return; /* null pointer */
1080 for (i
=0; i
<p
->size
; i
++) {
1081 free_evalue_refs(&(p
->arr
[i
]));
1085 } /* free_evalue_refs */
1087 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1088 Vector
* val
, evalue
*res
)
1090 unsigned nparam
= periods
->Size
;
1093 double d
= compute_evalue(e
, val
->p
);
1098 value_set_si(res
->d
, 1);
1099 value_init(res
->x
.n
);
1100 value_set_double(res
->x
.n
, d
);
1101 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1104 if (value_one_p(periods
->p
[p
]))
1105 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1110 value_assign(tmp
, periods
->p
[p
]);
1111 value_set_si(res
->d
, 0);
1112 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1114 value_decrement(tmp
, tmp
);
1115 value_assign(val
->p
[p
], tmp
);
1116 mod2table_r(e
, periods
, m
, p
+1, val
,
1117 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1118 } while (value_pos_p(tmp
));
1124 void evalue_mod2table(evalue
*e
, int nparam
)
1129 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1132 for (i
=0; i
<p
->size
; i
++) {
1133 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1135 if (p
->type
== modulo
) {
1136 Vector
*periods
= Vector_Alloc(nparam
);
1137 Vector
*val
= Vector_Alloc(nparam
);
1143 value_set_si(tmp
, p
->pos
);
1144 Vector_Set(periods
->p
, 1, nparam
);
1145 Vector_Set(val
->p
, 0, nparam
);
1146 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1149 assert(p
->type
== polynomial
);
1150 assert(p
->size
== 2);
1151 assert(value_one_p(p
->arr
[1].d
));
1152 Gcd(tmp
, p
->arr
[1].x
.n
, &periods
->p
[p
->pos
-1]);
1153 value_division(periods
->p
[p
->pos
-1], tmp
, periods
->p
[p
->pos
-1]);
1155 value_set_si(tmp
, p
->pos
);
1157 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1160 evalue_set_si(&res
, 0, 1);
1161 /* Compute the polynomial using Horner's rule */
1162 for (i
=p
->size
-1;i
>1;i
--) {
1163 eadd(&p
->arr
[i
], &res
);
1166 eadd(&p
->arr
[1], &res
);
1168 free_evalue_refs(e
);
1169 free_evalue_refs(&EP
);
1174 Vector_Free(periods
);
1176 } /* evalue_mod2table */
1178 /********************************************************/
1179 /* function in domain */
1180 /* check if the parameters in list_args */
1181 /* verifies the constraints of Domain P */
1182 /********************************************************/
1183 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1186 Value v
; /* value of the constraint of a row when
1187 parameters are instanciated*/
1193 /*P->Constraint constraint matrice of polyhedron P*/
1194 for(row
=0;row
<P
->NbConstraints
;row
++) {
1195 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1196 for(col
=1;col
<P
->Dimension
+1;col
++) {
1197 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1198 value_addto(v
,v
,tmp
);
1200 if (value_notzero_p(P
->Constraint
[row
][0])) {
1202 /*if v is not >=0 then this constraint is not respected */
1203 if (value_neg_p(v
)) {
1207 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1212 /*if v is not = 0 then this constraint is not respected */
1213 if (value_notzero_p(v
))
1218 /*if not return before this point => all
1219 the constraints are respected */
1225 /****************************************************/
1226 /* function compute enode */
1227 /* compute the value of enode p with parameters */
1228 /* list "list_args */
1229 /* compute the polynomial or the periodic */
1230 /****************************************************/
1232 static double compute_enode(enode
*p
, Value
*list_args
) {
1244 if (p
->type
== polynomial
) {
1246 value_assign(param
,list_args
[p
->pos
-1]);
1248 /* Compute the polynomial using Horner's rule */
1249 for (i
=p
->size
-1;i
>0;i
--) {
1250 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1251 res
*=VALUE_TO_DOUBLE(param
);
1253 res
+=compute_evalue(&p
->arr
[0],list_args
);
1255 else if (p
->type
== modulo
) {
1256 double d
= compute_evalue(&p
->arr
[0], list_args
);
1261 value_set_double(param
, d
);
1262 value_set_si(m
, p
->pos
);
1263 mpz_fdiv_r(param
, param
, m
);
1265 /* Compute the polynomial using Horner's rule */
1266 for (i
=p
->size
-1;i
>1;i
--) {
1267 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1268 res
*=VALUE_TO_DOUBLE(param
);
1270 res
+=compute_evalue(&p
->arr
[1],list_args
);
1272 else if (p
->type
== periodic
) {
1273 value_assign(param
,list_args
[p
->pos
-1]);
1275 /* Choose the right element of the periodic */
1276 value_absolute(m
,param
);
1277 value_set_si(param
,p
->size
);
1278 value_modulus(m
,m
,param
);
1279 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
1281 else if (p
->type
== relation
) {
1282 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 0.5)
1283 res
= compute_evalue(&p
->arr
[1], list_args
);
1284 else if (p
->size
> 2)
1285 res
= compute_evalue(&p
->arr
[2], list_args
);
1287 else if (p
->type
== partition
) {
1288 for (i
= 0; i
< p
->size
/2; ++i
)
1289 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
1290 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
1297 } /* compute_enode */
1299 /*************************************************/
1300 /* return the value of Ehrhart Polynomial */
1301 /* It returns a double, because since it is */
1302 /* a recursive function, some intermediate value */
1303 /* might not be integral */
1304 /*************************************************/
1306 double compute_evalue(evalue
*e
,Value
*list_args
) {
1310 if (value_notzero_p(e
->d
)) {
1311 if (value_notone_p(e
->d
))
1312 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
1314 res
= VALUE_TO_DOUBLE(e
->x
.n
);
1317 res
= compute_enode(e
->x
.p
,list_args
);
1319 } /* compute_evalue */
1322 /****************************************************/
1323 /* function compute_poly : */
1324 /* Check for the good validity domain */
1325 /* return the number of point in the Polyhedron */
1326 /* in allocated memory */
1327 /* Using the Ehrhart pseudo-polynomial */
1328 /****************************************************/
1329 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
1332 /* double d; int i; */
1334 tmp
= (Value
*) malloc (sizeof(Value
));
1335 assert(tmp
!= NULL
);
1337 value_set_si(*tmp
,0);
1340 return(tmp
); /* no ehrhart polynomial */
1341 if(en
->ValidityDomain
) {
1342 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
1343 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1348 return(tmp
); /* no Validity Domain */
1350 if(in_domain(en
->ValidityDomain
,list_args
)) {
1352 #ifdef EVAL_EHRHART_DEBUG
1353 Print_Domain(stdout
,en
->ValidityDomain
);
1354 print_evalue(stdout
,&en
->EP
);
1357 /* d = compute_evalue(&en->EP,list_args);
1359 printf("(double)%lf = %d\n", d, i ); */
1360 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1366 value_set_si(*tmp
,0);
1367 return(tmp
); /* no compatible domain with the arguments */
1368 } /* compute_poly */