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);
193 if (value_notzero_p(p
->arr
[0].d
)) {
194 if (value_zero_p(p
->arr
[0].x
.n
)) {
196 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
198 free_evalue_refs(&(p
->arr
[2]));
202 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
204 evalue_set_si(e
, 0, 1);
205 free_evalue_refs(&(p
->arr
[1]));
207 free_evalue_refs(&(p
->arr
[0]));
211 } /* reduce_evalue */
213 void reduce_evalue (evalue
*e
) {
214 if (value_notzero_p(e
->d
))
215 return; /* a rational number, its already reduced */
217 if (e
->x
.p
->type
== partition
) {
220 struct fixed_param
*fixed
= 0;
222 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
224 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
226 if (!D
->next
&& D
->NbEq
) {
229 fixed
= (struct fixed_param
*)
230 malloc(D
->Dimension
* sizeof(*fixed
));
231 for (j
= 0; j
< dim
; ++j
)
232 value_init(fixed
[j
].v
);
234 for (j
= 0; j
< D
->NbEq
; ++j
) {
235 for (k
= 0; k
< D
->Dimension
; ++k
)
236 if (value_notzero_p(D
->Constraint
[j
][k
+1])) {
238 for (l
= k
+1; l
< D
->Dimension
; ++l
)
239 if (value_notzero_p(D
->Constraint
[j
][l
+1]))
241 if (l
< D
->Dimension
)
244 if (value_one_p(D
->Constraint
[j
][k
+1]))
245 value_oppose(fixed
[n
].v
, D
->Constraint
[j
][dim
+1]);
246 else if (value_mone_p(D
->Constraint
[j
][k
+1]))
247 value_assign(fixed
[n
].v
, D
->Constraint
[j
][dim
+1]);
249 fprintf(stderr
, "%d %d\n", j
, k
);
250 Polyhedron_Print(stderr
, P_VALUE_FMT
, D
);
258 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], n
, fixed
);
259 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
260 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
261 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
262 value_clear(e
->x
.p
->arr
[2*i
].d
);
264 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
265 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
271 for (j
= 0; j
< dim
; ++j
)
272 value_clear(fixed
[j
].v
);
276 _reduce_evalue(e
, 0, 0);
279 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
281 if(value_notzero_p(e
->d
)) {
282 if(value_notone_p(e
->d
)) {
283 value_print(DST
,VALUE_FMT
,e
->x
.n
);
285 value_print(DST
,VALUE_FMT
,e
->d
);
288 value_print(DST
,VALUE_FMT
,e
->x
.n
);
292 print_enode(DST
,e
->x
.p
,pname
);
296 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
301 fprintf(DST
, "NULL");
307 for (i
=0; i
<p
->size
; i
++) {
308 print_evalue(DST
, &p
->arr
[i
], pname
);
312 fprintf(DST
, " }\n");
316 for (i
=p
->size
-1; i
>=0; i
--) {
317 print_evalue(DST
, &p
->arr
[i
], pname
);
318 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
320 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
322 fprintf(DST
, " )\n");
326 for (i
=0; i
<p
->size
; i
++) {
327 print_evalue(DST
, &p
->arr
[i
], pname
);
328 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
330 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
334 for (i
=p
->size
-1; i
>=1; i
--) {
335 print_evalue(DST
, &p
->arr
[i
], pname
);
341 print_evalue(DST
, &p
->arr
[0], pname
);
342 fprintf(DST
, ") mod %d", p
->pos
);
344 fprintf(DST
, ")^%d + ", i
-1);
346 fprintf(DST
, " + ", i
-1);
349 fprintf(DST
, " )\n");
353 print_evalue(DST
, &p
->arr
[0], pname
);
354 fprintf(DST
, "= 0 ] * \n");
355 print_evalue(DST
, &p
->arr
[1], pname
);
357 fprintf(DST
, " +\n [ ");
358 print_evalue(DST
, &p
->arr
[0], pname
);
359 fprintf(DST
, "!= 0 ] * \n");
360 print_evalue(DST
, &p
->arr
[2], pname
);
364 for (i
=0; i
<p
->size
/2; i
++) {
365 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
366 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
375 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
377 if (value_notzero_p(e1
->d
)) {
378 if (value_zero_p(e2
->d
))
380 return value_lt(e1
->x
.n
, e2
->x
.n
);
382 if (value_notzero_p(e2
->d
))
384 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
386 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
389 return mod_term_smaller(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
392 static void eadd_rev(evalue
*e1
, evalue
*res
)
396 evalue_copy(&ev
, e1
);
398 free_evalue_refs(res
);
402 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
406 evalue_copy(&ev
, e1
);
407 eadd(res
, &ev
.x
.p
->arr
[ev
.x
.p
->type
==modulo
]);
408 free_evalue_refs(res
);
412 struct section
{ Polyhedron
* D
; evalue E
; };
414 void eadd_partitions (evalue
*e1
,evalue
*res
)
419 s
= (struct section
*)
420 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
421 sizeof(struct section
));
425 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
426 assert(res
->x
.p
->size
>= 2);
427 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
428 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
430 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
432 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
441 value_init(s
[n
].E
.d
);
442 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
446 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
447 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
448 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
450 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
451 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
457 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
458 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
460 value_init(s
[n
].E
.d
);
461 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
462 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
467 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
471 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
472 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
473 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
474 value_clear(res
->x
.p
->arr
[2*i
].d
);
478 res
->x
.p
= new_enode(partition
, 2*n
, -1);
479 for (j
= 0; j
< n
; ++j
) {
480 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
481 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
482 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
483 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
489 static void explicit_complement(evalue
*res
)
491 enode
*rel
= new_enode(relation
, 3, 0);
493 value_clear(rel
->arr
[0].d
);
494 rel
->arr
[0] = res
->x
.p
->arr
[0];
495 value_clear(rel
->arr
[1].d
);
496 rel
->arr
[1] = res
->x
.p
->arr
[1];
497 value_set_si(rel
->arr
[2].d
, 1);
498 value_init(rel
->arr
[2].x
.n
);
499 value_set_si(rel
->arr
[2].x
.n
, 0);
504 void eadd(evalue
*e1
,evalue
*res
) {
507 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
508 /* Add two rational numbers */
514 value_multiply(m1
,e1
->x
.n
,res
->d
);
515 value_multiply(m2
,res
->x
.n
,e1
->d
);
516 value_addto(res
->x
.n
,m1
,m2
);
517 value_multiply(res
->d
,e1
->d
,res
->d
);
518 Gcd(res
->x
.n
,res
->d
,&g
);
519 if (value_notone_p(g
)) {
520 value_division(res
->d
,res
->d
,g
);
521 value_division(res
->x
.n
,res
->x
.n
,g
);
523 value_clear(g
); value_clear(m1
); value_clear(m2
);
526 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
527 switch (res
->x
.p
->type
) {
529 /* Add the constant to the constant term of a polynomial*/
530 eadd(e1
, &res
->x
.p
->arr
[0]);
533 /* Add the constant to all elements of a periodic number */
534 for (i
=0; i
<res
->x
.p
->size
; i
++) {
535 eadd(e1
, &res
->x
.p
->arr
[i
]);
539 fprintf(stderr
, "eadd: cannot add const with vector\n");
542 eadd(e1
, &res
->x
.p
->arr
[1]);
545 assert(EVALUE_IS_ZERO(*e1
));
546 break; /* Do nothing */
548 /* Create (zero) complement if needed */
549 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
550 explicit_complement(res
);
551 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
552 eadd(e1
, &res
->x
.p
->arr
[i
]);
558 /* add polynomial or periodic to constant
559 * you have to exchange e1 and res, before doing addition */
561 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
565 else { // ((e1->d==0) && (res->d==0))
566 assert(!((e1
->x
.p
->type
== partition
) ^
567 (res
->x
.p
->type
== partition
)));
568 if (e1
->x
.p
->type
== partition
) {
569 eadd_partitions(e1
, res
);
572 if (e1
->x
.p
->type
== relation
&&
573 (res
->x
.p
->type
!= relation
||
574 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
578 if (res
->x
.p
->type
== relation
) {
579 if (e1
->x
.p
->type
== relation
&&
580 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
581 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
582 explicit_complement(res
);
583 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
584 explicit_complement(e1
);
585 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
586 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
589 if (res
->x
.p
->size
< 3)
590 explicit_complement(res
);
591 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
592 eadd(e1
, &res
->x
.p
->arr
[i
]);
595 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
596 /* adding to evalues of different type. two cases are possible
597 * res is periodic and e1 is polynomial, you have to exchange
598 * e1 and res then to add e1 to the constant term of res */
599 if (e1
->x
.p
->type
== polynomial
) {
600 eadd_rev_cst(e1
, res
);
602 else if (res
->x
.p
->type
== polynomial
) {
603 /* res is polynomial and e1 is periodic,
604 add e1 to the constant term of res */
606 eadd(e1
,&res
->x
.p
->arr
[0]);
612 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
613 (res
->x
.p
->type
== modulo
&&
614 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
615 /* adding evalues of different position (i.e function of different unknowns
616 * to case are possible */
618 switch (res
->x
.p
->type
) {
620 if(mod_term_smaller(res
, e1
))
621 eadd(e1
,&res
->x
.p
->arr
[1]);
623 eadd_rev_cst(e1
, res
);
625 case polynomial
: // res and e1 are polynomials
626 // add e1 to the constant term of res
628 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
629 eadd(e1
,&res
->x
.p
->arr
[0]);
631 eadd_rev_cst(e1
, res
);
632 // value_clear(g); value_clear(m1); value_clear(m2);
634 case periodic
: // res and e1 are pointers to periodic numbers
635 //add e1 to all elements of res
637 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
638 for (i
=0;i
<res
->x
.p
->size
;i
++) {
639 eadd(e1
,&res
->x
.p
->arr
[i
]);
648 //same type , same pos and same size
649 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
650 // add any element in e1 to the corresponding element in res
651 if (res
->x
.p
->type
== modulo
)
652 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
653 i
= res
->x
.p
->type
== modulo
? 1 : 0;
654 for (; i
<res
->x
.p
->size
; i
++) {
655 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
660 /* Sizes are different */
661 switch(res
->x
.p
->type
) {
664 /* VIN100: if e1-size > res-size you have to copy e1 in a */
665 /* new enode and add res to that new node. If you do not do */
666 /* that, you lose the the upper weight part of e1 ! */
668 if(e1
->x
.p
->size
> res
->x
.p
->size
)
672 if (res
->x
.p
->type
== modulo
)
673 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
674 i
= res
->x
.p
->type
== modulo
? 1 : 0;
675 for (; i
<e1
->x
.p
->size
; i
++) {
676 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
683 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
686 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
687 of the sizes of e1 and res, then to copy res periodicaly in ne, after
688 to add periodicaly elements of e1 to elements of ne, and finaly to
693 value_init(ex
); value_init(ey
);value_init(ep
);
696 value_set_si(ex
,e1
->x
.p
->size
);
697 value_set_si(ey
,res
->x
.p
->size
);
698 value_assign (ep
,*Lcm(ex
,ey
));
699 p
=(int)mpz_get_si(ep
);
700 ne
= (evalue
*) malloc (sizeof(evalue
));
702 value_set_si( ne
->d
,0);
704 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
706 value_assign(ne
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%y
].d
);
707 if (value_notzero_p(ne
->x
.p
->arr
[i
].d
)) {
708 value_init(ne
->x
.p
->arr
[i
].x
.n
);
709 value_assign(ne
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%y
].x
.n
);
712 ne
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%y
].x
.p
);
716 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
719 value_assign(res
->d
, ne
->d
);
725 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
732 static void emul_rev (evalue
*e1
, evalue
*res
)
736 evalue_copy(&ev
, e1
);
738 free_evalue_refs(res
);
742 static void emul_poly (evalue
*e1
, evalue
*res
)
744 int i
, j
, o
= res
->x
.p
->type
== modulo
;
746 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
748 value_set_si(tmp
.d
,0);
749 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
751 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
752 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
753 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
754 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
757 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
758 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
759 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
762 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
763 emul(&res
->x
.p
->arr
[i
], &ev
);
764 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
765 free_evalue_refs(&ev
);
767 free_evalue_refs(res
);
771 void emul_partitions (evalue
*e1
,evalue
*res
)
776 s
= (struct section
*)
777 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
778 sizeof(struct section
));
782 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
783 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
784 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
785 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
791 /* This code is only needed because the partitions
792 are not true partitions.
794 for (k
= 0; k
< n
; ++k
) {
795 if (DomainIncludes(s
[k
].D
, d
))
797 if (DomainIncludes(d
, s
[k
].D
)) {
799 free_evalue_refs(&s
[k
].E
);
810 value_init(s
[n
].E
.d
);
811 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
812 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
816 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
817 value_clear(res
->x
.p
->arr
[2*i
].d
);
818 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
822 res
->x
.p
= new_enode(partition
, 2*n
, -1);
823 for (j
= 0; j
< n
; ++j
) {
824 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
825 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
826 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
832 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
833 * do a copy of "res" befor calling this function if you nead it after. The vector type of
834 * evalues is not treated here */
836 void emul (evalue
*e1
, evalue
*res
){
839 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
840 fprintf(stderr
, "emul: do not proced on evector type !\n");
844 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
845 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
846 emul_partitions(e1
, res
);
849 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
850 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
851 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
853 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
854 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
855 emul(e1
, &res
->x
.p
->arr
[i
]);
857 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
858 switch(e1
->x
.p
->type
) {
860 switch(res
->x
.p
->type
) {
862 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
863 /* Product of two polynomials of the same variable */
868 /* Product of two polynomials of different variables */
870 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
871 for( i
=0; i
<res
->x
.p
->size
; i
++)
872 emul(e1
, &res
->x
.p
->arr
[i
]);
880 /* Product of a polynomial and a periodic or modulo */
885 switch(res
->x
.p
->type
) {
887 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
888 /* Product of two periodics of the same parameter and period */
890 for(i
=0; i
<res
->x
.p
->size
;i
++)
891 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
896 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
897 /* Product of two periodics of the same parameter and different periods */
901 value_init(x
); value_init(y
);value_init(z
);
904 value_set_si(x
,e1
->x
.p
->size
);
905 value_set_si(y
,res
->x
.p
->size
);
906 value_assign (z
,*Lcm(x
,y
));
907 lcm
=(int)mpz_get_si(z
);
908 newp
= (evalue
*) malloc (sizeof(evalue
));
910 value_set_si( newp
->d
,0);
911 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
913 value_assign(newp
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%iy
].d
);
914 if (value_notzero_p(newp
->x
.p
->arr
[i
].d
)) {
915 value_assign(newp
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%iy
].x
.n
);
918 newp
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%iy
].x
.p
);
923 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
925 value_assign(res
->d
,newp
->d
);
928 value_clear(x
); value_clear(y
);value_clear(z
);
932 /* Product of two periodics of different parameters */
934 for(i
=0; i
<res
->x
.p
->size
; i
++)
935 emul(e1
, &(res
->x
.p
->arr
[i
]));
941 /* Product of a periodic and a polynomial */
943 for(i
=0; i
<res
->x
.p
->size
; i
++)
944 emul(e1
, &(res
->x
.p
->arr
[i
]));
950 switch(res
->x
.p
->type
) {
952 for(i
=0; i
<res
->x
.p
->size
; i
++)
953 emul(e1
, &(res
->x
.p
->arr
[i
]));
958 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
959 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
960 if (e1
->x
.p
->pos
!= 2)
964 /* x mod 2 == (x mod 2)^2 */
965 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1) (x mod 2) */
966 assert(e1
->x
.p
->size
== 3);
967 assert(res
->x
.p
->size
== 3);
969 evalue_copy(&tmp
, &res
->x
.p
->arr
[1]);
970 eadd(&res
->x
.p
->arr
[2], &tmp
);
971 emul(&e1
->x
.p
->arr
[2], &tmp
);
972 emul(&e1
->x
.p
->arr
[1], res
);
973 eadd(&tmp
, &res
->x
.p
->arr
[2]);
974 free_evalue_refs(&tmp
);
977 if(mod_term_smaller(res
, e1
))
978 for(i
=1; i
<res
->x
.p
->size
; i
++)
979 emul(e1
, &(res
->x
.p
->arr
[i
]));
994 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
995 /* Product of two rational numbers */
999 value_multiply(res
->d
,e1
->d
,res
->d
);
1000 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1001 Gcd(res
->x
.n
, res
->d
,&g
);
1002 if (value_notone_p(g
)) {
1003 value_division(res
->d
,res
->d
,g
);
1004 value_division(res
->x
.n
,res
->x
.n
,g
);
1010 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1011 /* Product of an expression (polynomial or peririodic) and a rational number */
1017 /* Product of a rationel number and an expression (polynomial or peririodic) */
1019 i
= res
->x
.p
->type
== modulo
? 1 : 0;
1020 for (; i
<res
->x
.p
->size
; i
++)
1021 emul(e1
, &res
->x
.p
->arr
[i
]);
1032 void emask(evalue
*mask
, evalue
*res
) {
1038 assert(mask
->x
.p
->type
== partition
);
1039 assert(res
->x
.p
->type
== partition
);
1041 s
= (struct section
*)
1042 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1043 sizeof(struct section
));
1047 evalue_set_si(&mone
, -1, 1);
1050 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1051 assert(mask
->x
.p
->size
>= 2);
1052 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1053 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1055 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1057 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1066 value_init(s
[n
].E
.d
);
1067 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1071 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1072 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1073 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1074 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1075 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1077 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1078 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1084 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1085 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1087 value_init(s
[n
].E
.d
);
1088 evalue_copy(&s
[n
].E
, &mask
->x
.p
->arr
[2*i
+1]);
1089 emul(&res
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1094 assert(0); // We don't allow this.
1098 free_evalue_refs(&mone
);
1099 free_evalue_refs(mask
);
1100 free_evalue_refs(res
);
1102 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1103 for (j
= 0; j
< n
; ++j
) {
1104 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1105 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1106 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1112 void evalue_copy(evalue
*dst
, evalue
*src
)
1114 value_assign(dst
->d
, src
->d
);
1115 if(value_notzero_p(src
->d
)) {
1116 value_init(dst
->x
.n
);
1117 value_assign(dst
->x
.n
, src
->x
.n
);
1119 dst
->x
.p
= ecopy(src
->x
.p
);
1122 enode
*new_enode(enode_type type
,int size
,int pos
) {
1128 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1131 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1135 for(i
=0; i
<size
; i
++) {
1136 value_init(res
->arr
[i
].d
);
1137 value_set_si(res
->arr
[i
].d
,0);
1138 res
->arr
[i
].x
.p
= 0;
1143 enode
*ecopy(enode
*e
) {
1148 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1149 for(i
=0;i
<e
->size
;++i
) {
1150 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1151 if(value_zero_p(res
->arr
[i
].d
))
1152 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1153 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1154 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1156 value_init(res
->arr
[i
].x
.n
);
1157 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1163 int eequal(evalue
*e1
,evalue
*e2
) {
1168 if (value_ne(e1
->d
,e2
->d
))
1171 /* e1->d == e2->d */
1172 if (value_notzero_p(e1
->d
)) {
1173 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1176 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1180 /* e1->d == e2->d == 0 */
1183 if (p1
->type
!= p2
->type
) return 0;
1184 if (p1
->size
!= p2
->size
) return 0;
1185 if (p1
->pos
!= p2
->pos
) return 0;
1186 for (i
=0; i
<p1
->size
; i
++)
1187 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1192 void free_evalue_refs(evalue
*e
) {
1197 if (EVALUE_IS_DOMAIN(*e
)) {
1198 Domain_Free(EVALUE_DOMAIN(*e
));
1201 } else if (value_pos_p(e
->d
)) {
1203 /* 'e' stores a constant */
1205 value_clear(e
->x
.n
);
1208 assert(value_zero_p(e
->d
));
1211 if (!p
) return; /* null pointer */
1212 for (i
=0; i
<p
->size
; i
++) {
1213 free_evalue_refs(&(p
->arr
[i
]));
1217 } /* free_evalue_refs */
1219 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1220 Vector
* val
, evalue
*res
)
1222 unsigned nparam
= periods
->Size
;
1225 double d
= compute_evalue(e
, val
->p
);
1230 value_set_si(res
->d
, 1);
1231 value_init(res
->x
.n
);
1232 value_set_double(res
->x
.n
, d
);
1233 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1236 if (value_one_p(periods
->p
[p
]))
1237 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1242 value_assign(tmp
, periods
->p
[p
]);
1243 value_set_si(res
->d
, 0);
1244 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1246 value_decrement(tmp
, tmp
);
1247 value_assign(val
->p
[p
], tmp
);
1248 mod2table_r(e
, periods
, m
, p
+1, val
,
1249 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1250 } while (value_pos_p(tmp
));
1256 void evalue_mod2table(evalue
*e
, int nparam
)
1261 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1264 for (i
=0; i
<p
->size
; i
++) {
1265 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1267 if (p
->type
== modulo
) {
1268 Vector
*periods
= Vector_Alloc(nparam
);
1269 Vector
*val
= Vector_Alloc(nparam
);
1275 value_set_si(tmp
, p
->pos
);
1276 Vector_Set(periods
->p
, 1, nparam
);
1277 Vector_Set(val
->p
, 0, nparam
);
1278 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1281 assert(p
->type
== polynomial
);
1282 assert(p
->size
== 2);
1283 assert(value_one_p(p
->arr
[1].d
));
1284 Gcd(tmp
, p
->arr
[1].x
.n
, &periods
->p
[p
->pos
-1]);
1285 value_division(periods
->p
[p
->pos
-1], tmp
, periods
->p
[p
->pos
-1]);
1287 value_set_si(tmp
, p
->pos
);
1289 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1292 evalue_set_si(&res
, 0, 1);
1293 /* Compute the polynomial using Horner's rule */
1294 for (i
=p
->size
-1;i
>1;i
--) {
1295 eadd(&p
->arr
[i
], &res
);
1298 eadd(&p
->arr
[1], &res
);
1300 free_evalue_refs(e
);
1301 free_evalue_refs(&EP
);
1306 Vector_Free(periods
);
1308 } /* evalue_mod2table */
1310 /********************************************************/
1311 /* function in domain */
1312 /* check if the parameters in list_args */
1313 /* verifies the constraints of Domain P */
1314 /********************************************************/
1315 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1318 Value v
; /* value of the constraint of a row when
1319 parameters are instanciated*/
1325 /*P->Constraint constraint matrice of polyhedron P*/
1326 for(row
=0;row
<P
->NbConstraints
;row
++) {
1327 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1328 for(col
=1;col
<P
->Dimension
+1;col
++) {
1329 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1330 value_addto(v
,v
,tmp
);
1332 if (value_notzero_p(P
->Constraint
[row
][0])) {
1334 /*if v is not >=0 then this constraint is not respected */
1335 if (value_neg_p(v
)) {
1339 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1344 /*if v is not = 0 then this constraint is not respected */
1345 if (value_notzero_p(v
))
1350 /*if not return before this point => all
1351 the constraints are respected */
1357 /****************************************************/
1358 /* function compute enode */
1359 /* compute the value of enode p with parameters */
1360 /* list "list_args */
1361 /* compute the polynomial or the periodic */
1362 /****************************************************/
1364 static double compute_enode(enode
*p
, Value
*list_args
) {
1376 if (p
->type
== polynomial
) {
1378 value_assign(param
,list_args
[p
->pos
-1]);
1380 /* Compute the polynomial using Horner's rule */
1381 for (i
=p
->size
-1;i
>0;i
--) {
1382 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1383 res
*=VALUE_TO_DOUBLE(param
);
1385 res
+=compute_evalue(&p
->arr
[0],list_args
);
1387 else if (p
->type
== modulo
) {
1388 double d
= compute_evalue(&p
->arr
[0], list_args
);
1393 value_set_double(param
, d
);
1394 value_set_si(m
, p
->pos
);
1395 mpz_fdiv_r(param
, param
, m
);
1397 /* Compute the polynomial using Horner's rule */
1398 for (i
=p
->size
-1;i
>1;i
--) {
1399 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1400 res
*=VALUE_TO_DOUBLE(param
);
1402 res
+=compute_evalue(&p
->arr
[1],list_args
);
1404 else if (p
->type
== periodic
) {
1405 value_assign(param
,list_args
[p
->pos
-1]);
1407 /* Choose the right element of the periodic */
1408 value_absolute(m
,param
);
1409 value_set_si(param
,p
->size
);
1410 value_modulus(m
,m
,param
);
1411 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
1413 else if (p
->type
== relation
) {
1414 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 0.5)
1415 res
= compute_evalue(&p
->arr
[1], list_args
);
1416 else if (p
->size
> 2)
1417 res
= compute_evalue(&p
->arr
[2], list_args
);
1419 else if (p
->type
== partition
) {
1420 for (i
= 0; i
< p
->size
/2; ++i
)
1421 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
1422 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
1429 } /* compute_enode */
1431 /*************************************************/
1432 /* return the value of Ehrhart Polynomial */
1433 /* It returns a double, because since it is */
1434 /* a recursive function, some intermediate value */
1435 /* might not be integral */
1436 /*************************************************/
1438 double compute_evalue(evalue
*e
,Value
*list_args
) {
1442 if (value_notzero_p(e
->d
)) {
1443 if (value_notone_p(e
->d
))
1444 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
1446 res
= VALUE_TO_DOUBLE(e
->x
.n
);
1449 res
= compute_enode(e
->x
.p
,list_args
);
1451 } /* compute_evalue */
1454 /****************************************************/
1455 /* function compute_poly : */
1456 /* Check for the good validity domain */
1457 /* return the number of point in the Polyhedron */
1458 /* in allocated memory */
1459 /* Using the Ehrhart pseudo-polynomial */
1460 /****************************************************/
1461 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
1464 /* double d; int i; */
1466 tmp
= (Value
*) malloc (sizeof(Value
));
1467 assert(tmp
!= NULL
);
1469 value_set_si(*tmp
,0);
1472 return(tmp
); /* no ehrhart polynomial */
1473 if(en
->ValidityDomain
) {
1474 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
1475 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1480 return(tmp
); /* no Validity Domain */
1482 if(in_domain(en
->ValidityDomain
,list_args
)) {
1484 #ifdef EVAL_EHRHART_DEBUG
1485 Print_Domain(stdout
,en
->ValidityDomain
);
1486 print_evalue(stdout
,&en
->EP
);
1489 /* d = compute_evalue(&en->EP,list_args);
1491 printf("(double)%lf = %d\n", d, i ); */
1492 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1498 value_set_si(*tmp
,0);
1499 return(tmp
); /* no compatible domain with the arguments */
1500 } /* compute_poly */