polylib: polyhedron.c Source File

- Main Page
- Classes
- Files

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