polylib: polyhedron.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# polyhedron.c

Go to the documentation of this file.

    00001 /*
    00002     This file is part of PolyLib.
    00003
    00004     PolyLib is free software: you can redistribute it and/or modify
    00005     it under the terms of the GNU General Public License as published by
    00006     the Free Software Foundation, either version 3 of the License, or
    00007     (at your option) any later version.
    00008
    00009     PolyLib is distributed in the hope that it will be useful,
    00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00012     GNU General Public License for more details.
    00013
    00014     You should have received a copy of the GNU General Public License
    00015     along with PolyLib.  If not, see <http://www.gnu.org/licenses/>.
    00016 */
    00017
    00018 /* polyhedron.c
    00019      COPYRIGHT
    00020           Both this software and its documentation are
    00021
    00022               Copyright 1993 by IRISA /Universite de Rennes I - France,
    00023               Copyright 1995,1996 by BYU, Provo, Utah
    00024                          all rights reserved.
    00025
    00026           Permission is granted to copy, use, and distribute
    00027           for any commercial or noncommercial purpose under the terms
    00028           of the GNU General Public license, version 2, June 1991
    00029           (see file : LICENSING).
    00030 */
    00031
    00032 /*
    00033
    00034 1997/12/02 - Olivier Albiez
    00035   Ce fichier contient les fonctions de la polylib de l'IRISA,
    00036   passees en 64bits.
    00037   La structure de la polylib a donc ete modifie pour permettre
    00038   le passage aux Value. La fonction Chernikova a ete reecrite.
    00039
    00040 */
    00041
    00042 /*
    00043
    00044 1998/26/02 - Vincent Loechner
    00045   Ajout de nombreuses fonctions, a la fin de ce fichier,
    00046   pour les polyedres parametres 64 bits.
    00047 1998/16/03
    00048   #define DEBUG  printf
    00049   tests out of memory
    00050   compatibilite avec la version de doran
    00051
    00052 */
    00053
    00054 #undef POLY_DEBUG               /* debug printf: general functions */
    00055 #undef POLY_RR_DEBUG            /* debug printf: Remove Redundants */
    00056 #undef POLY_CH_DEBUG            /* debug printf: Chernikova */
    00057
    00058 #include <stdio.h>
    00059 #include <stdlib.h>
    00060 #include <string.h>
    00061 #include <assert.h>
    00062 #include <polylib/polylib.h>
    00063
    00064 #ifdef MAC_OS
    00065   #define abs __abs
    00066 #endif
    00067
    00068 /* WSIZE is the number of bits in a word or int type */
    00069 #define WSIZE (8*sizeof(int))
    00070
    00071 #define bexchange(a, b, l)\
    00072 {\
    00073   char *t = (char *)malloc(l*sizeof(char));\
    00074   memcpy((t), (char *)(a), (int)(l));\
    00075   memcpy((char *)(a), (char *)(b), (int)(l));\
    00076   memcpy((char *)(b), (t), (int)(l));\
    00077   free(t); \
    00078 }
    00079
    00080 #define exchange(a, b, t)\
    00081 { (t)=(a); (a)=(b); (b)=(t); }
    00082
    00083 /*  errormsg1 is an external function which is usually supplied by the
    00084     calling program (e.g. Domlib.c, ReadAlpha, etc...).
    00085     See errormsg.c for an example of such a function.  */
    00086
    00087 void errormsg1(const char *f, const char *msgname, const char *msg);
    00088
    00089 int Pol_status;                    /* error status after operations */
    00090
    00091 /*
    00092  * The Saturation matrix is defined to be an integer (int type) matrix.
    00093  * It is a boolean matrix which has a row for every constraint and a column
    00094  * for every line or ray. The bits in the binary format of each integer in
    00095  * the stauration matrix stores the information whether the corresponding
    00096  * constraint is saturated by ray(line) or not.
    00097  */
    00098
    00099 typedef struct {
    00100   unsigned int NbRows;
    00101   unsigned int NbColumns;
    00102   int **p;
    00103   int *p_init;
    00104 } SatMatrix;
    00105
    00106 /*
    00107  * Allocate memory space for a saturation matrix.
    00108  */
    00109 static SatMatrix *SMAlloc(int rows,int cols) {
    00110
    00111   int **q, *p, i;
    00112   SatMatrix *result;
    00113
    00114   result = (SatMatrix *) malloc (sizeof(SatMatrix));
    00115   if(!result) {
    00116     errormsg1("SMAlloc", "outofmem", "out of memory space");
    00117     return 0;
    00118   }
    00119   result->NbRows = rows;
    00120   result->NbColumns = cols;
    00121   if(rows == 0 || cols == 0) {
    00122     result->p = NULL;
    00123     return result;
    00124   }
    00125   result->p = q = (int **)malloc(rows * sizeof(int *));
    00126   if(!result->p) {
    00127     errormsg1("SMAlloc", "outofmem", "out of memory space");
    00128     return 0;
    00129   }
    00130   result->p_init = p = (int *)malloc (rows * cols * sizeof (int));
    00131   if(!result->p_init) {
    00132     errormsg1("SMAlloc", "outofmem", "out of memory space");
    00133     return 0;
    00134   }
    00135   for (i=0; i<rows; i++) {
    00136     *q++ = p;
    00137     p += cols;
    00138   }
    00139   return result;
    00140 } /* SMAlloc */
    00141
    00142 /*
    00143  * Free the memory space occupied by saturation matrix.
    00144  */
    00145 static void SMFree (SatMatrix **matrix) {
    00146   SatMatrix *SM = *matrix;
    00147
    00148   if (SM) {
    00149     if (SM->p) {
    00150       free ((char *) SM->p_init);
    00151       free ((char *) SM->p);
    00152     }
    00153     free ((char *) SM);
    00154     *matrix = NULL;
    00155   }
    00156 } /* SMFree */
    00157
    00158 /*
    00159  * Print the contents of a saturation matrix.
    00160  * This function is defined only for debugging purpose.
    00161  */
    00162 static void SMPrint (SatMatrix *matrix) {
    00163
    00164   int *p;
    00165   int i, j;
    00166   unsigned NbRows, NbColumns;
    00167
    00168   fprintf(stderr,"%d %d\n",NbRows=matrix->NbRows, NbColumns=matrix->NbColumns);
    00169   for (i=0;i<NbRows;i++) {
    00170     p = *(matrix->p+i);
    00171     for (j=0;j<NbColumns;j++)
    00172       fprintf(stderr, " %10X ", *p++);
    00173     fprintf(stderr, "\n");
    00174   }
    00175 } /* SMPrint */
    00176
    00177 /*
    00178  * Compute the bitwise OR of two saturation matrices.
    00179  */
    00180 static void SatVector_OR(int *p1,int *p2,int *p3,unsigned length) {
    00181
    00182   int *cp1, *cp2, *cp3;
    00183   int i;
    00184
    00185   cp1=p1;
    00186   cp2=p2;
    00187   cp3=p3;
    00188   for (i=0;i<length;i++) {
    00189     *cp3 = *cp1 | *cp2;
    00190     cp3++;
    00191     cp1++;
    00192     cp2++;
    00193   }
    00194 } /* SatVector_OR */
    00195
    00196 /*
    00197  * Copy a saturation matrix to another (macro definition).
    00198  */
    00199 #define SMVector_Copy(p1, p2, length) \
    00200   memcpy((char *)(p2), (char *)(p1), (int)((length)*sizeof(int)))
    00201
    00202 /*
    00203  * Initialize a saturation matrix with zeros (macro definition)
    00204  */
    00205 #define SMVector_Init(p1, length) \
    00206   memset((char *)(p1), 0, (int)((length)*sizeof(int)))
    00207
    00208 /*
    00209  * Defining operations on polyhedron --
    00210  */
    00211
    00212 /*
    00213  * Vector p3 is a linear combination of two vectors (p1 and p2) such that
    00214  * p3[pos] is zero. First element of each vector (p1,p2,p3) is a status
    00215  * element and is not changed in p3. The value of 'pos' may be 0 however.
    00216  * The parameter 'length' does not include status element one.
    00217  */
    00218 static void Combine(Value *p1, Value *p2, Value *p3, int pos, unsigned length) {
    00219
    00220   Value a1, a2, gcd;
    00221   Value abs_a1,abs_a2,neg_a1;
    00222
    00223   /* Initialize all the 'Value' variables */
    00224   value_init(a1); value_init(a2); value_init(gcd);
    00225   value_init(abs_a1); value_init(abs_a2); value_init(neg_a1);
    00226
    00227   /* a1 = p1[pos] */
    00228   value_assign(a1,p1[pos]);
    00229
    00230   /* a2 = p2[pos] */
    00231   value_assign(a2,p2[pos]);
    00232
    00233   /* a1_abs = |a1| */
    00234   value_absolute(abs_a1,a1);
    00235
    00236   /* a2_abs = |a2| */
    00237   value_absolute(abs_a2,a2);
    00238
    00239   /* gcd  = Gcd(abs(a1), abs(a2)) */
    00240   value_gcd(gcd, abs_a1, abs_a2);
    00241
    00242   /* a1 = a1/gcd */
    00243   value_divexact(a1, a1, gcd);
    00244
    00245   /* a2 = a2/gcd */
    00246   value_divexact(a2, a2, gcd);
    00247
    00248   /* neg_a1 = -(a1) */
    00249   value_oppose(neg_a1,a1);
    00250
    00251   Vector_Combine(p1+1,p2+1,p3+1,a2,neg_a1,length);
    00252   Vector_Normalize(p3+1,length);
    00253
    00254   /* Clear all the 'Value' variables */
    00255   value_clear(a1); value_clear(a2); value_clear(gcd);
    00256   value_clear(abs_a1); value_clear(abs_a2); value_clear(neg_a1);
    00257
    00258   return;
    00259 } /* Combine */
    00260
    00261 /*
    00262  * Return the transpose of the saturation matrix 'Sat'. 'Mat' is a matrix
    00263  * of constraints and 'Ray' is a matrix of ray vectors and 'Sat' is the
    00264  * corresponding saturation matrix.
    00265  */
    00266 static SatMatrix *TransformSat(Matrix *Mat, Matrix *Ray, SatMatrix *Sat) {
    00267
    00268   int i, j, sat_nbcolumns;
    00269   unsigned jx1, jx2, bx1, bx2;
    00270   SatMatrix *result;
    00271
    00272   if (Mat->NbRows != 0)
    00273     sat_nbcolumns = (Mat->NbRows-1) /(sizeof(int)*8) + 1;
    00274   else
    00275     sat_nbcolumns = 0;
    00276
    00277   result = SMAlloc(Ray->NbRows, sat_nbcolumns);
    00278   SMVector_Init(result->p_init, Ray->NbRows * sat_nbcolumns);
    00279
    00280   for(i=0,jx1=0,bx1=MSB; i<Ray->NbRows; i++) {
    00281     for(j=0,jx2=0,bx2=MSB; j<Mat->NbRows; j++) {
    00282       if (Sat->p[j][jx1] & bx1)
    00283         result->p[i][jx2] |= bx2;
    00284       NEXT(jx2,bx2);
    00285     }
    00286     NEXT(jx1, bx1);
    00287   }
    00288   return result;
    00289 } /* TransformSat */
    00290
    00291 /*
    00292  * Sort the rays (Ray, Sat) into three tiers as used in 'Chernikova' function:
    00293  * NbBid         <= i <  equal_bound    : saturates the constraint
    00294  * equal_bound   <= i <  sup_bound      : verifies the constraint
    00295  * sup_bound     <= i <  NbRay          : does not verify
    00296  *
    00297  * 'Ray' is the matrix of rays and 'Sat' is the corresponding saturation
    00298  * matrix. (jx,bx) pair specify the constraint in the saturation matrix. The
    00299  * status element of the 'Ray' matrix holds the saturation value w.r.t the
    00300  * constraint specified by (jx,bx). Thus
    00301  * Ray->p[i][0]  = 0 -> ray(i) saturates the constraint
    00302  * Ray->p[i][0]  > 0 -> ray(i) verifies  the constraint
    00303  * Ray->p[i][0]  < 0 -> ray(i) doesn't verify the constraint
    00304  */
    00305 static void RaySort(Matrix *Ray,SatMatrix *Sat,int NbBid,int NbRay,int *equal_bound,int *sup_bound,unsigned RowSize1, unsigned RowSize2, unsigned bx, unsigned jx) {
    00306
    00307   int inf_bound;
    00308   Value **uni_eq, **uni_sup, **uni_inf;
    00309   int **inc_eq, **inc_sup, **inc_inf;
    00310
    00311   /* 'uni_eq' points to the first ray in the ray matrix which verifies a
    00312    * constraint, 'inc_eq' is the corresponding pointer in saturation
    00313    * matrix. 'uni_inf' points to the first ray (from top) which doesn't
    00314    * verify a constraint, 'inc_inf' is the corresponding pointer in
    00315    * saturation matrix. 'uni_sup' scans the ray matrix and 'inc_sup' is
    00316    * the corresponding pointer in saturation matrix. 'inf_bound' holds the
    00317    * number of the first ray which does not verify the constraints.
    00318    */
    00319
    00320   *sup_bound = *equal_bound = NbBid;
    00321   uni_sup = uni_eq = Ray->p+NbBid;
    00322   inc_sup = inc_eq = Sat->p+NbBid;
    00323   inf_bound = NbRay;
    00324   uni_inf = Ray->p+NbRay;
    00325   inc_inf = Sat->p+NbRay;
    00326
    00327   while (inf_bound>*sup_bound) {
    00328     if (value_zero_p(**uni_sup)) {               /* status = satisfy */
    00329       if (inc_eq != inc_sup) {
    00330         Vector_Exchange(*uni_eq,*uni_sup,RowSize1);
    00331         bexchange(*inc_eq,*inc_sup,RowSize2);
    00332       }
    00333       (*equal_bound)++; uni_eq++; inc_eq++;
    00334       (*sup_bound)++; uni_sup++; inc_sup++;
    00335     }
    00336     else {
    00337       *((*inc_sup)+jx)|=bx;
    00338
    00339       /* if (**uni_sup<0) */
    00340       if (value_neg_p(**uni_sup)) {             /* Status != verify  */
    00341         inf_bound--; uni_inf--; inc_inf--;
    00342         if (inc_inf != inc_sup) {
    00343           Vector_Exchange(*uni_inf,*uni_sup,RowSize1);
    00344           bexchange(*inc_inf,*inc_sup,RowSize2);
    00345         }
    00346       }
    00347       else {                                     /* status == verify */
    00348          (*sup_bound)++; uni_sup++; inc_sup++;
    00349       }
    00350     }
    00351   }
    00352 } /* RaySort */
    00353
    00354 static void SatMatrix_Extend(SatMatrix *Sat, Matrix* Mat, unsigned rows)
    00355 {
    00356   int i;
    00357   unsigned cols;
    00358   cols = (Mat->NbRows - 1)/(sizeof(int)*8) + 1;
    00359
    00360   Sat->p = (int **)realloc(Sat->p, rows * sizeof(int *));
    00361   if(!Sat->p) {
    00362     errormsg1("SatMatrix_Extend", "outofmem", "out of memory space");
    00363     return;
    00364   }
    00365   Sat->p_init = (int *)realloc(Sat->p_init, rows * cols * sizeof (int));
    00366   if(!Sat->p_init) {
    00367     errormsg1("SatMatrix_Extend", "outofmem", "out of memory space");
    00368     return;
    00369   }
    00370   for (i = 0; i < rows; ++i)
    00371     Sat->p[i] = Sat->p_init + (i * cols);
    00372   Sat->NbRows = rows;
    00373 }
    00374
    00375 /*
    00376  * Compute the dual of matrix 'Mat' and place it in matrix 'Ray'.'Mat'
    00377  * contains the constraints (equalities and inequalities) in rows and 'Ray'
    00378  * contains the ray space (lines and rays) in its rows. 'Sat' is a boolean
    00379  * saturation matrix defined as Sat(i,j)=0 if ray(i) saturates constraint(j),
    00380  *  otherwise 1. The constraints in the 'Mat' matrix are processed starting at
    00381  * 'FirstConstraint', 'Ray' and 'Sat' matrices are changed accordingly.'NbBid'
    00382  * is the number of lines in the ray matrix and 'NbMaxRays' is the maximum
    00383  * number of rows (rays) permissible in the 'Ray' and 'Sat' matrix. Return 0
    00384  * if successful, otherwise return 1.
    00385  */
    00386 static int Chernikova (Matrix *Mat,Matrix *Ray,SatMatrix *Sat, unsigned NbBid, unsigned NbMaxRays, unsigned FirstConstraint,unsigned dual) {
    00387
    00388   unsigned NbRay, Dimension, NbConstraints, RowSize1, RowSize2, sat_nbcolumns;
    00389   int sup_bound, equal_bound, index_non_zero, bound;
    00390   int i, j, k, l, redundant, rayonly, nbcommonconstraints;
    00391   int *Temp, aux;
    00392   int *ip1, *ip2;
    00393   unsigned bx, m, jx;
    00394   Value *p1, *p2, *p3;
    00395
    00396 #ifdef POLY_CH_DEBUG
    00397   fprintf(stderr, "[Chernikova: Input]\nRay = ");
    00398   Matrix_Print(stderr,0,Ray);
    00399   fprintf(stderr, "\nConstraints = ");
    00400   Matrix_Print(stderr,0,Mat);
    00401   fprintf(stderr, "\nSat = ");
    00402   SMPrint(Sat);
    00403 #endif
    00404
    00405   NbConstraints=Mat->NbRows;
    00406   NbRay = Ray->NbRows;
    00407   Dimension = Mat->NbColumns-1;         /* Homogeneous Dimension */
    00408   sat_nbcolumns=Sat->NbColumns;
    00409
    00410   RowSize1=(Dimension+1);
    00411   RowSize2=sat_nbcolumns * sizeof(int);
    00412
    00413   Temp=(int *)malloc(RowSize2);
    00414   if(!Temp) {
    00415     errormsg1("Chernikova", "outofmem", "out of memory space");
    00416     return 0;
    00417   }
    00418   CATCH(any_exception_error) {
    00419
    00420   /*
    00421    * In case of overflow, free the allocated memory!
    00422    * Rethrow upwards the stack to forward the exception.
    00423    */
    00424     free(Temp);
    00425     RETHROW();
    00426   }
    00427   TRY {
    00428     jx = FirstConstraint/WSIZE;
    00429     bx = MSB; bx >>= FirstConstraint%WSIZE;
    00430     for (k=FirstConstraint; k<NbConstraints; k++) {
    00431
    00432       /* Set the status word of each ray[i] to ray[i] dot constraint[k] */
    00433       /* This is equivalent to evaluating each ray by the constraint[k] */
    00434       /* 'index_non_zero' is assigned the smallest ray index which does */
    00435       /* not saturate the constraint.                                   */
    00436
    00437       index_non_zero = NbRay;
    00438       for (i=0; i<NbRay; i++) {
    00439         p1 = Ray->p[i]+1;
    00440         p2 = Mat->p[k]+1;
    00441         p3 = Ray->p[i];
    00442
    00443         /* *p3 = *p1 * *p2 */
    00444         value_multiply(*p3,*p1,*p2);
    00445         p1++; p2++;
    00446         for (j=1; j<Dimension; j++) {
    00447
    00448           /* *p3 +=  *p1 * *p2 */
    00449           value_addmul(*p3, *p1, *p2);
    00450           p1++; p2++;
    00451         }
    00452         if (value_notzero_p(*p3) && (i<index_non_zero))
    00453           index_non_zero=i;
    00454       }
    00455
    00456 #ifdef POLY_CH_DEBUG
    00457       fprintf(stderr, "[Chernikova: A]\nRay = ");
    00458       Matrix_Print(stderr,0,Ray);
    00459       fprintf(stderr, "\nConstraints = ");
    00460       Matrix_Print(stderr,0,Mat);
    00461       fprintf(stderr, "\nSat = ");
    00462       SMPrint (Sat);
    00463 #endif
    00464
    00465       /* Find a bidirectional ray z such that cz <> 0 */
    00466       if (index_non_zero<NbBid) {
    00467
    00468         /* Discard index_non_zero bidirectional ray */
    00469         NbBid--;
    00470         if (NbBid!=index_non_zero)
    00471           Vector_Exchange(Ray->p[index_non_zero],Ray->p[NbBid],RowSize1);
    00472
    00473 #ifdef POLY_CH_DEBUG
    00474         fprintf(stderr,"************\n");
    00475         for(i=0;i<RowSize1;i++) {
    00476           value_print(stderr,P_VALUE_FMT,Ray->p[index_non_zero][i]);
    00477         }
    00478         fprintf(stderr,"\n******\n");
    00479         for(i=0;i<RowSize1;i++) {
    00480           value_print(stderr,P_VALUE_FMT,Ray->p[NbBid][i]);
    00481         }
    00482         fprintf(stderr,"\n*******\n");
    00483 #endif
    00484
    00485         /* Compute the new lineality space */
    00486         for (i=0; i<NbBid; i++)
    00487           if (value_notzero_p(Ray->p[i][0]))
    00488             Combine(Ray->p[i],Ray->p[NbBid],Ray->p[i],0,Dimension);
    00489
    00490         /* Add the positive part of index_non_zero bidirectional ray to  */
    00491         /* the set of unidirectional rays                                */
    00492
    00493         if (value_neg_p(Ray->p[NbBid][0])) {
    00494           p1=Ray->p[NbBid];
    00495           for (j=0;j<Dimension+1; j++) {
    00496
    00497             /* *p1 = - *p1 */
    00498             value_oppose(*p1,*p1);
    00499             p1++;
    00500           }
    00501         }
    00502
    00503 #ifdef POLY_CH_DEBUG
    00504         fprintf(stderr, "[Chernikova: B]\nRay = ");
    00505         Ray->NbRows=NbRay;
    00506         Matrix_Print(stderr,0,Ray);
    00507         fprintf(stderr, "\nConstraints = ");
    00508         Matrix_Print(stderr,0,Mat);
    00509         fprintf(stderr, "\nSat = ");
    00510         SMPrint(Sat);
    00511 #endif
    00512
    00513         /* Compute the new pointed cone */
    00514         for (i=NbBid+1; i<NbRay; i++)
    00515           if (value_notzero_p(Ray->p[i][0]))
    00516             Combine(Ray->p[i],Ray->p[NbBid],Ray->p[i],0,Dimension);
    00517
    00518         /* Add the new ray */
    00519         if (value_notzero_p(Mat->p[k][0])) { /* Constraint is an inequality */
    00520           for (j=0;j<sat_nbcolumns;j++) {
    00521             Sat->p[NbBid][j] = 0;     /* Saturation vec for new ray */
    00522           }
    00523           /* The new ray saturates everything except last inequality */
    00524           Sat->p[NbBid][jx] |= bx;
    00525         }
    00526         else {                        /* Constraint is an equality */
    00527           if (--NbRay != NbBid) {
    00528             Vector_Copy(Ray->p[NbRay],Ray->p[NbBid],Dimension+1);
    00529             SMVector_Copy(Sat->p[NbRay],Sat->p[NbBid],sat_nbcolumns);
    00530           }
    00531         }
    00532
    00533 #ifdef POLY_CH_DEBUG
    00534         fprintf(stderr, "[Chernikova: C]\nRay = ");
    00535         Ray->NbRows=NbRay;
    00536         Matrix_Print(stderr,0,Ray);
    00537         fprintf(stderr, "\nConstraints = ");
    00538         Matrix_Print(stderr,0,Mat);
    00539         fprintf(stderr, "\nSat = ");
    00540         SMPrint (Sat);
    00541 #endif
    00542
    00543       }
    00544       else {  /* If the new constraint satisfies all the rays */
    00545         RaySort(Ray, Sat, NbBid, NbRay, &equal_bound, &sup_bound,
    00546                 RowSize1, RowSize2,bx,jx);
    00547
    00548         /* Sort the unidirectional rays into R0, R+, R- */
    00549         /* Ray
    00550            NbRay-> bound-> ________
    00551                            |  R-  |    R- ==> ray.eq < 0  (outside domain)
    00552                      sup-> |------|
    00553                            |  R+  |    R+ ==> ray.eq > 0  (inside domain)
    00554                    equal-> |------|
    00555                            |  R0  |    R0 ==> ray.eq = 0  (on face of domain)
    00556                    NbBid-> |______|
    00557         */
    00558
    00559 #ifdef POLY_CH_DEBUG
    00560         fprintf(stderr, "[Chernikova: D]\nRay = ");
    00561         Ray->NbRows=NbRay;
    00562         Matrix_Print(stderr,0,Ray);
    00563         fprintf(stderr, "\nConstraints = ");
    00564         Matrix_Print(stderr,0,Mat);
    00565         fprintf(stderr, "\nSat = ");
    00566         SMPrint (Sat);
    00567 #endif
    00568
    00569         /* Compute only the new pointed cone */
    00570         bound=NbRay;
    00571         for (i=equal_bound; i<sup_bound; i++) /* for all pairs of R- and R+ */
    00572           for(j=sup_bound; j<bound; j++) {
    00573
    00574           /*--------------------------------------------------------------*/
    00575           /* Count the set of constraints saturated by R+ and R- */
    00576           /* Includes equalities, inequalities and the positivity constraint */
    00577           /*-----------------------------------------------------------------*/
    00578
    00579             nbcommonconstraints = 0;
    00580             for (l=0; l<jx; l++) {
    00581               aux = Temp[l] = Sat->p[i][l] | Sat->p[j][l];
    00582               for (m=MSB; m!=0; m>>=1)
    00583                 if (!(aux&m))
    00584                   nbcommonconstraints++;
    00585             }
    00586             aux = Temp[jx] =  Sat->p[i][jx] | Sat->p[j][jx];
    00587             for (m=MSB; m!=bx; m>>=1)
    00588               if (!(aux&m))
    00589                 nbcommonconstraints++;
    00590             rayonly = (value_zero_p(Ray->p[i][Dimension])  &&
    00591                        value_zero_p(Ray->p[j][Dimension]) &&
    00592                        (dual == 0));
    00593             if(rayonly)
    00594               nbcommonconstraints++;      /* account for pos constr */
    00595
    00596           /*-----------------------------------------------------------------*/
    00597           /* Adjacency Test : is combination [R-,R+] a non redundant ray?    */
    00598           /*-----------------------------------------------------------------*/
    00599
    00600             if (nbcommonconstraints+NbBid>=Dimension-2) { /* Dimensionality check*/
    00601               /* Check whether a ray m saturates the same set of constraints */
    00602               redundant=0;
    00603               for (m=NbBid; m<bound; m++)
    00604                 if ((m!=i)&&(m!=j)) {
    00605
    00606                   /* Two rays (r+ r-) are never made redundant by a vertex */
    00607                   /* because the positivity constraint saturates both rays */
    00608                   /* but not the vertex                                    */
    00609
    00610                   if (rayonly && value_notzero_p(Ray->p[m][Dimension]))
    00611                     continue;
    00612
    00613                   /* (r+ r-) is redundant if there doesn't exist an equation */
    00614                   /* which saturates both r+ and r- but not rm.              */
    00615
    00616                   ip1 = Temp;
    00617                   ip2 = Sat->p[m];
    00618                   for (l=0; l<=jx; l++,ip2++,ip1++)
    00619                     if (*ip2 & ~*ip1)
    00620                       break;
    00621                   if (l>jx) {
    00622                     redundant=1;
    00623                     break;
    00624                   }
    00625                 }
    00626
    00627 #ifdef POLY_CH_DEBUG
    00628               fprintf(stderr, "[Chernikova: E]\nRay = ");
    00629               Ray->NbRows=NbRay;
    00630               Matrix_Print(stderr,0,Ray);
    00631               fprintf(stderr, "\nConstraints = ");
    00632               Matrix_Print(stderr,0,Mat);
    00633               fprintf(stderr, "\nSat = ");
    00634               SMPrint (Sat);
    00635 #endif
    00636
    00637               /*------------------------------------------------------------*/
    00638               /* Add new ray generated by [R+,R-]                           */
    00639               /*------------------------------------------------------------*/
    00640
    00641               if (!redundant) {
    00642                 if (NbRay==NbMaxRays) {
    00643                   NbMaxRays *= 2;
    00644                   Ray->NbRows = NbRay;
    00645                   Matrix_Extend(Ray, NbMaxRays);
    00646                   SatMatrix_Extend(Sat, Mat, NbMaxRays);
    00647                 }
    00648
    00649                 /* Compute the new ray */
    00650                 Combine(Ray->p[j],Ray->p[i],Ray->p[NbRay],0,Dimension);
    00651                 SatVector_OR(Sat->p[j],Sat->p[i],Sat->p[NbRay],sat_nbcolumns);
    00652                 Sat->p[NbRay][jx] &= ~bx;
    00653                 NbRay++;
    00654               }
    00655             }
    00656           }
    00657
    00658 #ifdef POLY_CH_DEBUG
    00659         fprintf(stderr,
    00660                 "[Chernikova: F]\n"
    00661                 "sup_bound=%d\n"
    00662                 "equal_bound=%d\n"
    00663                 "bound=%d\n"
    00664                 "NbRay=%d\n"
    00665                 "Dimension = %d\n"
    00666                 "Ray = ",sup_bound,equal_bound,bound,NbRay,Dimension);
    00667 #endif
    00668 #ifdef POLY_CH_DEBUG
    00669         Ray->NbRows=NbRay;
    00670         fprintf(stderr, "[Chernikova: F]:\nRay = ");
    00671         Matrix_Print(stderr,0,Ray);
    00672 #endif
    00673
    00674         /* Eliminates all non extremal rays */
    00675         /* j = (Mat->p[k][0]) ? */
    00676
    00677         j = (value_notzero_p(Mat->p[k][0])) ?
    00678           sup_bound : equal_bound;
    00679
    00680         i = NbRay;
    00681 #ifdef POLY_CH_DEBUG
    00682         fprintf(stderr, "i = %d\nj = %d \n", i, j);
    00683 #endif
    00684         while ((j<bound)&&(i>bound)) {
    00685           i--;
    00686           Vector_Copy(Ray->p[i],Ray->p[j],Dimension+1);
    00687           SMVector_Copy(Sat->p[i],Sat->p[j],sat_nbcolumns);
    00688           j++;
    00689         }
    00690
    00691 #ifdef POLY_CH_DEBUG
    00692         fprintf(stderr, "i = %d\nj = %d \n", i, j);
    00693         fprintf(stderr,
    00694                 "[Chernikova: F]\n"
    00695                 "sup_bound=%d\n"
    00696                 "equal_bound=%d\n"
    00697                 "bound=%d\n"
    00698                 "NbRay=%d\n"
    00699                 "Dimension = %d\n"
    00700                 "Ray = ",sup_bound,equal_bound,bound,NbRay, Dimension);
    00701 #endif
    00702 #ifdef POLY_CH_DEBUG
    00703         Ray->NbRows=NbRay;
    00704         fprintf(stderr, "[Chernikova: G]\nRay = ");
    00705         Matrix_Print(stderr,0,Ray);
    00706 #endif
    00707         if (j==bound)
    00708           NbRay=i;
    00709         else
    00710           NbRay=j;
    00711       }
    00712       NEXT(jx,bx);
    00713     }
    00714     Ray->NbRows=NbRay;
    00715     Sat->NbRows=NbRay;
    00716
    00717   } /* End of TRY */
    00718
    00719   UNCATCH(any_exception_error);
    00720   free(Temp);
    00721
    00722 #ifdef POLY_CH_DEBUG
    00723   fprintf(stderr, "[Chernikova: Output]\nRay = ");
    00724   Matrix_Print(stderr,0,Ray);
    00725   fprintf(stderr, "\nConstraints = ");
    00726   Matrix_Print(stderr,0,Mat);
    00727   fprintf(stderr, "\nSat = ");
    00728   SMPrint (Sat);
    00729 #endif
    00730
    00731   return 0;
    00732 } /* Chernikova */
    00733
    00734 static int Gauss4(Value **p, int NbEq, int NbRows, int Dimension)
    00735 {
    00736   int i, j, k, pivot, Rank;
    00737   int *column_index = NULL;
    00738   Value gcd;
    00739
    00740   value_init(gcd);
    00741   column_index=(int *)malloc(Dimension * sizeof(int));
    00742   if(!column_index) {
    00743     errormsg1("Gauss","outofmem","out of memory space");
    00744     value_clear(gcd);
    00745     return 0;
    00746   }
    00747   Rank=0;
    00748
    00749   CATCH(any_exception_error) {
    00750     if (column_index)
    00751       free(column_index);
    00752     value_clear(gcd);
    00753     RETHROW();
    00754   }
    00755   TRY {
    00756
    00757     for (j=1; j<=Dimension; j++) {   /* for each column (except status) */
    00758       for (i=Rank; i<NbEq; i++)      /* starting at diagonal, look down */
    00759
    00760         /* if (Mat->p[i][j] != 0) */
    00761         if (value_notzero_p(p[i][j]))
    00762           break;                    /* Find the first non zero element  */
    00763       if (i!=NbEq) {                /* If a non-zero element is found?  */
    00764         if (i!=Rank)                /* If it is found below the diagonal*/
    00765           Vector_Exchange(p[Rank]+1,p[i]+1,Dimension);
    00766
    00767         /* Normalize the pivot row by dividing it by the gcd */
    00768         /* gcd = Vector_Gcd(p[Rank]+1,Dimension) */
    00769         Vector_Gcd(p[Rank]+1,Dimension,&gcd);
    00770
    00771         if (value_cmp_si(gcd, 2) >= 0)
    00772           Vector_AntiScale(p[Rank]+1, p[Rank]+1, gcd, Dimension);
    00773
    00774         if (value_neg_p(p[Rank][j]))
    00775           Vector_Oppose(p[Rank]+1, p[Rank]+1, Dimension);
    00776
    00777         pivot=i;
    00778         for (i=pivot+1; i<NbEq; i++) {  /* Zero out the rest of the column */
    00779
    00780           /* if (Mat->p[i][j] != 0) */
    00781           if (value_notzero_p(p[i][j]))
    00782             Combine(p[i],p[Rank],p[i],j,Dimension);
    00783         }
    00784
    00785         /* For each row with non-zero entry Mat->p[Rank], store the column */
    00786         /* number 'j' in 'column_index[Rank]'. This information will be    */
    00787         /* useful in performing Gaussian elimination backward step.        */
    00788
    00789         column_index[Rank]=j;
    00790         Rank++;
    00791       }
    00792     } /* end of Gaussian elimination forward step */
    00793
    00794     /* Back Substitution -- normalize the system of equations */
    00795     for (k=Rank-1; k>=0; k--) {
    00796       j = column_index[k];
    00797
    00798       /* Normalize the equations */
    00799       for (i=0; i<k; i++) {
    00800
    00801         /* if (Mat->p[i][j] != 0) */
    00802         if (value_notzero_p(p[i][j]))
    00803           Combine(p[i],p[k],p[i],j,Dimension);
    00804       }
    00805
    00806       /* Normalize the inequalities */
    00807       for (i=NbEq;i<NbRows;i++) {
    00808
    00809         /* if (Mat->p[i][j] != 0) */
    00810         if (value_notzero_p(p[i][j]))
    00811           Combine(p[i],p[k],p[i],j,Dimension);
    00812       }
    00813     }
    00814   } /* end of TRY */
    00815
    00816   UNCATCH(any_exception_error);
    00817   free(column_index), column_index = NULL;
    00818
    00819   value_clear(gcd);
    00820   return Rank;
    00821 } /* Gauss */
    00822
    00823 /*
    00824  * Compute a minimal system of equations using Gausian elimination method.
    00825  * 'Mat' is a matrix of constraints in which the first 'Nbeq' constraints
    00826  * are equations. The dimension of the homogenous system is 'Dimension'.
    00827  * The function returns the rank of the matrix 'Mat'.
    00828  */
    00829 int Gauss(Matrix *Mat, int NbEq, int Dimension)
    00830 {
    00831   int Rank;
    00832
    00833 #ifdef POLY_DEBUG
    00834   fprintf(stderr, "[Gauss : Input]\nRay =");
    00835   Matrix_Print(stderr,0,Mat);
    00836 #endif
    00837
    00838   Rank = Gauss4(Mat->p, NbEq, Mat->NbRows, Dimension);
    00839
    00840 #ifdef POLY_DEBUG
    00841   fprintf(stderr, "[Gauss : Output]\nRay =");
    00842   Matrix_Print(stderr,0,Mat);
    00843 #endif
    00844
    00845   return Rank;
    00846 }
    00847
    00848 /*
    00849  * Given 'Mat' - a matrix of equations and inequalities, 'Ray' - a matrix of
    00850  * lines and rays, 'Sat' - the corresponding saturation matrix, and 'Filter'
    00851  * - an array to mark (with 1) the non-redundant equalities and inequalities,
    00852  * compute a polyhedron composed of 'Mat' as constraint matrix and 'Ray' as
    00853  * ray matrix after reductions. This function is usually called as a follow
    00854  * up to 'Chernikova' to remove redundant constraints or rays.
    00855  * Note: (1) 'Chernikova' ensures that there are no redundant lines and rays.
    00856  *       (2) The same function can be used with constraint and ray matrix used
    00857   interchangbly.
    00858  */
    00859 static Polyhedron *Remove_Redundants(Matrix *Mat,Matrix *Ray,SatMatrix *Sat,unsigned *Filter) {
    00860
    00861   int i, j, k;
    00862   unsigned Dimension, sat_nbcolumns, NbRay, NbConstraints, RowSize2,
    00863            *Trace = NULL, *bx = NULL, *jx = NULL, Dim_RaySpace, b;
    00864   unsigned NbBid, NbUni, NbEq, NbIneq;
    00865   unsigned NbBid2, NbUni2, NbEq2, NbIneq2;
    00866   int Redundant;
    00867   int aux, *temp2 = NULL;
    00868   Polyhedron *Pol = NULL;
    00869   Vector *temp1 = NULL;
    00870   unsigned Status;
    00871
    00872   Dimension = Mat->NbColumns-1;     /* Homogeneous Dimension */
    00873   NbRay = Ray->NbRows;
    00874   sat_nbcolumns = Sat->NbColumns;
    00875   NbConstraints = Mat->NbRows;
    00876   RowSize2=sat_nbcolumns * sizeof(int);
    00877
    00878   temp1 = Vector_Alloc(Dimension+1);
    00879   if (!temp1) {
    00880     errormsg1("Remove_Redundants", "outofmem", "out of memory space");
    00881     return 0;
    00882   }
    00883
    00884   if (Filter) {
    00885     temp2 = (int *)calloc(sat_nbcolumns, sizeof(int));
    00886     if (!temp2)
    00887       goto oom;
    00888   }
    00889
    00890   /* Introduce indirections into saturation matrix 'Sat' to simplify */
    00891   /* processing with 'Sat' and allow easy exchanges of columns.      */
    00892   bx = (unsigned *)malloc(NbConstraints * sizeof(unsigned));
    00893   if (!bx)
    00894     goto oom;
    00895   jx = (unsigned *)malloc(NbConstraints * sizeof(unsigned));
    00896   if (!jx)
    00897     goto oom;
    00898   CATCH(any_exception_error) {
    00899
    00900     Vector_Free(temp1);
    00901     if (temp2) free(temp2);
    00902     if (bx) free(bx);
    00903     if (jx) free(jx);
    00904     if (Trace) free(Trace);
    00905     if (Pol) Polyhedron_Free(Pol);
    00906
    00907     RETHROW();
    00908   }
    00909   TRY {
    00910
    00911     /* For each constraint 'j' following mapping is defined to facilitate  */
    00912     /* data access from saturation matrix 'Sat' :-                         */
    00913     /* (1) jx[j] -> floor[j/(8*sizeof(int))]                               */
    00914     /* (2) bx[j] -> bin(00..10..0) where position of 1 = j%(8*sizeof(int)) */
    00915
    00916     i = 0;
    00917     b = MSB;
    00918     for (j=0; j<NbConstraints; j++) {
    00919       jx[j] = i;
    00920       bx[j] = b;
    00921       NEXT(i,b);
    00922     }
    00923
    00924     /*
    00925      * STEP(0): Count the number of vertices among the rays while initializing
    00926      * the ray status count to 0. If no vertices are found, quit the procedure
    00927      * and return an empty polyhedron as the result.
    00928      */
    00929
    00930     /* Reset the status element of each ray to zero. Store the number of  */
    00931     /* vertices in 'aux'.                                                 */
    00932     aux = 0;
    00933     for (i=0; i<NbRay; i++) {
    00934
    00935       /* Ray->p[i][0] = 0 */
    00936       value_set_si(Ray->p[i][0],0);
    00937
    00938       /* If ray(i) is a vertex of the Inhomogenous system */
    00939       if (value_notzero_p(Ray->p[i][Dimension]))
    00940         aux++;
    00941     }
    00942
    00943     /* If no vertices, return an empty polyhedron. */
    00944     if (!aux)
    00945       goto empty;
    00946
    00947 #ifdef POLY_RR_DEBUG
    00948     fprintf(stderr, "[Remove_redundants : Init]\nConstraints =");
    00949     Matrix_Print(stderr,0,Mat);
    00950     fprintf(stderr, "\nRays =");
    00951     Matrix_Print(stderr,0,Ray);
    00952 #endif
    00953
    00954     /*
    00955      * STEP(1): Compute status counts for both rays and inequalities. For each
    00956      * constraint, count the number of vertices/rays saturated by that
    00957      * constraint, and put the result in the status words. At the same time,
    00958      * for each vertex/ray, count the number of constraints saturated by it.
    00959      * Delete any positivity constraints, but give rays credit in their status
    00960      * counts for saturating the positivity constraint.
    00961      */
    00962
    00963     NbEq=0;
    00964
    00965 #ifdef POLY_RR_DEBUG
    00966     fprintf (stderr, " j = ");
    00967 #endif
    00968
    00969     for (j=0; j<NbConstraints; j++) {
    00970
    00971 #ifdef POLY_RR_DEBUG
    00972       fprintf (stderr, " %i ", j);
    00973       fflush (stderr);
    00974 #endif
    00975
    00976       /* If constraint(j) is an equality, mark '1' in array 'temp2' */
    00977       if (Filter && value_zero_p(Mat->p[j][0]))
    00978         temp2[jx[j]] |= bx[j];
    00979       /* Reset the status element of each constraint to zero */
    00980       value_set_si(Mat->p[j][0],0);
    00981
    00982       /* Identify and remove the positivity constraint 1>=0 */
    00983       i = First_Non_Zero(Mat->p[j]+1, Dimension-1);
    00984
    00985 #ifdef POLY_RR_DEBUG
    00986       fprintf(stderr, "[Remove_redundants : IntoStep1]\nConstraints =");
    00987       Matrix_Print(stderr,0,Mat);
    00988       fprintf (stderr, " j = %i \n", j);
    00989 #endif
    00990
    00991       /* Check if constraint(j) is a positivity constraint, 1 >= 0, or if it */
    00992       /* is 1==0. If constraint(j) saturates all the rays of the matrix 'Ray'*/
    00993       /* then it is an equality. in this case, return an empty polyhedron.   */
    00994
    00995       if (i == -1) {
    00996         for (i=0; i<NbRay; i++)
    00997           if (!(Sat->p[i][jx[j]]&bx[j])) {
    00998
    00999             /* Mat->p[j][0]++ */
    01000             value_increment(Mat->p[j][0],Mat->p[j][0]);
    01001           }
    01002
    01003         /* if ((Mat->p[j][0] == NbRay) &&   : it is an equality
    01004            (Mat->p[j][Dimension] != 0)) : and its not 0=0 */
    01005         if ((value_cmp_si(Mat->p[j][0], NbRay) == 0) &&
    01006             (value_notzero_p(Mat->p[j][Dimension])))
    01007           goto empty;
    01008
    01009         /* Delete the positivity constraint */
    01010         NbConstraints--;
    01011         if (j==NbConstraints) continue;
    01012         Vector_Exchange(Mat->p[j], Mat->p[NbConstraints], temp1->Size);
    01013         exchange(jx[j], jx[NbConstraints], aux);
    01014         exchange(bx[j], bx[NbConstraints], aux);
    01015         j--; continue;
    01016       }
    01017
    01018       /* Count the number of vertices/rays saturated by each constraint. At  */
    01019       /* the same time, count the number of constraints saturated by each ray*/
    01020       for (i=0; i<NbRay; i++)
    01021         if (!(Sat->p[i][jx[j]]&bx[j])) {
    01022
    01023           /* Mat->p[j][0]++ */
    01024           value_increment(Mat->p[j][0],Mat->p[j][0]);
    01025
    01026           /* Ray->p[i][0]++ */
    01027           value_increment (Ray->p[i][0],Ray->p[i][0]);
    01028         }
    01029
    01030       /* if (Mat->p[j][0]==NbRay) then increment the number of eq. count */
    01031       if (value_cmp_si(Mat->p[j][0], NbRay) == 0)
    01032         NbEq++;    /* all vertices/rays are saturated */
    01033     }
    01034     Mat->NbRows = NbConstraints;
    01035
    01036     NbBid=0;
    01037     for (i=0; i<NbRay; i++) {
    01038
    01039       /* Give rays credit for saturating the positivity constraint */
    01040       if (value_zero_p(Ray->p[i][Dimension]))
    01041
    01042         /* Ray->p[i][0]++ */
    01043         value_increment(Ray->p[i][0],Ray->p[i][0]);
    01044
    01045       /* If ray(i) saturates all the constraints including positivity  */
    01046       /* constraint then it is a bi-directional ray or line. Increment */
    01047       /* 'NbBid' by one.                                               */
    01048
    01049       /* if (Ray->p[i][0]==NbConstraints+1) */
    01050       if (value_cmp_si(Ray->p[i][0], NbConstraints+1) == 0)
    01051         NbBid++;
    01052     }
    01053
    01054 #ifdef POLY_RR_DEBUG
    01055     fprintf(stderr, "[Remove_redundants : Step1]\nConstraints =");
    01056     Matrix_Print(stderr,0,Mat);
    01057     fprintf(stderr, "\nRay =");
    01058     Matrix_Print(stderr,0,Ray);
    01059 #endif
    01060
    01061     /*
    01062      * STEP(2): Sort equalities to the top of constraint matrix 'Mat'. Detect
    01063      * implicit equations such as y>=3; y<=3. Keep Inequalities in same
    01064      * relative order. (Note: Equalities are constraints which saturate all of
    01065      * the rays)
    01066      */
    01067
    01068     for (i=0; i<NbEq; i++) {
    01069
    01070       /* If constraint(i) doesn't saturate some ray, then it is an inequality*/
    01071       if (value_cmp_si(Mat->p[i][0], NbRay) != 0) {
    01072
    01073         /* Skip over inequalities and find an equality */
    01074         for (k=i+1; value_cmp_si(Mat->p[k][0], NbRay) != 0 && k < NbConstraints; k++)
    01075           ;
    01076         if (k==NbConstraints) /* If none found then error */ break;
    01077
    01078         /* Slide inequalities down the array 'Mat' and move equality up to */
    01079         /* position 'i'.                                                   */
    01080         Vector_Copy(Mat->p[k], temp1->p, temp1->Size);
    01081         aux = jx[k];
    01082         j   = bx[k];
    01083         for (;k>i;k--) {
    01084           Vector_Copy(Mat->p[k-1], Mat->p[k], temp1->Size);
    01085           jx[k] = jx[k-1];
    01086           bx[k] = bx[k-1];
    01087         }
    01088         Vector_Copy(temp1->p, Mat->p[i], temp1->Size);
    01089         jx[i] = aux;
    01090         bx[i] = j;
    01091       }
    01092     }
    01093
    01094     /* for SIMPLIFY */
    01095     if (Filter) {
    01096       Value mone;
    01097       value_init(mone);
    01098       value_set_si(mone, -1);
    01099       /* Normalize equalities to have lexpositive coefficients to
    01100        * be able to detect identical equalities.
    01101        */
    01102       for (i = 0; i < NbEq; i++) {
    01103         int pos = First_Non_Zero(Mat->p[i]+1, Dimension);
    01104         if (pos == -1)
    01105           continue;
    01106         if (value_neg_p(Mat->p[i][1+pos]))
    01107           Vector_Scale(Mat->p[i]+1, Mat->p[i]+1, mone, Dimension);
    01108       }
    01109       value_clear(mone);
    01110       for (i=0; i<NbEq; i++) {
    01111
    01112         /* Detect implicit constraints such as y>=3 and y<=3 */
    01113         Redundant = 0;
    01114         for (j=i+1; j<NbEq; j++) {
    01115           /* Only check equalities, i.e., 'temp2' has entry 1             */
    01116           if (!(temp2[jx[j]] & bx[j]))
    01117             continue;
    01118           /* Redundant if both are same `and' constraint(j) was equality. */
    01119           if (Vector_Equal(Mat->p[i]+1, Mat->p[j]+1, Dimension)) {
    01120             Redundant=1;
    01121             break;
    01122           }
    01123         }
    01124
    01125         /* Set 'Filter' entry to 1 corresponding to the irredundant equality*/
    01126         if (!Redundant) Filter[jx[i]] |= bx[i];  /* set flag */
    01127       }
    01128     }
    01129
    01130 #ifdef POLY_RR_DEBUG
    01131     fprintf(stderr, "[Remove_redundants : Step2]\nConstraints =");
    01132     Matrix_Print(stderr,0,Mat);
    01133     fprintf(stderr, "\nRay =");
    01134     Matrix_Print(stderr,0,Ray);
    01135 #endif
    01136
    01137     /*
    01138      * STEP(3): Perform Gaussian elimiation on the list of equalities. Obtain
    01139      * a minimal basis by solving for as many variables as possible. Use this
    01140      * solution to reduce the inequalities by eliminating as many variables as
    01141      * possible. Set NbEq2 to the rank of the system of equalities.
    01142      */
    01143
    01144     NbEq2 = Gauss(Mat,NbEq,Dimension);
    01145
    01146     /* If number of equalities is not less then the homogenous dimension, */
    01147     /* return an empty polyhedron.                                        */
    01148
    01149     if (NbEq2 >= Dimension)
    01150       goto empty;
    01151
    01152 #ifdef POLY_RR_DEBUG
    01153     fprintf(stderr, "[Remove_redundants : Step3]\nConstraints =");
    01154     Matrix_Print(stderr,0,Mat);
    01155     fprintf(stderr, "\nRay =");
    01156     Matrix_Print(stderr,0,Ray);
    01157 #endif
    01158
    01159     /*
    01160      * STEP(4): Sort lines to the top of ray matrix 'Ray', leaving rays
    01161      * afterwards. Detect implicit lines such as ray(1,2) and ray(-1,-2).
    01162      * (Note: Lines are rays which saturate all of the constraints including
    01163      * the positivity constraint 1>=0.
    01164      */
    01165
    01166
    01167     for (i=0, k=NbRay; i<NbBid && k>i; i++) {
    01168       /* If ray(i) doesn't saturate some constraint then it is not a line */
    01169       if (value_cmp_si(Ray->p[i][0], NbConstraints+1) != 0) {
    01170
    01171         /* Skip over rays and vertices and find a line (bi-directional rays) */
    01172         while (--k > i && value_cmp_si(Ray->p[k][0], NbConstraints+1) != 0)
    01173           ;
    01174
    01175         /* Exchange positions of ray(i) and line(k), thus sorting lines to */
    01176         /* the top of matrix 'Ray'.                                        */
    01177         Vector_Exchange(Ray->p[i], Ray->p[k], temp1->Size);
    01178         bexchange(Sat->p[i], Sat->p[k], RowSize2);
    01179       }
    01180     }
    01181
    01182 #ifdef POLY_RR_DEBUG
    01183     fprintf(stderr, "[Remove_redundants : Step4]\nConstraints =");
    01184     Matrix_Print(stderr,0,Mat);
    01185     fprintf(stderr, "\nRay =");
    01186     Matrix_Print(stderr,0,Ray);
    01187 #endif
    01188
    01189     /*
    01190      * STEP(5): Perform Gaussian elimination on the lineality space to obtain
    01191      * a minimal basis of lines. Use this basis to reduce the representation
    01192      * of the uniderectional rays. Set 'NbBid2' to the rank of the system of
    01193      * lines.
    01194      */
    01195
    01196     NbBid2 = Gauss(Ray, NbBid, Dimension);
    01197
    01198 #ifdef POLY_RR_DEBUG
    01199     fprintf(stderr, "[Remove_redundants : After Gauss]\nRay =");
    01200     Matrix_Print(stderr,0,Ray);
    01201 #endif
    01202
    01203     /* If number of lines is not less then the homogenous dimension, return */
    01204     /* an empty polyhedron.                                                 */
    01205     if (NbBid2>=Dimension) {
    01206       errormsg1("RemoveRedundants", "rmrdt", "dimension error");
    01207       goto empty;
    01208     }
    01209
    01210     /* Compute dimension of non-homogenous ray space */
    01211     Dim_RaySpace = Dimension-1-NbEq2-NbBid2;
    01212
    01213 #ifdef POLY_RR_DEBUG
    01214     fprintf(stderr, "[Remove_redundants : Step5]\nConstraints =");
    01215     Matrix_Print(stderr,0,Mat);
    01216     fprintf(stderr, "\nRay =");
    01217     Matrix_Print(stderr,0,Ray);
    01218 #endif
    01219
    01220     /*
    01221      * STEP(6): Do a first pass filter of inequalities and equality identifi-
    01222      * cation. New positivity constraints may have been created by step(3).
    01223      * Check for and eliminate them. Count the irredundant inequalities and
    01224      * store count in 'NbIneq'.
    01225      */
    01226
    01227     NbIneq=0;
    01228     for (j=0; j<NbConstraints; j++) {
    01229
    01230       /* Identify and remove the positivity constraint 1>=0 */
    01231       i = First_Non_Zero(Mat->p[j]+1, Dimension-1);
    01232
    01233       /* Check if constraint(j) is a positivity constraint, 1>= 0, or if it */
    01234       /* is 1==0.                                                           */
    01235       if (i == -1) {
    01236         /* if ((Mat->p[j][0]==NbRay) &&   : it is an equality
    01237            (Mat->p[j][Dimension]!=0))    : and its not 0=0 */
    01238         if ((value_cmp_si(Mat->p[j][0], NbRay) == 0) &&
    01239             (value_notzero_p(Mat->p[j][Dimension])))
    01240           goto empty;
    01241
    01242         /* Set the positivity constraint redundant by setting status element */
    01243         /* equal to 2.                                                       */
    01244         value_set_si(Mat->p[j][0],2);
    01245         continue;
    01246       }
    01247
    01248       Status = VALUE_TO_INT(Mat->p[j][0]);
    01249
    01250       if (Status == 0)
    01251         value_set_si(Mat->p[j][0], 2);  /* constraint is redundant */
    01252       else if (Status < Dim_RaySpace)
    01253         value_set_si(Mat->p[j][0], 2);  /* constraint is redundant */
    01254       else if (Status == NbRay)
    01255         value_set_si(Mat->p[j][0], 0);  /* constraint is an equality */
    01256       else {
    01257         NbIneq++;                       /* constraint is an irredundant inequality */
    01258         value_set_si(Mat->p[j][0], 1);  /* inequality */
    01259       }
    01260     }
    01261
    01262 #ifdef POLY_RR_DEBUG
    01263     fprintf(stderr, "[Remove_redundants : Step6]\nConstraints =");
    01264     Matrix_Print(stderr,0,Mat);
    01265     fprintf(stderr, "\nRay =");
    01266     Matrix_Print(stderr,0,Ray);
    01267 #endif
    01268
    01269     /*
    01270      * STEP(7): Do a first pass filter of rays and identification of lines.
    01271      * Count the irredundant Rays and store count in 'NbUni'.
    01272      */
    01273
    01274     NbUni=0;
    01275     for (j=0; j<NbRay; j++) {
    01276       Status = VALUE_TO_INT(Ray->p[j][0]);
    01277
    01278       if (Status < Dim_RaySpace)
    01279         value_set_si(Ray->p[j][0], 2);  /* ray is redundant */
    01280       else if (Status == NbConstraints+1)
    01281         value_set_si(Ray->p[j][0], 0);  /* ray is a line */
    01282       else {
    01283         NbUni++;                        /* an irredundant unidirectional ray. */
    01284         value_set_si(Ray->p[j][0], 1);  /* ray */
    01285       }
    01286     }
    01287
    01288     /*
    01289      * STEP(8): Create the polyhedron (using approximate sizes).
    01290      * Number of constraints = NbIneq + NbEq2 + 1
    01291      * Number of rays = NbUni + NbBid2
    01292      * Partially fill the polyhedron structure with the lines computed in step
    01293      * 3 and the equalities computed in step 5.
    01294      */
    01295
    01296     Pol = Polyhedron_Alloc(Dimension-1, NbIneq+NbEq2+1, NbUni+NbBid2);
    01297     if (!Pol) {
    01298       UNCATCH(any_exception_error);
    01299       goto oom;
    01300     }
    01301     Pol->NbBid = NbBid2;
    01302     Pol->NbEq  = NbEq2;
    01303
    01304     /* Partially fill the polyhedron structure */
    01305     if (NbBid2) Vector_Copy(Ray->p[0], Pol->Ray[0], (Dimension+1)*NbBid2);
    01306     if (NbEq2)  Vector_Copy(Mat->p[0], Pol->Constraint[0], (Dimension+1)*NbEq2);
    01307
    01308 #ifdef POLY_RR_DEBUG
    01309     fprintf(stderr, "[Remove_redundants : Step7]\nConstraints =");
    01310     Matrix_Print(stderr,0,Mat);
    01311     fprintf(stderr, "\nRay =");
    01312     Matrix_Print(stderr,0,Ray);
    01313 #endif
    01314
    01315     /*
    01316      * STEP(9): Final Pass filter of inequalities and detection of redundant
    01317      * inequalities. Redundant inequalities include:
    01318      * (1) Inequalities which are always true, such as 1>=0,
    01319      * (2) Redundant inequalities such as y>=4 given y>=3, or x>=1 given x=2.
    01320      * (3) Redundant inequalities such as x+y>=5 given x>=3 and y>=2.
    01321      * Every 'good' inequality must saturate at least 'Dimension' rays and be
    01322      * unique.
    01323      */
    01324
    01325     /* 'Trace' is a (1 X sat_nbcolumns) row matrix to hold the union of all */
    01326     /* rows (corresponding to irredundant rays) of saturation matrix 'Sat'  */
    01327     /* which saturate some constraint 'j'. See figure below:-               */
    01328     Trace=(unsigned *)malloc(sat_nbcolumns * sizeof(unsigned));
    01329     if(!Trace) {
    01330       UNCATCH(any_exception_error);
    01331       goto oom;
    01332     }
    01333
    01334     /*                         NbEq      NbConstraints
    01335                                |----------->
    01336                                 ___________j____
    01337                                |           |   |
    01338                                |      Mat  |   |
    01339                                |___________|___|
    01340                                            |
    01341      NbRay  ^ ________         ____________|____
    01342             | |-------|--------|-----------0---|t1
    01343             |i|-------|--------|-----------0---|t2
    01344             | | Ray   |        |    Sat        |
    01345      NbBid  - |-------|--------|-----------0---|tk
    01346               |_______|        |_______________|
    01347                                            |
    01348                                            |
    01349                                       -OR- (of rows t1,t2,...,tk)
    01350                                ________|___|____
    01351                                |_____Trace_0___|
    01352
    01353     */
    01354
    01355     NbIneq2 = 0;
    01356     for (j=NbEq; j<NbConstraints; j++) {
    01357
    01358       /* if (Mat->p[j][0]==1) : non-redundant inequality */
    01359       if (value_one_p (Mat->p[j][0])) {
    01360         for (k=0; k<sat_nbcolumns; k++) Trace[k]=0;  /* init Trace */
    01361
    01362         /* Compute Trace: the union of all rows of Sat where constraint(j) */
    01363         /* is saturated.                                                   */
    01364         for (i=NbBid; i<NbRay; i++)
    01365
    01366           /* if (Ray->p[i][0]==1) */
    01367           if (value_one_p(Ray->p[i][0])) {
    01368             if (!(Sat->p[i][jx[j]]&bx[j]))
    01369               for (k=0; k<sat_nbcolumns; k++) Trace[k] |= Sat->p[i][k];
    01370           }
    01371
    01372         /* Only constraint(j) should saturate this set of vertices/rays. */
    01373         /* If another non-redundant constraint also saturates this set,  */
    01374         /* then constraint(j) is redundant                               */
    01375         Redundant=0;
    01376         for (i=NbEq; i<NbConstraints; i++) {
    01377
    01378           /* if ((Mat->p[i][0] ==1) && (i!=j) && !(Trace[jx[i]] & bx[i]) ) */
    01379           if (value_one_p(Mat->p[i][0]) && (i!=j) && !(Trace[jx[i]] & bx[i])) {
    01380             Redundant=1;
    01381             break;
    01382           }
    01383         }
    01384         if (Redundant) {
    01385           value_set_si(Mat->p[j][0],2);
    01386         }
    01387         else {
    01388           Vector_Copy(Mat->p[j], Pol->Constraint[NbEq2+NbIneq2], Dimension+1);
    01389           if (Filter) Filter[jx[j]] |= bx[j];           /* for SIMPLIFY */
    01390           NbIneq2++;
    01391         }
    01392       }
    01393     }
    01394     free(Trace), Trace = NULL;
    01395
    01396 #ifdef POLY_RR_DEBUG
    01397     fprintf(stderr, "[Remove_redundants : Step8]\nConstraints =");
    01398     Matrix_Print(stderr,0,Mat);
    01399     fprintf(stderr, "\nRay =");
    01400     Matrix_Print(stderr,0,Ray);
    01401 #endif
    01402
    01403     /*
    01404      * Step(10): Final pass filter of rays and detection of redundant rays.
    01405      * The final list of rays is written to polyhedron.
    01406      */
    01407
    01408     /* Trace is a (NbRay x 1) column matrix to hold the union of all columns */
    01409     /* (corresponding to irredundant inequalities) of saturation matrix 'Sat'*/
    01410     /* which saturate some ray 'i'. See figure below:-                       */
    01411
    01412     Trace=(unsigned *)malloc(NbRay * sizeof(unsigned));
    01413     if(!Trace) {
    01414       UNCATCH(any_exception_error);
    01415       goto oom;
    01416     }
    01417
    01418     /*                     NbEq     NbConstraints
    01419                              |---------->
    01420                         ___________j_____
    01421                         |      | |   |  |
    01422                         |      Mat   |  |
    01423                         |______|_|___|__|
    01424                                | |   |
    01425 NbRay ^ _________       _______|_|___|__   ___
    01426       | |       |       |      | |   |  |  |T|
    01427       | |  Ray  |       |   Sat| |   |  |  |r|
    01428       | |       |       |      | |   |  |  |a|  Trace = Union[col(t1,t2,..,tk)]
    01429       |i|-------|------>i      0 0   0  |  |c|
    01430 NbBid - |       |       |      | |   |  |  |e|
    01431         |_______|       |______|_|___|__|  |_|
    01432                               t1 t2  tk
    01433     */
    01434
    01435     NbUni2 = 0;
    01436
    01437     /* Let 'aux' be the number of rays not vertices */
    01438     aux = 0;
    01439     for (i=NbBid; i<NbRay; i++) {
    01440
    01441       /* if (Ray->p[i][0]==1) */
    01442       if (value_one_p (Ray->p[i][0])) {
    01443
    01444         /* if (Ray->p[i][Dimension]!=0) : vertex */
    01445         if (value_notzero_p (Ray->p[i][Dimension]))
    01446           for (k=NbBid; k<NbRay; k++) Trace[k]=0;         /* init Trace */
    01447         else /* for ray */
    01448
    01449           /* Include the positivity constraint incidences for rays. The */
    01450           /* positivity constraint saturates all rays and no vertices   */
    01451
    01452           for (k=NbBid; k<NbRay; k++)
    01453
    01454             /* Trace[k]=(Ray->p[k][Dimension]!=0); */
    01455             Trace[k] = (value_notzero_p (Ray->p[k][Dimension]));
    01456
    01457         /* Compute Trace: the union of all columns of Sat where ray(i) is  */
    01458         /* saturated.                                                      */
    01459         for (j=NbEq; j<NbConstraints; j++)
    01460
    01461           /* if (Mat->p[j][0]==1) : inequality */
    01462           if (value_one_p (Mat->p[j][0])) {
    01463             if (!(Sat->p[i][jx[j]]&bx[j]))
    01464               for (k=NbBid; k<NbRay; k++) Trace[k] |= Sat->p[k][jx[j]]&bx[j];
    01465           }
    01466
    01467         /* If ray i does not saturate any inequalities (other than the   */
    01468         /* the positivity constraint, then it is the case that there is  */
    01469         /* only one inequality and that ray is its orthogonal            */
    01470
    01471         /* only ray(i) should saturate this set of inequalities. If      */
    01472         /* another non-redundant ray also saturates this set, then ray(i)*/
    01473         /* is redundant                                                  */
    01474
    01475         Redundant = 0;
    01476         for (j=NbBid; j<NbRay; j++) {
    01477
    01478           /* if ( (Ray->p[j][0]==1) && (i!=j) && !Trace[j] ) */
    01479           if (value_one_p (Ray->p[j][0]) && (i!=j) && !Trace[j]) {
    01480             Redundant=1;
    01481             break;
    01482           }
    01483         }
    01484         if (Redundant)
    01485           value_set_si(Ray->p[i][0],2);
    01486         else {
    01487           Vector_Copy(Ray->p[i], Pol->Ray[NbBid2+NbUni2], Dimension+1);
    01488           NbUni2++;  /* Increment number of uni-directional rays */
    01489
    01490           /* if (Ray->p[i][Dimension]==0) */
    01491           if (value_zero_p (Ray->p[i][Dimension]))
    01492             aux++; /* Increment number of rays which are not vertices */
    01493         }
    01494       }
    01495     }
    01496
    01497     /* Include the positivity constraint */
    01498     if (aux>=Dim_RaySpace) {
    01499       Vector_Set(Pol->Constraint[NbEq2+NbIneq2],0,Dimension+1);
    01500       value_set_si(Pol->Constraint[NbEq2+NbIneq2][0],1);
    01501       value_set_si(Pol->Constraint[NbEq2+NbIneq2][Dimension],1);
    01502       NbIneq2++;
    01503     }
    01504   } /* end of TRY */
    01505
    01506   UNCATCH(any_exception_error);
    01507
    01508 #ifdef POLY_RR_DEBUG
    01509   fprintf(stderr, "[Remove_redundants : Step9]\nConstraints =");
    01510   Matrix_Print(stderr,0,Mat);
    01511   fprintf(stderr, "\nRay =");
    01512   Matrix_Print(stderr,0,Ray);
    01513 #endif
    01514
    01515   free(Trace);
    01516   free(bx);
    01517   free(jx);
    01518   if (temp2)
    01519     free(temp2);
    01520
    01521   Pol->NbConstraints = NbEq2 + NbIneq2;
    01522   Pol->NbRays = NbBid2 + NbUni2;
    01523
    01524   Vector_Free(temp1);
    01525   F_SET(Pol,
    01526         POL_VALID | POL_INEQUALITIES | POL_FACETS | POL_POINTS | POL_VERTICES);
    01527   return Pol;
    01528
    01529 oom:
    01530   errormsg1("Remove_Redundants", "outofmem", "out of memory space");
    01531
    01532   Vector_Free(temp1);
    01533   if (temp2)
    01534     free(temp2);
    01535   if (bx)
    01536     free(bx);
    01537   if (jx)
    01538     free(jx);
    01539   return NULL;
    01540
    01541 empty:
    01542   Vector_Free(temp1);
    01543   if (temp2)
    01544     free(temp2);
    01545   if (bx)
    01546     free(bx);
    01547   if (jx)
    01548     free(jx);
    01549   UNCATCH(any_exception_error);
    01550   return Empty_Polyhedron(Dimension-1);
    01551 } /* Remove_Redundants */
    01552
    01553 /*
    01554  * Allocate memory space for polyhedron.
    01555  */
    01556 Polyhedron* Polyhedron_Alloc(unsigned Dimension,unsigned NbConstraints,unsigned NbRays) {
    01557
    01558   Polyhedron *Pol;
    01559   unsigned NbRows,NbColumns;
    01560   int i,j;
    01561   Value *p, **q;
    01562
    01563   Pol=(Polyhedron *)malloc(sizeof(Polyhedron));
    01564   if(!Pol) {
    01565     errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
    01566     return 0;
    01567   }
    01568
    01569   Pol->next          = (Polyhedron *)0;
    01570   Pol->Dimension     = Dimension;
    01571   Pol->NbConstraints = NbConstraints;
    01572   Pol->NbRays        = NbRays;
    01573   Pol->NbEq          = 0;
    01574   Pol->NbBid         = 0;
    01575   Pol->flags         = 0;
    01576   NbRows             = NbConstraints + NbRays;
    01577   NbColumns          = Dimension + 2;
    01578
    01579   q = (Value **)malloc(NbRows * sizeof(Value *));
    01580   if(!q) {
    01581     errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
    01582     return 0;
    01583   }
    01584   p = value_alloc(NbRows*NbColumns, &Pol->p_Init_size);
    01585   if(!p) {
    01586     free(q);
    01587     errormsg1("Polyhedron_Alloc", "outofmem", "out of memory space");
    01588     return 0;
    01589   }
    01590   Pol->Constraint    = q;
    01591   Pol->Ray           = q + NbConstraints;
    01592   Pol->p_Init        = p;
    01593   for (i=0;i<NbRows;i++) {
    01594     *q++ = p;
    01595     p += NbColumns;
    01596   }
    01597   return Pol;
    01598 } /* Polyhedron_Alloc */
    01599
    01600 /*
    01601  * Free the memory space occupied by the single polyhedron.
    01602  */
    01603 void Polyhedron_Free(Polyhedron *Pol)
    01604 {
    01605   if(!Pol)
    01606     return;
    01607   value_free(Pol->p_Init, Pol->p_Init_size);
    01608   free(Pol->Constraint);
    01609   free(Pol);
    01610   return;
    01611 } /* Polyhedron_Free */
    01612
    01613 /*
    01614  * Free the memory space occupied by the domain.
    01615  */
    01616 void Domain_Free(Polyhedron *Pol)
    01617 {
    01618   Polyhedron *Next;
    01619
    01620   for (; Pol; Pol = Next) {
    01621     Next = Pol->next;
    01622     Polyhedron_Free(Pol);
    01623   }
    01624   return;
    01625 } /* Domain_Free */
    01626
    01627 /*
    01628  * Print the contents of a polyhedron.
    01629  */
    01630 void Polyhedron_Print(FILE *Dst, const char *Format, const Polyhedron *Pol)
    01631 {
    01632   unsigned Dimension, NbConstraints, NbRays;
    01633   int      i, j;
    01634   Value    *p;
    01635
    01636   if (!Pol) {
    01637     fprintf(Dst, "<null polyhedron>\n");
    01638     return;
    01639   }
    01640
    01641   Dimension     = Pol->Dimension + 2;  /* Homogenous Dimension + status */
    01642   NbConstraints = Pol->NbConstraints;
    01643   NbRays        = Pol->NbRays;
    01644   fprintf(Dst, "POLYHEDRON Dimension:%d\n", Pol->Dimension);
    01645   fprintf(Dst,"           Constraints:%d  Equations:%d  Rays:%d  Lines:%d\n",
    01646           Pol->NbConstraints, Pol->NbEq, Pol->NbRays, Pol->NbBid);
    01647   fprintf(Dst,"Constraints %d %d\n", NbConstraints, Dimension);
    01648
    01649   for (i=0;i<NbConstraints;i++) {
    01650     p=Pol->Constraint[i];
    01651
    01652     /* if (*p) */
    01653     if (value_notzero_p (*p))
    01654       fprintf(Dst,"Inequality: [");
    01655     else
    01656       fprintf(Dst,"Equality:   [");
    01657     p++;
    01658     for (j=1;j<Dimension;j++) {
    01659       value_print(Dst,Format,*p++);
    01660     }
    01661     (void)fprintf(Dst," ]\n");
    01662   }
    01663
    01664   (void)fprintf(Dst, "Rays %d %d\n", NbRays, Dimension);
    01665   for (i=0;i<NbRays;i++) {
    01666     p=Pol->Ray[i];
    01667
    01668     /* if (*p) */
    01669     if (value_notzero_p (*p)) {
    01670       p++;
    01671
    01672       /* if ( p[Dimension-2] ) */
    01673       if (value_notzero_p (p[Dimension-2]))
    01674         fprintf(Dst, "Vertex: [");
    01675       else
    01676         fprintf(Dst, "Ray:    [");
    01677     }
    01678     else {
    01679       p++;
    01680       fprintf(Dst, "Line:   [");
    01681     }
    01682     for (j=1; j < Dimension-1; j++) {
    01683       value_print(Dst,Format,*p++);
    01684     }
    01685
    01686     /* if (*p) */
    01687     if (value_notzero_p (*p)) {
    01688       fprintf( Dst, " ]/" );
    01689       value_print(Dst,VALUE_FMT,*p);
    01690       fprintf( Dst, "\n" );
    01691     }
    01692     else
    01693       fprintf(Dst, " ]\n");
    01694   }
    01695   if (Pol->next) {
    01696     fprintf(Dst, "UNION ");
    01697     Polyhedron_Print(Dst,Format,Pol->next);
    01698   }
    01699 } /* Polyhedron_Print */
    01700
    01701 /*
    01702  * Print the contents of a polyhedron 'Pol' (used for debugging purpose).
    01703  */
    01704 void PolyPrint (Polyhedron *Pol) {
    01705   Polyhedron_Print(stderr,"%4d",Pol);
    01706 } /* PolyPrint */
    01707
    01708 /*
    01709  * Create and return an empty polyhedron of non-homogenous dimension
    01710  * 'Dimension'. An empty polyhedron is characterized by :-
    01711  *  (a) The dimension of the ray-space is -1.
    01712  *  (b) There is an over-constrained system of equations given by:
    01713  *      x=0, y=0, ...... z=0, 1=0
    01714  */
    01715 Polyhedron *Empty_Polyhedron(unsigned Dimension) {
    01716
    01717   Polyhedron *Pol;
    01718   int i;
    01719
    01720   Pol = Polyhedron_Alloc(Dimension, Dimension+1, 0);
    01721   if (!Pol) {
    01722     errormsg1("Empty_Polyhedron", "outofmem", "out of memory space");
    01723     return 0;
    01724   }
    01725   Vector_Set(Pol->Constraint[0],0,(Dimension+1)*(Dimension+2));
    01726   for (i=0; i<=Dimension; i++) {
    01727
    01728     /* Pol->Constraint[i][i+1]=1 */
    01729     value_set_si(Pol->Constraint[i][i+1],1);
    01730   }
    01731   Pol->NbEq = Dimension+1;
    01732   Pol->NbBid = 0;
    01733   F_SET(Pol,
    01734         POL_VALID | POL_INEQUALITIES | POL_FACETS | POL_POINTS | POL_VERTICES);
    01735   return Pol;
    01736 } /* Empty_Polyhedron */
    01737
    01738 /*
    01739  * Create and return a universe polyhedron of non-homogenous dimension
    01740  * 'Dimension'. A universe polyhedron is characterized by :-
    01741  * (a) The dimension of rayspace is zero.
    01742  * (b) The dimension of lineality space is the dimension of the polyhedron.
    01743  * (c) There is only one constraint (positivity constraint) in the constraint
    01744  *     set given by : 1 >= 0.
    01745  * (d) The bi-directional ray set is the canonical set of vectors.
    01746  * (e) The only vertex is the origin (0,0,0,....0).
    01747  */
    01748 Polyhedron *Universe_Polyhedron(unsigned Dimension) {
    01749
    01750   Polyhedron *Pol;
    01751   int i;
    01752
    01753   Pol = Polyhedron_Alloc(Dimension,1,Dimension+1);
    01754   if (!Pol) {
    01755     errormsg1("Universe_Polyhedron", "outofmem", "out of memory space");
    01756     return 0;
    01757   }
    01758   Vector_Set(Pol->Constraint[0],0,(Dimension+2));
    01759
    01760   /* Pol->Constraint[0][0] = 1 */
    01761   value_set_si(Pol->Constraint[0][0],1);
    01762
    01763   /* Pol->Constraint[0][Dimension+1] = 1 */
    01764   value_set_si(Pol->Constraint[0][Dimension+1],1);
    01765   Vector_Set(Pol->Ray[0],0,(Dimension+1)*(Dimension+2));
    01766   for (i=0;i<=Dimension;i++) {
    01767
    01768     /* Pol->Ray[i][i+1]=1 */
    01769     value_set_si(Pol->Ray[i][i+1],1);
    01770   }
    01771
    01772   /* Pol->Ray[Dimension][0] = 1 :  vertex status */
    01773   value_set_si(Pol->Ray[Dimension][0],1);
    01774   Pol->NbEq = 0;
    01775   Pol->NbBid = Dimension;
    01776   F_SET(Pol,
    01777         POL_VALID | POL_INEQUALITIES | POL_FACETS | POL_POINTS | POL_VERTICES);
    01778   return Pol;
    01779 } /* Universe_Polyhedron */
    01780
    01781 /*
    01782
    01783 Sort constraints and remove trivially redundant constraints.
    01784
    01785 */
    01786 static void SortConstraints(Matrix *Constraints, unsigned NbEq)
    01787 {
    01788     int i, j, k;
    01789     for (i = NbEq; i < Constraints->NbRows; ++i) {
    01790         int max = i;
    01791         for (k = i+1; k < Constraints->NbRows; ++k) {
    01792             for (j = 1; j < Constraints->NbColumns-1; ++j) {
    01793                 if (value_eq(Constraints->p[k][j],
    01794                              Constraints->p[max][j]))
    01795                     continue;
    01796                 if (value_abs_lt(Constraints->p[k][j],
    01797                                  Constraints->p[max][j]))
    01798                     break;
    01799                 if (value_abs_eq(Constraints->p[k][j],
    01800                                  Constraints->p[max][j]) &&
    01801                     value_pos_p(Constraints->p[max][j]))
    01802                         break;
    01803                 max = k;
    01804                 break;
    01805             }
    01806             /* equal, except for possibly the constant
    01807              * => remove constraint with biggest constant
    01808              */
    01809             if (j == Constraints->NbColumns-1) {
    01810                 if (value_lt(Constraints->p[k][j], Constraints->p[max][j]))
    01811                     Vector_Exchange(Constraints->p[k],
    01812                                     Constraints->p[max],
    01813                                     Constraints->NbColumns);
    01814                 Constraints->NbRows--;
    01815                 if (k < Constraints->NbRows)
    01816                     Vector_Exchange(Constraints->p[k],
    01817                                     Constraints->p[Constraints->NbRows],
    01818                                     Constraints->NbColumns);
    01819                 k--;
    01820             }
    01821         }
    01822         if (max != i)
    01823             Vector_Exchange(Constraints->p[max], Constraints->p[i],
    01824                             Constraints->NbColumns);
    01825     }
    01826 }
    01827
    01828 /*
    01829
    01830 Search for trivial implicit equalities,
    01831 assuming the constraints have been sorted.
    01832
    01833 */
    01834
    01835 static int ImplicitEqualities(Matrix *Constraints, unsigned NbEq)
    01836 {
    01837     int row, nrow, k;
    01838     int found = 0;
    01839     Value tmp;
    01840     for (row = NbEq; row < Constraints->NbRows; ++row) {
    01841         int d = First_Non_Zero(Constraints->p[row]+1, Constraints->NbColumns-2);
    01842         if (d == -1) {
    01843             /* -n >= 0 */
    01844             if (value_neg_p(Constraints->p[row][Constraints->NbColumns-1])) {
    01845                 value_set_si(Constraints->p[row][0], 0);
    01846                 found = 1;
    01847             }
    01848             break;
    01849         }
    01850         if (value_neg_p(Constraints->p[row][1+d]))
    01851             continue;
    01852         for (nrow = row+1; nrow < Constraints->NbRows; ++nrow) {
    01853             if (value_zero_p(Constraints->p[nrow][1+d]))
    01854                 break;
    01855             if (value_pos_p(Constraints->p[nrow][1+d]))
    01856                 continue;
    01857             for (k = d; k < Constraints->NbColumns-1; ++k) {
    01858                 if (value_abs_ne(Constraints->p[row][1+k],
    01859                                  Constraints->p[nrow][1+k]))
    01860                     break;
    01861                 if (value_zero_p(Constraints->p[row][1+k]))
    01862                     continue;
    01863                 if (value_eq(Constraints->p[row][1+k], Constraints->p[nrow][1+k]))
    01864                     break;
    01865             }
    01866             if (k == Constraints->NbColumns-1) {
    01867                 value_set_si(Constraints->p[row][0], 0);
    01868                 value_set_si(Constraints->p[nrow][0], 0);
    01869                 found = 1;
    01870                 break;
    01871             }
    01872             if (k != Constraints->NbColumns-2)
    01873                 continue;
    01874             /* if the constants are such that
    01875              * the sum c1+c2 is negative then the constraints conflict
    01876              */
    01877             value_init(tmp);
    01878             value_addto(tmp, Constraints->p[row][1+k],
    01879                              Constraints->p[nrow][1+k]);
    01880             if (value_sign(tmp) < 0) {
    01881                 Vector_Set(Constraints->p[row], 0, Constraints->NbColumns-1);
    01882                 Vector_Set(Constraints->p[nrow], 0, Constraints->NbColumns-1);
    01883                 value_set_si(Constraints->p[row][1+k], 1);
    01884                 value_set_si(Constraints->p[nrow][1+k], 1);
    01885                 found = 1;
    01886             }
    01887             value_clear(tmp);
    01888             if (found)
    01889                 break;
    01890         }
    01891     }
    01892     return found;
    01893 }
    01894
    01895 /**
    01896
    01897 Given a matrix of constraints ('Constraints'), construct and return a
    01898 polyhedron.
    01899
    01900 @param Constraints Constraints (may be modified!)
    01901 @param NbMaxRays Estimated number of rays in the ray matrix of the
    01902 polyhedron.
    01903 @return newly allocated Polyhedron
    01904
    01905 */
    01906 Polyhedron *Constraints2Polyhedron(Matrix *Constraints,unsigned NbMaxRays) {
    01907
    01908   Polyhedron *Pol = NULL;
    01909   Matrix *Ray = NULL;
    01910   SatMatrix *Sat = NULL;
    01911   unsigned Dimension, nbcolumns;
    01912   int i;
    01913
    01914   Dimension = Constraints->NbColumns - 1;  /* Homogeneous Dimension */
    01915   if (Dimension < 1) {
    01916     errormsg1("Constraints2Polyhedron","invalidpoly","invalid polyhedron dimension");
    01917     return 0;
    01918   }
    01919
    01920   /* If there is no constraint in the constraint matrix, return universe */
    01921   /* polyhderon.                                                         */
    01922   if (Constraints->NbRows==0) {
    01923     Pol = Universe_Polyhedron(Dimension-1);
    01924     return Pol;
    01925   }
    01926
    01927   if (POL_ISSET(NbMaxRays, POL_NO_DUAL)) {
    01928     unsigned NbEq;
    01929     unsigned Rank;
    01930     Value tmp;
    01931     if (POL_ISSET(NbMaxRays, POL_INTEGER))
    01932       value_init(tmp);
    01933     do {
    01934       NbEq = 0;
    01935       /* Move equalities up */
    01936       for (i = 0; i < Constraints->NbRows; ++i)
    01937         if (value_zero_p(Constraints->p[i][0])) {
    01938           if (POL_ISSET(NbMaxRays, POL_INTEGER) &&
    01939             ConstraintSimplify(Constraints->p[i],
    01940                                Constraints->p[i], Dimension+1, &tmp)) {
    01941             value_clear(tmp);
    01942             return Empty_Polyhedron(Dimension-1);
    01943           }
    01944           /* detect 1 == 0, possibly created by ImplicitEqualities */
    01945           if (First_Non_Zero(Constraints->p[i]+1, Dimension-1) == -1 &&
    01946               value_notzero_p(Constraints->p[i][Dimension])) {
    01947             if (POL_ISSET(NbMaxRays, POL_INTEGER))
    01948               value_clear(tmp);
    01949             return Empty_Polyhedron(Dimension-1);
    01950           }
    01951           if (i != NbEq)
    01952             ExchangeRows(Constraints, i, NbEq);
    01953           ++NbEq;
    01954         }
    01955       Rank = Gauss(Constraints, NbEq, Dimension);
    01956       if (POL_ISSET(NbMaxRays, POL_INTEGER))
    01957         for (i = NbEq; i < Constraints->NbRows; ++i)
    01958           ConstraintSimplify(Constraints->p[i],
    01959                              Constraints->p[i], Dimension+1, &tmp);
    01960       SortConstraints(Constraints, NbEq);
    01961     } while (ImplicitEqualities(Constraints, NbEq));
    01962     if (POL_ISSET(NbMaxRays, POL_INTEGER))
    01963       value_clear(tmp);
    01964     Pol = Polyhedron_Alloc(Dimension-1, Constraints->NbRows - (NbEq-Rank), 0);
    01965     if (Rank > 0)
    01966         Vector_Copy(Constraints->p[0], Pol->Constraint[0],
    01967                     Rank * Constraints->NbColumns);
    01968     if (Constraints->NbRows > NbEq)
    01969         Vector_Copy(Constraints->p[NbEq], Pol->Constraint[Rank],
    01970                     (Constraints->NbRows - NbEq) * Constraints->NbColumns);
    01971     Pol->NbEq = Rank;
    01972     /* Make sure nobody accesses the rays by accident */
    01973     Pol->Ray = 0;
    01974     F_SET(Pol, POL_VALID | POL_INEQUALITIES);
    01975     return Pol;
    01976   }
    01977
    01978   if (Dimension > NbMaxRays)
    01979     NbMaxRays = Dimension;
    01980
    01981   /*
    01982    * Rather than adding a 'positivity constraint', it is better to
    01983    * initialize the lineality space with line in each of the index
    01984    * dimensions, but no line in the lambda dimension. Then initialize
    01985    * the ray space with an origin at 0.  This is what you get anyway,
    01986    * after the positivity constraint has been processed by Chernikova
    01987    * function.
    01988    */
    01989
    01990   /* Allocate and initialize the Ray Space */
    01991   Ray = Matrix_Alloc(NbMaxRays, Dimension+1);
    01992   if(!Ray) {
    01993     errormsg1("Constraints2Polyhedron","outofmem","out of memory space");
    01994     return 0;
    01995   }
    01996   Vector_Set(Ray->p_Init,0, NbMaxRays * (Dimension+1));
    01997   for (i=0; i<Dimension; i++) {
    01998
    01999     /* Ray->p[i][i+1] = 1 */
    02000     value_set_si(Ray->p[i][i+1],1);
    02001   }
    02002
    02003   /* Ray->p[Dimension-1][0] = 1 : mark for ray */
    02004   value_set_si(Ray->p[Dimension-1][0],1);
    02005   Ray->NbRows = Dimension;
    02006
    02007   /* Initialize the Sat Matrix */
    02008   nbcolumns = (Constraints->NbRows - 1)/(sizeof(int)*8) + 1;
    02009   Sat = SMAlloc(NbMaxRays, nbcolumns);
    02010   SMVector_Init(Sat->p_init,Dimension*nbcolumns);
    02011   Sat->NbRows = Dimension;
    02012
    02013   CATCH(any_exception_error) {
    02014
    02015     /* In case of overflow, free the allocated memory and forward. */
    02016     if (Sat) SMFree(&Sat);
    02017     if (Ray) Matrix_Free(Ray);
    02018     if (Pol) Polyhedron_Free(Pol);
    02019     RETHROW();
    02020   }
    02021   TRY {
    02022
    02023     /* Create ray matrix 'Ray' from constraint matrix 'Constraints' */
    02024     Chernikova(Constraints,Ray,Sat,Dimension-1,NbMaxRays,0,0);
    02025
    02026 #ifdef POLY_DEBUG
    02027     fprintf(stderr, "[constraints2polyhedron]\nConstraints = ");
    02028     Matrix_Print(stderr,0,Constraints);
    02029     fprintf(stderr, "\nRay = ");
    02030     Matrix_Print(stderr,0,Ray);
    02031     fprintf(stderr, "\nSat = ");
    02032     SMPrint(Sat);
    02033 #endif
    02034
    02035     /* Remove the redundant constraints and create the polyhedron */
    02036     Pol = Remove_Redundants(Constraints,Ray,Sat,0);
    02037   } /* end of TRY */
    02038
    02039   UNCATCH(any_exception_error);
    02040
    02041 #ifdef POLY_DEBUG
    02042   fprintf(stderr, "\nPol = ");
    02043   Polyhedron_Print(stderr,"%4d",Pol);
    02044 #endif
    02045
    02046   SMFree(&Sat), Sat = NULL;
    02047   Matrix_Free(Ray), Ray = NULL;
    02048   return Pol;
    02049 } /* Constraints2Polyhedron */
    02050
    02051 #undef POLY_DEBUG
    02052
    02053 /*
    02054  * Given a polyhedron 'Pol', return a matrix of constraints.
    02055  */
    02056 Matrix *Polyhedron2Constraints(Polyhedron *Pol) {
    02057
    02058   Matrix     *Mat;
    02059   unsigned NbConstraints,Dimension;
    02060
    02061   POL_ENSURE_INEQUALITIES(Pol);
    02062
    02063   NbConstraints = Pol->NbConstraints;
    02064   Dimension     = Pol->Dimension+2;
    02065   Mat = Matrix_Alloc(NbConstraints,Dimension);
    02066   if(!Mat) {
    02067     errormsg1("Polyhedron2Constraints", "outofmem", "out of memory space");
    02068     return 0;
    02069   }
    02070   Vector_Copy(Pol->Constraint[0],Mat->p_Init,NbConstraints * Dimension);
    02071   return Mat;
    02072 } /* Polyhedron2Constraints */
    02073
    02074 /**
    02075
    02076 Given a matrix of rays 'Ray', create and return a polyhedron.
    02077
    02078 @param Ray Rays (may be modified!)
    02079 @param NbMaxConstrs Estimated number of constraints in the polyhedron.
    02080 @return newly allocated Polyhedron
    02081
    02082 */
    02083 Polyhedron *Rays2Polyhedron(Matrix *Ray,unsigned NbMaxConstrs) {
    02084
    02085   Polyhedron *Pol = NULL;
    02086   Matrix *Mat = NULL;
    02087   SatMatrix *Sat = NULL, *SatTranspose = NULL;
    02088   unsigned Dimension, nbcolumns;
    02089   int i;
    02090
    02091   Dimension = Ray->NbColumns-1;        /* Homogeneous Dimension */
    02092   Sat = NULL;
    02093   SatTranspose = NULL;
    02094   Mat = NULL;
    02095
    02096   if (Ray->NbRows==0) {
    02097
    02098     /* If there is no ray in the matrix 'Ray', return an empty polyhedron */
    02099     Pol = Empty_Polyhedron(Dimension-1);
    02100     return(Pol);
    02101   }
    02102
    02103   /* Ignore for now */
    02104   if (POL_ISSET(NbMaxConstrs, POL_NO_DUAL))
    02105     NbMaxConstrs = 0;
    02106
    02107   if (Dimension > NbMaxConstrs)
    02108     NbMaxConstrs = Dimension;
    02109
    02110   /* Allocate space for constraint matrix 'Mat' */
    02111   Mat = Matrix_Alloc(NbMaxConstrs,Dimension+1);
    02112   if(!Mat) {
    02113     errormsg1("Rays2Polyhedron","outofmem","out of memory space");
    02114     return 0;
    02115   }
    02116
    02117   /* Initialize the constraint matrix 'Mat' */
    02118   Vector_Set(Mat->p_Init,0,NbMaxConstrs * (Dimension+1));
    02119   for (i=0; i<Dimension; i++) {
    02120
    02121     /* Mat->p[i][i+1]=1 */
    02122     value_set_si(Mat->p[i][i+1],1);
    02123   }
    02124
    02125   /* Allocate and assign the saturation matrix. Remember we are using a */
    02126   /* transposed saturation matrix referenced by (constraint,ray) pair.  */
    02127   Mat->NbRows = Dimension;
    02128   nbcolumns = (Ray->NbRows -1)/(sizeof(int)*8) + 1;
    02129   SatTranspose = SMAlloc(NbMaxConstrs,nbcolumns);
    02130   SMVector_Init(SatTranspose->p[0],Dimension * nbcolumns);
    02131   SatTranspose->NbRows = Dimension;
    02132
    02133 #ifdef POLY_DEBUG
    02134   fprintf(stderr, "[ray2polyhedron: Before]\nRay = ");
    02135   Matrix_Print(stderr,0,Ray);
    02136   fprintf(stderr, "\nConstraints = ");
    02137   Matrix_Print(stderr,0,Mat);
    02138   fprintf(stderr, "\nSatTranspose = ");
    02139   SMPrint (SatTranspose);
    02140 #endif
    02141
    02142   CATCH(any_exception_error) {
    02143
    02144     /* In case of overflow, free the allocated memory before forwarding
    02145      * the exception.
    02146      */
    02147     if (SatTranspose) SMFree(&SatTranspose);
    02148     if (Sat) SMFree(&Sat);
    02149     if (Mat) Matrix_Free(Mat);
    02150     if (Pol) Polyhedron_Free(Pol);
    02151     RETHROW();
    02152   }
    02153   TRY {
    02154
    02155     /* Create constraint matrix 'Mat' from ray matrix 'Ray' */
    02156     Chernikova(Ray,Mat,SatTranspose,Dimension,NbMaxConstrs,0,1);
    02157
    02158 #ifdef POLY_DEBUG
    02159     fprintf(stderr, "[ray2polyhedron: After]\nRay = ");
    02160     Matrix_Print(stderr,0,Ray);
    02161     fprintf(stderr, "\nConstraints = ");
    02162     Matrix_Print(stderr,0,Mat);
    02163     fprintf(stderr, "\nSatTranspose = ");
    02164     SMPrint (SatTranspose);
    02165 #endif
    02166
    02167     /* Transform the saturation matrix 'SatTranspose' in the standard  */
    02168     /* format, that is, ray X constraint format.                       */
    02169     Sat = TransformSat(Mat,Ray,SatTranspose);
    02170
    02171 #ifdef POLY_DEBUG
    02172     fprintf(stderr, "\nSat =");
    02173     SMPrint(Sat);
    02174 #endif
    02175
    02176     SMFree(&SatTranspose), SatTranspose = NULL;
    02177
    02178     /* Remove redundant rays from the ray matrix 'Ray' */
    02179     Pol = Remove_Redundants(Mat,Ray,Sat,0);
    02180   } /* of TRY */
    02181
    02182   UNCATCH(any_exception_error);
    02183
    02184 #ifdef POLY_DEBUG
    02185   fprintf(stderr, "\nPol = ");
    02186   Polyhedron_Print(stderr,"%4d",Pol);
    02187 #endif
    02188
    02189   SMFree(&Sat);
    02190   Matrix_Free(Mat);
    02191   return Pol;
    02192 } /* Rays2Polyhedron */
    02193
    02194 /*
    02195  * Compute the dual representation if P only contains one representation.
    02196  * Currently only handles the case where only the equalities are known.
    02197  */
    02198 void Polyhedron_Compute_Dual(Polyhedron *P)
    02199 {
    02200   if (!F_ISSET(P, POL_VALID))
    02201     return;
    02202
    02203   if (F_ISSET(P, POL_FACETS | POL_VERTICES))
    02204     return;
    02205
    02206   if (F_ISSET(P, POL_INEQUALITIES)) {
    02207     Matrix M;
    02208     Polyhedron tmp, *Q;
    02209     /* Pretend P is a Matrix for a second */
    02210     M.NbRows = P->NbConstraints;
    02211     M.NbColumns = P->Dimension+2;
    02212     M.p_Init = P->p_Init;
    02213     M.p = P->Constraint;
    02214     Q = Constraints2Polyhedron(&M, 0);
    02215
    02216     /* Switch contents of P and Q ... */
    02217     tmp = *Q;
    02218     *Q = *P;
    02219     *P = tmp;
    02220     /* ... but keep the next pointer */
    02221     P->next = Q->next;
    02222     Polyhedron_Free(Q);
    02223     return;
    02224   }
    02225
    02226   /* other cases not handled yet */
    02227   assert(0);
    02228 }
    02229
    02230 /*
    02231  * Build a saturation matrix from constraint matrix 'Mat' and ray matrix
    02232  * 'Ray'. Only 'NbConstraints' constraint of matrix 'Mat' are considered
    02233  * in creating the saturation matrix. 'NbMaxRays' is the maximum number
    02234  * of rows (rays) allowed in the saturation matrix.
    02235  * Vin100's stuff, for the polyparam vertices to work.
    02236  */
    02237 static SatMatrix *BuildSat(Matrix *Mat,Matrix *Ray,unsigned NbConstraints,unsigned NbMaxRays) {
    02238
    02239   SatMatrix *Sat = NULL;
    02240   int i, j, k, jx;
    02241   Value *p1, *p2, *p3;
    02242   unsigned Dimension, NbRay, bx, nbcolumns;
    02243
    02244   CATCH(any_exception_error) {
    02245     if (Sat)
    02246       SMFree(&Sat);
    02247     RETHROW();
    02248   }
    02249   TRY {
    02250     NbRay = Ray->NbRows;
    02251     Dimension = Mat->NbColumns-1;   /* Homogeneous Dimension */
    02252
    02253     /* Build the Sat matrix */
    02254     nbcolumns = (Mat->NbRows - 1)/(sizeof(int)*8) + 1;
    02255     Sat = SMAlloc(NbMaxRays,nbcolumns);
    02256     Sat->NbRows = NbRay;
    02257     SMVector_Init(Sat->p_init, nbcolumns * NbRay);
    02258     jx=0; bx=MSB;
    02259     for (k=0; k<NbConstraints; k++) {
    02260       for (i=0; i<NbRay; i++) {
    02261
    02262         /* Compute the dot product of ray(i) and constraint(k) and */
    02263         /* store in the status element of ray(i).                  */
    02264         p1 = Ray->p[i]+1;
    02265         p2 = Mat->p[k]+1;
    02266         p3 = Ray->p[i];
    02267         value_set_si(*p3,0);
    02268         for (j=0; j<Dimension; j++) {
    02269           value_addmul(*p3, *p1, *p2);
    02270           p1++; p2++;
    02271         }
    02272       }
    02273       for (j=0; j<NbRay; j++) {
    02274
    02275         /* Set 1 in the saturation matrix if the ray doesn't saturate */
    02276         /* the constraint, otherwise the entry is 0.                  */
    02277         if (value_notzero_p(Ray->p[j][0]))
    02278           Sat->p[j][jx]|=bx;
    02279       }
    02280       NEXT(jx, bx);
    02281     }
    02282   } /* end of TRY */
    02283
    02284   UNCATCH(any_exception_error);
    02285   return Sat;
    02286 } /* BuildSat */
    02287
    02288 /*
    02289  * Add 'Nbconstraints' new constraints to polyhedron 'Pol'. Constraints are
    02290  * pointed by 'Con' and the maximum allowed rays in the new polyhedron is
    02291  * 'NbMaxRays'.
    02292  */
    02293 Polyhedron *AddConstraints(Value *Con,unsigned NbConstraints,Polyhedron *Pol,unsigned NbMaxRays) {
    02294
    02295   Polyhedron *NewPol = NULL;
    02296   Matrix   *Mat = NULL, *Ray = NULL;
    02297   SatMatrix *Sat = NULL;
    02298   unsigned NbRay, NbCon, Dimension;
    02299
    02300   if (NbConstraints == 0)
    02301     return Polyhedron_Copy(Pol);
    02302
    02303   POL_ENSURE_INEQUALITIES(Pol);
    02304   Dimension     = Pol->Dimension + 2;   /* Homogeneous Dimension + Status */
    02305
    02306   if (POL_ISSET(NbMaxRays, POL_NO_DUAL)) {
    02307     NbCon       = Pol->NbConstraints + NbConstraints;
    02308
    02309     Mat = Matrix_Alloc(NbCon, Dimension);
    02310     if (!Mat) {
    02311       errormsg1("AddConstraints", "outofmem", "out of memory space");
    02312       return NULL;
    02313     }
    02314     Vector_Copy(Pol->Constraint[0], Mat->p[0], Pol->NbConstraints * Dimension);
    02315     Vector_Copy(Con, Mat->p[Pol->NbConstraints], NbConstraints * Dimension);
    02316     NewPol = Constraints2Polyhedron(Mat, NbMaxRays);
    02317     Matrix_Free(Mat);
    02318     return NewPol;
    02319   }
    02320
    02321   POL_ENSURE_VERTICES(Pol);
    02322
    02323   CATCH(any_exception_error) {
    02324     if (NewPol) Polyhedron_Free(NewPol);
    02325     if (Mat) Matrix_Free(Mat);
    02326     if (Ray) Matrix_Free(Ray);
    02327     if (Sat) SMFree(&Sat);
    02328     RETHROW();
    02329   }
    02330   TRY {
    02331     NbRay       = Pol->NbRays;
    02332     NbCon       = Pol->NbConstraints + NbConstraints;
    02333
    02334     if (NbRay > NbMaxRays)
    02335       NbMaxRays = NbRay;
    02336
    02337     Mat = Matrix_Alloc(NbCon, Dimension);
    02338     if(!Mat) {
    02339       errormsg1("AddConstraints", "outofmem", "out of memory space");
    02340       UNCATCH(any_exception_error);
    02341       return 0;
    02342     }
    02343
    02344     /* Copy constraints of polyhedron 'Pol' to matrix 'Mat' */
    02345     Vector_Copy(Pol->Constraint[0], Mat->p[0], Pol->NbConstraints * Dimension);
    02346
    02347     /* Add the new constraints pointed by 'Con' to matrix 'Mat' */
    02348     Vector_Copy(Con, Mat->p[Pol->NbConstraints], NbConstraints * Dimension);
    02349
    02350     /* Allocate space for ray matrix 'Ray' */
    02351     Ray = Matrix_Alloc(NbMaxRays, Dimension);
    02352     if(!Ray) {
    02353       errormsg1("AddConstraints", "outofmem", "out of memory space");
    02354       UNCATCH(any_exception_error);
    02355       return 0;
    02356     }
    02357     Ray->NbRows = NbRay;
    02358
    02359     /* Copy rays of polyhedron 'Pol' to matrix 'Ray' */
    02360     if (NbRay)
    02361         Vector_Copy(Pol->Ray[0], Ray->p[0], NbRay * Dimension);
    02362
    02363     /* Create the saturation matrix 'Sat' from constraint matrix 'Mat' and */
    02364     /* ray matrix 'Ray' .                                                  */
    02365     Sat = BuildSat(Mat, Ray, Pol->NbConstraints, NbMaxRays);
    02366
    02367     /* Create the ray matrix 'Ray' from the constraint matrix 'Mat' */
    02368     Pol_status = Chernikova(Mat, Ray, Sat, Pol->NbBid, NbMaxRays, Pol->NbConstraints,0);
    02369
    02370     /* Remove redundant constraints from matrix 'Mat' */
    02371     NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
    02372
    02373   } /* end of TRY */
    02374
    02375   UNCATCH(any_exception_error);
    02376   SMFree(&Sat);
    02377   Matrix_Free(Ray);
    02378   Matrix_Free(Mat);
    02379   return NewPol;
    02380 } /* AddConstraints */
    02381
    02382 /*
    02383  * Return 1 if 'Pol1' includes (covers) 'Pol2', 0 otherwise.
    02384  * Polyhedron 'A' includes polyhedron 'B' if the rays of 'B' saturate
    02385  * the equalities and verify the inequalities of 'A'. Both 'Pol1' and
    02386  * 'Pol2' have same dimensions.
    02387  */
    02388 int PolyhedronIncludes(Polyhedron *Pol1,Polyhedron *Pol2) {
    02389
    02390   int Dimension = Pol1->Dimension + 1;   /* Homogenous Dimension */
    02391   int i, j, k;
    02392   Value *p1, *p2, p3;
    02393
    02394   POL_ENSURE_FACETS(Pol1);
    02395   POL_ENSURE_VERTICES(Pol1);
    02396   POL_ENSURE_FACETS(Pol2);
    02397   POL_ENSURE_VERTICES(Pol2);
    02398
    02399   value_init(p3);
    02400   for (k=0; k<Pol1->NbConstraints; k++) {
    02401     for (i=0;i<Pol2->NbRays;i++) {
    02402
    02403       /* Compute the dot product of ray(i) and constraint(k) and store in p3 */
    02404       p1 = Pol2->Ray[i]+1;
    02405       p2 = Pol1->Constraint[k]+1;
    02406       value_set_si(p3,0);
    02407       for(j=0;j<Dimension;j++) {
    02408         value_addmul(p3, *p1,*p2);
    02409         p1++; p2++;
    02410       }
    02411
    02412       /* If (p3 < 0) or (p3 > 0 and (constraint(k) is equality
    02413                                      or ray(i) is a line)), return 0 */
    02414       if(value_neg_p(p3) ||
    02415           (value_notzero_p(p3)
    02416              && (value_zero_p(Pol1->Constraint[k][0]) || (value_zero_p(Pol2->Ray[i][0]))   ) )) {
    02417         value_clear(p3);
    02418         return 0;
    02419       }
    02420     }
    02421   }
    02422   value_clear(p3);
    02423   return 1;
    02424 } /* PolyhedronIncludes */
    02425
    02426 /*
    02427  * Add Polyhedron 'Pol' to polhedral domain 'PolDomain'. If 'Pol' covers
    02428  * some polyhedron in the domain 'PolDomain', it is removed from the list.
    02429  * On the other hand if some polyhedron in the domain covers polyhedron
    02430  * 'Pol' then 'Pol' is not included in the domain.
    02431  */
    02432 Polyhedron *AddPolyToDomain(Polyhedron *Pol,Polyhedron *PolDomain) {
    02433
    02434   Polyhedron *p, *pnext, *p_domain_end = (Polyhedron *) 0;
    02435   int Redundant;
    02436
    02437   if (!Pol)
    02438     return PolDomain;
    02439   if (!PolDomain)
    02440     return Pol;
    02441
    02442   POL_ENSURE_FACETS(Pol);
    02443   POL_ENSURE_VERTICES(Pol);
    02444
    02445   /* Check for emptiness of polyhedron 'Pol' */
    02446   if (emptyQ(Pol)) {
    02447     Polyhedron_Free(Pol);
    02448     return PolDomain;
    02449   }
    02450
    02451   POL_ENSURE_FACETS(PolDomain);
    02452   POL_ENSURE_VERTICES(PolDomain);
    02453
    02454   /* Check for emptiness of polyhedral domain 'PolDomain' */
    02455   if (emptyQ(PolDomain)) {
    02456     Polyhedron_Free(PolDomain);
    02457     return Pol;
    02458   }
    02459
    02460   /* Test 'Pol' against the domain 'PolDomain' */
    02461   Redundant = 0;
    02462   for (p=PolDomain,PolDomain=(Polyhedron *)0; p; p=pnext) {
    02463
    02464     /* If 'Pol' covers 'p' */
    02465     if (PolyhedronIncludes(Pol, p))
    02466     {
    02467        /* free p */
    02468                  pnext = p->next;
    02469        Polyhedron_Free( p );
    02470        continue;
    02471     }
    02472
    02473     /* Add polyhedron p to the new domain list */
    02474     if (!PolDomain) PolDomain = p; else p_domain_end->next = p;
    02475     p_domain_end = p;
    02476
    02477     /* If p covers Pol */
    02478     if (PolyhedronIncludes(p,Pol)) {
    02479       Redundant = 1;
    02480       break;
    02481     }
    02482     pnext = p->next;
    02483   }
    02484   if (!Redundant) {
    02485
    02486     /* The whole list has been checked. Add new polyhedron 'Pol' to the */
    02487     /* new domain list.                                                 */
    02488     if (!PolDomain) PolDomain = Pol; else p_domain_end->next = Pol;
    02489   }
    02490   else {
    02491
    02492     /* The rest of the list is just inherited from p */
    02493     Polyhedron_Free(Pol);
    02494   }
    02495   return PolDomain;
    02496 } /* AddPolyToDomain */
    02497
    02498 /*
    02499  * Given a polyhedra 'Pol' and a single constraint 'Con' and an integer 'Pass'
    02500  * whose value ranges from 0 to 3, add the inverse of constraint 'Con' to the
    02501  * constraint set of 'Pol' and return the new polyhedron. 'NbMaxRays' is the
    02502  * maximum allowed rays in the new generated polyhedron.
    02503  * If Pass == 0, add ( -constraint -1) >= 0
    02504  * If Pass == 1, add ( +constraint -1) >= 0
    02505  * If Pass == 2, add ( -constraint   ) >= 0
    02506  * If Pass == 3, add ( +constraint   ) >= 0
    02507  */
    02508 Polyhedron *SubConstraint(Value *Con,Polyhedron *Pol,unsigned NbMaxRays,int Pass) {
    02509
    02510   Polyhedron *NewPol = NULL;
    02511   Matrix   *Mat = NULL, *Ray = NULL;
    02512   SatMatrix *Sat = NULL;
    02513   unsigned NbRay, NbCon, NbEle1, Dimension;
    02514   int i;
    02515
    02516   POL_ENSURE_FACETS(Pol);
    02517   POL_ENSURE_VERTICES(Pol);
    02518
    02519   CATCH(any_exception_error) {
    02520     if (NewPol) Polyhedron_Free(NewPol);
    02521     if (Mat) Matrix_Free(Mat);
    02522     if (Ray) Matrix_Free(Ray);
    02523     if (Sat) SMFree(&Sat);
    02524     RETHROW();
    02525   }
    02526   TRY {
    02527
    02528     /* If 'Con' is the positivity constraint, return Null */
    02529     Dimension  = Pol->Dimension+1;      /* Homogeneous Dimension */
    02530     for (i=1; i<Dimension; i++)
    02531       if (value_notzero_p(Con[i])) break;
    02532     if (i==Dimension) {
    02533       UNCATCH(any_exception_error);
    02534       return (Polyhedron *) 0;
    02535     }
    02536
    02537     NbRay     = Pol->NbRays;
    02538     NbCon     = Pol->NbConstraints;
    02539     Dimension = Pol->Dimension+2;       /* Homogeneous Dimension + Status */
    02540     NbEle1    = NbCon * Dimension;
    02541
    02542     /* Ignore for now */
    02543     if (POL_ISSET(NbMaxRays, POL_NO_DUAL))
    02544       NbMaxRays = 0;
    02545
    02546     if (NbRay > NbMaxRays)
    02547       NbMaxRays = NbRay;
    02548
    02549     Mat = Matrix_Alloc(NbCon + 1, Dimension);
    02550     if(!Mat) {
    02551       errormsg1("SubConstraint", "outofmem", "out of memory space");
    02552       UNCATCH(any_exception_error);
    02553       return 0;
    02554     }
    02555
    02556     /* Set the constraints of Pol */
    02557     Vector_Copy(Pol->Constraint[0], Mat->p[0], NbEle1);
    02558
    02559     /* Add the new constraint */
    02560     value_set_si(Mat->p[NbCon][0],1);
    02561     if (!(Pass&1))
    02562       for(i=1; i<Dimension; i++)
    02563         value_oppose(Mat->p[NbCon][i],Con[i]);
    02564     else
    02565       for(i=1; i<Dimension; i++)
    02566         value_assign(Mat->p[NbCon][i],Con[i]);
    02567     if (!(Pass&2))
    02568       value_decrement(Mat->p[NbCon][Dimension-1],Mat->p[NbCon][Dimension-1]);
    02569
    02570     /* Allocate the ray matrix. */
    02571     Ray = Matrix_Alloc(NbMaxRays, Dimension);
    02572     if(!Ray) {
    02573       errormsg1("SubConstraint", "outofmem", "out of memory space");
    02574       UNCATCH(any_exception_error);
    02575       return 0;
    02576     }
    02577
    02578     /* Initialize the ray matrix with the rays of polyhedron 'Pol' */
    02579     Ray->NbRows = NbRay;
    02580     if (NbRay)
    02581         Vector_Copy(Pol->Ray[0], Ray->p[0], NbRay * Dimension);
    02582
    02583     /* Create the saturation matrix from the constraint matrix 'mat' and */
    02584     /* ray matrix 'Ray'.                                                 */
    02585     Sat = BuildSat(Mat, Ray, NbCon, NbMaxRays);
    02586
    02587     /* Create the ray matrix 'Ray' from consraint matrix 'Mat'           */
    02588     Pol_status = Chernikova(Mat, Ray, Sat, Pol->NbBid, NbMaxRays, NbCon,0);
    02589
    02590     /* Remove redundant constraints from matrix 'Mat' */
    02591     NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
    02592
    02593   } /* end of TRY */
    02594
    02595   UNCATCH(any_exception_error);
    02596
    02597   SMFree(&Sat);
    02598   Matrix_Free(Ray);
    02599   Matrix_Free(Mat);
    02600   return NewPol;
    02601 } /* SubConstraint */
    02602
    02603 /*
    02604  * Return the intersection of two polyhedral domains 'Pol1' and 'Pol2'.
    02605  * The maximum allowed rays in the new polyhedron generated is 'NbMaxRays'.
    02606  */
    02607 Polyhedron *DomainIntersection(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
    02608
    02609   Polyhedron *p1, *p2, *p3, *d;
    02610
    02611   if (!Pol1 || !Pol2) return (Polyhedron*) 0;
    02612   if (Pol1->Dimension != Pol2->Dimension) {
    02613     errormsg1( "DomainIntersection", "diffdim",
    02614                "operation on different dimensions");
    02615     return (Polyhedron*) 0;
    02616   }
    02617
    02618   /* For every polyhedron pair (p1,p2) where p1 belongs to domain Pol1 and */
    02619   /* p2 belongs to domain Pol2, compute the intersection and add it to the */
    02620   /* new domain 'd'.                                                       */
    02621   d = (Polyhedron *)0;
    02622   for (p1=Pol1; p1; p1=p1->next) {
    02623     for (p2=Pol2; p2; p2=p2->next) {
    02624       p3 = AddConstraints(p2->Constraint[0],
    02625                           p2->NbConstraints, p1, NbMaxRays);
    02626       d = AddPolyToDomain(p3,d);
    02627     }
    02628   }
    02629   if (!d)
    02630     return Empty_Polyhedron(Pol1->Dimension);
    02631   else
    02632     return d;
    02633
    02634 } /* DomainIntersection */
    02635
    02636 /*
    02637  * Given a polyhedron 'Pol', return a matrix of rays.
    02638  */
    02639 Matrix *Polyhedron2Rays(Polyhedron *Pol) {
    02640
    02641   Matrix     *Ray;
    02642   unsigned NbRays, Dimension;
    02643
    02644   POL_ENSURE_POINTS(Pol);
    02645
    02646   NbRays    = Pol->NbRays;
    02647   Dimension = Pol->Dimension+2;         /* Homogeneous Dimension + Status */
    02648   Ray = Matrix_Alloc(NbRays, Dimension);
    02649   if(!Ray) {
    02650     errormsg1("Polyhedron2Rays", "outofmem", "out of memory space");
    02651     return 0;
    02652   }
    02653   Vector_Copy(Pol->Ray[0], Ray->p_Init, NbRays*Dimension);
    02654   return Ray;
    02655 } /* Polyhedron2Rays */
    02656
    02657 /*
    02658  * Add 'NbAddedRays' rays to polyhedron 'Pol'. Rays are pointed by 'AddedRays'
    02659  * and the maximum allowed constraints in the new polyhedron is 'NbMaxConstrs'.
    02660  */
    02661 Polyhedron *AddRays(Value *AddedRays,unsigned NbAddedRays,Polyhedron *Pol,unsigned NbMaxConstrs) {
    02662
    02663   Polyhedron *NewPol = NULL;
    02664   Matrix   *Mat = NULL, *Ray = NULL;
    02665   SatMatrix *Sat = NULL, *SatTranspose = NULL;
    02666   unsigned NbCon, NbRay,NbEle1, Dimension;
    02667
    02668   POL_ENSURE_FACETS(Pol);
    02669   POL_ENSURE_VERTICES(Pol);
    02670
    02671   CATCH(any_exception_error) {
    02672     if (NewPol) Polyhedron_Free(NewPol);
    02673     if (Mat) Matrix_Free(Mat);
    02674     if (Ray) Matrix_Free(Ray);
    02675     if (Sat) SMFree(&Sat);
    02676     if (SatTranspose) SMFree(&SatTranspose);
    02677     RETHROW();
    02678   }
    02679   TRY {
    02680
    02681     NbCon      = Pol->NbConstraints;
    02682     NbRay      = Pol->NbRays;
    02683     Dimension  = Pol->Dimension + 2;    /* Homogeneous Dimension + Status */
    02684     NbEle1     = NbRay * Dimension;
    02685
    02686     Ray = Matrix_Alloc(NbAddedRays + NbRay, Dimension);
    02687     if(!Ray) {
    02688       errormsg1("AddRays", "outofmem", "out of memory space");
    02689       UNCATCH(any_exception_error);
    02690       return 0;
    02691     }
    02692
    02693     /* Copy rays of polyhedron 'Pol' to matrix 'Ray' */
    02694     if (NbRay)
    02695       Vector_Copy(Pol->Ray[0], Ray->p_Init, NbEle1);
    02696
    02697     /* Add the new rays pointed by 'AddedRays' to matrix 'Ray' */
    02698     Vector_Copy(AddedRays, Ray->p_Init+NbEle1, NbAddedRays * Dimension);
    02699
    02700     /* Ignore for now */
    02701     if (POL_ISSET(NbMaxConstrs, POL_NO_DUAL))
    02702       NbMaxConstrs = 0;
    02703
    02704     /* We need at least NbCon rows */
    02705     if (NbMaxConstrs < NbCon)
    02706         NbMaxConstrs = NbCon;
    02707
    02708     /* Allocate space for constraint matrix 'Mat' */
    02709     Mat = Matrix_Alloc(NbMaxConstrs, Dimension);
    02710     if(!Mat) {
    02711       errormsg1("AddRays", "outofmem", "out of memory space");
    02712       UNCATCH(any_exception_error);
    02713       return 0;
    02714     }
    02715     Mat->NbRows = NbCon;
    02716
    02717     /* Copy constraints of polyhedron 'Pol' to matrix 'Mat' */
    02718     Vector_Copy(Pol->Constraint[0], Mat->p_Init, NbCon*Dimension);
    02719
    02720     /* Create the saturation matrix 'SatTranspose' from constraint matrix */
    02721     /* 'Mat' and ray matrix 'Ray'. Remember the saturation matrix is      */
    02722     /* referenced by (constraint,ray) pair                                */
    02723     SatTranspose = BuildSat(Ray, Mat, NbRay, NbMaxConstrs);
    02724
    02725     /* Create the constraint matrix 'Mat' from the ray matrix 'Ray' */
    02726     Pol_status = Chernikova(Ray, Mat, SatTranspose, Pol->NbEq, NbMaxConstrs, NbRay,1);
    02727
    02728     /* Transform the saturation matrix 'SatTranspose' in the standard format */
    02729     /* , that is, (ray X constraint) format.                                 */
    02730     Sat = TransformSat(Mat, Ray, SatTranspose);
    02731     SMFree(&SatTranspose), SatTranspose = NULL;
    02732
    02733     /* Remove redundant rays from the ray matrix 'Ray' */
    02734     NewPol = Remove_Redundants(Mat, Ray, Sat, 0);
    02735
    02736     SMFree(&Sat), Sat = NULL;
    02737     Matrix_Free(Mat), Mat = NULL;
    02738     Matrix_Free(Ray), Ray = NULL;
    02739   } /* end of TRY */
    02740
    02741   UNCATCH(any_exception_error);
    02742   return NewPol;
    02743 } /* AddRays */
    02744
    02745 /*
    02746  * Add rays pointed by 'Ray' to each and every polyhedron in the polyhedral
    02747  * domain 'Pol'. 'NbMaxConstrs' is maximum allowed constraints in the
    02748  * constraint set of a polyhedron.
    02749  */
    02750 Polyhedron *DomainAddRays(Polyhedron *Pol,Matrix *Ray,unsigned NbMaxConstrs) {
    02751
    02752   Polyhedron *PolA, *PolEndA, *p1, *p2, *p3;
    02753   int Redundant;
    02754
    02755   if (!Pol) return (Polyhedron*) 0;
    02756   if (!Ray || Ray->NbRows == 0)
    02757     return Domain_Copy(Pol);
    02758   if (Pol->Dimension != Ray->NbColumns-2) {
    02759     errormsg1(
    02760               "DomainAddRays", "diffdim", "operation on different dimensions");
    02761     return (Polyhedron*) 0;
    02762   }
    02763
    02764   /* Copy Pol to PolA */
    02765   PolA = PolEndA = (Polyhedron *)0;
    02766   for (p1=Pol; p1; p1=p1->next) {
    02767     p3 = AddRays(Ray->p[0], Ray->NbRows, p1, NbMaxConstrs);
    02768
    02769     /* Does any component of PolA cover 'p3' ? */
    02770     Redundant = 0;
    02771     for (p2=PolA; p2; p2=p2->next) {
    02772       if (PolyhedronIncludes(p2, p3)) { /* If p2 covers p3 */
    02773         Redundant = 1;
    02774         break;
    02775       }
    02776     }
    02777
    02778     /* If the new polyheron is not redundant, add it ('p3') to the list */
    02779     if (Redundant)
    02780       Polyhedron_Free(p3);
    02781     else {
    02782       if (!PolEndA)
    02783         PolEndA = PolA = p3;
    02784       else {
    02785         PolEndA->next = p3;
    02786         PolEndA = PolEndA->next;
    02787       }
    02788     }
    02789   }
    02790   return PolA;
    02791 } /* DomainAddRays */
    02792
    02793 /*
    02794  * Create a copy of the polyhedron 'Pol'
    02795  */
    02796 Polyhedron *Polyhedron_Copy(Polyhedron *Pol) {
    02797
    02798   Polyhedron *Pol1;
    02799
    02800   if (!Pol) return (Polyhedron *)0;
    02801
    02802   /* Allocate space for the new polyhedron */
    02803   Pol1 = Polyhedron_Alloc(Pol->Dimension, Pol->NbConstraints, Pol->NbRays);
    02804   if (!Pol1) {
    02805     errormsg1("Polyhedron_Copy", "outofmem", "out of memory space");
    02806     return 0;
    02807   }
    02808   if( Pol->NbConstraints )
    02809     Vector_Copy(Pol->Constraint[0], Pol1->Constraint[0],
    02810               Pol->NbConstraints*(Pol->Dimension+2));
    02811   if( Pol->NbRays )
    02812     Vector_Copy(Pol->Ray[0], Pol1->Ray[0],
    02813               Pol->NbRays*(Pol->Dimension+2));
    02814   Pol1->NbBid = Pol->NbBid;
    02815   Pol1->NbEq = Pol->NbEq;
    02816   Pol1->flags = Pol->flags;
    02817   return Pol1;
    02818 } /* Polyhedron_Copy */
    02819
    02820 /*
    02821  * Create a copy of a polyhedral domain.
    02822  */
    02823 Polyhedron *Domain_Copy(Polyhedron *Pol) {
    02824
    02825   Polyhedron *Pol1;
    02826
    02827   if (!Pol) return (Polyhedron *) 0;
    02828   Pol1 = Polyhedron_Copy(Pol);
    02829   if (Pol->next) Pol1->next = Domain_Copy(Pol->next);
    02830   return Pol1;
    02831 } /* Domain_Copy */
    02832
    02833 /*
    02834  * Given constraint number 'k' of a polyhedron, and an array 'Filter' to store
    02835  * the non-redundant constraints of the polyhedron in bit-wise notation, and
    02836  * a Matrix 'Sat', add the constraint 'k' in 'Filter' array. tmpR[i] stores the
    02837  * number of constraints, other than those in 'Filter', which ray(i) saturates
    02838  * or verifies. In case, ray(i) does not saturate or verify a constraint in
    02839  * array 'Filter', it is assigned to -1. Similarly, tmpC[j] stores the number
    02840  * of rays which constraint(j), if it doesn't belong to Filter, saturates or
    02841  * verifies. If constraint(j) belongs to 'Filter', then tmpC[j] is assigned to
    02842  * -1. 'NbConstraints' is the number of constraints in the constraint matrix of
    02843  * the polyhedron.
    02844  * NOTE: (1) 'Sat' is not the saturation matrix of the polyhedron. In fact,
    02845  *           entry in 'Sat' is set to 1 if ray(i) of polyhedron1 verifies or
    02846  *           saturates the constraint(j) of polyhedron2 and otherwise it is set
    02847  *           to 0. So here the difference with saturation matrix is in terms
    02848  *           definition and entries(1<->0) of the matrix 'Sat'.
    02849  *
    02850  * ALGORITHM:->
    02851  * (1) Include constraint(k) in array 'Filter'.
    02852  * (2) Set tmpC[k] to -1.
    02853  * (3) For all ray(i) {
    02854  *        If ray(i) saturates or verifies constraint(k) then --(tmpR[i])
    02855  *        Else {
    02856  *           Discard ray(i) by assigning tmpR[i] = -1
    02857  *           Decrement tmpC[j] for all constraint(j) not in array 'Filter'.
    02858  *        }
    02859  *     }
    02860  */
    02861 static void addToFilter(int k, unsigned *Filter, SatMatrix *Sat,Value *tmpR,Value *tmpC,int NbRays,int NbConstraints) {
    02862
    02863   int kj, i,j, jx;
    02864   unsigned kb, bx;
    02865
    02866   /* Remove constraint k */
    02867   kj =   k/WSIZE; kb = MSB; kb >>= k%WSIZE;
    02868   Filter[kj]|=kb;
    02869   value_set_si(tmpC[k],-1);
    02870
    02871   /* Remove rays excluded by constraint k */
    02872   for(i=0; i<NbRays; i++)
    02873     if (value_posz_p(tmpR[i])) {
    02874       if (Sat->p[i][kj]&kb)
    02875         value_decrement(tmpR[i],tmpR[i]);  /* adjust included ray */
    02876       else {
    02877
    02878         /* Constraint k excludes ray i -- delete ray i */
    02879         value_set_si(tmpR[i],-1);
    02880
    02881         /* Adjust non-deleted constraints */
    02882         jx=0; bx=MSB;
    02883         for(j=0; j<NbConstraints; j++) {
    02884           if (value_posz_p(tmpC[j]) && (Sat->p[i][jx]&bx) )
    02885             value_decrement(tmpC[j],tmpC[j]);
    02886           NEXT(jx,bx);
    02887         }
    02888       }
    02889     }
    02890 } /* addToFilter */
    02891
    02892 /*
    02893  * Given polyhedra 'P1' and 'P2' such that their intersection is an empty
    02894  * polyhedron, find the minimal set of constraints of 'P1' which contradict
    02895  * all of the constraints of 'P2'. This is believed to be an NP-hard problem
    02896  * and so a heuristic is employed to solve it in worst case. The heuristic is
    02897  * to select in every turn that constraint of 'P1' which excludes most rays of
    02898  * 'P2'. A bit in the binary format of an element of array 'Filter' is set to
    02899  * 1 if the corresponding constraint is to be included in the minimal set of
    02900  * constraints otherwise it is set to 0.
    02901  */
    02902 static void FindSimple(Polyhedron *P1,Polyhedron *P2,unsigned *Filter,unsigned NbMaxRays) {
    02903
    02904   Matrix *Mat = NULL;
    02905   SatMatrix *Sat = NULL;
    02906   int i, j, k, jx, found;
    02907   Value *p1, *p2, p3;
    02908   unsigned Dimension, NbRays, NbConstraints, bx, nc;
    02909   Value NbConstraintsLeft, tmp;
    02910   Value *tmpC = NULL, *tmpR = NULL;
    02911   Polyhedron *Pol = NULL, *Pol2 = NULL;
    02912
    02913   /* Initialize all the 'Value' variables */
    02914   value_init(p3); value_init(NbConstraintsLeft);
    02915   value_init(tmp);
    02916
    02917   CATCH(any_exception_error) {
    02918     if (tmpC) free(tmpC);
    02919     if (tmpR) free(tmpR);
    02920     if (Mat) Matrix_Free(Mat);
    02921     if (Sat) SMFree(&Sat);
    02922     if (Pol2 && Pol2!=P2) Polyhedron_Free(Pol2);
    02923     if (Pol && Pol!=Pol2 && Pol!=P2) Polyhedron_Free(Pol);
    02924
    02925     /* Clear all the 'Value' variables */
    02926     value_clear(p3); value_clear(NbConstraintsLeft);
    02927     value_clear(tmp);
    02928     RETHROW();
    02929   }
    02930   TRY {
    02931
    02932     Dimension = P1->Dimension+2;       /* status + homogeneous Dimension */
    02933     Mat = Matrix_Alloc(P1->NbConstraints, Dimension);
    02934     if(!Mat) {
    02935       errormsg1("FindSimple", "outofmem", "out of memory space");
    02936       UNCATCH(any_exception_error);
    02937
    02938       /* Clear all the 'Value' variables */
    02939       value_clear(p3); value_clear(NbConstraintsLeft); value_clear(tmp);
    02940       return;
    02941     }
    02942
    02943     /* Post constraints in P1 already included by Filter */
    02944     jx = 0; bx = MSB; Mat->NbRows=0;
    02945     value_set_si(NbConstraintsLeft,0);
    02946     for (k=0; k<P1->NbConstraints; k++) {
    02947       if (Filter[jx]&bx) {
    02948         Vector_Copy(P1->Constraint[k], Mat->p[Mat->NbRows], Dimension);
    02949         Mat->NbRows++;
    02950       }
    02951       else
    02952         value_increment(NbConstraintsLeft,NbConstraintsLeft);
    02953       NEXT(jx,bx);
    02954     }
    02955     Pol2 = P2;
    02956
    02957     for (;;) {
    02958       if (Mat->NbRows==0)
    02959         Pol = Polyhedron_Copy(Pol2);
    02960       else {
    02961         Pol = AddConstraints(Mat->p_Init, Mat->NbRows, Pol2, NbMaxRays);
    02962         if (Pol2 != P2) Polyhedron_Free(Pol2), Pol2 = NULL;
    02963       }
    02964       if (emptyQ(Pol)) {
    02965         Matrix_Free(Mat), Mat = NULL;
    02966         Polyhedron_Free(Pol), Pol = NULL;
    02967         UNCATCH(any_exception_error);
    02968
    02969         /* Clear all the 'Value' variables */
    02970         value_clear(p3); value_clear(NbConstraintsLeft); value_clear(tmp);
    02971         return;
    02972       }
    02973       Mat->NbRows = 0;        /* Reset Mat */
    02974       Pol2 = Pol;
    02975
    02976       /* Its not enough-- find some more constraints */
    02977       Dimension         = Pol->Dimension+1;       /* homogeneous Dimension */
    02978       NbRays            = Pol->NbRays;
    02979       NbConstraints     = P1->NbConstraints;
    02980       tmpR = (Value *)malloc(NbRays*sizeof(Value));
    02981       if(!tmpR) {
    02982         errormsg1("FindSimple", "outofmem", "out of memory space");
    02983         UNCATCH(any_exception_error);
    02984
    02985         /* Clear all the 'Value' variables */
    02986         value_clear(p3); value_clear(NbConstraintsLeft); value_clear(tmp);
    02987         return;
    02988       }
    02989       for(i=0;i<NbRays;i++)
    02990         value_init(tmpR[i]);
    02991       tmpC = (Value *)malloc(NbConstraints*sizeof(Value));
    02992       if(!tmpC) {
    02993         errormsg1("FindSimple", "outofmem", "out of memory space");
    02994         UNCATCH(any_exception_error);
    02995
    02996         /* Clear all the 'Value' variables */
    02997         value_clear(p3); value_clear(NbConstraintsLeft);
    02998         for(i=0;i<NbRays;i++)
    02999           value_clear(tmpR[i]);
    03000         free(tmpR);
    03001         return;
    03002       }
    03003       for(i=0;i<NbConstraints;i++)
    03004         value_init(tmpC[i]);
    03005       Vector_Set(tmpR,0,NbRays);
    03006       Vector_Set(tmpC,0,NbConstraints);
    03007
    03008       /* Build the Sat matrix */
    03009       nc      = (NbConstraints - 1) / (sizeof(int)*8) + 1;
    03010       Sat     = SMAlloc(NbRays, nc);
    03011       Sat->NbRows = NbRays;
    03012       SMVector_Init(Sat->p_init, nc*NbRays);
    03013
    03014       jx=0; bx=MSB;
    03015       for (k=0; k<NbConstraints; k++) {
    03016         if (Filter[jx]&bx)
    03017           value_set_si(tmpC[k],-1);
    03018         else
    03019           for (i=0; i<NbRays; i++) {
    03020             p1 = Pol->Ray[i]+1;
    03021             p2 = P1->Constraint[k]+1;
    03022             value_set_si(p3,0);
    03023             for (j=0; j<Dimension; j++) {
    03024               value_addmul(p3, *p1, *p2);
    03025               p1++; p2++;
    03026             }
    03027             if(value_zero_p(p3) ||
    03028                (value_pos_p(p3) && value_notzero_p(P1->Constraint[k][0]))) {
    03029               Sat->p[i][jx]|=bx;  /* constraint includes ray, set flag */
    03030               value_increment(tmpR[i],tmpR[i]);
    03031               value_increment(tmpC[k],tmpC[k]);
    03032             }
    03033           }
    03034         NEXT(jx, bx);
    03035       }
    03036
    03037       do { /* find all of the essential constraints */
    03038         found = 0;
    03039         for(i=0; i<NbRays; i++)
    03040           if(value_posz_p(tmpR[i])) {
    03041             value_add_int(tmp,tmpR[i],1);
    03042             if(value_eq(tmp,NbConstraintsLeft)) {
    03043
    03044               /* Ray i is excluded by only one constraint... find it */
    03045               jx = 0; bx = MSB;
    03046               for(k=0; k<NbConstraints; k++) {
    03047                 if(value_posz_p(tmpC[k]) && ((Sat->p[i][jx]&bx)==0)) {
    03048                   addToFilter(k, Filter, Sat, tmpR, tmpC,
    03049                               NbRays, NbConstraints);
    03050                   Vector_Copy(P1->Constraint[k],
    03051                               Mat->p[Mat->NbRows],Dimension+1);
    03052                   Mat->NbRows++;
    03053                   value_decrement(NbConstraintsLeft,NbConstraintsLeft);
    03054                   found=1;
    03055                   break;
    03056                 }
    03057                 NEXT(jx,bx);
    03058               }
    03059               break;
    03060             }
    03061           }
    03062       }
    03063       while (found);
    03064
    03065       if (!Mat->NbRows) { /* Well then, just use a stupid heuristic */
    03066         /* find the constraint which excludes the most */
    03067         Value cmax;
    03068         value_init(cmax);
    03069
    03070 #ifndef LINEAR_VALUE_IS_CHARS
    03071         value_set_si(cmax,(NbRays * NbConstraints+1));
    03072 #else
    03073         value_set_si(cmax,1);
    03074 #endif
    03075
    03076         j = -1;
    03077         for(k=0; k<NbConstraints; k++)
    03078           if (value_posz_p(tmpC[k])) {
    03079             if (value_gt(cmax,tmpC[k])) {
    03080               value_assign(cmax,tmpC[k]);
    03081               j = k;
    03082             }
    03083           }
    03084         value_clear(cmax);
    03085         if (j<0) {
    03086           errormsg1("DomSimplify","logerror","logic error");
    03087         }
    03088         else {
    03089           addToFilter(j, Filter, Sat, tmpR, tmpC, NbRays, NbConstraints);
    03090           Vector_Copy(P1->Constraint[j],Mat->p[Mat->NbRows],Dimension+1);
    03091           Mat->NbRows++;
    03092           value_decrement(NbConstraintsLeft,NbConstraintsLeft);
    03093         }
    03094       }
    03095       SMFree(&Sat), Sat = NULL;
    03096       free(tmpC), tmpC = NULL;
    03097       free(tmpR), tmpR = NULL;
    03098     }
    03099   } /* end of TRY */
    03100
    03101   /* Clear all the 'Value' variables */
    03102   value_clear(p3); value_clear(NbConstraintsLeft);
    03103   value_clear(tmp);
    03104   for(i=0;i<NbRays;i++)
    03105     value_clear(tmpR[i]);
    03106   for(i=0;i<NbRays;i++)
    03107     value_clear(tmpC[i]);
    03108
    03109   UNCATCH(any_exception_error);
    03110 } /* FindSimple */
    03111
    03112 /*
    03113  * Return 0 if the intersection of Pol1 and Pol2 is empty, otherwise return 1.
    03114  * If the intersection is non-empty, store the non-redundant constraints in
    03115  * 'Filter' array. If the intersection is empty then store the smallest set of
    03116  * constraints of 'Pol1' which on intersection with 'Pol2' gives empty set, in
    03117  * 'Filter' array. 'NbMaxRays' is the maximum allowed rays in the intersection
    03118  *  of 'Pol1' and 'Pol2'.
    03119  */
    03120 static int SimplifyConstraints(Polyhedron *Pol1,Polyhedron *Pol2,unsigned *Filter,unsigned NbMaxRays) {
    03121
    03122   Polyhedron *Pol = NULL;
    03123   Matrix   *Mat = NULL, *Ray = NULL;
    03124   SatMatrix *Sat = NULL;
    03125   unsigned NbRay, NbCon, NbCon1, NbCon2, NbEle1, Dimension, notempty;
    03126
    03127   CATCH(any_exception_error) {
    03128     if (Pol) Polyhedron_Free(Pol);
    03129     if (Mat) Matrix_Free(Mat);
    03130     if (Ray) Matrix_Free(Ray);
    03131     if (Sat) SMFree(&Sat);
    03132     RETHROW();
    03133   }
    03134   TRY {
    03135
    03136     NbRay         = Pol1->NbRays;
    03137     NbCon1        = Pol1->NbConstraints;
    03138     NbCon2        = Pol2->NbConstraints;
    03139     NbCon         = NbCon1 + NbCon2;
    03140     Dimension     = Pol1->Dimension+2;    /* Homogeneous Dimension + Status */
    03141     NbEle1        = NbCon1*Dimension;
    03142
    03143     /* Ignore for now */
    03144     if (POL_ISSET(NbMaxRays, POL_NO_DUAL))
    03145       NbMaxRays = 0;
    03146
    03147     if (NbRay > NbMaxRays)
    03148       NbMaxRays = NbRay;
    03149
    03150     /* Allocate space for constraint matrix 'Mat' */
    03151     Mat = Matrix_Alloc(NbCon, Dimension);
    03152     if(!Mat) {
    03153       errormsg1("SimplifyConstraints", "outofmem", "out of memory space");
    03154       UNCATCH(any_exception_error);
    03155       return 0;
    03156     }
    03157
    03158     /* Copy constraints of 'Pol1' to matrix 'Mat' */
    03159     Vector_Copy(Pol1->Constraint[0], Mat->p_Init, NbEle1);
    03160
    03161     /* Add constraints of 'Pol2' to matrix 'Mat'*/
    03162     Vector_Copy(Pol2->Constraint[0], Mat->p_Init+NbEle1, NbCon2*Dimension);
    03163
    03164     /* Allocate space for ray matrix 'Ray' */
    03165     Ray = Matrix_Alloc(NbMaxRays, Dimension);
    03166     if(!Ray) {
    03167       errormsg1("SimplifyConstraints", "outofmem", "out of memory space");
    03168       UNCATCH(any_exception_error);
    03169       return 0;
    03170     }
    03171     Ray->NbRows = NbRay;
    03172
    03173     /* Copy rays of polyhedron 'Pol1' to matrix 'Ray' */
    03174     Vector_Copy(Pol1->Ray[0], Ray->p_Init, NbRay*Dimension);
    03175
    03176     /* Create saturation matrix from constraint matrix 'Mat' and ray matrix */
    03177     /* 'Ray'.                                                               */
    03178     Sat = BuildSat(Mat, Ray, NbCon1, NbMaxRays);
    03179
    03180     /* Create the ray matrix 'Ray' from the constraint matrix 'Mat' */
    03181     Pol_status = Chernikova(Mat, Ray, Sat, Pol1->NbBid, NbMaxRays, NbCon1,0);
    03182
    03183     /* Remove redundant constraints from the constraint matrix 'Mat' */
    03184     Pol = Remove_Redundants(Mat, Ray, Sat, Filter);
    03185     notempty = 1;
    03186     if (Filter && emptyQ(Pol)) {
    03187       notempty = 0;
    03188       FindSimple(Pol1, Pol2, Filter, NbMaxRays);
    03189     }
    03190     /* Polyhedron_Print(stderr,"%4d",Pol1); */
    03191
    03192     Polyhedron_Free(Pol), Pol = NULL;
    03193     SMFree(&Sat), Sat = NULL;
    03194     Matrix_Free(Ray), Ray = NULL;
    03195     Matrix_Free(Mat), Mat = NULL;
    03196
    03197   } /* end of TRY */
    03198
    03199   UNCATCH(any_exception_error);
    03200   return notempty;
    03201 } /* SimplifyConstraints */
    03202
    03203 /*
    03204  * Eliminate equations of Pol1 using equations of Pol2. Mark as needed,
    03205  * equations of Pol1 that are not eliminated. Or info into Filter vector.
    03206  */
    03207 static void SimplifyEqualities(Polyhedron *Pol1, Polyhedron *Pol2, unsigned *Filter) {
    03208
    03209   int i,j;
    03210   unsigned ix, bx, NbEqn, NbEqn1, NbEqn2, NbEle2, Dimension;
    03211   Matrix   *Mat;
    03212
    03213   NbEqn1        = Pol1->NbEq;
    03214   NbEqn2        = Pol2->NbEq;
    03215   NbEqn         = NbEqn1 + NbEqn2;
    03216   Dimension     = Pol1->Dimension+2;    /* Homogeneous Dimension + Status */
    03217   NbEle2        = NbEqn2*Dimension;
    03218
    03219   Mat = Matrix_Alloc(NbEqn, Dimension);
    03220   if (!Mat) {
    03221     errormsg1("SimplifyEqualities", "outofmem", "out of memory space");
    03222     Pol_status = 1;
    03223     return;
    03224   }
    03225
    03226   /* Set the equalities of Pol2 */
    03227   Vector_Copy(Pol2->Constraint[0], Mat->p_Init, NbEle2);
    03228
    03229   /* Add the equalities of Pol1 */
    03230   Vector_Copy(Pol1->Constraint[0], Mat->p_Init+NbEle2, NbEqn1*Dimension);
    03231
    03232   Gauss(Mat, NbEqn2, Dimension-1);
    03233
    03234   ix = 0;
    03235   bx = MSB;
    03236   for (i=NbEqn2; i<NbEqn; i++) {
    03237     for (j=1; j<Dimension; j++) {
    03238       if (value_notzero_p(Mat->p[i][j])) {
    03239         /* If any coefficient of the equation is non-zero */
    03240         /* Set the filter bit for the equation */
    03241
    03242         Filter[ix] |= bx;
    03243         break;
    03244       }
    03245     }
    03246     NEXT(ix,bx);
    03247   }
    03248   Matrix_Free(Mat);
    03249   return;
    03250 } /* SimplifyEqualities */
    03251
    03252
    03253 /*
    03254  * Given two polyhedral domains 'Pol1' and 'Pol2', find the largest domain
    03255  * set (or the smallest list of non-redundant constraints), that when
    03256  * intersected with polyhedral domain 'Pol2' equals (Pol1)intersect(Pol2).
    03257  * The output is a polyhedral domain with the "redundant" constraints removed.
    03258  * 'NbMaxRays' is the maximium allowed rays in the new polyhedra.
    03259  */
    03260 Polyhedron *DomainSimplify(Polyhedron *Pol1, Polyhedron *Pol2, unsigned NbMaxRays) {
    03261
    03262   Polyhedron *p1, *p2, *p3, *d;
    03263   unsigned k, jx, bx, nbentries, NbConstraints, Dimension, NbCon, empty;
    03264   unsigned *Filter;
    03265   Matrix *Constraints;
    03266
    03267
    03268   if (!Pol1 || !Pol2) return Pol1;
    03269   if (Pol1->Dimension != Pol2->Dimension) {
    03270     errormsg1("DomSimplify","diffdim","operation on different dimensions");
    03271     Pol_status = 1;
    03272     return 0;
    03273   }
    03274   POL_ENSURE_VERTICES(Pol1);
    03275   POL_ENSURE_VERTICES(Pol2);
    03276   if (emptyQ(Pol1)||emptyQ(Pol2))
    03277     return Empty_Polyhedron(Pol1->Dimension);
    03278
    03279   /* Find the maximum number of constraints over all polyhedron in the  */
    03280   /* polyhedral domain 'Pol2' and store in 'NbCon'.                     */
    03281   NbCon = 0;
    03282   for (p2=Pol2; p2; p2=p2->next)
    03283     if (p2->NbConstraints > NbCon)
    03284       NbCon = p2->NbConstraints;
    03285
    03286   Dimension = Pol1->Dimension+2;     /* Homogenous Dimension + Status  */
    03287   d = (Polyhedron *)0;
    03288   for (p1=Pol1; p1; p1=p1->next) {
    03289
    03290     POL_ENSURE_VERTICES(p1);
    03291
    03292     /* Filter is an array of integers, each bit in an element of Filter */
    03293     /* array corresponds to a constraint. The bit is marked 1 if the    */
    03294     /* corresponding constraint is non-redundant and is 0 if it is      */
    03295     /* redundant.                                                       */
    03296
    03297     NbConstraints = p1->NbConstraints;
    03298     nbentries = (NbConstraints + NbCon - 1) / (sizeof(int)*8) + 1;
    03299
    03300     /* Allocate space for array 'Filter' */
    03301     Filter  = (unsigned *)malloc(nbentries * sizeof(int));
    03302     if (!Filter) {
    03303       errormsg1("DomSimplify", "outofmem", "out of memory space\n");
    03304       Pol_status = 1;
    03305       return 0;
    03306     }
    03307
    03308     /* Initialize 'Filter' with zeros */
    03309     SMVector_Init(Filter, nbentries);
    03310
    03311     /* Filter the constraints of p1 in context of polyhedra p2(s) */
    03312     empty = 1;
    03313     for (p2=Pol2; p2; p2=p2->next) {
    03314
    03315       POL_ENSURE_VERTICES(p2);
    03316
    03317       /* Store the non-redundant constraints in array 'Filter'. With    */
    03318       /* successive loops, the array 'Filter' holds the union of all    */
    03319       /* non-redundant constraints. 'empty' is set to zero if the       */
    03320       /* intersection of two polyhedra is non-empty and Filter is !Null */
    03321
    03322       SimplifyEqualities(p1, p2, Filter);
    03323       if (SimplifyConstraints(p1, p2, Filter, NbMaxRays))
    03324         empty=0;
    03325
    03326       /* takes the union of all non redundant constraints */
    03327     }
    03328
    03329     if (!empty) {
    03330
    03331       /* Copy all non-redundant constraints to matrix 'Constraints' */
    03332       Constraints = Matrix_Alloc(NbConstraints, Dimension);
    03333       if (!Constraints) {
    03334         errormsg1("DomSimplify", "outofmem", "out of memory space\n");
    03335         Pol_status = 1;
    03336         return 0;
    03337       }
    03338       Constraints->NbRows = 0;
    03339       for (k=0, jx=0, bx=MSB; k<NbConstraints; k++) {
    03340
    03341         /* If a bit entry in Filter[jx] is marked 1, copy the correspond- */
    03342         /* ing constraint in matrix 'Constraints'.                        */
    03343         if (Filter[jx]&bx) {
    03344           Vector_Copy(p1->Constraint[k],
    03345                       Constraints->p[Constraints->NbRows],
    03346                       Dimension);
    03347           Constraints->NbRows++;
    03348         }
    03349         NEXT(jx,bx);
    03350       }
    03351
    03352       /* Create the polyhedron 'p3' corresponding to the constraints in   */
    03353       /* matrix 'Constraints'.                                            */
    03354       p3 = Constraints2Polyhedron(Constraints,NbMaxRays);
    03355       Matrix_Free(Constraints);
    03356
    03357       /* Add polyhedron 'p3' in the domain 'd'. */
    03358       d = AddPolyToDomain (p3, d);
    03359       p3 = NULL;
    03360     }
    03361     free(Filter);
    03362   }
    03363   if (!d)
    03364     return Empty_Polyhedron(Pol1->Dimension);
    03365   else return d;
    03366
    03367 } /* DomainSimplify */
    03368
    03369 /*
    03370  * Domain Simplify as defined in Strasborg Polylib version.
    03371  */
    03372 Polyhedron *Stras_DomainSimplify(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
    03373
    03374   Polyhedron *p1, *p2, *p3 = NULL, *d = NULL;
    03375   unsigned k, jx, bx, nbentries, NbConstraints, Dimension, NbCon, empty;
    03376   unsigned  *Filter = NULL;
    03377   Matrix *Constraints = NULL;
    03378
    03379   CATCH(any_exception_error) {
    03380     if (Constraints) Matrix_Free(Constraints);
    03381     if (Filter) free(Filter);
    03382     if (d) Polyhedron_Free(d);
    03383     if (p2) Polyhedron_Free(p3);
    03384     RETHROW();
    03385   }
    03386   TRY {
    03387     if (!Pol1 || !Pol2) {
    03388       UNCATCH(any_exception_error);
    03389       return Pol1;
    03390     }
    03391     if (Pol1->Dimension != Pol2->Dimension) {
    03392       errormsg1("DomainSimplify","diffdim","operation on different dimensions");
    03393       UNCATCH(any_exception_error);
    03394       return 0;
    03395     }
    03396     POL_ENSURE_VERTICES(Pol1);
    03397     POL_ENSURE_VERTICES(Pol2);
    03398     if (emptyQ(Pol1)||emptyQ(Pol2)) {
    03399       UNCATCH(any_exception_error);
    03400       return Empty_Polyhedron(Pol1->Dimension);
    03401     }
    03402
    03403     /* Find the maximum number of constraints over all polyhedron in the  */
    03404     /* polyhedral domain 'Pol2' and store in 'NbCon'.                     */
    03405     NbCon = 0;
    03406     for (p2=Pol2; p2; p2=p2->next)
    03407       if (p2->NbConstraints > NbCon)
    03408         NbCon = p2->NbConstraints;
    03409
    03410     Dimension = Pol1->Dimension+2;      /* Homogenous Dimension + Status  */
    03411     d = (Polyhedron *)0;
    03412     for (p1=Pol1; p1; p1=p1->next) {
    03413
    03414       /* Filter is an array of integers, each bit in an element of Filter */
    03415       /* array corresponds to a constraint. The bit is marked 1 if the    */
    03416       /* corresponding constraint is non-redundant and is 0 if it is      */
    03417       /* redundant.                                                       */
    03418
    03419       NbConstraints = p1->NbConstraints;
    03420       nbentries = (NbConstraints + NbCon - 1)/(sizeof(int)*8) + 1;
    03421
    03422       /* Allocate space for array 'Filter' */
    03423       Filter  = (unsigned *)malloc(nbentries * sizeof(int));
    03424       if(!Filter) {
    03425         errormsg1("DomainSimplify", "outofmem", "out of memory space");
    03426         UNCATCH(any_exception_error);
    03427         return 0;
    03428       }
    03429
    03430       /* Initialize 'Filter' with zeros */
    03431       SMVector_Init(Filter, nbentries);
    03432
    03433       /* Filter the constraints of p1 in context to the polyhedra p2(s)   */
    03434       empty = 1;
    03435       for (p2=Pol2; p2; p2=p2->next) {
    03436
    03437         /* Store the non-redundant constraints in array 'Filter'. With    */
    03438         /* successive loops, the array 'Filter' holds the union of all    */
    03439         /* non-redundant constraints. 'empty' is set to zero if the       */
    03440         /* intersection of two polyhedra is non-empty and Filter is !Null */
    03441
    03442         if (SimplifyConstraints(p1, p2, Filter, NbMaxRays))
    03443           empty=0;
    03444       }
    03445
    03446       if (!empty) {
    03447
    03448         /* Copy all non-redundant constraints to matrix 'Constraints' */
    03449         Constraints = Matrix_Alloc(NbConstraints,Dimension);
    03450         if(!Constraints) {
    03451           errormsg1("DomainSimplify", "outofmem", "out of memory space");
    03452           UNCATCH(any_exception_error);
    03453           return 0;
    03454         }
    03455         Constraints->NbRows = 0;
    03456         for (k=0, jx=0, bx=MSB; k<NbConstraints; k++) {
    03457
    03458           /* If a bit entry in Filter[jx] is marked 1, copy the correspond- */
    03459           /* ing constraint in matrix 'Constraints'.                        */
    03460           if (Filter[jx]&bx) {
    03461             Vector_Copy(p1->Constraint[k],
    03462                         Constraints->p[Constraints->NbRows],
    03463                         Dimension);
    03464             Constraints->NbRows++;
    03465           }
    03466           NEXT(jx,bx);
    03467         }
    03468
    03469         /* Create the polyhedron 'p3' corresponding to the constraints in   */
    03470         /* matrix 'Constraints'.                                            */
    03471         p3 = Constraints2Polyhedron(Constraints,NbMaxRays);
    03472         Matrix_Free(Constraints), Constraints = NULL;
    03473
    03474         /* Add polyhedron 'p3' in the domain 'd'. */
    03475         d = AddPolyToDomain (p3, d);
    03476         p3 = NULL;
    03477       }
    03478       free(Filter), Filter = NULL;
    03479     }
    03480   } /* end of TRY */
    03481
    03482   UNCATCH(any_exception_error);
    03483   if (!d)
    03484     return Empty_Polyhedron(Pol1->Dimension);
    03485   else
    03486     return d;
    03487 } /* DomainSimplify */
    03488
    03489 /*
    03490  * Return the Union of two polyhedral domains 'Pol1' and Pol2'. The result is
    03491  * a new polyhedral domain.
    03492  */
    03493 Polyhedron *DomainUnion(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
    03494
    03495   Polyhedron *PolA, *PolEndA, *PolB, *PolEndB, *p1, *p2;
    03496   int Redundant;
    03497
    03498   if (!Pol1 || !Pol2) return (Polyhedron *) 0;
    03499   if (Pol1->Dimension != Pol2->Dimension) {
    03500     errormsg1("DomainUnion","diffdim","operation on different dimensions");
    03501     return (Polyhedron*) 0;
    03502   }
    03503
    03504
    03505
    03506
    03507
    03508
    03509   /* Copy 'Pol1' to 'PolA' */
    03510   PolA = PolEndA = (Polyhedron *)0;
    03511   for (p1=Pol1; p1; p1=p1->next) {
    03512
    03513     /* Does any component of 'Pol2' cover 'p1' ? */
    03514     Redundant = 0;
    03515     for (p2=Pol2; p2; p2=p2->next) {
    03516       if (PolyhedronIncludes(p2, p1) ) { /* p2 covers p1 */
    03517         Redundant = 1;
    03518
    03519
    03520         break;
    03521
    03522       }
    03523     }
    03524     if (!Redundant) {
    03525
    03526       /* Add 'p1' to 'PolA' */
    03527       if (!PolEndA)
    03528         PolEndA = PolA = Polyhedron_Copy(p1);
    03529       else {
    03530         PolEndA->next = Polyhedron_Copy(p1);
    03531         PolEndA = PolEndA->next;
    03532       }
    03533
    03534     }
    03535   }
    03536
    03537   /* Copy 'Pol2' to PolB */
    03538   PolB = PolEndB = (Polyhedron *)0;
    03539   for (p2=Pol2; p2; p2=p2->next) {
    03540
    03541     /* Does any component of PolA cover 'p2' ? */
    03542     Redundant = 0;
    03543     for (p1=PolA; p1; p1=p1->next) {
    03544       if (PolyhedronIncludes(p1, p2)) { /* p1 covers p2 */
    03545         Redundant = 1;
    03546         break;
    03547       }
    03548     }
    03549     if (!Redundant) {
    03550
    03551       /* Add 'p2' to 'PolB' */
    03552       if (!PolEndB)
    03553         PolEndB = PolB = Polyhedron_Copy(p2);
    03554       else {
    03555         PolEndB->next = Polyhedron_Copy(p2);
    03556         PolEndB = PolEndB->next;
    03557       }
    03558
    03559
    03560     }
    03561   }
    03562
    03563   if (!PolA) return PolB;
    03564   PolEndA->next = PolB;
    03565   return PolA;
    03566 } /* DomainUnion */
    03567
    03568 /*
    03569  * Given a polyhedral domain 'Pol', concatenate the lists of rays and lines
    03570  * of the two (or more) polyhedra in the domain into one combined list, and
    03571  * find the set of constraints which tightly bound all of those objects.
    03572  * 'NbMaxConstrs' is the maximum allowed constraints in the new polyhedron.
    03573  */
    03574 Polyhedron *DomainConvex(Polyhedron *Pol,unsigned NbMaxConstrs) {
    03575
    03576   Polyhedron *p, *q, *NewPol = NULL;
    03577
    03578   CATCH(any_exception_error) {
    03579     if (NewPol) Polyhedron_Free(NewPol);
    03580     RETHROW();
    03581   }
    03582   TRY {
    03583
    03584     if (!Pol) {
    03585       UNCATCH(any_exception_error);
    03586       return (Polyhedron*) 0;
    03587     }
    03588
    03589     POL_ENSURE_VERTICES(Pol);
    03590     NewPol = Polyhedron_Copy(Pol);
    03591     for (p=Pol->next; p; p=p->next) {
    03592       POL_ENSURE_VERTICES(p);
    03593       q = AddRays(p->Ray[0], p->NbRays, NewPol, NbMaxConstrs);
    03594       Polyhedron_Free(NewPol);
    03595       NewPol = q;
    03596     }
    03597   } /* end of TRY */
    03598
    03599   UNCATCH(any_exception_error);
    03600
    03601   return NewPol;
    03602 } /* DomainConvex */
    03603
    03604 /*
    03605  * Given polyhedral domains 'Pol1' and 'Pol2', create a new polyhedral
    03606  * domain which is mathematically the differnce of the two domains.
    03607  */
    03608 Polyhedron *DomainDifference(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
    03609
    03610   Polyhedron *p1, *p2, *p3, *d;
    03611   int i;
    03612
    03613   if (!Pol1 || !Pol2) return (Polyhedron*) 0;
    03614   if (Pol1->Dimension != Pol2->Dimension) {
    03615     errormsg1("DomainDifference",
    03616               "diffdim", "operation on different dimensions");
    03617     return (Polyhedron*) 0;
    03618   }
    03619   POL_ENSURE_FACETS(Pol1);
    03620   POL_ENSURE_VERTICES(Pol1);
    03621   POL_ENSURE_FACETS(Pol2);
    03622   POL_ENSURE_VERTICES(Pol2);
    03623   if (emptyQ(Pol1) || emptyQ(Pol2))
    03624     return (Domain_Copy(Pol1));
    03625   d = (Polyhedron *)0;
    03626   for (p2=Pol2; p2; p2=p2->next) {
    03627     for (p1=Pol1; p1; p1=p1->next) {
    03628       for (i=0; i<p2->NbConstraints; i++) {
    03629
    03630         /* Add the constraint ( -p2->constraint[i] -1) >= 0 in 'p1' */
    03631         /* and create the new polyhedron 'p3'.                      */
    03632         p3 = SubConstraint(p2->Constraint[i], p1, NbMaxRays,0);
    03633
    03634         /* Add 'p3' in the new domain 'd' */
    03635         d = AddPolyToDomain (p3, d);
    03636
    03637         /* If the constraint p2->constraint[i][0] is an equality, then  */
    03638         /* add the constraint ( +p2->constraint[i] -1) >= 0  in 'p1' and*/
    03639         /* create the new polyhedron 'p3'.                              */
    03640
    03641         if( value_notzero_p(p2->Constraint[i][0]) ) /* Inequality */
    03642           continue;
    03643         p3 = SubConstraint(p2->Constraint[i], p1, NbMaxRays,1);
    03644
    03645         /* Add 'p3' in the new domain 'd' */
    03646         d = AddPolyToDomain (p3, d);
    03647       }
    03648     }
    03649     if (p2 != Pol2)
    03650         Domain_Free(Pol1);
    03651     Pol1 = d;
    03652     d = (Polyhedron *)0;
    03653   }
    03654   if (!Pol1)
    03655     return Empty_Polyhedron(Pol2->Dimension);
    03656   else
    03657     return Pol1;
    03658 } /* DomainDifference */
    03659
    03660 /*
    03661  * Given a polyhedral domain 'Pol', convert it to a new polyhedral domain
    03662  * with dimension expanded to 'align_dimension'. 'NbMaxRays' is the maximum
    03663  * allowed rays in the new polyhedra.
    03664  */
    03665 Polyhedron *align_context(Polyhedron *Pol,int align_dimension,int NbMaxRays) {
    03666
    03667   int i, j, k;
    03668   Polyhedron *p = NULL, **next, *result = NULL;
    03669   unsigned dim;
    03670
    03671   CATCH(any_exception_error) {
    03672     if (result) Polyhedron_Free(result);
    03673     RETHROW();
    03674   }
    03675   TRY {
    03676
    03677     if (!Pol) return Pol;
    03678     dim = Pol->Dimension;
    03679     if (align_dimension < Pol->Dimension) {
    03680       errormsg1("align_context", "diffdim", "context dimension exceeds data");
    03681       UNCATCH(any_exception_error);
    03682       return NULL;
    03683     }
    03684     if (align_dimension == Pol->Dimension) {
    03685       UNCATCH(any_exception_error);
    03686       return Domain_Copy(Pol);
    03687     }
    03688
    03689     /* 'k' is the dimension increment */
    03690     k = align_dimension - Pol->Dimension;
    03691     next = &result;
    03692
    03693     /* Expand the dimension of all polyhedra in the polyhedral domain 'Pol' */
    03694     for (; Pol; Pol=Pol->next) {
    03695       int have_cons = !F_ISSET(Pol, POL_VALID) || F_ISSET(Pol, POL_INEQUALITIES);
    03696       int have_rays = !F_ISSET(Pol, POL_VALID) || F_ISSET(Pol, POL_POINTS);
    03697       unsigned NbCons = have_cons ? Pol->NbConstraints : 0;
    03698       unsigned NbRays = have_rays ? Pol->NbRays + k : 0;
    03699
    03700       if (Pol->Dimension != dim) {
    03701         Domain_Free(result);
    03702         errormsg1("align_context", "diffdim", "context not of uniform dimension");
    03703         UNCATCH(any_exception_error);
    03704         return NULL;
    03705       }
    03706
    03707       p = Polyhedron_Alloc(align_dimension, NbCons, NbRays);
    03708       if (have_cons) {
    03709         for (i = 0; i < NbCons; ++i) {
    03710           value_assign(p->Constraint[i][0], Pol->Constraint[i][0]);  /* Status bit */
    03711           Vector_Copy(Pol->Constraint[i]+1, p->Constraint[i]+k+1, Pol->Dimension+1);
    03712         }
    03713         p->NbEq = Pol->NbEq;
    03714       }
    03715
    03716       if (have_rays) {
    03717         for (i = 0; i < k; ++i)
    03718           value_set_si(p->Ray[i][1+i], 1);                          /* A line */
    03719         for (i = 0; i < Pol->NbRays; ++i) {
    03720           value_assign(p->Ray[k+i][0], Pol->Ray[i][0]);             /* Status bit */
    03721           Vector_Copy(Pol->Ray[i]+1, p->Ray[i+k]+k+1, Pol->Dimension+1);
    03722         }
    03723         p->NbBid = Pol->NbBid + k;
    03724       }
    03725       p->flags = Pol->flags;
    03726
    03727       *next = p;
    03728       next = &p->next;
    03729     }
    03730   } /* end of TRY */
    03731
    03732   UNCATCH(any_exception_error);
    03733   return result;
    03734 } /* align_context */
    03735
    03736 /*----------------------------------------------------------------------*/
    03737 /* Polyhedron *Polyhedron_Scan(D, C, NbMaxRays)                         */
    03738 /*       D : Domain to be scanned (single polyhedron only)              */
    03739 /*       C : Context domain                                             */
    03740 /*       NbMaxRays : Workspace size                                     */
    03741 /* Returns a linked list of scan domains, outer loop first              */
    03742 /*----------------------------------------------------------------------*/
    03743 Polyhedron *Polyhedron_Scan(Polyhedron *D, Polyhedron *C,unsigned NbMaxRays) {
    03744
    03745   int i, j, dim ;
    03746   Matrix *Mat;
    03747   Polyhedron *C1, *C2, *D1, *D2;
    03748   Polyhedron *res, *last, *tmp;
    03749
    03750   dim = D->Dimension - C->Dimension;
    03751   res = last = (Polyhedron *) 0;
    03752   if (dim==0) return (Polyhedron *)0;
    03753
    03754   assert(!D->next);
    03755
    03756   POL_ENSURE_FACETS(D);
    03757   POL_ENSURE_VERTICES(D);
    03758   POL_ENSURE_FACETS(C);
    03759   POL_ENSURE_VERTICES(C);
    03760
    03761   /* Allocate space for constraint matrix. */
    03762   Mat   = Matrix_Alloc(D->Dimension, D->Dimension+2);
    03763   if(!Mat) {
    03764     errormsg1("Polyhedron_Scan", "outofmem", "out of memory space");
    03765     return 0;
    03766   }
    03767   C1  = align_context(C,D->Dimension,NbMaxRays);
    03768   if(!C1) {
    03769     return 0;
    03770   }
    03771   /* Vin100, aug 16, 2001:  The context is intersected with D */
    03772   D2 = DomainIntersection( C1, D, NbMaxRays);
    03773
    03774   for (i=0; i<dim; i++)
    03775   {
    03776     Vector_Set(Mat->p_Init,0,D2->Dimension*(D2->Dimension + 2));
    03777     for (j=i+1; j<dim; j++) {
    03778       value_set_si(Mat->p[j-i-1][j+1],1);
    03779     }
    03780     Mat->NbRows = dim-i-1;
    03781     D1 = Mat->NbRows ? DomainAddRays(D2, Mat, NbMaxRays) : D2;
    03782     tmp = DomainSimplify(D1, C1, NbMaxRays);
    03783     if (!last) res = last = tmp;
    03784     else { last->next = tmp; last = tmp; }
    03785     C2 = DomainIntersection(C1, D1, NbMaxRays);
    03786     Domain_Free(C1);
    03787     C1 = C2;
    03788     if (Mat->NbRows) Domain_Free(D1);
    03789   }
    03790   Domain_Free(D2);
    03791   Domain_Free(C1);
    03792   Matrix_Free(Mat);
    03793   return res;
    03794 } /* Polyhedron_Scan */
    03795
    03796 /*---------------------------------------------------------------------*/
    03797 /* int lower_upper_bounds(pos,P,context,LBp,UBp)                       */
    03798 /*    pos : index position of current loop index (1..hdim-1)           */
    03799 /*    P: loop domain                                                   */
    03800 /*    context : context values for fixed indices                       */
    03801 /*              notice that context[hdim] must be 1                    */
    03802 /*    LBp, UBp : pointers to resulting bounds                          */
    03803 /* returns the flag = (UB_INFINITY, LB_INFINITY)                       */
    03804 /*---------------------------------------------------------------------*/
    03805 int lower_upper_bounds(int pos,Polyhedron *P,Value *context,Value *LBp,Value *UBp) {
    03806
    03807   Value LB, UB;
    03808   int flag, i;
    03809   Value n, n1, d, tmp;
    03810
    03811   POL_ENSURE_FACETS(P);
    03812   POL_ENSURE_VERTICES(P);
    03813
    03814   /* Initialize all the 'Value' variables */
    03815   value_init(LB); value_init(UB); value_init(tmp);
    03816   value_init(n); value_init(n1); value_init(d);
    03817
    03818   value_set_si(LB,0);
    03819   value_set_si(UB,0);
    03820
    03821   /* Compute Upper Bound and Lower Bound for current loop */
    03822   flag = LB_INFINITY | UB_INFINITY;
    03823   for (i=0; i<P->NbConstraints; i++) {
    03824     value_assign(d,P->Constraint[i][pos]);
    03825     Inner_Product(&context[1],&(P->Constraint[i][1]),P->Dimension+1,&n);
    03826     if (value_zero_p(d)) {
    03827       /* If context doesn't satisfy constraints, return empty loop. */
    03828       if (value_neg_p(n) ||
    03829           (value_zero_p(P->Constraint[i][0]) && value_notzero_p(n)))
    03830         goto empty_loop;
    03831       continue;
    03832     }
    03833     value_oppose(n,n);
    03834
    03835     /*---------------------------------------------------*/
    03836     /* Compute n/d        n/d<0              n/d>0       */
    03837     /*---------------------------------------------------*/
    03838     /*  n%d == 0    floor   = n/d      floor   = n/d     */
    03839     /*              ceiling = n/d      ceiling = n/d     */
    03840     /*---------------------------------------------------*/
    03841     /*  n%d != 0    floor   = n/d - 1  floor   = n/d     */
    03842     /*              ceiling = n/d      ceiling = n/d + 1 */
    03843     /*---------------------------------------------------*/
    03844
    03845     /* Check to see if constraint is inequality */
    03846     /* if constraint is equality, both upper and lower bounds are fixed */
    03847     if(value_zero_p(P->Constraint[i][0])) {     /* Equality */
    03848       value_modulus(tmp,n,d);
    03849
    03850       /* if not integer, return 0; */
    03851       if (value_notzero_p(tmp))
    03852         goto empty_loop;
    03853
    03854       value_division(n1,n,d);
    03855
    03856       /* Upper and Lower bounds found */
    03857       if((flag&LB_INFINITY) || value_gt(n1,LB))
    03858         value_assign(LB,n1);
    03859       if((flag&UB_INFINITY) || value_lt(n1,UB))
    03860         value_assign(UB,n1);
    03861       flag = 0;
    03862     }
    03863
    03864     if (value_pos_p(d)) {  /* Lower Bound */
    03865       value_modulus(tmp,n,d);
    03866
    03867       /* n1 = ceiling(n/d) */
    03868       if (value_pos_p(n) && value_notzero_p(tmp)) {
    03869         value_division(n1,n,d);
    03870         value_add_int(n1,n1,1);
    03871       }
    03872       else
    03873         value_division(n1,n,d);
    03874       if (flag&LB_INFINITY) {
    03875         value_assign(LB,n1);
    03876         flag^=LB_INFINITY;
    03877       }
    03878       else if(value_gt(n1,LB))
    03879         value_assign(LB,n1);
    03880     }
    03881
    03882     if (value_neg_p(d)) {   /* Upper Bound */
    03883       value_modulus(tmp,n,d);
    03884
    03885       /* n1 = floor(n/d) */
    03886       if (value_pos_p(n) && value_notzero_p(tmp)) {
    03887         value_division(n1,n,d);
    03888         value_sub_int(n1,n1,1);
    03889       }
    03890       else
    03891         value_division(n1,n,d);
    03892
    03893       if (flag&UB_INFINITY) {
    03894         value_assign(UB,n1);
    03895         flag^=UB_INFINITY;
    03896       }
    03897       else if (value_lt(n1,UB))
    03898         value_assign(UB, n1);
    03899     }
    03900   }
    03901   if ((flag & LB_INFINITY)==0) value_assign(*LBp,LB);
    03902   if ((flag & UB_INFINITY)==0) value_assign(*UBp,UB);
    03903
    03904   if (0) {
    03905 empty_loop:
    03906     flag = 0;
    03907     value_set_si(*LBp, 1);
    03908     value_set_si(*UBp, 0);      /* empty loop */
    03909   }
    03910
    03911   /* Clear all the 'Value' variables */
    03912   value_clear(LB); value_clear(UB); value_clear(tmp);
    03913   value_clear(n); value_clear(n1); value_clear(d);
    03914   return flag;
    03915 } /* lower_upper_bounds */
    03916
    03917 /*
    03918  *  C = A x B
    03919  */
    03920 static void Rays_Mult(Value **A, Matrix *B, Value **C, unsigned NbRays)
    03921 {
    03922   int i, j, k;
    03923   unsigned Dimension1, Dimension2;
    03924   Value Sum, tmp;
    03925
    03926   value_init(Sum); value_init(tmp);
    03927
    03928   CATCH(any_exception_error) {
    03929     value_clear(Sum); value_clear(tmp);
    03930     RETHROW();
    03931   }
    03932   TRY {
    03933     Dimension1 = B->NbRows;
    03934     Dimension2 = B->NbColumns;
    03935
    03936     for (i=0; i<NbRays; i++) {
    03937       value_assign(C[i][0],A[i][0]);
    03938       for (j=0; j<Dimension2; j++) {
    03939         value_set_si(Sum,0);
    03940         for (k=0; k<Dimension1; k++) {
    03941
    03942           /* Sum+=A[i][k+1] * B->p[k][j]; */
    03943           value_addmul(Sum, A[i][k+1], B->p[k][j]);
    03944         }
    03945         value_assign(C[i][j+1],Sum);
    03946       }
    03947       Vector_Gcd(C[i]+1, Dimension2, &tmp);
    03948       if (value_notone_p(tmp))
    03949           Vector_AntiScale(C[i]+1, C[i]+1, tmp, Dimension2);
    03950     }
    03951   }
    03952   UNCATCH(any_exception_error);
    03953   value_clear(Sum); value_clear(tmp);
    03954 }
    03955
    03956 /*
    03957  *  C = A x B^T
    03958  */
    03959 static void Rays_Mult_Transpose(Value **A, Matrix *B, Value **C,
    03960                                 unsigned NbRays)
    03961 {
    03962   int i, j, k;
    03963   unsigned Dimension1, Dimension2;
    03964   Value Sum, tmp;
    03965
    03966   value_init(Sum); value_init(tmp);
    03967
    03968   CATCH(any_exception_error) {
    03969     value_clear(Sum); value_clear(tmp);
    03970     RETHROW();
    03971   }
    03972   TRY {
    03973     Dimension1 = B->NbColumns;
    03974     Dimension2 = B->NbRows;
    03975
    03976     for (i=0; i<NbRays; i++) {
    03977       value_assign(C[i][0],A[i][0]);
    03978       for (j=0; j<Dimension2; j++) {
    03979         value_set_si(Sum,0);
    03980         for (k=0; k<Dimension1; k++) {
    03981
    03982           /* Sum+=A[i][k+1] * B->p[j][k]; */
    03983           value_addmul(Sum, A[i][k+1], B->p[j][k]);
    03984         }
    03985         value_assign(C[i][j+1],Sum);
    03986       }
    03987       Vector_Gcd(C[i]+1, Dimension2, &tmp);
    03988       if (value_notone_p(tmp))
    03989           Vector_AntiScale(C[i]+1, C[i]+1, tmp, Dimension2);
    03990     }
    03991   }
    03992   UNCATCH(any_exception_error);
    03993   value_clear(Sum); value_clear(tmp);
    03994 }
    03995
    03996 /*
    03997  * Given a polyhedron 'Pol' and a transformation matrix 'Func', return the
    03998  * polyhedron which when transformed by mapping function 'Func' gives 'Pol'.
    03999  * 'NbMaxRays' is the maximum number of rays that can be in the ray matrix
    04000  * of the resulting polyhedron.
    04001  */
    04002 Polyhedron *Polyhedron_Preimage(Polyhedron *Pol,Matrix *Func,unsigned NbMaxRays) {
    04003
    04004   Matrix *Constraints = NULL;
    04005   Polyhedron *NewPol = NULL;
    04006   unsigned NbConstraints, Dimension1, Dimension2;
    04007
    04008   POL_ENSURE_INEQUALITIES(Pol);
    04009
    04010   CATCH(any_exception_error) {
    04011     if (Constraints) Matrix_Free(Constraints);
    04012     if (NewPol) Polyhedron_Free(NewPol);
    04013     RETHROW();
    04014   }
    04015   TRY {
    04016
    04017     NbConstraints = Pol->NbConstraints;
    04018     Dimension1    = Pol->Dimension+1;   /* Homogeneous Dimension */
    04019     Dimension2    = Func->NbColumns;    /* Homogeneous Dimension */
    04020     if (Dimension1!=(Func->NbRows)) {
    04021       errormsg1("Polyhedron_Preimage", "dimincomp", "incompatable dimensions");
    04022       UNCATCH(any_exception_error);
    04023       return Empty_Polyhedron(Dimension2-1);
    04024     }
    04025
    04026     /*            Dim1           Dim2            Dim2
    04027                   __k__          __j__           __j__
    04028             NbCon |   |  X   Dim1|   |  =  NbCon |   |
    04029               i   |___|       k  |___|       i   |___|
    04030             Pol->Constraints Function        Constraints
    04031     */
    04032
    04033     /* Allocate space for the resulting constraint matrix */
    04034     Constraints = Matrix_Alloc(NbConstraints, Dimension2+1);
    04035     if (!Constraints) {
    04036       errormsg1("Polyhedron_Preimage", "outofmem", "out of memory space\n");
    04037       Pol_status = 1;
    04038       UNCATCH(any_exception_error);
    04039       return 0;
    04040     }
    04041
    04042     /* The new constraint matrix is the product of constraint matrix of the */
    04043     /* polyhedron and the function matrix.                                  */
    04044     Rays_Mult(Pol->Constraint, Func, Constraints->p, NbConstraints);
    04045     NewPol = Constraints2Polyhedron(Constraints, NbMaxRays);
    04046     Matrix_Free(Constraints), Constraints = NULL;
    04047
    04048   } /* end of TRY */
    04049
    04050   UNCATCH(any_exception_error);
    04051
    04052   return NewPol;
    04053 } /* Polyhedron_Preimage */
    04054
    04055 /*
    04056  * Given a polyhedral domain 'Pol' and a transformation matrix 'Func', return
    04057  * the polyhedral domain which when transformed by mapping function 'Func'
    04058  * gives 'Pol'. 'NbMaxRays' is the maximum number of rays that can be in the
    04059  * ray matrix of the resulting domain.
    04060  */
    04061 Polyhedron *DomainPreimage(Polyhedron *Pol,Matrix *Func,unsigned NbMaxRays) {
    04062
    04063   Polyhedron *p, *q, *d = NULL;
    04064
    04065   CATCH(any_exception_error) {
    04066     if (d) Polyhedron_Free(d);
    04067     RETHROW();
    04068   }
    04069   TRY {
    04070     if (!Pol || !Func) {
    04071       UNCATCH(any_exception_error);
    04072       return (Polyhedron *) 0;
    04073     }
    04074     d = (Polyhedron *) 0;
    04075     for (p=Pol; p; p=p->next) {
    04076       q = Polyhedron_Preimage(p, Func, NbMaxRays);
    04077       d = AddPolyToDomain (q, d);
    04078     }
    04079   } /* end of TRY */
    04080   UNCATCH(any_exception_error);
    04081   return d;
    04082 } /* DomainPreimage */
    04083
    04084 /*
    04085  * Transform a polyhedron 'Pol' into another polyhedron according to a given
    04086  * affine mapping function 'Func'. 'NbMaxConstrs' is the maximum number of
    04087  * constraints that can be in the constraint matrix of the new polyhedron.
    04088  */
    04089 Polyhedron *Polyhedron_Image(Polyhedron *Pol, Matrix *Func,unsigned NbMaxConstrs) {
    04090
    04091   Matrix *Rays = NULL;
    04092   Polyhedron *NewPol = NULL;
    04093   unsigned NbRays, Dimension1, Dimension2;
    04094
    04095   POL_ENSURE_FACETS(Pol);
    04096   POL_ENSURE_VERTICES(Pol);
    04097
    04098   CATCH(any_exception_error) {
    04099     if (Rays) Matrix_Free(Rays);
    04100     if (NewPol) Polyhedron_Free(NewPol);
    04101     RETHROW();
    04102   }
    04103   TRY {
    04104
    04105     NbRays     = Pol->NbRays;
    04106     Dimension1 = Pol->Dimension+1;      /* Homogeneous Dimension */
    04107     Dimension2 = Func->NbRows;          /* Homogeneous Dimension */
    04108     if (Dimension1!=Func->NbColumns) {
    04109       errormsg1("Polyhedron_Image", "dimincomp", "incompatible dimensions");
    04110       UNCATCH(any_exception_error);
    04111       return Empty_Polyhedron(Dimension2-1);
    04112     }
    04113
    04114     /*
    04115         Dim1     /      Dim1  \Transpose      Dim2
    04116         __k__    |      __k__ |              __j__
    04117   NbRays|   |  X | Dim2 |   | |     =  NbRays|   |
    04118     i   |___|    |   j  |___| |          i   |___|
    04119      Pol->Rays  \       Func /               Rays
    04120
    04121     */
    04122
    04123     if (Dimension1 == Dimension2) {
    04124         Matrix *M, *M2;
    04125         int ok;
    04126         M = Matrix_Copy(Func);
    04127         M2 = Matrix_Alloc(Dimension2, Dimension1);
    04128         if (!M2) {
    04129           errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
    04130           UNCATCH(any_exception_error);
    04131           return 0;
    04132         }
    04133
    04134         ok = Matrix_Inverse(M, M2);
    04135         Matrix_Free(M);
    04136         if (ok) {
    04137             NewPol = Polyhedron_Alloc(Pol->Dimension, Pol->NbConstraints,
    04138                                       Pol->NbRays);
    04139             if (!NewPol) {
    04140               errormsg1("Polyhedron_Image", "outofmem",
    04141                         "out of memory space\n");
    04142               UNCATCH(any_exception_error);
    04143               return 0;
    04144             }
    04145             Rays_Mult_Transpose(Pol->Ray, Func, NewPol->Ray, NbRays);
    04146             Rays_Mult(Pol->Constraint, M2, NewPol->Constraint,
    04147                       Pol->NbConstraints);
    04148             NewPol->NbEq = Pol->NbEq;
    04149             NewPol->NbBid = Pol->NbBid;
    04150             if (NewPol->NbEq)
    04151               Gauss4(NewPol->Constraint, NewPol->NbEq, NewPol->NbConstraints,
    04152                      NewPol->Dimension+1);
    04153             if (NewPol->NbBid)
    04154               Gauss4(NewPol->Ray, NewPol->NbBid, NewPol->NbRays,
    04155                      NewPol->Dimension+1);
    04156         }
    04157         Matrix_Free(M2);
    04158     }
    04159
    04160     if (!NewPol) {
    04161         /* Allocate space for the resulting ray matrix */
    04162         Rays = Matrix_Alloc(NbRays, Dimension2+1);
    04163         if (!Rays) {
    04164           errormsg1("Polyhedron_Image", "outofmem", "out of memory space\n");
    04165           UNCATCH(any_exception_error);
    04166           return 0;
    04167         }
    04168
    04169         /* The new ray space is the product of ray matrix of the polyhedron and */
    04170         /* the transpose matrix of the mapping function.                        */
    04171         Rays_Mult_Transpose(Pol->Ray, Func, Rays->p, NbRays);
    04172         NewPol = Rays2Polyhedron(Rays, NbMaxConstrs);
    04173         Matrix_Free(Rays), Rays = NULL;
    04174     }
    04175
    04176   } /* end of TRY */
    04177
    04178   UNCATCH(any_exception_error);
    04179   return NewPol;
    04180 } /* Polyhedron_Image */
    04181
    04182 /*
    04183  *Transform a polyhedral domain 'Pol' into another domain according to a given
    04184  * affine mapping function 'Func'. 'NbMaxConstrs' is the maximum number of
    04185  * constraints that can be in the constraint matrix of the resulting domain.
    04186  */
    04187 Polyhedron *DomainImage(Polyhedron *Pol,Matrix *Func,unsigned NbMaxConstrs) {
    04188
    04189   Polyhedron *p, *q, *d = NULL;
    04190
    04191   CATCH(any_exception_error) {
    04192     if (d) Polyhedron_Free(d);
    04193     RETHROW();
    04194   }
    04195   TRY {
    04196
    04197     if (!Pol || !Func) {
    04198       UNCATCH(any_exception_error);
    04199       return (Polyhedron *) 0;
    04200     }
    04201     d = (Polyhedron *) 0;
    04202     for (p=Pol; p; p=p->next) {
    04203       q = Polyhedron_Image(p, Func, NbMaxConstrs);
    04204       d = AddPolyToDomain (q, d);
    04205     }
    04206   } /* end of TRY */
    04207
    04208   UNCATCH(any_exception_error);
    04209
    04210   return d;
    04211 } /* DomainImage */
    04212
    04213 /*
    04214  * Given a polyhedron 'Pol' and an affine cost function 'Cost', compute the
    04215  * maximum and minimum value of the function over set of points representing
    04216  * polyhedron.
    04217  * Note: If Polyhedron 'Pol' is empty, then there is no feasible solution.
    04218  * Otherwise, if there is a bidirectional ray with Sum[cost(i)*ray(i)] != 0 or
    04219  * a unidirectional ray with Sum[cost(i)*ray(i)] >0, then the maximum is un-
    04220  * bounded else the finite optimal solution occurs at one of the vertices of
    04221  * the polyhderon.
    04222  */
    04223 Interval *DomainCost(Polyhedron *Pol,Value *Cost) {
    04224
    04225   int i, j, NbRay, Dim;
    04226   Value *p1, *p2, p3, d, status;
    04227   Value tmp1, tmp2, tmp3;
    04228   Value **Ray;
    04229   Interval *I = NULL;
    04230
    04231   value_init(p3); value_init(d); value_init(status);
    04232   value_init(tmp1); value_init(tmp2); value_init(tmp3);
    04233
    04234   POL_ENSURE_FACETS(Pol);
    04235   POL_ENSURE_VERTICES(Pol);
    04236
    04237   CATCH(any_exception_error) {
    04238     if (I) free(I);
    04239     RETHROW();
    04240     value_clear(p3); value_clear(d); value_clear(status);
    04241     value_clear(tmp1); value_clear(tmp2); value_clear(tmp3);
    04242   }
    04243   TRY {
    04244
    04245     Ray = Pol->Ray;
    04246     NbRay = Pol->NbRays;
    04247     Dim = Pol->Dimension+1;             /* Homogenous Dimension */
    04248     I = (Interval *) malloc (sizeof(Interval));
    04249     if (!I) {
    04250       errormsg1("DomainCost", "outofmem", "out of memory space\n");
    04251       UNCATCH(any_exception_error);
    04252       value_clear(p3); value_clear(d); value_clear(status);
    04253       value_clear(tmp1); value_clear(tmp2); value_clear(tmp3);
    04254       return 0;
    04255     }
    04256
    04257     /* The maximum and minimum values of the cost function over polyhedral  */
    04258     /* domain is stored in 'I'. I->MaxN and I->MaxD store the numerator and */
    04259     /* denominator of the maximum value. Likewise,I->MinN and I->MinD store */
    04260     /* the numerator and denominator of the minimum value. I->MaxI and      */
    04261     /* I->MinI store the ray indices corresponding to the max and min values*/
    04262     /* of the function.                                                     */
    04263
    04264     value_set_si(I->MaxN,-1);
    04265     value_set_si(I->MaxD,0);          /* Actual cost is MaxN/MaxD */
    04266     I->MaxI = -1;
    04267     value_set_si(I->MinN,1);
    04268     value_set_si(I->MinD,0);
    04269     I->MinI = -1;
    04270
    04271     /* Compute the cost of each ray[i] */
    04272     for (i=0; i<NbRay; i++) {
    04273       p1 = Ray[i];
    04274       value_assign(status, *p1);
    04275       p1++;
    04276       p2 = Cost;
    04277
    04278       /* p3 = *p1++ * *p2++; */
    04279       value_multiply(p3,*p1,*p2);
    04280       p1++; p2++;
    04281       for (j=1; j<Dim; j++) {
    04282         value_multiply(tmp1,*p1,*p2);
    04283
    04284         /* p3 += *p1++ * *p2++; */
    04285         value_addto(p3,p3,tmp1);
    04286         p1++; p2++;
    04287       }
    04288
    04289       /* d = *--p1; */
    04290       p1--;
    04291       value_assign(d,*p1); /* d == 0 for lines and ray, non-zero for vertex */
    04292       value_multiply(tmp1,p3,I->MaxD);
    04293       value_multiply(tmp2,I->MaxN,d);
    04294       value_set_si(tmp3,1);
    04295
    04296       /* Compare p3/d with MaxN/MaxD to assign new maximum cost value */
    04297       if (I->MaxI==-1 ||
    04298           value_gt(tmp1,tmp2) ||
    04299           (value_eq(tmp1,tmp2) &&
    04300            value_eq(d,tmp3) && value_ne(I->MaxD,tmp3))) {
    04301         value_assign(I->MaxN,p3);
    04302         value_assign(I->MaxD,d);
    04303         I->MaxI = i;
    04304       }
    04305       value_multiply(tmp1,p3,I->MinD);
    04306       value_multiply(tmp2,I->MinN,d);
    04307       value_set_si(tmp3,1);
    04308
    04309       /* Compare p3/d with MinN/MinD to assign new minimum cost value */
    04310       if (I->MinI==-1 ||
    04311           value_lt(tmp1,tmp2) ||
    04312           (value_eq(tmp1,tmp2) &&
    04313            value_eq(d,tmp3) && value_ne(I->MinD,tmp3))) {
    04314         value_assign(I->MinN, p3);
    04315         value_assign(I->MinD, d);
    04316         I->MinI = i;
    04317       }
    04318       value_multiply(tmp1,p3,I->MaxD);
    04319       value_set_si(tmp2,0);
    04320
    04321       /* If there is a line, assign max to +infinity and min to -infinity */
    04322       if (value_zero_p(status)) { /* line , d is 0 */
    04323         if (value_lt(tmp1,tmp2)) {
    04324           value_oppose(I->MaxN,p3);
    04325           value_set_si(I->MaxD,0);
    04326           I->MaxI = i;
    04327         }
    04328         value_multiply(tmp1,p3,I->MinD);
    04329         value_set_si(tmp2,0);
    04330
    04331         if (value_gt(tmp1,tmp2)) {
    04332           value_oppose(I->MinN,p3);
    04333           value_set_si(I->MinD,0);
    04334           I->MinI = i;
    04335         }
    04336       }
    04337     }
    04338   } /* end of TRY */
    04339
    04340   UNCATCH(any_exception_error);
    04341   value_clear(p3); value_clear(d); value_clear(status);
    04342   value_clear(tmp1); value_clear(tmp2); value_clear(tmp3);
    04343   return I;
    04344 } /* DomainCost */
    04345
    04346 /*
    04347  * Add constraints pointed by 'Mat' to each and every polyhedron in the
    04348  * polyhedral domain 'Pol'. 'NbMaxRays' is maximum allowed rays in the ray
    04349  * matrix of a polyhedron.
    04350  */
    04351 Polyhedron *DomainAddConstraints(Polyhedron *Pol,Matrix *Mat,unsigned NbMaxRays) {
    04352
    04353   Polyhedron *PolA, *PolEndA, *p1, *p2, *p3;
    04354   int Redundant;
    04355
    04356   if (!Pol) return (Polyhedron*) 0;
    04357   if (!Mat) return Pol;
    04358   if (Pol->Dimension != Mat->NbColumns-2) {
    04359     errormsg1("DomainAddConstraints",
    04360               "diffdim", "operation on different dimensions");
    04361     return (Polyhedron*) 0;
    04362   }
    04363
    04364   /* Copy 'Pol' to 'PolA' */
    04365   PolA = PolEndA = (Polyhedron *)0;
    04366   for (p1=Pol; p1; p1=p1->next) {
    04367     p3 = AddConstraints(Mat->p_Init, Mat->NbRows, p1, NbMaxRays);
    04368
    04369     /* Does any component of 'PolA' cover 'p3' */
    04370     Redundant = 0;
    04371     for (p2=PolA; p2; p2=p2->next) {
    04372       if (PolyhedronIncludes(p2, p3)) { /* 'p2' covers 'p3' */
    04373         Redundant = 1;
    04374         break;
    04375       }
    04376     }
    04377
    04378     /* If the new polyhedron 'p3' is not redundant, add it to the domain */
    04379     if (Redundant)
    04380       Polyhedron_Free(p3);
    04381     else {
    04382       if (!PolEndA)
    04383         PolEndA = PolA = p3;
    04384       else {
    04385         PolEndA->next = p3;
    04386         PolEndA = PolEndA->next;
    04387       }
    04388     }
    04389   }
    04390   return PolA;
    04391 } /* DomainAddConstraints */
    04392
    04393
    04394 /*
    04395  * Computes the disjoint union of a union of polyhedra.
    04396  * If flag = 0 the result is such that there are no intersections
    04397  *                   between the resulting polyhedra,
    04398  * if flag = 1 it computes a joint union, the resulting polyhedra are
    04399  *                   adjacent (they have their facets in common).
    04400  *
    04401  * WARNING: if all polyhedra are not of same geometrical dimension
    04402  *          duplicates may appear.
    04403  */
    04404 Polyhedron *Disjoint_Domain( Polyhedron *P, int flag, unsigned NbMaxRays )
    04405 {
    04406         Polyhedron *lP, *tmp, *Result, *lR, *prec, *reste;
    04407         Polyhedron *p1, *p2, *p3, *Pol1, *dx, *d1, *d2, *pi, *newpi;
    04408         int i;
    04409
    04410         if( flag!=0 && flag!=1 )
    04411         {
    04412                 errormsg1("Disjoint_Domain",
    04413                         "invalidarg", "flag should be equal to 0 or 1");
    04414                 return (Polyhedron*) 0;
    04415         }
    04416         if(!P) return (Polyhedron*) 0;
    04417         if(!P->next) return Polyhedron_Copy(P);
    04418
    04419         Result = (Polyhedron *)0;
    04420
    04421         for(lP=P;lP;lP=lP->next)
    04422         {
    04423                 reste = Polyhedron_Copy(lP);
    04424                 prec = (Polyhedron *)0; /* preceeding lR */
    04425                 /* Intersection with each polyhedron of the current Result */
    04426                 lR=Result;
    04427                 while( lR && reste )
    04428                 {
    04429                         /* dx = DomainIntersection(reste,lR->P,WS); */
    04430                         dx = (Polyhedron *)0;
    04431                         for( p1=reste; p1; p1=p1->next )
    04432                         {
    04433                                 p3 = AddConstraints(lR->Constraint[0], lR->NbConstraints, p1,
    04434                                                 NbMaxRays);
    04435                                 dx = AddPolyToDomain(p3,dx);
    04436                         }
    04437
    04438                         /* if empty intersection, continue */
    04439                         if(!dx)
    04440                         {       prec = lR;
    04441                                 lR=lR->next;
    04442                                 continue;
    04443                         }
    04444                         if (emptyQ(dx)) {
    04445                                 Domain_Free(dx);
    04446                                 prec = lR;
    04447                                 lR=lR->next;
    04448                                 continue;
    04449                 }
    04450
    04451                         /* intersection is not empty, we need to compute the differences */
    04452                         /* between the intersection and the two polyhedra, such that the */
    04453                         /* results are disjoint unions (according to flag)               */
    04454                         /* d1 = reste \ P = DomainDifference(reste,lR->P,WS);   */
    04455                         /* d2 = P \ reste = DomainDifference(lR->P,reste,WS); */
    04456
    04457                         /* compute d1 */
    04458                         d1 = (Polyhedron *)0;
    04459                         for (p1=reste; p1; p1=p1->next)
    04460                         {
    04461                                 pi = p1;
    04462                                 for (i=0; i<P->NbConstraints && pi ; i++)
    04463                                 {
    04464
    04465                                         /* Add the constraint ( -P->constraint[i] [-1 if flag=0]) >= 0 in 'p1' */
    04466                                         /* and create the new polyhedron 'p3'.                      */
    04467                                         p3 = SubConstraint(P->Constraint[i], pi, NbMaxRays,2*flag);
    04468                                         /* Add 'p3' in the new domain 'd1' */
    04469                                         d1 = AddPolyToDomain (p3, d1);
    04470
    04471                                         /* If the constraint P->constraint[i][0] is an equality, then add   */
    04472                                         /* the constraint ( +P->constraint[i] [-1 if flag=0]) >= 0  in 'pi' */
    04473                                         /* and create the new polyhedron 'p3'.                              */
    04474                                         if( value_zero_p(P->Constraint[i][0]) ) /* Inequality */
    04475                                         {
    04476                                                 p3 = SubConstraint(P->Constraint[i], pi, NbMaxRays,1+2*flag);
    04477                                                 /* Add 'p3' in the new domain 'd1' */
    04478                                                 d1 = AddPolyToDomain (p3, d1);
    04479
    04480                                                 /* newpi : add constraint P->constraint[i]==0 to pi */
    04481                                                 newpi = AddConstraints( P->Constraint[i], 1, pi, NbMaxRays);
    04482                                         }
    04483                                         else
    04484                                         {
    04485                                                 /* newpi : add constraint +P->constraint[i] >= 0 in pi */
    04486                                                 newpi = SubConstraint(P->Constraint[i], pi, NbMaxRays,3);
    04487                                         }
    04488                                         if( newpi && emptyQ( newpi ) )
    04489                                         {
    04490                                                 Domain_Free( newpi );
    04491                                                 newpi = (Polyhedron *)0;
    04492                                         }
    04493                                         if( pi != p1 )
    04494                                                 Domain_Free( pi );
    04495                                         pi = newpi;
    04496                                 }
    04497                                 if( pi != p1 )
    04498                                         Domain_Free( pi );
    04499                         }
    04500
    04501                         /* and now d2 */
    04502                         Pol1 = Polyhedron_Copy( lR );
    04503                         for (p2=reste; p2; p2=p2->next)
    04504                         {
    04505                                 d2 = (Polyhedron *)0;
    04506                                 for (p1=Pol1; p1; p1=p1->next)
    04507                                 {
    04508                                         pi = p1;
    04509                                         for (i=0; i<p2->NbConstraints && pi ; i++)
    04510                                         {
    04511
    04512                                                 /* Add the constraint ( -p2->constraint[i] [-1 if flag=0]) >= 0 in 'pi' */
    04513                                                 /* and create the new polyhedron 'p3'.                      */
    04514                                                 p3 = SubConstraint(p2->Constraint[i], pi, NbMaxRays,2*flag);
    04515                                                 /* Add 'p3' in the new domain 'd2' */
    04516                                                 d2 = AddPolyToDomain (p3, d2);
    04517
    04518                                                 /* If the constraint p2->constraint[i][0] is an equality, then add   */
    04519                                                 /* the constraint ( +p2->constraint[i] [-1 if flag=0]) >= 0  in 'pi' */
    04520                                                 /* and create the new polyhedron 'p3'.                              */
    04521                                                 if( value_zero_p(p2->Constraint[i][0]) ) /* Inequality */
    04522                                                 {
    04523                                                         p3 = SubConstraint(p2->Constraint[i], pi, NbMaxRays,1+2*flag);
    04524                                                         /* Add 'p3' in the new domain 'd2' */
    04525                                                         d2 = AddPolyToDomain (p3, d2);
    04526
    04527                                                         /* newpi : add constraint p2->constraint[i]==0 to pi */
    04528                                                         newpi = AddConstraints( p2->Constraint[i], 1, pi, NbMaxRays);
    04529                                                 }
    04530                                                 else
    04531                                                 {
    04532                                                         /* newpi : add constraint +p2->constraint[i] >= 0 in pi */
    04533                                                         newpi = SubConstraint(p2->Constraint[i], pi, NbMaxRays,3);
    04534                                                 }
    04535                                                 if( newpi && emptyQ( newpi ) )
    04536                                                 {
    04537                                                         Domain_Free( newpi );
    04538                                                         newpi = (Polyhedron *)0;
    04539                                                 }
    04540                                                 if( pi != p1 )
    04541                                                         Domain_Free( pi );
    04542                                                 pi = newpi;
    04543                                         }
    04544                                         if( pi && pi!=p1 )
    04545                                                 Domain_Free( pi );
    04546                                 }
    04547                                 if( Pol1 )
    04548                                         Domain_Free( Pol1 );
    04549                                 Pol1 = d2;
    04550                         }
    04551                         /* ok, d1 and d2 are computed */
    04552
    04553                         /* now, replace lR by d2+dx (at least dx is nonempty) and set reste to d1 */
    04554                         if( d1 && emptyQ(d1) )
    04555                         {
    04556                                 Domain_Free( d1 );
    04557                                 d1 = NULL;
    04558                         }
    04559                         if( d2 && emptyQ(d2) )
    04560                         {
    04561                                 Domain_Free( d2 );
    04562                                 d2 = NULL;
    04563                         }
    04564
    04565                         /* set reste */
    04566                         Domain_Free( reste );
    04567                         reste = d1;
    04568
    04569                         /* add d2 at beginning of Result */
    04570                         if( d2 )
    04571                         {
    04572                                 for( tmp=d2 ; tmp->next ; tmp=tmp->next )
    04573                                                 ;
    04574                                 tmp->next = Result;
    04575                                 Result = d2;
    04576                                 if( !prec )
    04577                                         prec = tmp;
    04578                         }
    04579
    04580                         /* add dx at beginning of Result */
    04581                         for( tmp=dx ; tmp->next ; tmp=tmp->next )
    04582                                 ;
    04583                         tmp->next = Result;
    04584                         Result = dx;
    04585                         if( !prec )
    04586                                 prec = tmp;
    04587
    04588                         /* suppress current lR */
    04589                         if( !prec )
    04590                                 errormsg1( "Disjoint_Domain","internalerror","internal error");
    04591                         prec->next = lR->next;
    04592                         Polyhedron_Free( lR );
    04593                         lR = prec->next;
    04594                 } /* end for result */
    04595
    04596                   /* if there is something left, add it to Result : */
    04597                 if(reste)
    04598                 {
    04599                         if(emptyQ(reste))
    04600                         {
    04601                                 Domain_Free( reste );
    04602                                 reste = NULL;
    04603                         }
    04604                         else
    04605                         {
    04606                                 Polyhedron *tnext;
    04607                                 for( tmp=reste ; tmp ; tmp=tnext )
    04608                                 {
    04609                                         tnext = tmp->next;
    04610                                         tmp->next = NULL;
    04611                                         Result = AddPolyToDomain(tmp, Result);
    04612                                 }
    04613                 }
    04614                 }
    04615         }
    04616
    04617         return( Result );
    04618 }
    04619
    04620
    04621
    04622 /* Procedure to print constraint matrix of a polyhedron */
    04623 void Polyhedron_PrintConstraints(FILE *Dst, const char *Format, Polyhedron *Pol)
    04624 {
    04625         int i,j;
    04626
    04627         fprintf( Dst, "%d %d\n", Pol->NbConstraints, Pol->Dimension+2 );
    04628         for( i=0 ; i<Pol->NbConstraints ; i++ )
    04629         {
    04630                 for( j=0 ; j<Pol->Dimension+2 ; j++ )
    04631                         value_print( Dst, Format, Pol->Constraint[i][j] );
    04632                 fprintf( Dst, "\n" );
    04633         }
    04634
    04635 }
    04636
    04637 /* Procedure to print constraint matrix of a domain */
    04638 void Domain_PrintConstraints(FILE *Dst, const char *Format, Polyhedron *Pol)
    04639 {
    04640     Polyhedron *Q;
    04641     for (Q = Pol; Q; Q = Q->next)
    04642         Polyhedron_PrintConstraints(Dst, Format, Q);
    04643 }
    04644
    04645 static Polyhedron *p_simplify_constraints(Polyhedron *P, Vector *row,
    04646                                           Value *g, unsigned MaxRays)
    04647 {
    04648     Polyhedron *T, *R = P;
    04649     int len = P->Dimension+2;
    04650     int r;
    04651
    04652     /* Also look at equalities.
    04653      * If an equality can be "simplified" then there
    04654      * are no integer solutions and we return an empty polyhedron
    04655      */
    04656     for (r = 0; r < R->NbConstraints; ++r) {
    04657         if (ConstraintSimplify(R->Constraint[r], row->p, len, g)) {
    04658             T = R;
    04659             if (value_zero_p(R->Constraint[r][0])) {
    04660                 R = Empty_Polyhedron(R->Dimension);
    04661                 r = R->NbConstraints;
    04662             } else if (POL_ISSET(MaxRays, POL_NO_DUAL)) {
    04663                 R = Polyhedron_Copy(R);
    04664                 F_CLR(R, POL_FACETS | POL_VERTICES | POL_POINTS);
    04665                 Vector_Copy(row->p+1, R->Constraint[r]+1, R->Dimension+1);
    04666             } else {
    04667                 R = AddConstraints(row->p, 1, R, MaxRays);
    04668                 r = -1;
    04669             }
    04670             if (T != P)
    04671                 Polyhedron_Free(T);
    04672         }
    04673     }
    04674     if (R != P)
    04675         Polyhedron_Free(P);
    04676     return R;
    04677 }
    04678
    04679 /*
    04680  * Replaces constraint a x >= c by x >= ceil(c/a)
    04681  * where "a" is a common factor in the coefficients
    04682  * Destroys P and returns a newly allocated Polyhedron
    04683  * or just returns P in case no changes were made
    04684  */
    04685 Polyhedron *DomainConstraintSimplify(Polyhedron *P, unsigned MaxRays)
    04686 {
    04687     Polyhedron **prev;
    04688     int len = P->Dimension+2;
    04689     Vector *row = Vector_Alloc(len);
    04690     Value g;
    04691     Polyhedron *R = P, *N;
    04692     value_set_si(row->p[0], 1);
    04693     value_init(g);
    04694
    04695     for (prev = &R; P; P = N) {
    04696         Polyhedron *T;
    04697         N = P->next;
    04698         T = p_simplify_constraints(P, row, &g, MaxRays);
    04699
    04700         if (emptyQ(T) && prev != &R) {
    04701             Polyhedron_Free(T);
    04702             *prev = NULL;
    04703             continue;
    04704         }
    04705
    04706         if (T != P)
    04707             T->next = N;
    04708         *prev = T;
    04709         prev = &T->next;
    04710     }
    04711
    04712     if (R->next && emptyQ(R)) {
    04713         N = R->next;
    04714         Polyhedron_Free(R);
    04715         R = N;
    04716     }
    04717
    04718     value_clear(g);
    04719     Vector_Free(row);
    04720     return R;
    04721 }