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 */
70 void _reduce_evalue (evalue
*e
, int n
, struct fixed_param
*fixed
) {
75 if (value_notzero_p(e
->d
))
76 return; /* a rational number, its already reduced */
78 return; /* hum... an overflow probably occured */
80 /* First reduce the components of p */
81 for (i
=0; i
<p
->size
; i
++)
82 _reduce_evalue(&p
->arr
[i
], n
, fixed
);
84 if (p
->type
==periodic
) {
86 /* Try to reduce the period */
87 for (i
=1; i
<=(p
->size
)/2; i
++) {
88 if ((p
->size
% i
)==0) {
90 /* Can we reduce the size to i ? */
92 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
93 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
96 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
100 you_lose
: /* OK, lets not do it */
105 /* Try to reduce its strength */
108 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
112 else if (p
->type
==polynomial
) {
113 for (k
= 0; k
< n
; ++k
) {
114 if (fixed
[k
].pos
== p
->pos
) {
117 value_set_si(v
.d
, 1);
119 value_assign(v
.x
.n
, fixed
[k
].v
);
120 for (i
=p
->size
-1;i
>=1;i
--) {
121 emul(&v
, &p
->arr
[i
]);
122 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
123 free_evalue_refs(&(p
->arr
[i
]));
126 free_evalue_refs(&v
);
130 /* Try to reduce the degree */
131 for (i
=p
->size
-1;i
>=1;i
--) {
132 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
134 /* Zero coefficient */
135 free_evalue_refs(&(p
->arr
[i
]));
140 /* Try to reduce its strength */
143 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
147 else if (p
->type
==modulo
) {
148 if (value_notzero_p(p
->arr
[0].d
)) {
151 value_set_si(v
.d
, 1);
153 value_set_si(p
->arr
[0].d
, p
->pos
);
154 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
156 for (i
=p
->size
-1;i
>=2;i
--) {
157 emul(&v
, &p
->arr
[i
]);
158 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
159 free_evalue_refs(&(p
->arr
[i
]));
162 free_evalue_refs(&v
);
165 /* Try to reduce the degree */
166 for (i
=p
->size
-1;i
>=2;i
--) {
167 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
169 /* Zero coefficient */
170 free_evalue_refs(&(p
->arr
[i
]));
175 /* Try to reduce its strength */
178 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
179 free_evalue_refs(&(p
->arr
[0]));
183 else if (p
->type
== relation
) {
184 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
185 free_evalue_refs(&(p
->arr
[2]));
188 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
189 free_evalue_refs(&(p
->arr
[1]));
190 free_evalue_refs(&(p
->arr
[0]));
191 evalue_set_si(e
, 0, 1);
194 } /* reduce_evalue */
196 void reduce_evalue (evalue
*e
) {
197 if (value_notzero_p(e
->d
))
198 return; /* a rational number, its already reduced */
200 if (e
->x
.p
->type
== partition
) {
203 struct fixed_param
*fixed
= 0;
205 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
207 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
209 if (!D
->next
&& D
->NbEq
) {
212 fixed
= (struct fixed_param
*)
213 malloc(D
->Dimension
* sizeof(*fixed
));
214 for (j
= 0; j
< dim
; ++j
)
215 value_init(fixed
[j
].v
);
217 for (j
= 0; j
< D
->NbEq
; ++j
) {
218 for (k
= 0; k
< D
->Dimension
; ++k
)
219 if (value_notzero_p(D
->Constraint
[j
][k
+1])) {
221 if (value_one_p(D
->Constraint
[j
][k
+1]))
222 value_oppose(fixed
[n
].v
, D
->Constraint
[j
][dim
+1]);
223 else if (value_mone_p(D
->Constraint
[j
][k
+1]))
224 value_assign(fixed
[n
].v
, D
->Constraint
[j
][dim
+1]);
231 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], n
, fixed
);
235 for (j
= 0; j
< dim
; ++j
)
236 value_clear(fixed
[j
].v
);
240 _reduce_evalue(e
, 0, 0);
243 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
245 if(value_notzero_p(e
->d
)) {
246 if(value_notone_p(e
->d
)) {
247 value_print(DST
,VALUE_FMT
,e
->x
.n
);
249 value_print(DST
,VALUE_FMT
,e
->d
);
252 value_print(DST
,VALUE_FMT
,e
->x
.n
);
256 print_enode(DST
,e
->x
.p
,pname
);
260 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
265 fprintf(DST
, "NULL");
271 for (i
=0; i
<p
->size
; i
++) {
272 print_evalue(DST
, &p
->arr
[i
], pname
);
276 fprintf(DST
, " }\n");
280 for (i
=p
->size
-1; i
>=0; i
--) {
281 print_evalue(DST
, &p
->arr
[i
], pname
);
282 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
284 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
286 fprintf(DST
, " )\n");
290 for (i
=0; i
<p
->size
; i
++) {
291 print_evalue(DST
, &p
->arr
[i
], pname
);
292 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
294 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
298 for (i
=p
->size
-1; i
>=1; i
--) {
299 print_evalue(DST
, &p
->arr
[i
], pname
);
305 print_evalue(DST
, &p
->arr
[0], pname
);
306 fprintf(DST
, ") mod %d", p
->pos
);
308 fprintf(DST
, ")^%d + ", i
-1);
310 fprintf(DST
, " + ", i
-1);
313 fprintf(DST
, " )\n");
317 print_evalue(DST
, &p
->arr
[0], pname
);
318 fprintf(DST
, "= 0 ] * \n");
319 print_evalue(DST
, &p
->arr
[1], pname
);
321 fprintf(DST
, " +\n [ ");
322 print_evalue(DST
, &p
->arr
[0], pname
);
323 fprintf(DST
, "!= 0 ] * \n");
324 print_evalue(DST
, &p
->arr
[2], pname
);
328 for (i
=0; i
<p
->size
/2; i
++) {
329 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
330 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
339 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
341 if (value_notzero_p(e1
->d
)) {
342 if (value_zero_p(e2
->d
))
344 return value_lt(e1
->x
.n
, e2
->x
.n
);
346 if (value_notzero_p(e2
->d
))
348 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
350 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
353 return mod_term_smaller(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
356 static void eadd_rev(evalue
*e1
, evalue
*res
)
360 evalue_copy(&ev
, e1
);
362 free_evalue_refs(res
);
366 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
370 evalue_copy(&ev
, e1
);
371 eadd(res
, &ev
.x
.p
->arr
[ev
.x
.p
->type
==modulo
]);
372 free_evalue_refs(res
);
376 struct section
{ Polyhedron
* D
; evalue E
; };
378 void eadd_partitions (evalue
*e1
,evalue
*res
)
383 s
= (struct section
*)
384 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
385 sizeof(struct section
));
389 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
390 assert(res
->x
.p
->size
>= 2);
391 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
392 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
394 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
396 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
405 value_init(s
[n
].E
.d
);
406 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
410 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
411 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
412 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
414 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
415 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
421 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
422 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
424 value_init(s
[n
].E
.d
);
425 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
426 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
431 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
435 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
436 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
437 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
438 value_clear(res
->x
.p
->arr
[2*i
].d
);
442 res
->x
.p
= new_enode(partition
, 2*n
, -1);
443 for (j
= 0; j
< n
; ++j
) {
444 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
445 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
446 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
452 static void explicit_complement(evalue
*res
)
454 enode
*rel
= new_enode(relation
, 3, 0);
456 value_clear(rel
->arr
[0].d
);
457 rel
->arr
[0] = res
->x
.p
->arr
[0];
458 value_clear(rel
->arr
[1].d
);
459 rel
->arr
[1] = res
->x
.p
->arr
[1];
460 value_set_si(rel
->arr
[2].d
, 1);
461 value_init(rel
->arr
[2].x
.n
);
462 value_set_si(rel
->arr
[2].x
.n
, 0);
467 void eadd(evalue
*e1
,evalue
*res
) {
470 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
471 /* Add two rational numbers */
477 value_multiply(m1
,e1
->x
.n
,res
->d
);
478 value_multiply(m2
,res
->x
.n
,e1
->d
);
479 value_addto(res
->x
.n
,m1
,m2
);
480 value_multiply(res
->d
,e1
->d
,res
->d
);
481 Gcd(res
->x
.n
,res
->d
,&g
);
482 if (value_notone_p(g
)) {
483 value_division(res
->d
,res
->d
,g
);
484 value_division(res
->x
.n
,res
->x
.n
,g
);
486 value_clear(g
); value_clear(m1
); value_clear(m2
);
489 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
490 switch (res
->x
.p
->type
) {
492 /* Add the constant to the constant term of a polynomial*/
493 eadd(e1
, &res
->x
.p
->arr
[0]);
496 /* Add the constant to all elements of a periodic number */
497 for (i
=0; i
<res
->x
.p
->size
; i
++) {
498 eadd(e1
, &res
->x
.p
->arr
[i
]);
502 fprintf(stderr
, "eadd: cannot add const with vector\n");
505 eadd(e1
, &res
->x
.p
->arr
[1]);
508 assert(EVALUE_IS_ZERO(*e1
));
509 break; /* Do nothing */
511 /* Create (zero) complement if needed */
512 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
513 explicit_complement(res
);
514 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
515 eadd(e1
, &res
->x
.p
->arr
[i
]);
521 /* add polynomial or periodic to constant
522 * you have to exchange e1 and res, before doing addition */
524 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
528 else { // ((e1->d==0) && (res->d==0))
529 assert(!((e1
->x
.p
->type
== partition
) ^
530 (res
->x
.p
->type
== partition
)));
531 if (e1
->x
.p
->type
== partition
) {
532 eadd_partitions(e1
, res
);
535 if (e1
->x
.p
->type
== relation
&&
536 (res
->x
.p
->type
!= relation
||
537 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
541 if (res
->x
.p
->type
== relation
) {
542 if (e1
->x
.p
->type
== relation
&&
543 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
544 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
545 explicit_complement(res
);
546 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
547 explicit_complement(e1
);
548 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
549 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
552 if (res
->x
.p
->size
< 3)
553 explicit_complement(res
);
554 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
555 eadd(e1
, &res
->x
.p
->arr
[i
]);
558 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
559 /* adding to evalues of different type. two cases are possible
560 * res is periodic and e1 is polynomial, you have to exchange
561 * e1 and res then to add e1 to the constant term of res */
562 if (e1
->x
.p
->type
== polynomial
) {
563 eadd_rev_cst(e1
, res
);
565 else if (res
->x
.p
->type
== polynomial
) {
566 /* res is polynomial and e1 is periodic,
567 add e1 to the constant term of res */
569 eadd(e1
,&res
->x
.p
->arr
[0]);
575 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
576 (res
->x
.p
->type
== modulo
&&
577 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
578 /* adding evalues of different position (i.e function of different unknowns
579 * to case are possible */
581 switch (res
->x
.p
->type
) {
583 if(mod_term_smaller(res
, e1
))
584 eadd(e1
,&res
->x
.p
->arr
[1]);
586 eadd_rev_cst(e1
, res
);
588 case polynomial
: // res and e1 are polynomials
589 // add e1 to the constant term of res
591 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
592 eadd(e1
,&res
->x
.p
->arr
[0]);
594 eadd_rev_cst(e1
, res
);
595 // value_clear(g); value_clear(m1); value_clear(m2);
597 case periodic
: // res and e1 are pointers to periodic numbers
598 //add e1 to all elements of res
600 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
601 for (i
=0;i
<res
->x
.p
->size
;i
++) {
602 eadd(e1
,&res
->x
.p
->arr
[i
]);
611 //same type , same pos and same size
612 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
613 // add any element in e1 to the corresponding element in res
614 if (res
->x
.p
->type
== modulo
)
615 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
616 i
= res
->x
.p
->type
== modulo
? 1 : 0;
617 for (; i
<res
->x
.p
->size
; i
++) {
618 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
623 /* Sizes are different */
624 switch(res
->x
.p
->type
) {
627 /* VIN100: if e1-size > res-size you have to copy e1 in a */
628 /* new enode and add res to that new node. If you do not do */
629 /* that, you lose the the upper weight part of e1 ! */
631 if(e1
->x
.p
->size
> res
->x
.p
->size
)
635 if (res
->x
.p
->type
== modulo
)
636 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
637 i
= res
->x
.p
->type
== modulo
? 1 : 0;
638 for (; i
<e1
->x
.p
->size
; i
++) {
639 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
646 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
649 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
650 of the sizes of e1 and res, then to copy res periodicaly in ne, after
651 to add periodicaly elements of e1 to elements of ne, and finaly to
656 value_init(ex
); value_init(ey
);value_init(ep
);
659 value_set_si(ex
,e1
->x
.p
->size
);
660 value_set_si(ey
,res
->x
.p
->size
);
661 value_assign (ep
,*Lcm(ex
,ey
));
662 p
=(int)mpz_get_si(ep
);
663 ne
= (evalue
*) malloc (sizeof(evalue
));
665 value_set_si( ne
->d
,0);
667 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
669 value_assign(ne
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%y
].d
);
670 if (value_notzero_p(ne
->x
.p
->arr
[i
].d
)) {
671 value_init(ne
->x
.p
->arr
[i
].x
.n
);
672 value_assign(ne
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%y
].x
.n
);
675 ne
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%y
].x
.p
);
679 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
682 value_assign(res
->d
, ne
->d
);
688 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
695 static void emul_rev (evalue
*e1
, evalue
*res
)
699 evalue_copy(&ev
, e1
);
701 free_evalue_refs(res
);
705 static void emul_poly (evalue
*e1
, evalue
*res
)
707 int i
, j
, o
= res
->x
.p
->type
== modulo
;
709 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
711 value_set_si(tmp
.d
,0);
712 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
714 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
715 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
716 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
717 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
720 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
721 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
722 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
725 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
726 emul(&res
->x
.p
->arr
[i
], &ev
);
727 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
728 free_evalue_refs(&ev
);
730 free_evalue_refs(res
);
734 void emul_partitions (evalue
*e1
,evalue
*res
)
739 s
= (struct section
*)
740 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
741 sizeof(struct section
));
745 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
746 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
747 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
748 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
754 /* This code is only needed because the partitions
755 are not true partitions.
757 for (k
= 0; k
< n
; ++k
) {
758 if (DomainIncludes(s
[k
].D
, d
))
760 if (DomainIncludes(d
, s
[k
].D
)) {
762 free_evalue_refs(&s
[k
].E
);
773 value_init(s
[n
].E
.d
);
774 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
775 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
779 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
780 value_clear(res
->x
.p
->arr
[2*i
].d
);
781 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
785 res
->x
.p
= new_enode(partition
, 2*n
, -1);
786 for (j
= 0; j
< n
; ++j
) {
787 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
788 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
789 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
795 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
796 * do a copy of "res" befor calling this function if you nead it after. The vector type of
797 * evalues is not treated here */
799 void emul (evalue
*e1
, evalue
*res
){
802 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
803 fprintf(stderr
, "emul: do not proced on evector type !\n");
807 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
808 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
809 emul_partitions(e1
, res
);
812 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
813 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
814 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
816 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
817 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
818 emul(e1
, &res
->x
.p
->arr
[i
]);
820 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
821 switch(e1
->x
.p
->type
) {
823 switch(res
->x
.p
->type
) {
825 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
826 /* Product of two polynomials of the same variable */
831 /* Product of two polynomials of different variables */
833 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
834 for( i
=0; i
<res
->x
.p
->size
; i
++)
835 emul(e1
, &res
->x
.p
->arr
[i
]);
843 /* Product of a polynomial and a periodic or modulo */
848 switch(res
->x
.p
->type
) {
850 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
851 /* Product of two periodics of the same parameter and period */
853 for(i
=0; i
<res
->x
.p
->size
;i
++)
854 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
859 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
860 /* Product of two periodics of the same parameter and different periods */
864 value_init(x
); value_init(y
);value_init(z
);
867 value_set_si(x
,e1
->x
.p
->size
);
868 value_set_si(y
,res
->x
.p
->size
);
869 value_assign (z
,*Lcm(x
,y
));
870 lcm
=(int)mpz_get_si(z
);
871 newp
= (evalue
*) malloc (sizeof(evalue
));
873 value_set_si( newp
->d
,0);
874 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
876 value_assign(newp
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%iy
].d
);
877 if (value_notzero_p(newp
->x
.p
->arr
[i
].d
)) {
878 value_assign(newp
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%iy
].x
.n
);
881 newp
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%iy
].x
.p
);
886 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
888 value_assign(res
->d
,newp
->d
);
891 value_clear(x
); value_clear(y
);value_clear(z
);
895 /* Product of two periodics of different parameters */
897 for(i
=0; i
<res
->x
.p
->size
; i
++)
898 emul(e1
, &(res
->x
.p
->arr
[i
]));
904 /* Product of a periodic and a polynomial */
906 for(i
=0; i
<res
->x
.p
->size
; i
++)
907 emul(e1
, &(res
->x
.p
->arr
[i
]));
913 switch(res
->x
.p
->type
) {
915 for(i
=0; i
<res
->x
.p
->size
; i
++)
916 emul(e1
, &(res
->x
.p
->arr
[i
]));
921 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
922 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
923 if (e1
->x
.p
->pos
!= 2)
927 /* x mod 2 == (x mod 2)^2 */
928 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1) (x mod 2) */
929 assert(e1
->x
.p
->size
== 3);
930 assert(res
->x
.p
->size
== 3);
932 evalue_copy(&tmp
, &res
->x
.p
->arr
[1]);
933 eadd(&res
->x
.p
->arr
[2], &tmp
);
934 emul(&e1
->x
.p
->arr
[2], &tmp
);
935 emul(&e1
->x
.p
->arr
[1], res
);
936 eadd(&tmp
, &res
->x
.p
->arr
[2]);
937 free_evalue_refs(&tmp
);
940 if(mod_term_smaller(res
, e1
))
941 for(i
=1; i
<res
->x
.p
->size
; i
++)
942 emul(e1
, &(res
->x
.p
->arr
[i
]));
957 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
958 /* Product of two rational numbers */
962 value_multiply(res
->d
,e1
->d
,res
->d
);
963 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
964 Gcd(res
->x
.n
, res
->d
,&g
);
965 if (value_notone_p(g
)) {
966 value_division(res
->d
,res
->d
,g
);
967 value_division(res
->x
.n
,res
->x
.n
,g
);
973 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
974 /* Product of an expression (polynomial or peririodic) and a rational number */
980 /* Product of a rationel number and an expression (polynomial or peririodic) */
982 i
= res
->x
.p
->type
== modulo
? 1 : 0;
983 for (; i
<res
->x
.p
->size
; i
++)
984 emul(e1
, &res
->x
.p
->arr
[i
]);
995 void emask(evalue
*mask
, evalue
*res
) {
1001 assert(mask
->x
.p
->type
== partition
);
1002 assert(res
->x
.p
->type
== partition
);
1004 s
= (struct section
*)
1005 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1006 sizeof(struct section
));
1010 evalue_set_si(&mone
, -1, 1);
1013 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1014 assert(mask
->x
.p
->size
>= 2);
1015 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1016 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1018 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1020 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1029 value_init(s
[n
].E
.d
);
1030 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1034 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1035 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1036 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1037 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1038 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1040 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1041 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1047 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1048 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1050 value_init(s
[n
].E
.d
);
1051 evalue_copy(&s
[n
].E
, &mask
->x
.p
->arr
[2*i
+1]);
1052 emul(&res
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1057 assert(0); // We don't allow this.
1061 free_evalue_refs(&mone
);
1062 free_evalue_refs(mask
);
1063 free_evalue_refs(res
);
1065 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1066 for (j
= 0; j
< n
; ++j
) {
1067 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1068 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1069 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1075 void evalue_copy(evalue
*dst
, evalue
*src
)
1077 value_assign(dst
->d
, src
->d
);
1078 if(value_notzero_p(src
->d
)) {
1079 value_init(dst
->x
.n
);
1080 value_assign(dst
->x
.n
, src
->x
.n
);
1082 dst
->x
.p
= ecopy(src
->x
.p
);
1085 enode
*new_enode(enode_type type
,int size
,int pos
) {
1091 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1094 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1098 for(i
=0; i
<size
; i
++) {
1099 value_init(res
->arr
[i
].d
);
1100 value_set_si(res
->arr
[i
].d
,0);
1101 res
->arr
[i
].x
.p
= 0;
1106 enode
*ecopy(enode
*e
) {
1111 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1112 for(i
=0;i
<e
->size
;++i
) {
1113 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1114 if(value_zero_p(res
->arr
[i
].d
))
1115 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1116 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1117 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1119 value_init(res
->arr
[i
].x
.n
);
1120 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1126 int eequal(evalue
*e1
,evalue
*e2
) {
1131 if (value_ne(e1
->d
,e2
->d
))
1134 /* e1->d == e2->d */
1135 if (value_notzero_p(e1
->d
)) {
1136 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1139 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1143 /* e1->d == e2->d == 0 */
1146 if (p1
->type
!= p2
->type
) return 0;
1147 if (p1
->size
!= p2
->size
) return 0;
1148 if (p1
->pos
!= p2
->pos
) return 0;
1149 for (i
=0; i
<p1
->size
; i
++)
1150 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1155 void free_evalue_refs(evalue
*e
) {
1160 if (EVALUE_IS_DOMAIN(*e
)) {
1161 Domain_Free(EVALUE_DOMAIN(*e
));
1164 } else if (value_pos_p(e
->d
)) {
1166 /* 'e' stores a constant */
1168 value_clear(e
->x
.n
);
1171 assert(value_zero_p(e
->d
));
1174 if (!p
) return; /* null pointer */
1175 for (i
=0; i
<p
->size
; i
++) {
1176 free_evalue_refs(&(p
->arr
[i
]));
1180 } /* free_evalue_refs */
1182 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1183 Vector
* val
, evalue
*res
)
1185 unsigned nparam
= periods
->Size
;
1188 double d
= compute_evalue(e
, val
->p
);
1193 value_set_si(res
->d
, 1);
1194 value_init(res
->x
.n
);
1195 value_set_double(res
->x
.n
, d
);
1196 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1199 if (value_one_p(periods
->p
[p
]))
1200 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1205 value_assign(tmp
, periods
->p
[p
]);
1206 value_set_si(res
->d
, 0);
1207 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1209 value_decrement(tmp
, tmp
);
1210 value_assign(val
->p
[p
], tmp
);
1211 mod2table_r(e
, periods
, m
, p
+1, val
,
1212 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1213 } while (value_pos_p(tmp
));
1219 void evalue_mod2table(evalue
*e
, int nparam
)
1224 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1227 for (i
=0; i
<p
->size
; i
++) {
1228 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1230 if (p
->type
== modulo
) {
1231 Vector
*periods
= Vector_Alloc(nparam
);
1232 Vector
*val
= Vector_Alloc(nparam
);
1238 value_set_si(tmp
, p
->pos
);
1239 Vector_Set(periods
->p
, 1, nparam
);
1240 Vector_Set(val
->p
, 0, nparam
);
1241 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1244 assert(p
->type
== polynomial
);
1245 assert(p
->size
== 2);
1246 assert(value_one_p(p
->arr
[1].d
));
1247 Gcd(tmp
, p
->arr
[1].x
.n
, &periods
->p
[p
->pos
-1]);
1248 value_division(periods
->p
[p
->pos
-1], tmp
, periods
->p
[p
->pos
-1]);
1250 value_set_si(tmp
, p
->pos
);
1252 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1255 evalue_set_si(&res
, 0, 1);
1256 /* Compute the polynomial using Horner's rule */
1257 for (i
=p
->size
-1;i
>1;i
--) {
1258 eadd(&p
->arr
[i
], &res
);
1261 eadd(&p
->arr
[1], &res
);
1263 free_evalue_refs(e
);
1264 free_evalue_refs(&EP
);
1269 Vector_Free(periods
);
1271 } /* evalue_mod2table */
1273 /********************************************************/
1274 /* function in domain */
1275 /* check if the parameters in list_args */
1276 /* verifies the constraints of Domain P */
1277 /********************************************************/
1278 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1281 Value v
; /* value of the constraint of a row when
1282 parameters are instanciated*/
1288 /*P->Constraint constraint matrice of polyhedron P*/
1289 for(row
=0;row
<P
->NbConstraints
;row
++) {
1290 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1291 for(col
=1;col
<P
->Dimension
+1;col
++) {
1292 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1293 value_addto(v
,v
,tmp
);
1295 if (value_notzero_p(P
->Constraint
[row
][0])) {
1297 /*if v is not >=0 then this constraint is not respected */
1298 if (value_neg_p(v
)) {
1302 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1307 /*if v is not = 0 then this constraint is not respected */
1308 if (value_notzero_p(v
))
1313 /*if not return before this point => all
1314 the constraints are respected */
1320 /****************************************************/
1321 /* function compute enode */
1322 /* compute the value of enode p with parameters */
1323 /* list "list_args */
1324 /* compute the polynomial or the periodic */
1325 /****************************************************/
1327 static double compute_enode(enode
*p
, Value
*list_args
) {
1339 if (p
->type
== polynomial
) {
1341 value_assign(param
,list_args
[p
->pos
-1]);
1343 /* Compute the polynomial using Horner's rule */
1344 for (i
=p
->size
-1;i
>0;i
--) {
1345 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1346 res
*=VALUE_TO_DOUBLE(param
);
1348 res
+=compute_evalue(&p
->arr
[0],list_args
);
1350 else if (p
->type
== modulo
) {
1351 double d
= compute_evalue(&p
->arr
[0], list_args
);
1356 value_set_double(param
, d
);
1357 value_set_si(m
, p
->pos
);
1358 mpz_fdiv_r(param
, param
, m
);
1360 /* Compute the polynomial using Horner's rule */
1361 for (i
=p
->size
-1;i
>1;i
--) {
1362 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1363 res
*=VALUE_TO_DOUBLE(param
);
1365 res
+=compute_evalue(&p
->arr
[1],list_args
);
1367 else if (p
->type
== periodic
) {
1368 value_assign(param
,list_args
[p
->pos
-1]);
1370 /* Choose the right element of the periodic */
1371 value_absolute(m
,param
);
1372 value_set_si(param
,p
->size
);
1373 value_modulus(m
,m
,param
);
1374 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
1376 else if (p
->type
== relation
) {
1377 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 0.5)
1378 res
= compute_evalue(&p
->arr
[1], list_args
);
1379 else if (p
->size
> 2)
1380 res
= compute_evalue(&p
->arr
[2], list_args
);
1382 else if (p
->type
== partition
) {
1383 for (i
= 0; i
< p
->size
/2; ++i
)
1384 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
1385 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
1392 } /* compute_enode */
1394 /*************************************************/
1395 /* return the value of Ehrhart Polynomial */
1396 /* It returns a double, because since it is */
1397 /* a recursive function, some intermediate value */
1398 /* might not be integral */
1399 /*************************************************/
1401 double compute_evalue(evalue
*e
,Value
*list_args
) {
1405 if (value_notzero_p(e
->d
)) {
1406 if (value_notone_p(e
->d
))
1407 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
1409 res
= VALUE_TO_DOUBLE(e
->x
.n
);
1412 res
= compute_enode(e
->x
.p
,list_args
);
1414 } /* compute_evalue */
1417 /****************************************************/
1418 /* function compute_poly : */
1419 /* Check for the good validity domain */
1420 /* return the number of point in the Polyhedron */
1421 /* in allocated memory */
1422 /* Using the Ehrhart pseudo-polynomial */
1423 /****************************************************/
1424 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
1427 /* double d; int i; */
1429 tmp
= (Value
*) malloc (sizeof(Value
));
1430 assert(tmp
!= NULL
);
1432 value_set_si(*tmp
,0);
1435 return(tmp
); /* no ehrhart polynomial */
1436 if(en
->ValidityDomain
) {
1437 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
1438 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1443 return(tmp
); /* no Validity Domain */
1445 if(in_domain(en
->ValidityDomain
,list_args
)) {
1447 #ifdef EVAL_EHRHART_DEBUG
1448 Print_Domain(stdout
,en
->ValidityDomain
);
1449 print_evalue(stdout
,&en
->EP
);
1452 /* d = compute_evalue(&en->EP,list_args);
1454 printf("(double)%lf = %d\n", d, i ); */
1455 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1461 value_set_si(*tmp
,0);
1462 return(tmp
); /* no compatible domain with the arguments */
1463 } /* compute_poly */