Main Page   Compound List   File List   Compound Members   File Members  

polyhedron.c

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

Generated on Mon Mar 15 10:59:51 2004 for polylib by doxygen1.2.18