2 This file is part of PolyLib.
4 PolyLib is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 PolyLib is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with PolyLib. If not, see <http://www.gnu.org/licenses/>.
18 #include <polylib/polylib.h>
21 static ZPolyhedron
* ZPolyhedronIntersection(ZPolyhedron
*, ZPolyhedron
*);
22 static ZPolyhedron
*ZPolyhedron_Copy(ZPolyhedron
*A
);
23 static void ZPolyhedron_Free(ZPolyhedron
*Zpol
);
24 static ZPolyhedron
* ZPolyhedronDifference(ZPolyhedron
*, ZPolyhedron
*);
25 static ZPolyhedron
* ZPolyhedronImage(ZPolyhedron
*, Matrix
*);
26 static ZPolyhedron
* ZPolyhedronPreimage(ZPolyhedron
*, Matrix
*);
27 static ZPolyhedron
*AddZPolytoZDomain(ZPolyhedron
*A
, ZPolyhedron
*Head
);
28 static void ZPolyhedronPrint(FILE *fp
, const char *format
, ZPolyhedron
*A
);
30 typedef struct forsimplify
{
33 struct forsimplify
*next
;
38 * Returns True if 'Zpol' is empty, otherwise returns False
40 Bool
isEmptyZPolyhedron (ZPolyhedron
*Zpol
) {
44 if((isEmptyLattice (Zpol
->Lat
)) || (emptyQ(Zpol
->P
)))
47 } /* isEmptyZPolyhedron */
50 * Given Lattice 'Lat' and a Polyhderon 'Poly', allocate space, and return
51 * the Z-polyhderon corresponding to the image of the polyhderon 'Poly' by the
52 * lattice 'Lat'. If the input lattice 'Lat' is not integeral, it integralises
53 * it, i.e. the lattice of the Z-polyhderon returned is integeral.
55 ZPolyhedron
*ZPolyhedron_Alloc(Lattice
*Lat
, Polyhedron
*Poly
) {
59 POL_ENSURE_FACETS(Poly
);
60 POL_ENSURE_VERTICES(Poly
);
62 if(Lat
->NbRows
!= Poly
->Dimension
+1) {
63 fprintf(stderr
,"\nInZPolyAlloc - The Lattice and the Polyhedron");
64 fprintf(stderr
," are not compatible to form a ZPolyhedra\n");
67 if((!(isEmptyLattice(Lat
))) && (!isfulldim (Lat
))) {
68 fprintf(stderr
,"\nZPolAlloc: Lattice not Full Dimensional\n");
71 A
= (ZPolyhedron
*)malloc(sizeof(ZPolyhedron
));
73 fprintf(stderr
,"ZPolAlloc : Out of Memory\n");
77 A
->P
= Domain_Copy(Poly
);
78 A
->Lat
= Matrix_Copy(Lat
);
80 if(IsLattice(Lat
) == False
) {
83 Res
= IntegraliseLattice (A
);
88 } /* ZPolyhedron_Alloc */
91 * Free the memory used by the Z-domain 'Head'
93 void ZDomain_Free (ZPolyhedron
*Head
) {
97 if (Head
->next
!= NULL
)
98 ZDomain_Free(Head
->next
);
99 ZPolyhedron_Free(Head
);
103 * Free the memory used by the Z-polyhderon 'Zpol'
105 static void ZPolyhedron_Free (ZPolyhedron
*Zpol
) {
109 Matrix_Free((Matrix
*) Zpol
->Lat
);
110 Domain_Free(Zpol
->P
);
113 } /* ZPolyhderon_Free */
116 * Return a copy of the Z-domain 'Head'
118 ZPolyhedron
*ZDomain_Copy(ZPolyhedron
*Head
) {
121 Zpol
= ZPolyhedron_Copy(Head
);
123 if (Head
->next
!= NULL
)
124 Zpol
->next
= ZDomain_Copy(Head
->next
);
129 * Return a copy of the Z-polyhderon 'A'
131 static ZPolyhedron
*ZPolyhedron_Copy(ZPolyhedron
*A
) {
135 Zpol
= ZPolyhedron_Alloc(A
->Lat
, A
->P
);
137 } /* ZPolyhderon_Copy */
140 * Add the ZPolyhedron 'Zpol' to the Z-domain 'Result' and return a pointer
141 * to the new Z-domain.
143 static ZPolyhedron
*AddZPoly2ZDomain(ZPolyhedron
*Zpol
, ZPolyhedron
*Result
) {
147 if (isEmptyZPolyhedron(Zpol
))
149 A
= ZPolyhedron_Copy(Zpol
);
152 if (isEmptyZPolyhedron (Result
)) {
153 ZDomain_Free (Result
);
158 } /* AddZPoly2ZDomain */
161 * Given a Z-polyhderon 'A' and a Z-domain 'Head', return a new Z-domain with
162 * 'A' added to it. If the new Z-polyhedron 'A', is already included in the
163 * Z-domain 'Head', it is not added in the list. Othewise, the function checks
164 * if the new Z-polyhedron 'A' to be added to the Z-domain 'Head' has a common
165 * lattice with some other Z-polyhderon already present in the Z-domain. If it
166 * is so, it takes the union of the underlying polyhdera; domains and returns.
167 * The function tries to make sure that the added Z-polyhedron 'A' is in the
170 static ZPolyhedron
*AddZPolytoZDomain(ZPolyhedron
*A
, ZPolyhedron
*Head
) {
172 ZPolyhedron
*Zpol
, *temp
, *temp1
;
176 if ((A
== NULL
) || (isEmptyZPolyhedron(A
)))
179 /* For each "underlying" Pol, find the Cnf and add Zpol in Cnf*/
180 for(i
=A
->P
; i
!= NULL
; i
=i
->next
) {
187 Image
= Domain_Copy(i
);
188 Domain_Free(Image
->next
);
190 Z1
= ZPolyhedron_Alloc(A
->Lat
,Image
);
192 CanonicalForm(Z1
,&Z
,&H
);
194 Lat
= (Lattice
*)Matrix_Alloc(H
->NbRows
,Z
->Lat
->NbColumns
);
195 Matrix_Product(H
,Z
->Lat
,(Matrix
*)Lat
);
197 AffineHermite(Lat
,(Lattice
**)&H
,&U
);
198 Image
= DomainImage(Z
->P
,U
,MAXNOOFRAYS
);
201 Zpol
=ZPolyhedron_Alloc((Lattice
*)H
,Image
);
203 Matrix_Free((Matrix
*)Lat
);
207 if ((Head
== NULL
) || (isEmptyZPolyhedron (Head
))) {
213 /* Check if the curr pol is included in the zpol or vice versa. */
214 for(; temp
!= NULL
; temp
= temp
->next
) {
215 if (ZPolyhedronIncludes(Zpol
, temp
) == True
) {
216 ZPolyhedron_Free (Zpol
);
220 else if (ZPolyhedronIncludes(temp
, Zpol
) == True
) {
222 Zpol
->next
= temp
->next
;
224 ZPolyhedron_Free (temp
);
229 Zpol
->next
= temp
->next
;
230 ZPolyhedron_Free (temp
);
238 for(temp
= Head
; temp
!= NULL
; temp
= temp
->next
) {
239 if(sameLattice(temp
->Lat
, Zpol
->Lat
) == True
) {
242 Union
= DomainUnion (temp
->P
,Zpol
->P
,MAXNOOFRAYS
);
244 fprintf (stderr
,"\n In AddZPolytoZDomain: Out of memory\n");
246 Domain_Free(temp
->P
);
249 ZPolyhedron_Free(Zpol
);
259 } /* AddZPolytoZDomain */
262 * Return the empty Z-polyhedron of dimension 'dimension'
264 ZPolyhedron
*EmptyZPolyhedron(int dimension
) {
272 fp
= fopen ("_debug", "a");
273 fprintf (fp
, "\nEntered EMPTYZPOLYHEDRON\n");
277 E
= EmptyLattice(dimension
+1);
278 P
= Empty_Polyhedron(dimension
);
279 Zpol
= ZPolyhedron_Alloc(E
,P
);
280 Matrix_Free((Matrix
*) E
);
283 } /* EmptyZPolyhedron */
286 * Given Z-domains 'A' and 'B', return True if A is included in 'B', otherwise
289 Bool
ZDomainIncludes(ZPolyhedron
*A
, ZPolyhedron
*B
) {
294 Diff
= ZDomainDifference(A
,B
);
295 if (isEmptyZPolyhedron(Diff
))
300 } /* ZDomainIncludes */
303 * Given Z-polyhedra 'A' and 'B', return True if 'A' is included in 'B',
304 * otherwise return False
306 Bool
ZPolyhedronIncludes(ZPolyhedron
*A
, ZPolyhedron
*B
) {
308 Polyhedron
*Diff
= NULL
;
313 fp
= fopen("_debug","a");
314 fprintf(fp
,"\nEntered ZPOLYHEDRONINCLUDES\n");
318 if (LatticeIncludes(A
->Lat
, B
->Lat
) == True
) {
319 Polyhedron
*ImageA
, *ImageB
;
321 ImageA
= DomainImage(A
->P
,A
->Lat
,MAXNOOFRAYS
);
322 ImageB
= DomainImage(B
->P
,B
->Lat
,MAXNOOFRAYS
);
324 Diff
= DomainDifference(ImageA
, ImageB
, MAXNOOFRAYS
);
328 Domain_Free (ImageA
);
329 Domain_Free (ImageB
);
333 } /* ZPolyhedronIncludes */
336 * Print the contents of a Z-domain 'A'
338 void ZDomainPrint(FILE *fp
, const char *format
, ZPolyhedron
*A
)
342 fp1
= fopen("_debug", "a");
343 fprintf(fp1
,"\nEntered ZDOMAINPRINT\n");
347 ZPolyhedronPrint(fp
,format
,A
);
348 if (A
->next
!= NULL
) {
349 fprintf(fp
,"\nUNIONED with\n");
350 ZDomainPrint(fp
,format
,A
->next
);
356 * Print the contents of a ZPolyhderon 'A'
358 static void ZPolyhedronPrint (FILE *fp
, const char *format
, ZPolyhedron
*A
)
362 fprintf(fp
,"\nZPOLYHEDRON: Dimension %d \n",A
->Lat
->NbRows
-1);
363 fprintf(fp
, "\nLATTICE: \n");
364 Matrix_Print(fp
,format
,(Matrix
*)A
->Lat
);
365 Polyhedron_Print(fp
,format
,A
->P
);
367 } /* ZPolyhedronPrint */
370 * Return the Z-domain union of the Z-domain 'A' and 'B'. The dimensions of the
371 * Z-domains 'A' and 'B' must be equal. All the Z-polyhedra of the resulting
372 * union are expected to be in Canonical forms.
374 ZPolyhedron
*ZDomainUnion (ZPolyhedron
*A
, ZPolyhedron
*B
) {
376 ZPolyhedron
*Result
= NULL
, *temp
;
380 fp
= fopen("_debug", "a");
381 fprintf(fp
,"\nEntered ZDOMAINUNION\n");
385 for(temp
= A
; temp
!= NULL
; temp
= temp
->next
)
386 Result
= AddZPolytoZDomain(temp
, Result
);
387 for(temp
= B
; temp
!= NULL
; temp
= temp
->next
)
388 Result
= AddZPolytoZDomain(temp
, Result
);
393 * Return the Z-domain intersection of the Z-domains 'A' and 'B'.The dimensions
394 * of domains 'A' and 'B' must be equal.
396 ZPolyhedron
*ZDomainIntersection (ZPolyhedron
*A
, ZPolyhedron
*B
) {
398 ZPolyhedron
*Result
= NULL
, *tempA
= NULL
, *tempB
= NULL
;
402 fp
= fopen("_debug", "a");
403 fprintf(fp
,"\nEntered ZDOMAININTERSECTION\n");
407 for(tempA
= A
; tempA
!= NULL
; tempA
= tempA
->next
)
408 for(tempB
= B
; tempB
!= NULL
; tempB
= tempB
->next
) {
410 Zpol
= ZPolyhedronIntersection(tempA
, tempB
);
411 Result
= AddZPolytoZDomain(Zpol
, Result
);
412 ZPolyhedron_Free (Zpol
);
415 return EmptyZPolyhedron (A
->Lat
->NbRows
-1);
417 } /* ZDomainIntersection */
420 * Return the Z-domain difference of the domains 'A' and 'B'. The dimensions of
421 * the Z-domains 'A' and 'B' must be equal. Note that the difference of two
422 * Z-polyhedra is a Union of Z-polyhedra. The algorithms is as given below :-
423 * Algorithm: (Given Z-domains A and B)
425 * for every Z-polyhderon Zpoly of A {
427 * for every Z-polyhderon Z1 of B
430 * Add temp to Result;
433 ZPolyhedron
*ZDomainDifference(ZPolyhedron
*A
, ZPolyhedron
*B
) {
435 ZPolyhedron
*Result
= NULL
, *tempA
= NULL
, *tempB
= NULL
;
436 ZPolyhedron
*templist
, *res
, *i
, *j
;
440 fp
= fopen("_debug", "a");
441 fprintf(fp
,"\nEntered ZDOMAINDIFFERENCE\n");
445 if (A
->Lat
->NbRows
!= B
->Lat
->NbRows
) {
446 fprintf(stderr
, "In ZDomainDifference : the input ZDomains ");
447 fprintf(stderr
, "do not have compatible dimensions\n");
448 fprintf(stderr
, "ZDomainDifference not performed\n");
452 for(tempA
= A
; tempA
!= NULL
; tempA
= tempA
->next
) {
453 ZPolyhedron
*temp
= NULL
;
454 temp
= ZPolyhedron_Copy(tempA
);
456 for(tempB
= B
; tempB
!= NULL
; tempB
= tempB
->next
) {
457 templist
= NULL
; res
= NULL
;
458 for(i
= temp
; i
!= NULL
; i
= i
->next
) {
459 res
= ZPolyhedronDifference(i
,tempB
);
460 for (j
= res
; j
!= NULL
; j
= j
->next
)
461 templist
= AddZPoly2ZDomain(j
,templist
);
466 for(i
= templist
; i
!= NULL
; i
= i
->next
)
467 temp
= AddZPoly2ZDomain(i
, temp
);
468 ZDomain_Free (templist
);
470 for(i
= temp
; i
!= NULL
; i
= i
->next
)
471 Result
= AddZPolytoZDomain(i
, Result
);
475 return (EmptyZPolyhedron(A
->Lat
->NbRows
-1));
477 } /* ZDomainDifference */
480 * Return the image of the Z-domain 'A' under the invertible, affine, rational
481 * transformation function 'Func'. The matrix representing the function 'Func'
482 * must be non-singular and the number of rows of the function must be equal
483 * to the number of rows in the matrix representing the lattice of 'A'.
484 * Note:: Image((Z1 U Z2),F) = Image(Z1,F) U Image(Z2 U F).
486 ZPolyhedron
*ZDomainImage (ZPolyhedron
*A
, Matrix
*Func
) {
488 ZPolyhedron
*Result
= NULL
, *temp
;
492 fp
= fopen ("_debug", "a");
493 fprintf (fp
, "\nEntered ZDOMAINIMAGE\n");
497 for(temp
= A
; temp
!= NULL
; temp
= temp
->next
) {
499 Zpol
= ZPolyhedronImage (temp
, Func
);
500 Result
= AddZPolytoZDomain (Zpol
, Result
);
501 ZPolyhedron_Free (Zpol
);
504 return EmptyZPolyhedron(A
->Lat
->NbRows
-1);
509 * Return the preimage of the Z-domain 'A' under the invertible, affine, ratio-
510 * nal transformation 'Func'. The number of rows of the matrix representing
511 * the function 'Func' must be equal to the number of rows of the matrix repr-
512 * senting the lattice of 'A'.
514 ZPolyhedron
*ZDomainPreimage (ZPolyhedron
*A
, Matrix
*Func
) {
516 ZPolyhedron
*Result
= NULL
, *temp
;
520 fp
= fopen("_debug", "a");
521 fprintf(fp
,"\nEntered ZDOMAINPREIMAGE\n");
525 if (A
->Lat
->NbRows
!= Func
->NbRows
) {
526 fprintf(stderr
,"\nError : In ZDomainPreimage, ");
527 fprintf(stderr
,"Incompatible dimensions of ZPolyhedron ");
528 fprintf(stderr
,"and the Function \n");
529 return(EmptyZPolyhedron(Func
->NbColumns
-1));
531 for(temp
= A
; temp
!= NULL
; temp
= temp
->next
) {
533 Zpol
= ZPolyhedronPreimage(temp
, Func
);
534 Result
= AddZPolytoZDomain(Zpol
, Result
);
535 ZPolyhedron_Free(Zpol
);
538 return(EmptyZPolyhedron(Func
->NbColumns
-1));
540 } /* ZDomainPreimage */
543 * Return the Z-polyhedron intersection of the Z-polyhedra 'A' and 'B'.
544 * Note: If Z1 = L1 (intersect) P1 and Z2 = L2 (intersect) P2, then
545 * Z1 (intersect) Z2 = (L1 (intersect) L2) (intersect) (P1 (intersect) P2)
547 static ZPolyhedron
*ZPolyhedronIntersection(ZPolyhedron
*A
, ZPolyhedron
*B
) {
549 ZPolyhedron
*Result
= NULL
;
551 Polyhedron
*PInter
, *ImageA
, *ImageB
, *PreImage
;
555 fp
= fopen("_debug","a");
556 fprintf(fp
,"\nEntered ZPOLYHEDRONINTERSECTION\n");
560 LInter
= LatticeIntersection(A
->Lat
,B
->Lat
);
561 if(isEmptyLattice(LInter
) == True
) {
562 ZPolyhedron_Free (Result
);
564 return (EmptyZPolyhedron(A
->Lat
->NbRows
-1));
566 ImageA
= DomainImage(A
->P
,A
->Lat
,MAXNOOFRAYS
);
567 ImageB
= DomainImage(B
->P
,B
->Lat
,MAXNOOFRAYS
);
568 PInter
= DomainIntersection(ImageA
,ImageB
,MAXNOOFRAYS
);
570 Result
= EmptyZPolyhedron(LInter
->NbRows
-1);
572 PreImage
= DomainPreimage(PInter
,(Matrix
*)LInter
,MAXNOOFRAYS
);
573 Result
= ZPolyhedron_Alloc(LInter
, PreImage
);
574 Domain_Free (PreImage
);
581 } /* ZPolyhedronIntersection */
584 * Return the difference of the two Z-polyhedra 'A' and 'B'. Below is the
585 * procedure to find the difference of 'A' and 'B' :-
587 * Let A = L1 (intersect) P1' and B = L2 (intersect) P2' where
588 * (P1' = DomImage(P1,L1) and P2' = DomImage(P2,L2)). Then
589 * A-B = L1 (intersect) (P1'-P2') Union
590 * (L1-L2) (intersect) (P1' (intersect) P2')
592 static ZPolyhedron
*ZPolyhedronDifference(ZPolyhedron
*A
, ZPolyhedron
*B
) {
594 ZPolyhedron
*Result
= NULL
;
595 LatticeUnion
*LatDiff
, *temp
;
596 Polyhedron
*DomDiff
, *DomInter
, *PreImage
, *ImageA
, *ImageB
;
601 fp
= fopen("_debug", "a");
602 fprintf(fp
,"\nEntered ZPOLYHEDRONDIFFERENCE\n");
606 if(isEmptyZPolyhedron (A
))
608 if(isEmptyZPolyhedron (B
)) {
609 Result
= ZDomain_Copy (A
);
612 ImageA
= DomainImage(A
->P
,(Matrix
*)A
->Lat
,MAXNOOFRAYS
);
613 ImageB
= DomainImage(B
->P
,(Matrix
*)B
->Lat
,MAXNOOFRAYS
);
614 DomDiff
= DomainDifference(ImageA
,ImageB
,MAXNOOFRAYS
);
615 if (emptyQ (DomDiff
))
619 PreImage
= DomainPreimage(DomDiff
,A
->Lat
,MAXNOOFRAYS
);
620 Z
= ZPolyhedron_Alloc(A
->Lat
,PreImage
);
621 Result
= AddZPolytoZDomain(Z
,Result
);
623 if (flag
== True
) /* DomDiff = NULL; DomInter = A */
624 DomInter
= Domain_Copy(ImageA
);
626 DomInter
= DomainIntersection(ImageA
,ImageB
,MAXNOOFRAYS
);
627 if (emptyQ(DomInter
)) {
629 return (EmptyZPolyhedron(A
->Lat
->NbRows
-1));
634 LatDiff
= LatticeDifference(A
->Lat
, B
->Lat
);
637 return(EmptyZPolyhedron (A
->Lat
->NbRows
-1));
639 while (LatDiff
!= NULL
) {
640 ZPolyhedron
*tempZ
= NULL
;
642 PreImage
= DomainPreimage(DomInter
, LatDiff
->M
, MAXNOOFRAYS
);
643 tempZ
= ZPolyhedron_Alloc(LatDiff
->M
, PreImage
);
644 Domain_Free(PreImage
);
645 Result
= AddZPoly2ZDomain(tempZ
,Result
);
646 ZPolyhedron_Free(tempZ
);
648 LatDiff
= LatDiff
->next
;
649 Matrix_Free ((Matrix
*) temp
->M
);
652 Domain_Free (DomInter
);
653 Domain_Free (DomDiff
);
655 } /* ZPolyhedronDifference */
658 * Return the image of the Z-polyhedron 'ZPol' under the invertible, affine,
659 * rational transformation function 'Func'. The matrix representing the funct-
660 * ion must be non-singular and the number of rows of the function must be
661 * equal to the number of rows in the matrix representing the lattice of 'ZPol'
663 * 1) Let ZPol = L (intersect) Q
664 * 2) L1 = LatticeImage(L,F)
665 * 3) Q1 = DomainImage(Q,F)
666 * 4) Z1 = L1(Inverse(L1)*Q1)
669 static ZPolyhedron
*ZPolyhedronImage(ZPolyhedron
*ZPol
,Matrix
*Func
) {
671 ZPolyhedron
*Result
= NULL
;
673 Polyhedron
*Pol
, *PolImage
;
677 fp
= fopen("_debug", "a");
678 fprintf(fp
,"\nEntered ZPOLYHEDRONIMAGE\n");
682 if ((Func
->NbRows
!= ZPol
->Lat
->NbRows
) || (Func
->NbColumns
!= ZPol
->Lat
->NbColumns
)) {
683 fprintf (stderr
, "In ZPolImage - The Function, is not compatible with the ZPolyhedron\n");
686 LatIm
= LatticeImage(ZPol
->Lat
,Func
);
687 if (isEmptyLattice(LatIm
)) {
691 Pol
= DomainImage(ZPol
->P
,ZPol
->Lat
,MAXNOOFRAYS
);
692 PolImage
= DomainImage(Pol
,Func
,MAXNOOFRAYS
);
694 if(emptyQ(PolImage
)) {
696 Domain_Free (PolImage
);
699 Pol
= DomainPreimage(PolImage
,LatIm
,MAXNOOFRAYS
);
700 Result
= ZPolyhedron_Alloc(LatIm
,Pol
);
702 Domain_Free(PolImage
);
705 } /* ZPolyhedronImage */
708 * Return the preimage of the Z-polyhedron 'Zpol' under an affine transformati-
709 * on function 'G'. The number of rows of matrix representing the function 'G',
710 * must be equal to the number of rows of the matrix representing the lattice
713 * 1) Let Zpol = L (intersect) Q
714 * 2) L1 =LatticePreimage(L,F);
715 * 3) Q1 = DomainPreimage(Q,F);
716 * 4) Z1 = L1(Inverse(L1)*Q1);
719 static ZPolyhedron
*ZPolyhedronPreimage(ZPolyhedron
*Zpol
, Matrix
*G
) {
722 Polyhedron
*Qprime
, *Q
, *Polpreim
;
727 fp
= fopen("_debug","a");
728 fprintf(fp
,"\nEntered ZPOLYHEDRONPREIMAGE\n");
732 if(G
->NbRows
!= Zpol
->Lat
->NbRows
) {
733 fprintf(stderr
,"\nIn ZPolyhedronPreimage: Error, The dimensions of the ");
734 fprintf(stderr
,"function are not compatible with that of the Zpolyhedron");
735 return EmptyZPolyhedron(G
->NbColumns
-1);
737 Q
= DomainImage(Zpol
->P
,Zpol
->Lat
,MAXNOOFRAYS
);
738 Polpreim
= DomainPreimage(Q
,G
,MAXNOOFRAYS
);
739 if (emptyQ(Polpreim
))
742 Latpreim
= LatticePreimage(Zpol
->Lat
,G
);
743 if(isEmptyLattice(Latpreim
))
746 Qprime
= DomainPreimage(Polpreim
, Latpreim
, MAXNOOFRAYS
);
747 Result
= ZPolyhedron_Alloc(Latpreim
, Qprime
);
750 Matrix_Free(Latpreim
);
754 } /* ZPolyhedronPreimage */
757 * Return the Z-polyhderon 'Zpol' in canonical form: 'Result' (for the Z-poly-
758 * hedron in canonical form) and Basis 'Basis' (for the basis with respect to
759 * which 'Result' is in canonical form.
761 void CanonicalForm(ZPolyhedron
*Zpol
,ZPolyhedron
**Result
,Matrix
**Basis
) {
763 Matrix
*B1
= NULL
, *B2
=NULL
, *T1
, *B2inv
;
766 Polyhedron
*Image
, *ImageP
;
767 Matrix
*H
, *U
, *temp
, *Hprime
, *Uprime
, *T2
;
771 fp
= fopen("_debug", "a");
772 fprintf(fp
,"\nEntered CANONICALFORM\n");
776 if(isEmptyZPolyhedron (Zpol
)) {
777 Basis
[0] = Identity(Zpol
->Lat
->NbRows
);
778 Result
[0] = ZDomain_Copy (Zpol
);
782 l1
= FindHermiteBasisofDomain(Zpol
->P
,&B1
);
783 Image
= DomainImage (Zpol
->P
,(Matrix
*)Zpol
->Lat
,MAXNOOFRAYS
);
784 l2
= FindHermiteBasisofDomain(Image
,&B2
);
787 fprintf(stderr
,"In CNF : Something wrong with the Input Zpolyhedra \n");
789 B2inv
= Matrix_Alloc(B2
->NbRows
, B2
->NbColumns
);
790 temp
= Matrix_Copy(B2
);
791 Matrix_Inverse(temp
,B2inv
);
794 temp
= Matrix_Alloc(B2inv
->NbRows
,Zpol
->Lat
->NbColumns
);
795 T1
= Matrix_Alloc(temp
->NbRows
,B1
->NbColumns
);
796 Matrix_Product(B2inv
,(Matrix
*)Zpol
->Lat
,temp
);
797 Matrix_Product(temp
,B1
,T1
);
800 T2
= ChangeLatticeDimension(T1
,l1
);
801 temp
= ChangeLatticeDimension(T2
,T2
->NbRows
+1);
803 /* Adding the affine part */
804 for(i
= 0; i
< l1
; i
++)
805 value_assign(temp
->p
[i
][temp
->NbColumns
-1],T1
->p
[i
][T1
->NbColumns
-1]);
807 AffineHermite(temp
,&H
,&U
);
808 Hprime
= ChangeLatticeDimension(H
,Zpol
->Lat
->NbRows
);
810 /* Exchanging the Affine part */
811 for(i
= 0; i
< l1
; i
++) {
812 value_assign(tmp
,Hprime
->p
[i
][Hprime
->NbColumns
-1]);
813 value_assign(Hprime
->p
[i
][Hprime
->NbColumns
-1],Hprime
->p
[i
][H
->NbColumns
-1]);
814 value_assign(Hprime
->p
[i
][H
->NbColumns
-1],tmp
);
816 Uprime
= ChangeLatticeDimension(U
,Zpol
->Lat
->NbRows
);
818 /* Exchanging the Affine part */
819 for (i
= 0;i
< l1
; i
++) {
820 value_assign(tmp
,Uprime
->p
[i
][Uprime
->NbColumns
-1]);
821 value_assign(Uprime
->p
[i
][Uprime
->NbColumns
-1],Uprime
->p
[i
][U
->NbColumns
-1]);
822 value_assign(Uprime
->p
[i
][U
->NbColumns
-1],tmp
);
824 Polyhedron_Free (Image
);
826 B2inv
= Matrix_Alloc(B1
->NbRows
, B1
->NbColumns
);
827 Matrix_Inverse(B1
,B2inv
);
828 ImageP
= DomainImage(Zpol
->P
, B2inv
, MAXNOOFRAYS
);
830 Image
= DomainImage(ImageP
, Uprime
, MAXNOOFRAYS
);
832 Result
[0] = ZPolyhedron_Alloc(Hprime
, Image
);
833 Basis
[0] = Matrix_Copy(B2
);
835 /* Free the variables */
836 Polyhedron_Free (Image
);
844 Matrix_Free (Hprime
);
845 Matrix_Free (Uprime
);
848 } /* CanonicalForm */
851 * Given a Z-polyhedron 'A' in which the Lattice is not integral, return the
852 * Z-polyhedron which contains all the integral points in the input lattice.
854 ZPolyhedron
*IntegraliseLattice(ZPolyhedron
*A
) {
857 Lattice
*M
= NULL
, *Id
;
858 Polyhedron
*Im
= NULL
, *Preim
= NULL
;
862 fp
= fopen("_debug","a");
863 fprintf(fp
,"\nEntered INTEGRALISELATTICE\n");
867 Im
= DomainImage(A
->P
,A
->Lat
,MAXNOOFRAYS
);
868 Id
= Identity(A
->Lat
->NbRows
);
869 M
= LatticeImage(Id
, A
->Lat
);
870 if (isEmptyLattice(M
))
871 Result
= EmptyZPolyhedron(A
->Lat
->NbRows
-1);
873 Preim
= DomainPreimage(Im
,M
,MAXNOOFRAYS
);
874 Result
= ZPolyhedron_Alloc(M
,Preim
);
880 } /* IntegraliseLattice */
883 * Return the simplified representation of the Z-domain 'ZDom'. It attempts to
884 * convexize unions of polyhedra when they correspond to the same lattices and
885 * to simplify union of lattices when they correspond to the same polyhdera.
887 ZPolyhedron
*ZDomainSimplify(ZPolyhedron
*ZDom
) {
889 ZPolyhedron
*Ztmp
, *Result
;
890 ForSimplify
*Head
, *Prev
, *Curr
;
891 ZPolyhedron
*ZDomHead
, *Emp
;
894 fprintf(stderr
,"\nError in ZDomainSimplify - ZDomHead = NULL\n");
897 if (ZDom
->next
== NULL
)
898 return (ZPolyhedron_Copy (ZDom
));
899 Emp
= EmptyZPolyhedron(ZDom
->Lat
->NbRows
-1);
900 ZDomHead
= ZDomainUnion(ZDom
, Emp
);
901 ZPolyhedron_Free(Emp
);
906 Img
= DomainImage(Ztmp
->P
,Ztmp
->Lat
,MAXNOOFRAYS
);
907 for(Curr
= Head
; Curr
!= NULL
; Curr
= Curr
->next
) {
911 Diff1
= DomainDifference(Img
,Curr
->Pol
,MAXNOOFRAYS
);
915 Diff2
= DomainDifference(Curr
->Pol
,Img
,MAXNOOFRAYS
);
924 temp
= (LatticeUnion
*)malloc(sizeof(LatticeUnion
));
925 temp
->M
= (Lattice
*)Matrix_Copy((Matrix
*)Ztmp
->Lat
);
926 temp
->next
= Curr
->LatUni
;
932 Curr
= (ForSimplify
*)malloc(sizeof(ForSimplify
));
933 Curr
->Pol
= Domain_Copy(Img
);
934 Curr
->LatUni
= (LatticeUnion
*)malloc(sizeof(LatticeUnion
));
935 Curr
->LatUni
->M
= (Lattice
*)Matrix_Copy((Matrix
*)Ztmp
->Lat
);
936 Curr
->LatUni
->next
= NULL
;
942 } while(Ztmp
!= NULL
);
944 for (Curr
= Head
; Curr
!= NULL
; Curr
= Curr
->next
)
945 Curr
->LatUni
= LatticeSimplify(Curr
->LatUni
);
947 for(Curr
= Head
; Curr
!= NULL
; Curr
= Curr
->next
) {
949 for(L
= Curr
->LatUni
; L
!= NULL
; L
= L
->next
) {
953 Preim
= DomainPreimage(Curr
->Pol
,L
->M
,MAXNOOFRAYS
);
954 Zpol
= ZPolyhedron_Alloc(L
->M
, Preim
);
961 while (Curr
!= NULL
) {
964 LatticeUnion_Free(Prev
->LatUni
);
965 Domain_Free(Prev
->Pol
);
969 } /* ZDomainSimplify */
971 ZPolyhedron
*SplitZpolyhedron(ZPolyhedron
*ZPol
,Lattice
*B
) {
973 Lattice
*Intersection
= NULL
;
974 Lattice
*B1
= NULL
, *B2
= NULL
, *newB1
= NULL
, *newB2
= NULL
;
975 Matrix
*U
= NULL
,*M1
= NULL
, *M2
= NULL
, *M1Inverse
= NULL
,*MtProduct
= NULL
;
976 Matrix
*Vinv
, *V
, *temp
, *DiagMatrix
;
977 Matrix
*H
, *U1
, *X
, *Y
;
978 ZPolyhedron
*zpnew
, *Result
;
979 LatticeUnion
*Head
= NULL
, *tempHead
= NULL
;
985 fp
= fopen("_debug", "a");
986 fprintf(fp
,"\nEntered SplitZpolyhedron \n");
991 if (B
->NbRows
!= B
->NbColumns
) {
992 fprintf(stderr
,"\n SplitZpolyhedron : The Input Matrix B is not a proper Lattice \n");
996 if (ZPol
->Lat
->NbRows
!= B
->NbRows
) {
997 fprintf(stderr
,"\nSplitZpolyhedron : The Lattice in Zpolyhedron and B have ");
998 fprintf(stderr
,"incompatible dimensions \n");
1002 if (isinHnf (ZPol
->Lat
) != True
) {
1003 AffineHermite(ZPol
->Lat
,&H
,&U1
);
1009 X
= Matrix_Copy(ZPol
->Lat
);
1011 if (isinHnf(B
) != True
) {
1012 AffineHermite(B
,&H
,&U1
);
1019 if (isEmptyLattice(X
)) {
1023 Head
=Lattice2LatticeUnion(X
,Y
);
1025 /* If the spliting operation can't be done the result is the original Zplyhedron. */
1041 zpnew
=ZPolyhedron_Alloc(tempHead
->M
,ZPol
->P
);
1042 Result
=AddZPoly2ZDomain(zpnew
,Result
);
1043 ZPolyhedron_Free(zpnew
);
1044 tempHead
->next
= NULL
;