4 #include "ev_operations.h"
7 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
9 void evalue_set_si(evalue
*ev
, int n
, int d
) {
10 value_set_si(ev
->d
, d
);
12 value_set_si(ev
->x
.n
, n
);
15 void evalue_set(evalue
*ev
, Value n
, Value d
) {
16 value_assign(ev
->d
, d
);
18 value_assign(ev
->x
.n
, n
);
21 void aep_evalue(evalue
*e
, int *ref
) {
26 if (value_notzero_p(e
->d
))
27 return; /* a rational number, its already reduced */
29 return; /* hum... an overflow probably occured */
31 /* First check the components of p */
32 for (i
=0;i
<p
->size
;i
++)
33 aep_evalue(&p
->arr
[i
],ref
);
36 if (p
->type
!= modulo
)
37 p
->pos
= ref
[p
->pos
-1]+1;
42 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
48 if (value_notzero_p(e
->d
))
49 return; /* a rational number, its already reduced */
51 return; /* hum... an overflow probably occured */
54 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
55 for(i
=0;i
<CT
->NbRows
-1;i
++)
56 for(j
=0;j
<CT
->NbColumns
;j
++)
57 if(value_notzero_p(CT
->p
[i
][j
])) {
62 /* Transform the references in e, using ref */
66 } /* addeliminatedparams_evalue */
75 struct fixed_param
*fixed
;
80 void _reduce_evalue (evalue
*e
, struct subst
*s
, int m
) {
85 if (value_notzero_p(e
->d
)) {
87 assert(value_one_p(e
->d
));
88 value_set_si(e
->d
, m
);
89 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
90 value_set_si(e
->d
, 1);
92 return; /* a rational number, its already reduced */
96 return; /* hum... an overflow probably occured */
98 /* First reduce the components of p */
99 for (i
=0; i
<p
->size
; i
++)
100 _reduce_evalue(&p
->arr
[i
], s
,
101 (i
== 0 && p
->type
==modulo
) ? p
->pos
: m
);
103 if (p
->type
==periodic
) {
105 /* Try to reduce the period */
106 for (i
=1; i
<=(p
->size
)/2; i
++) {
107 if ((p
->size
% i
)==0) {
109 /* Can we reduce the size to i ? */
111 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
112 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
115 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
119 you_lose
: /* OK, lets not do it */
124 /* Try to reduce its strength */
127 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
131 else if (p
->type
==polynomial
) {
132 for (k
= 0; s
&& k
< s
->n
; ++k
) {
133 if (s
->fixed
[k
].pos
== p
->pos
) {
134 if (value_notone_p(s
->fixed
[k
].d
))
137 for (i
=p
->size
-1;i
>=1;i
--) {
138 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
139 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
140 free_evalue_refs(&(p
->arr
[i
]));
147 /* Try to reduce the degree */
148 for (i
=p
->size
-1;i
>=1;i
--) {
149 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
151 /* Zero coefficient */
152 free_evalue_refs(&(p
->arr
[i
]));
157 /* Try to reduce its strength */
160 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
164 else if (p
->type
==modulo
) {
165 if (value_notzero_p(p
->arr
[0].d
)) {
168 value_set_si(v
.d
, 1);
170 value_set_si(p
->arr
[0].d
, p
->pos
);
171 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
173 for (i
=p
->size
-1;i
>=2;i
--) {
174 emul(&v
, &p
->arr
[i
]);
175 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
176 free_evalue_refs(&(p
->arr
[i
]));
179 free_evalue_refs(&v
);
182 /* Try to reduce the degree */
183 for (i
=p
->size
-1;i
>=2;i
--) {
184 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
186 /* Zero coefficient */
187 free_evalue_refs(&(p
->arr
[i
]));
192 /* Try to reduce its strength */
195 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
196 free_evalue_refs(&(p
->arr
[0]));
200 else if (p
->type
== relation
) {
201 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
202 free_evalue_refs(&(p
->arr
[2]));
205 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
206 free_evalue_refs(&(p
->arr
[1]));
207 free_evalue_refs(&(p
->arr
[0]));
208 evalue_set_si(e
, 0, 1);
210 } else if (value_notzero_p(p
->arr
[0].d
)) {
211 if (value_zero_p(p
->arr
[0].x
.n
)) {
213 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
215 free_evalue_refs(&(p
->arr
[2]));
219 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
221 evalue_set_si(e
, 0, 1);
222 free_evalue_refs(&(p
->arr
[1]));
224 free_evalue_refs(&(p
->arr
[0]));
228 } /* reduce_evalue */
230 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
235 for (k
= 0; k
< dim
; ++k
)
236 if (value_notzero_p(row
[k
+1]))
239 Vector_Normalize_Positive(row
+1, dim
+1, k
);
240 assert(s
->n
< s
->max
);
241 value_init(s
->fixed
[s
->n
].d
);
242 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
243 s
->fixed
[s
->n
].pos
= k
+1;
244 r
= &s
->fixed
[s
->n
].s
;
246 for (l
= k
+1; l
< dim
; ++l
)
247 if (value_notzero_p(row
[l
+1])) {
248 value_set_si(r
->d
, 0);
249 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
250 value_init(r
->x
.p
->arr
[1].x
.n
);
251 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
252 value_set_si(r
->x
.p
->arr
[1].d
, 1);
256 value_oppose(r
->x
.n
, row
[dim
+1]);
257 value_set_si(r
->d
, 1);
261 void reduce_evalue (evalue
*e
) {
262 if (value_notzero_p(e
->d
))
263 return; /* a rational number, its already reduced */
265 if (e
->x
.p
->type
== partition
) {
266 struct subst s
= { NULL
, 0, 0 };
269 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
271 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
272 /* This shouldn't really happen;
273 * Empty domains should not be added.
279 if (!D
->next
&& D
->NbEq
) {
283 NALLOC(s
.fixed
, dim
);
285 for (j
= 0; j
< D
->NbEq
; ++j
)
286 add_substitution(&s
, D
->Constraint
[j
], dim
);
288 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
289 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
291 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
292 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
293 value_clear(e
->x
.p
->arr
[2*i
].d
);
295 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
296 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
301 for (j
= 0; j
< s
.n
; ++j
) {
302 value_clear(s
.fixed
[j
].d
);
303 free_evalue_refs(&s
.fixed
[j
].s
);
310 _reduce_evalue(e
, 0, 0);
313 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
315 if(value_notzero_p(e
->d
)) {
316 if(value_notone_p(e
->d
)) {
317 value_print(DST
,VALUE_FMT
,e
->x
.n
);
319 value_print(DST
,VALUE_FMT
,e
->d
);
322 value_print(DST
,VALUE_FMT
,e
->x
.n
);
326 print_enode(DST
,e
->x
.p
,pname
);
330 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
335 fprintf(DST
, "NULL");
341 for (i
=0; i
<p
->size
; i
++) {
342 print_evalue(DST
, &p
->arr
[i
], pname
);
346 fprintf(DST
, " }\n");
350 for (i
=p
->size
-1; i
>=0; i
--) {
351 print_evalue(DST
, &p
->arr
[i
], pname
);
352 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
354 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
356 fprintf(DST
, " )\n");
360 for (i
=0; i
<p
->size
; i
++) {
361 print_evalue(DST
, &p
->arr
[i
], pname
);
362 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
364 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
368 for (i
=p
->size
-1; i
>=1; i
--) {
369 print_evalue(DST
, &p
->arr
[i
], pname
);
375 print_evalue(DST
, &p
->arr
[0], pname
);
376 fprintf(DST
, ") mod %d", p
->pos
);
378 fprintf(DST
, ")^%d + ", i
-1);
380 fprintf(DST
, " + ", i
-1);
383 fprintf(DST
, " )\n");
387 print_evalue(DST
, &p
->arr
[0], pname
);
388 fprintf(DST
, "= 0 ] * \n");
389 print_evalue(DST
, &p
->arr
[1], pname
);
391 fprintf(DST
, " +\n [ ");
392 print_evalue(DST
, &p
->arr
[0], pname
);
393 fprintf(DST
, "!= 0 ] * \n");
394 print_evalue(DST
, &p
->arr
[2], pname
);
398 for (i
=0; i
<p
->size
/2; i
++) {
399 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
400 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
409 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
411 if (value_notzero_p(e1
->d
)) {
412 if (value_zero_p(e2
->d
))
414 return value_lt(e1
->x
.n
, e2
->x
.n
);
416 if (value_notzero_p(e2
->d
))
418 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
420 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
423 return mod_term_smaller(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
426 static void eadd_rev(evalue
*e1
, evalue
*res
)
430 evalue_copy(&ev
, e1
);
432 free_evalue_refs(res
);
436 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
440 evalue_copy(&ev
, e1
);
441 eadd(res
, &ev
.x
.p
->arr
[ev
.x
.p
->type
==modulo
]);
442 free_evalue_refs(res
);
446 struct section
{ Polyhedron
* D
; evalue E
; };
448 void eadd_partitions (evalue
*e1
,evalue
*res
)
453 s
= (struct section
*)
454 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
455 sizeof(struct section
));
459 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
460 assert(res
->x
.p
->size
>= 2);
461 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
462 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
464 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
466 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
475 value_init(s
[n
].E
.d
);
476 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
480 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
481 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
482 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
484 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
485 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
491 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
492 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
494 value_init(s
[n
].E
.d
);
495 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
496 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
501 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
505 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
508 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
509 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
510 value_clear(res
->x
.p
->arr
[2*i
].d
);
514 res
->x
.p
= new_enode(partition
, 2*n
, -1);
515 for (j
= 0; j
< n
; ++j
) {
516 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
517 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
518 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
519 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
525 static void explicit_complement(evalue
*res
)
527 enode
*rel
= new_enode(relation
, 3, 0);
529 value_clear(rel
->arr
[0].d
);
530 rel
->arr
[0] = res
->x
.p
->arr
[0];
531 value_clear(rel
->arr
[1].d
);
532 rel
->arr
[1] = res
->x
.p
->arr
[1];
533 value_set_si(rel
->arr
[2].d
, 1);
534 value_init(rel
->arr
[2].x
.n
);
535 value_set_si(rel
->arr
[2].x
.n
, 0);
540 void eadd(evalue
*e1
,evalue
*res
) {
543 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
544 /* Add two rational numbers */
550 value_multiply(m1
,e1
->x
.n
,res
->d
);
551 value_multiply(m2
,res
->x
.n
,e1
->d
);
552 value_addto(res
->x
.n
,m1
,m2
);
553 value_multiply(res
->d
,e1
->d
,res
->d
);
554 Gcd(res
->x
.n
,res
->d
,&g
);
555 if (value_notone_p(g
)) {
556 value_division(res
->d
,res
->d
,g
);
557 value_division(res
->x
.n
,res
->x
.n
,g
);
559 value_clear(g
); value_clear(m1
); value_clear(m2
);
562 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
563 switch (res
->x
.p
->type
) {
565 /* Add the constant to the constant term of a polynomial*/
566 eadd(e1
, &res
->x
.p
->arr
[0]);
569 /* Add the constant to all elements of a periodic number */
570 for (i
=0; i
<res
->x
.p
->size
; i
++) {
571 eadd(e1
, &res
->x
.p
->arr
[i
]);
575 fprintf(stderr
, "eadd: cannot add const with vector\n");
578 eadd(e1
, &res
->x
.p
->arr
[1]);
581 assert(EVALUE_IS_ZERO(*e1
));
582 break; /* Do nothing */
584 /* Create (zero) complement if needed */
585 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
586 explicit_complement(res
);
587 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
588 eadd(e1
, &res
->x
.p
->arr
[i
]);
594 /* add polynomial or periodic to constant
595 * you have to exchange e1 and res, before doing addition */
597 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
601 else { // ((e1->d==0) && (res->d==0))
602 assert(!((e1
->x
.p
->type
== partition
) ^
603 (res
->x
.p
->type
== partition
)));
604 if (e1
->x
.p
->type
== partition
) {
605 eadd_partitions(e1
, res
);
608 if (e1
->x
.p
->type
== relation
&&
609 (res
->x
.p
->type
!= relation
||
610 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
614 if (res
->x
.p
->type
== relation
) {
615 if (e1
->x
.p
->type
== relation
&&
616 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
617 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
618 explicit_complement(res
);
619 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
620 explicit_complement(e1
);
621 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
622 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
625 if (res
->x
.p
->size
< 3)
626 explicit_complement(res
);
627 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
628 eadd(e1
, &res
->x
.p
->arr
[i
]);
631 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
632 /* adding to evalues of different type. two cases are possible
633 * res is periodic and e1 is polynomial, you have to exchange
634 * e1 and res then to add e1 to the constant term of res */
635 if (e1
->x
.p
->type
== polynomial
) {
636 eadd_rev_cst(e1
, res
);
638 else if (res
->x
.p
->type
== polynomial
) {
639 /* res is polynomial and e1 is periodic,
640 add e1 to the constant term of res */
642 eadd(e1
,&res
->x
.p
->arr
[0]);
648 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
649 (res
->x
.p
->type
== modulo
&&
650 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
651 /* adding evalues of different position (i.e function of different unknowns
652 * to case are possible */
654 switch (res
->x
.p
->type
) {
656 if(mod_term_smaller(res
, e1
))
657 eadd(e1
,&res
->x
.p
->arr
[1]);
659 eadd_rev_cst(e1
, res
);
661 case polynomial
: // res and e1 are polynomials
662 // add e1 to the constant term of res
664 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
665 eadd(e1
,&res
->x
.p
->arr
[0]);
667 eadd_rev_cst(e1
, res
);
668 // value_clear(g); value_clear(m1); value_clear(m2);
670 case periodic
: // res and e1 are pointers to periodic numbers
671 //add e1 to all elements of res
673 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
674 for (i
=0;i
<res
->x
.p
->size
;i
++) {
675 eadd(e1
,&res
->x
.p
->arr
[i
]);
684 //same type , same pos and same size
685 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
686 // add any element in e1 to the corresponding element in res
687 if (res
->x
.p
->type
== modulo
)
688 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
689 i
= res
->x
.p
->type
== modulo
? 1 : 0;
690 for (; i
<res
->x
.p
->size
; i
++) {
691 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
696 /* Sizes are different */
697 switch(res
->x
.p
->type
) {
700 /* VIN100: if e1-size > res-size you have to copy e1 in a */
701 /* new enode and add res to that new node. If you do not do */
702 /* that, you lose the the upper weight part of e1 ! */
704 if(e1
->x
.p
->size
> res
->x
.p
->size
)
708 if (res
->x
.p
->type
== modulo
)
709 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
710 i
= res
->x
.p
->type
== modulo
? 1 : 0;
711 for (; i
<e1
->x
.p
->size
; i
++) {
712 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
719 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
722 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
723 of the sizes of e1 and res, then to copy res periodicaly in ne, after
724 to add periodicaly elements of e1 to elements of ne, and finaly to
729 value_init(ex
); value_init(ey
);value_init(ep
);
732 value_set_si(ex
,e1
->x
.p
->size
);
733 value_set_si(ey
,res
->x
.p
->size
);
734 value_assign (ep
,*Lcm(ex
,ey
));
735 p
=(int)mpz_get_si(ep
);
736 ne
= (evalue
*) malloc (sizeof(evalue
));
738 value_set_si( ne
->d
,0);
740 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
742 value_assign(ne
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%y
].d
);
743 if (value_notzero_p(ne
->x
.p
->arr
[i
].d
)) {
744 value_init(ne
->x
.p
->arr
[i
].x
.n
);
745 value_assign(ne
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%y
].x
.n
);
748 ne
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%y
].x
.p
);
752 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
755 value_assign(res
->d
, ne
->d
);
761 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
768 static void emul_rev (evalue
*e1
, evalue
*res
)
772 evalue_copy(&ev
, e1
);
774 free_evalue_refs(res
);
778 static void emul_poly (evalue
*e1
, evalue
*res
)
780 int i
, j
, o
= res
->x
.p
->type
== modulo
;
782 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
784 value_set_si(tmp
.d
,0);
785 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
787 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
788 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
789 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
790 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
793 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
794 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
795 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
798 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
799 emul(&res
->x
.p
->arr
[i
], &ev
);
800 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
801 free_evalue_refs(&ev
);
803 free_evalue_refs(res
);
807 void emul_partitions (evalue
*e1
,evalue
*res
)
812 s
= (struct section
*)
813 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
814 sizeof(struct section
));
818 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
819 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
820 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
821 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
827 /* This code is only needed because the partitions
828 are not true partitions.
830 for (k
= 0; k
< n
; ++k
) {
831 if (DomainIncludes(s
[k
].D
, d
))
833 if (DomainIncludes(d
, s
[k
].D
)) {
835 free_evalue_refs(&s
[k
].E
);
846 value_init(s
[n
].E
.d
);
847 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
848 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
852 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
853 value_clear(res
->x
.p
->arr
[2*i
].d
);
854 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
858 res
->x
.p
= new_enode(partition
, 2*n
, -1);
859 for (j
= 0; j
< n
; ++j
) {
860 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
861 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
862 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
863 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
869 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
870 * do a copy of "res" befor calling this function if you nead it after. The vector type of
871 * evalues is not treated here */
873 void emul (evalue
*e1
, evalue
*res
){
876 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
877 fprintf(stderr
, "emul: do not proced on evector type !\n");
881 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
882 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
883 emul_partitions(e1
, res
);
886 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
887 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
888 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
890 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
891 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
892 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
893 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
894 explicit_complement(res
);
895 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
896 explicit_complement(e1
);
897 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
898 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
901 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
902 emul(e1
, &res
->x
.p
->arr
[i
]);
904 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
905 switch(e1
->x
.p
->type
) {
907 switch(res
->x
.p
->type
) {
909 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
910 /* Product of two polynomials of the same variable */
915 /* Product of two polynomials of different variables */
917 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
918 for( i
=0; i
<res
->x
.p
->size
; i
++)
919 emul(e1
, &res
->x
.p
->arr
[i
]);
927 /* Product of a polynomial and a periodic or modulo */
932 switch(res
->x
.p
->type
) {
934 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
935 /* Product of two periodics of the same parameter and period */
937 for(i
=0; i
<res
->x
.p
->size
;i
++)
938 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
943 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
944 /* Product of two periodics of the same parameter and different periods */
948 value_init(x
); value_init(y
);value_init(z
);
951 value_set_si(x
,e1
->x
.p
->size
);
952 value_set_si(y
,res
->x
.p
->size
);
953 value_assign (z
,*Lcm(x
,y
));
954 lcm
=(int)mpz_get_si(z
);
955 newp
= (evalue
*) malloc (sizeof(evalue
));
957 value_set_si( newp
->d
,0);
958 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
960 value_assign(newp
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%iy
].d
);
961 if (value_notzero_p(newp
->x
.p
->arr
[i
].d
)) {
962 value_assign(newp
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%iy
].x
.n
);
965 newp
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%iy
].x
.p
);
970 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
972 value_assign(res
->d
,newp
->d
);
975 value_clear(x
); value_clear(y
);value_clear(z
);
979 /* Product of two periodics of different parameters */
981 for(i
=0; i
<res
->x
.p
->size
; i
++)
982 emul(e1
, &(res
->x
.p
->arr
[i
]));
988 /* Product of a periodic and a polynomial */
990 for(i
=0; i
<res
->x
.p
->size
; i
++)
991 emul(e1
, &(res
->x
.p
->arr
[i
]));
997 switch(res
->x
.p
->type
) {
999 for(i
=0; i
<res
->x
.p
->size
; i
++)
1000 emul(e1
, &(res
->x
.p
->arr
[i
]));
1005 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1006 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1007 if (e1
->x
.p
->pos
!= 2)
1011 /* x mod 2 == (x mod 2)^2 */
1012 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1) (x mod 2) */
1013 assert(e1
->x
.p
->size
== 3);
1014 assert(res
->x
.p
->size
== 3);
1016 evalue_copy(&tmp
, &res
->x
.p
->arr
[1]);
1017 eadd(&res
->x
.p
->arr
[2], &tmp
);
1018 emul(&e1
->x
.p
->arr
[2], &tmp
);
1019 emul(&e1
->x
.p
->arr
[1], res
);
1020 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1021 free_evalue_refs(&tmp
);
1024 if(mod_term_smaller(res
, e1
))
1025 for(i
=1; i
<res
->x
.p
->size
; i
++)
1026 emul(e1
, &(res
->x
.p
->arr
[i
]));
1041 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1042 /* Product of two rational numbers */
1046 value_multiply(res
->d
,e1
->d
,res
->d
);
1047 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1048 Gcd(res
->x
.n
, res
->d
,&g
);
1049 if (value_notone_p(g
)) {
1050 value_division(res
->d
,res
->d
,g
);
1051 value_division(res
->x
.n
,res
->x
.n
,g
);
1057 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1058 /* Product of an expression (polynomial or peririodic) and a rational number */
1064 /* Product of a rationel number and an expression (polynomial or peririodic) */
1066 i
= res
->x
.p
->type
== modulo
? 1 : 0;
1067 for (; i
<res
->x
.p
->size
; i
++)
1068 emul(e1
, &res
->x
.p
->arr
[i
]);
1078 #define EVALUE_IS_ONE(ev) (value_pos_p((ev).d) && value_one_p((ev).x.n))
1081 void emask(evalue
*mask
, evalue
*res
) {
1087 if (EVALUE_IS_ZERO(*res
))
1090 assert(value_zero_p(mask
->d
));
1091 assert(mask
->x
.p
->type
== partition
);
1092 assert(value_zero_p(res
->d
));
1093 assert(res
->x
.p
->type
== partition
);
1095 s
= (struct section
*)
1096 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1097 sizeof(struct section
));
1101 evalue_set_si(&mone
, -1, 1);
1104 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1105 assert(mask
->x
.p
->size
>= 2);
1106 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1107 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1109 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1111 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1120 value_init(s
[n
].E
.d
);
1121 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1125 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1126 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1129 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1130 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1131 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1132 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1134 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1135 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1141 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1142 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1144 value_init(s
[n
].E
.d
);
1145 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1146 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1152 /* Just ignore; this may have been previously masked off */
1156 free_evalue_refs(&mone
);
1157 free_evalue_refs(mask
);
1158 free_evalue_refs(res
);
1161 evalue_set_si(res
, 0, 1);
1163 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1164 for (j
= 0; j
< n
; ++j
) {
1165 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1166 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1167 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1174 void evalue_copy(evalue
*dst
, evalue
*src
)
1176 value_assign(dst
->d
, src
->d
);
1177 if(value_notzero_p(src
->d
)) {
1178 value_init(dst
->x
.n
);
1179 value_assign(dst
->x
.n
, src
->x
.n
);
1181 dst
->x
.p
= ecopy(src
->x
.p
);
1184 enode
*new_enode(enode_type type
,int size
,int pos
) {
1190 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1193 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1197 for(i
=0; i
<size
; i
++) {
1198 value_init(res
->arr
[i
].d
);
1199 value_set_si(res
->arr
[i
].d
,0);
1200 res
->arr
[i
].x
.p
= 0;
1205 enode
*ecopy(enode
*e
) {
1210 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1211 for(i
=0;i
<e
->size
;++i
) {
1212 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1213 if(value_zero_p(res
->arr
[i
].d
))
1214 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1215 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1216 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1218 value_init(res
->arr
[i
].x
.n
);
1219 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1225 int eequal(evalue
*e1
,evalue
*e2
) {
1230 if (value_ne(e1
->d
,e2
->d
))
1233 /* e1->d == e2->d */
1234 if (value_notzero_p(e1
->d
)) {
1235 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1238 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1242 /* e1->d == e2->d == 0 */
1245 if (p1
->type
!= p2
->type
) return 0;
1246 if (p1
->size
!= p2
->size
) return 0;
1247 if (p1
->pos
!= p2
->pos
) return 0;
1248 for (i
=0; i
<p1
->size
; i
++)
1249 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1254 void free_evalue_refs(evalue
*e
) {
1259 if (EVALUE_IS_DOMAIN(*e
)) {
1260 Domain_Free(EVALUE_DOMAIN(*e
));
1263 } else if (value_pos_p(e
->d
)) {
1265 /* 'e' stores a constant */
1267 value_clear(e
->x
.n
);
1270 assert(value_zero_p(e
->d
));
1273 if (!p
) return; /* null pointer */
1274 for (i
=0; i
<p
->size
; i
++) {
1275 free_evalue_refs(&(p
->arr
[i
]));
1279 } /* free_evalue_refs */
1281 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1282 Vector
* val
, evalue
*res
)
1284 unsigned nparam
= periods
->Size
;
1287 double d
= compute_evalue(e
, val
->p
);
1292 value_set_si(res
->d
, 1);
1293 value_init(res
->x
.n
);
1294 value_set_double(res
->x
.n
, d
);
1295 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1298 if (value_one_p(periods
->p
[p
]))
1299 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1304 value_assign(tmp
, periods
->p
[p
]);
1305 value_set_si(res
->d
, 0);
1306 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1308 value_decrement(tmp
, tmp
);
1309 value_assign(val
->p
[p
], tmp
);
1310 mod2table_r(e
, periods
, m
, p
+1, val
,
1311 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1312 } while (value_pos_p(tmp
));
1318 void evalue_mod2table(evalue
*e
, int nparam
)
1323 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1326 for (i
=0; i
<p
->size
; i
++) {
1327 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1329 if (p
->type
== modulo
) {
1330 Vector
*periods
= Vector_Alloc(nparam
);
1331 Vector
*val
= Vector_Alloc(nparam
);
1337 value_set_si(tmp
, p
->pos
);
1338 Vector_Set(periods
->p
, 1, nparam
);
1339 Vector_Set(val
->p
, 0, nparam
);
1340 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1343 assert(p
->type
== polynomial
);
1344 assert(p
->size
== 2);
1345 assert(value_one_p(p
->arr
[1].d
));
1346 Gcd(tmp
, p
->arr
[1].x
.n
, &periods
->p
[p
->pos
-1]);
1347 value_division(periods
->p
[p
->pos
-1], tmp
, periods
->p
[p
->pos
-1]);
1349 value_set_si(tmp
, p
->pos
);
1351 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1354 evalue_set_si(&res
, 0, 1);
1355 /* Compute the polynomial using Horner's rule */
1356 for (i
=p
->size
-1;i
>1;i
--) {
1357 eadd(&p
->arr
[i
], &res
);
1360 eadd(&p
->arr
[1], &res
);
1362 free_evalue_refs(e
);
1363 free_evalue_refs(&EP
);
1368 Vector_Free(periods
);
1370 } /* evalue_mod2table */
1372 /********************************************************/
1373 /* function in domain */
1374 /* check if the parameters in list_args */
1375 /* verifies the constraints of Domain P */
1376 /********************************************************/
1377 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1380 Value v
; /* value of the constraint of a row when
1381 parameters are instanciated*/
1387 /*P->Constraint constraint matrice of polyhedron P*/
1388 for(row
=0;row
<P
->NbConstraints
;row
++) {
1389 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1390 for(col
=1;col
<P
->Dimension
+1;col
++) {
1391 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1392 value_addto(v
,v
,tmp
);
1394 if (value_notzero_p(P
->Constraint
[row
][0])) {
1396 /*if v is not >=0 then this constraint is not respected */
1397 if (value_neg_p(v
)) {
1401 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1406 /*if v is not = 0 then this constraint is not respected */
1407 if (value_notzero_p(v
))
1412 /*if not return before this point => all
1413 the constraints are respected */
1419 /****************************************************/
1420 /* function compute enode */
1421 /* compute the value of enode p with parameters */
1422 /* list "list_args */
1423 /* compute the polynomial or the periodic */
1424 /****************************************************/
1426 static double compute_enode(enode
*p
, Value
*list_args
) {
1438 if (p
->type
== polynomial
) {
1440 value_assign(param
,list_args
[p
->pos
-1]);
1442 /* Compute the polynomial using Horner's rule */
1443 for (i
=p
->size
-1;i
>0;i
--) {
1444 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1445 res
*=VALUE_TO_DOUBLE(param
);
1447 res
+=compute_evalue(&p
->arr
[0],list_args
);
1449 else if (p
->type
== modulo
) {
1450 double d
= compute_evalue(&p
->arr
[0], list_args
);
1455 value_set_double(param
, d
);
1456 value_set_si(m
, p
->pos
);
1457 mpz_fdiv_r(param
, param
, m
);
1459 /* Compute the polynomial using Horner's rule */
1460 for (i
=p
->size
-1;i
>1;i
--) {
1461 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1462 res
*=VALUE_TO_DOUBLE(param
);
1464 res
+=compute_evalue(&p
->arr
[1],list_args
);
1466 else if (p
->type
== periodic
) {
1467 value_assign(param
,list_args
[p
->pos
-1]);
1469 /* Choose the right element of the periodic */
1470 value_absolute(m
,param
);
1471 value_set_si(param
,p
->size
);
1472 value_modulus(m
,m
,param
);
1473 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
1475 else if (p
->type
== relation
) {
1476 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 0.5)
1477 res
= compute_evalue(&p
->arr
[1], list_args
);
1478 else if (p
->size
> 2)
1479 res
= compute_evalue(&p
->arr
[2], list_args
);
1481 else if (p
->type
== partition
) {
1482 for (i
= 0; i
< p
->size
/2; ++i
)
1483 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
1484 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
1491 } /* compute_enode */
1493 /*************************************************/
1494 /* return the value of Ehrhart Polynomial */
1495 /* It returns a double, because since it is */
1496 /* a recursive function, some intermediate value */
1497 /* might not be integral */
1498 /*************************************************/
1500 double compute_evalue(evalue
*e
,Value
*list_args
) {
1504 if (value_notzero_p(e
->d
)) {
1505 if (value_notone_p(e
->d
))
1506 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
1508 res
= VALUE_TO_DOUBLE(e
->x
.n
);
1511 res
= compute_enode(e
->x
.p
,list_args
);
1513 } /* compute_evalue */
1516 /****************************************************/
1517 /* function compute_poly : */
1518 /* Check for the good validity domain */
1519 /* return the number of point in the Polyhedron */
1520 /* in allocated memory */
1521 /* Using the Ehrhart pseudo-polynomial */
1522 /****************************************************/
1523 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
1526 /* double d; int i; */
1528 tmp
= (Value
*) malloc (sizeof(Value
));
1529 assert(tmp
!= NULL
);
1531 value_set_si(*tmp
,0);
1534 return(tmp
); /* no ehrhart polynomial */
1535 if(en
->ValidityDomain
) {
1536 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
1537 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1542 return(tmp
); /* no Validity Domain */
1544 if(in_domain(en
->ValidityDomain
,list_args
)) {
1546 #ifdef EVAL_EHRHART_DEBUG
1547 Print_Domain(stdout
,en
->ValidityDomain
);
1548 print_evalue(stdout
,&en
->EP
);
1551 /* d = compute_evalue(&en->EP,list_args);
1553 printf("(double)%lf = %d\n", d, i ); */
1554 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1560 value_set_si(*tmp
,0);
1561 return(tmp
); /* no compatible domain with the arguments */
1562 } /* compute_poly */
1564 size_t value_size(Value v
) {
1565 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
1566 * sizeof(v
[0]._mp_d
[0]);
1569 size_t domain_size(Polyhedron
*D
)
1572 size_t s
= sizeof(*D
);
1574 for (i
= 0; i
< D
->NbConstraints
; ++i
)
1575 for (j
= 0; j
< D
->Dimension
+2; ++j
)
1576 s
+= value_size(D
->Constraint
[i
][j
]);
1578 for (i
= 0; i
< D
->NbRays
; ++i
)
1579 for (j
= 0; j
< D
->Dimension
+2; ++j
)
1580 s
+= value_size(D
->Ray
[i
][j
]);
1585 size_t enode_size(enode
*p
) {
1586 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
1589 if (p
->type
== partition
)
1590 for (i
= 0; i
< p
->size
/2; ++i
) {
1591 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
1592 s
+= evalue_size(&p
->arr
[2*i
+1]);
1595 for (i
= 0; i
< p
->size
; ++i
) {
1596 s
+= evalue_size(&p
->arr
[i
]);
1601 size_t evalue_size(evalue
*e
)
1603 size_t s
= sizeof(*e
);
1604 s
+= value_size(e
->d
);
1605 if (value_notzero_p(e
->d
))
1606 s
+= value_size(e
->x
.n
);
1608 s
+= enode_size(e
->x
.p
);