Main Page | Class List | File List | Class Members | File Members

polyparam.c

Go to the documentation of this file.
00001 /***********************************************************************/
00002 /*                Parametrized polyhedra V4.20                         */
00003 /*                copyright 1995-2000 Vincent Loechner                 */
00004 /*                copyright 1996-1997, Doran Wilde                     */
00005 /*       Permission is granted to copy, use, and distribute            */
00006 /*       for any commercial or noncommercial purpose under the terms   */
00007 /*       of the GNU General Public license, version 2, June 1991       */
00008 /*       (see file : LICENSING).                                       */
00009 /***********************************************************************/
00010 
00011 /********************* -----------USER #DEFS-------- ***********************/
00012 /* These are mainly for debug purposes. You shouldn't need to change       */
00013 /* anything for daily usage...                                             */
00014 /***************************************************************************/
00015 
00016 /* you may define each macro independently */
00017 /* #define DEBUGPP      */
00018 /* #define DEBUGPP3     */              /* initialization of domain, context, ... */
00019 /* #define DEBUGPP31    */              /* even more init-domains */
00020 /* #define DEBUGPP32    */              /* even even more... (Elim_Columns) */
00021 /* #define DEBUGPP4     */              /* m-faces scan */
00022 /* #define DEBUGPP41    */              /* inverse Di in scan */
00023 /* #define DEBUGPP5     */              /* Compute_PDomains */
00024 /********************* ---------END USER #DEFS------ ***********************/
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <assert.h>
00030 #ifdef DEBUGPP
00031 #include <time.h>
00032 #endif
00033 
00034 #include <polylib/polylib.h>
00035 
00036 #ifdef __STDC__
00037 static void traite_m_face(Polyhedron *, unsigned int *);
00038 static void scan_m_face(int,int,Polyhedron *,unsigned int *);
00039 #else
00040 static void traite_m_face();
00041 static void scan_m_face();
00042 #endif /* __STDC__ */
00043 
00044 /*
00045  * Return the intersection of two polyhedral domains 'Pol1' and 'Pol2' such 
00046  * that if the intersection is a polyhedron of lower dimension (a degenerate
00047  * polyhedron) than the operands, it is discarded from the resulting polyhedra
00048  * list. 
00049  */
00050 Polyhedron *PDomainIntersection(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
00051         
00052   Polyhedron *p1, *p2, *p3, *d;
00053   
00054   if (!Pol1 || !Pol2) return (Polyhedron*) 0;
00055   if((Pol1->Dimension != Pol2->Dimension) || (Pol1->NbEq != Pol2->NbEq)) {
00056     fprintf(stderr,
00057             "? PDomainIntersection: operation on different dimensions\n");
00058     return (Polyhedron*) 0;
00059   }
00060   
00061   POL_ENSURE_FACETS(Pol1);
00062   POL_ENSURE_VERTICES(Pol1);
00063   POL_ENSURE_FACETS(Pol2);
00064   POL_ENSURE_VERTICES(Pol2);
00065  
00066   d = (Polyhedron *)0;
00067   for (p1=Pol1; p1; p1=p1->next) {
00068     for (p2=Pol2; p2; p2=p2->next) {
00069       p3 = AddConstraints(p2->Constraint[0],
00070                           p2->NbConstraints,p1,NbMaxRays);
00071       if (!p3) continue;
00072       
00073       /* If the new polyhedron 'p3' has lower dimension, discard it */
00074       if (p3->NbEq!=Pol1->NbEq)
00075         Polyhedron_Free(p3) ;
00076       
00077       /* Otherwise add it to the new polyhderal domain 'd'. */
00078       else
00079         d = AddPolyToDomain(p3,d);
00080     }
00081   }
00082   return d;
00083 } /* PDomainIntersection */
00084 
00085 /* 
00086  * Given polyhderal domains 'Pol1' and 'Pol2', return the difference of the 
00087  * two domains with a modification that the resulting polyhedra in the new 
00088  * domain don't have a 1 unit space around cut and the degenrate results are 
00089  * discarded. 
00090  */
00091 Polyhedron *PDomainDifference(Polyhedron *Pol1,Polyhedron *Pol2,unsigned NbMaxRays) {
00092   
00093   Polyhedron *p1, *p2, *p3, *d;
00094   int i;
00095   
00096   if (!Pol1 || !Pol2)
00097     return (Polyhedron*) 0;
00098   if((Pol1->Dimension != Pol2->Dimension) || (Pol1->NbEq != Pol2->NbEq)) {
00099     fprintf(stderr,
00100             "? PDomainDifference: operation on different dimensions\n");
00101     return (Polyhedron*) 0;
00102   }
00103 
00104   POL_ENSURE_FACETS(Pol1);
00105   POL_ENSURE_VERTICES(Pol1);
00106   POL_ENSURE_FACETS(Pol2);
00107   POL_ENSURE_VERTICES(Pol2);
00108  
00109   d = (Polyhedron *)0;
00110   for (p2=Pol2; p2; p2=p2->next) {
00111     for (p1=Pol1; p1; p1=p1->next) {
00112       for (i=0; i<p2->NbConstraints; i++) {
00113         
00114         /* Add the constraint (-p2->Constraint[i]) >= 0 in 'p1' */
00115         p3 = SubConstraint(p2->Constraint[i],p1,NbMaxRays,2);
00116         if (!p3) continue;
00117         
00118         /* If the new polyhedron 'p3' is empty or is a polyhedron of lower */
00119         /* dimension, discard it.                                          */
00120         if (emptyQ(p3) || p3->NbEq!=Pol1->NbEq)
00121           Polyhedron_Free(p3);
00122         
00123         /* Otherwise add 'p3' to the new polyhderal domain 'd' */
00124         else
00125           d = AddPolyToDomain(p3,d);
00126       }
00127     }
00128     if (p2 != Pol2)
00129         Domain_Free(Pol1);
00130     Pol1 = d;
00131     d = (Polyhedron *)0;
00132   }
00133   return Pol1;
00134 } /* PDomainDifference */
00135 
00136 /* 
00137  * Return 1 if matrix 'Mat' is full column ranked, otherwise return 0. 
00138  */  
00139 static int TestRank(Matrix *Mat) {
00140   
00141   int i,j,k;
00142   Value m1,m2,m3,gcd,tmp;
00143 
00144   /* Initialize all the 'Value' variables */
00145   value_init(m1); value_init(m2); 
00146   value_init(m3); value_init(gcd); value_init(tmp);
00147   
00148   for(k=0;k<Mat->NbColumns;++k) {
00149     
00150     /* If the digonal entry (k,k) is zero, search down the column(k) */
00151     /* starting from row(k) to find a non-zero entry                 */
00152     if(value_zero_p(Mat->p[k][k])) {
00153       for(j=k+1;j<Mat->NbRows;++j) {
00154         
00155         /* If a non-zero entry (j,k) is found */
00156         if(value_notzero_p(Mat->p[j][k])) {
00157           
00158           /* Exchange row(k) and row(j) */
00159           for(i=k;i<Mat->NbColumns;++i) {
00160             value_assign(tmp,Mat->p[j][i]);
00161             value_assign(Mat->p[j][i],Mat->p[k][i]);
00162             value_assign(Mat->p[k][i],tmp);
00163           }
00164           break;
00165         }
00166       }
00167       
00168       /* If no non-zero entry is found then the matrix 'Mat' is not full */
00169       /* ranked. Return zero.                                            */
00170       if(j>=Mat->NbRows) {
00171         
00172         /* Clear all the 'Value' variables */
00173         value_clear(m1); value_clear(m2); 
00174         value_clear(m3); value_clear(gcd); value_clear(tmp);
00175         return 0;
00176       } 
00177     }
00178     
00179     /* Now Mat[k][k] is the pivot element */
00180     for(j=k+1;j<Mat->NbRows;++j) {
00181       
00182       /* Make every other entry (below row(k)) in column(k) zero */
00183       Gcd(Mat->p[j][k],Mat->p[k][k],&gcd);
00184       for(i=k+1;i<Mat->NbColumns;++i) {
00185         
00186         /* pour tous les indices i > k */
00187         value_multiply(m1,Mat->p[j][i],Mat->p[k][k]);
00188         value_multiply(m2,Mat->p[j][k],Mat->p[k][i]);
00189         value_subtract(m3,m1,m2);
00190         value_division(Mat->p[j][i],m3,gcd);
00191       }
00192     }   
00193   }
00194 
00195   /* Clear all the 'Value' variables */
00196   value_clear(m1); value_clear(m2); 
00197   value_clear(m3); value_clear(gcd); value_clear(tmp);
00198   
00199   /* The matrix 'Mat' is full ranked, return 1 */
00200   return 1;
00201 } /* TestRank */
00202 
00203 /*
00204  * The Saturation matrix is defined to be an integer (int type) matrix. It is
00205  * a boolean matrix which has a row for every constraint and a column for 
00206  * every line or ray. The bits in the binary format of each integer in the 
00207  * saturation matrix stores the information whether the corresponding constr-
00208  * aint is saturated by ray(line) or not. 
00209  */
00210 typedef struct {
00211   unsigned int NbRows;
00212   unsigned int NbColumns;
00213   unsigned int **p;
00214   unsigned int *p_init;
00215 } SatMatrix; 
00216 
00217 static SatMatrix *SMAlloc(int rows,int cols) {
00218 
00219   unsigned int **q, *p;
00220   int i;
00221 
00222   SatMatrix *result = (SatMatrix *)malloc(sizeof(SatMatrix));
00223   assert (result != NULL);
00224 
00225   result->NbRows = rows;
00226   result->NbColumns = cols;
00227   result->p = q = (unsigned int **)malloc(rows * sizeof(unsigned int *));
00228   assert (result->p != NULL);  
00229   result->p_init = p = (unsigned int *)malloc(rows * cols * sizeof(unsigned int));
00230   assert (result->p_init != NULL);  
00231   
00232   for (i=0;i<rows;i++) {
00233     *q++ = p;
00234     p += cols;
00235   }
00236   
00237   return result;
00238 } /* SMAlloc */
00239 
00240 static void SMPrint (SatMatrix *matrix) {
00241   
00242   unsigned int *p;
00243   int i, j;
00244   unsigned NbRows, NbColumns;
00245   
00246   fprintf(stderr,"%d %d\n",NbRows=matrix->NbRows, NbColumns=matrix->NbColumns);
00247   for (i=0;i<NbRows;i++) {
00248     p = *(matrix->p+i);
00249     for (j=0;j<NbColumns;j++)
00250       fprintf(stderr, " %10X ", *p++);
00251     fprintf(stderr, "\n");
00252   }  
00253 } /* SMPrint */
00254 
00255 
00256 static void SMFree (SatMatrix *matrix) {
00257   
00258   free ((char *) matrix->p_init);
00259   free ((char *) matrix->p);
00260   free ((char *) matrix);
00261   return;
00262 } /* SMFree */
00263 
00264 /* -------------------------------------------------------------------------
00265  * Shared Global Variables:
00266  * Used by procedures: Find_m_face, scan_m_face, Poly2Sat, traite_m_face,
00267  *                     count_sat 
00268  * -------------------------------------------------------------------------
00269  */
00270 static int m;                   /* number of parameters */
00271 static int m_dim;               /* dimension of m-face */
00272 static int n;                   /* dimension (not including parameters) */
00273 static int ws;                  /* Working Space size */
00274 static int nr;                  /* (NbRays-1)/32 + 1 */
00275 
00276 static Polyhedron *CEqualities;/* Equalities in the context */
00277 static SatMatrix   *Sat;       /* Saturation Matrix (row=constraint, col=ray)*/
00278 static int *egalite;           /* Bool vector marking constraints in m-face  */
00279 static Matrix *Xi, *Pi;        /* Xi and Pi */
00280 static Matrix *PiTest;         /* Matrix used to test if Pi is full ranked? */
00281 static Matrix *CTest;
00282 static Matrix *PiInv;          /* Matrix inverse Pi, with the last col of   */
00283                                /* each line = denominator of the line       */
00284 static Matrix *RaysDi;         /* Constraint matrix for computing Di */
00285 
00286 static int KD;                   /* Flag : keep the full domains in memory ? */
00287                                  /* 1 = yes; 0 = no, keep constraints only   */
00288 
00289 static int nbPV;                  /* The number of parameterized vertices */
00290 static Param_Vertices *PV_Result; /* List of parameterized vertices */
00291 static Param_Domain *PDomains;    /* List of domains. */
00292 
00293 #ifdef DEBUGPP
00294 static int nbfaces;
00295 #endif
00296 
00297 /*
00298  * Add the constraints from the context polyhedron 'CEqualities' to the 
00299  * constraints of polyhedra in the polyhedral domain 'D' and return the new
00300  * polyhedral domain. Polyhedral domain 'D' is subsequently deleted from memory
00301  */
00302 static Polyhedron *Add_CEqualities(Polyhedron *D) {
00303   
00304   Polyhedron *d,*r,*tmp;
00305 
00306   if(!CEqualities)
00307     return D;
00308   else {
00309     if(!D || emptyQ(D)) {
00310       if(D)
00311         Domain_Free(D);
00312       return(Polyhedron_Copy(CEqualities));
00313     }
00314     r = AddConstraints(D->Constraint[0],D->NbConstraints,
00315                        CEqualities,ws);
00316     tmp = r;
00317     for(d=D->next;d;d=d->next) {
00318       tmp->next = AddConstraints(d->Constraint[0],d->NbConstraints,
00319                                  CEqualities,ws);
00320       tmp = tmp->next;
00321     }
00322     Domain_Free(D);
00323     return(r);
00324   }
00325 } /* Add_CEqualities */
00326 
00327 /*----------------------------------------------------------------------*/
00328 /* traite_m_face                                                        */
00329 /*       Given an m-face, compute the parameterized vertex              */
00330 /*----------------------------------------------------------------------*/
00331 static void traite_m_face(Polyhedron *D,unsigned int *mf) {
00332      /* D  - The entire domain */
00333      /* mf - Bit vector marking the lines/rays in the m-face */
00334 
00335   Matrix *Si;                           /* Solution */
00336   Polyhedron *PDi;                      /* polyhedron Di */
00337   Param_Vertices *PV;
00338   int j,k,c,r;
00339   unsigned kx, bx;
00340 
00341 #ifdef DEBUGPP
00342   ++nbfaces;
00343 #endif
00344   
00345   /* Extract  Xi, Pi, and RaysDi from D */
00346   RaysDi->NbRows = 0;
00347   for(k=0,c=0,kx=0,bx=MSB;k<D->NbRays;++k) {
00348     if(mf[kx]&bx) {      /* this ray is in the current m-face */      
00349       if(c<m+1) {       
00350         int i;
00351         
00352         /* tester si cette nouvelle colonne est lin. indep. des autres */
00353         /* i.e. si gauss ne donne pas de '0' sur la colonne Pi */
00354         /* jusqu'a l'indice 'c'                                */
00355         
00356         /* construit PiTest */
00357         for(j=0;j<m+1;++j) {
00358           for(i=0;i<c;++i)
00359             
00360             /* les c premieres colonnes */
00361             value_assign(PiTest->p[j][i],Pi->p[j][i]);
00362           
00363           /* la nouvelle */
00364           value_assign(PiTest->p[j][c],D->Ray[k][j+1+n]);
00365         }
00366         PiTest->NbColumns = c+1;
00367         r = TestRank(PiTest);
00368         if(r /* TestRank(PiTest) */) {
00369                                 
00370           /* Ok, c'est lin. indep. */
00371           for (j=0;j<n;j++)
00372             value_assign(Xi->p[j][c],D->Ray[k][j+1]);   /* Xi */
00373           for (j=0;j<m;j++)
00374             value_assign(Pi->p[j][c],D->Ray[k][j+1+n]); /* Pi */
00375           value_assign(Xi->p[n][c],D->Ray[k][n+m+1]);   /* const */
00376           value_assign(Pi->p[m][c],D->Ray[k][n+m+1]);   /* const */
00377           c++;
00378         }
00379       }
00380       
00381       /* Status bit */
00382       value_assign(RaysDi->p[RaysDi->NbRows][0],D->Ray[k][0]);     
00383       Vector_Copy(&D->Ray[k][n+1],&RaysDi->p[RaysDi->NbRows][1],(m+1));
00384       ++RaysDi->NbRows;
00385     }
00386     NEXT(kx,bx);
00387   }
00388   
00389 #ifdef DEBUGPP41
00390   fprintf(stderr, "\nRaysDi=\n");
00391   Matrix_Print(stderr,P_VALUE_FMT,RaysDi);
00392   if(c < m+1)
00393     fprintf(stderr, "Invalid ");
00394   fprintf(stderr, "Pi=\n");
00395   Matrix_Print(stderr,P_VALUE_FMT,Pi);
00396 #endif
00397   
00398 #ifdef DEBUGPP4
00399   if(c < m+1)
00400     fprintf(stderr,"Eliminated because of no vertex\n");
00401 #endif
00402 
00403   if(c < m+1)   
00404     return;
00405 
00406   /* RaysDi->numColumns = m+2; */  /* stays the same */
00407 
00408   /*    Xi->NbColumns = m+1;*/  /* VIN100: stays the same. was 'c'! */
00409   /*    Xi->NbRows = n+1; */    /* stays the same */
00410   /*    Pi->NbColumns = m+1;*/  /* VIN100: stays the same. was 'c'! */
00411   /*    Pi->NbRows = m+1; */            /* stays the same */
00412   
00413 #ifdef DEBUGPP4
00414   fprintf(stderr,"Xi = ");
00415   Matrix_Print(stderr,P_VALUE_FMT,Xi);
00416   fprintf(stderr,"Pi = ");
00417   Matrix_Print(stderr,P_VALUE_FMT,Pi);
00418 #endif
00419   
00420   /* (Right) invert Pi if POSSIBLE, if not then next m-face */
00421   /* Pi is destroyed                                        */
00422   if(!MatInverse(Pi,PiInv)) {
00423     
00424 #ifdef DEBUGPP4
00425     fprintf(stderr, "Eliminated because of no inverse Pi\n");
00426 #endif
00427     
00428     return;
00429   }
00430   
00431 #ifdef DEBUGPP4
00432   fprintf(stderr,"FACE GENERATED!\n");
00433   fprintf(stderr,"PiInv = ");
00434   Matrix_Print(stderr,P_VALUE_FMT,PiInv);
00435 #endif
00436   
00437   /* Compute  Si (now called Ti in the paper) */
00438   Si = Matrix_Alloc(Xi->NbRows,PiInv->NbColumns);
00439   rat_prodmat(Si,Xi,PiInv);
00440   
00441 #ifdef DEBUGPP4
00442   fprintf(stderr,"Si = ");
00443   Matrix_Print(stderr,P_VALUE_FMT,Si);
00444 #endif
00445   
00446   Si->NbRows--;      /* throw out the last row = 0 ... 0 1 */
00447   
00448   /* Copy all of that into the PV structure */
00449   PV = (Param_Vertices *) malloc(sizeof(Param_Vertices));
00450   PV->next = PV_Result;
00451   PV->Vertex = Si;
00452   PV->Domain = NULL;
00453   PV_Result = PV;
00454   nbPV++;         /* increment vertex count */
00455   
00456   /* Ok... now compute the parameter domain */
00457   PDi = Rays2Polyhedron(RaysDi,ws);
00458   
00459 #ifdef DEBUGPP3
00460   fprintf(stderr,"RaysDi = ");
00461   Matrix_Print(stderr,P_VALUE_FMT,RaysDi);
00462   fprintf(stderr,"PDi = ");
00463   Polyhedron_Print(stderr,P_VALUE_FMT,PDi);
00464 #endif
00465   
00466   if(KD==0) {
00467     
00468     /* Add the equalities again to the domain */
00469     PDi = Add_CEqualities(PDi);
00470     PV->Domain = Polyhedron2Constraints(PDi);
00471     Polyhedron_Free(PDi);
00472   }
00473   else {
00474     Param_Domain *PD;
00475     PD = (Param_Domain *) malloc(sizeof(Param_Domain));
00476     PD->Domain = PDi;
00477     PD->F = NULL;
00478     PD->next = PDomains;
00479     PDomains = PD;
00480   }
00481   return;
00482 } /* traite_m_face */
00483 
00484 /*----------------------------------------------------------------------*/
00485 /* count_sat                                                            */
00486 /*      count the number of saturated rays in the bit vector mf         */
00487 /*      Uses nr from global area                                        */
00488 /*----------------------------------------------------------------------*/
00489 int cntbit[256] = {                             /* counts for 8 bits */
00490 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
00491 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00492 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00493 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00494 
00495 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00496 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00497 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00498 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00499 
00500 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00501 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00502 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00503 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00504 
00505 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00506 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00507 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00508 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 };
00509 
00510 static int count_sat (unsigned int *mf) {
00511   
00512   register unsigned int i, tmp, cnt=0;
00513   
00514   for (i=0; i<nr; i++) {
00515     tmp = mf[i];
00516     cnt = cnt
00517       + cntbit[ tmp & 0xff ]
00518       + cntbit[ (tmp>>8) & 0xff ]
00519       + cntbit[ (tmp>>16) & 0xff ]
00520       + cntbit[ (tmp>>24) & 0xff ]
00521       ;
00522   }
00523   return cnt;
00524 } /* count_sat */
00525 
00526 /*----------------------------------------------------------------------*/
00527 /* let D + E + L be the dimension of the polyhedron                     */
00528 /* D = Dimension of polytope (ray space)                                */
00529 /* L = Dimension of Lineality space (number of lines, bid)              */
00530 /* E = Dimension of Affine hull (number of equations)                   */
00531 /* n = number of data indices                                           */
00532 /* m = number of parameters                                             */
00533 /* full domain:                                                         */
00534 /*     n + m = D + E + L                                                */
00535 /* projected domains:                                                   */
00536 /*     m = D_m + E_m + L_m                                              */
00537 /*     n = D_n + E_n + L_n                                              */
00538 /* What dimension M-face, when projected onto parameter space,          */
00539 /* will give an L_m-face?                                               */
00540 /* What are the conditions?                                             */
00541 /*   - at least one vertex                                              */
00542 /*   - number of rays >= D_m+1 after removal of redundants              */
00543 /*                                                                      */
00544 /* dim of face    nb saturated constraints   nb saturated lines,rays    */
00545 /* -----------    ------------------------   -----------------------    */
00546 /* (0+L)-face     all E eqns + >=D ineq      all L lines + 1 ray        */
00547 /* (M+L)-face     all E eqns + >=(D-M) ineq  all L lines + >=(M+1) rays */
00548 /* (D+L)-face     all E eqns + 0 ineq        all L lines + >=(D+1) rays */
00549 /*----------------------------------------------------------------------*/
00550 /*----------------------------------------------------------------------*/
00551 /* scan_m_face                                                          */
00552 /*      pos : the next candidate constraint position                    */
00553 /*    nb-un : number of saturated constraints needed to finish a face   */
00554 /*        D : the source polyhedron (context included )                 */
00555 /*       mf : bit-array marking rays which are saturated so far         */
00556 /* From Global area:                                                    */
00557 /* ----------------                                                     */
00558 /*        n : number of data indices                                    */
00559 /*        m : number of parameters                                      */
00560 /*  egalite : boolean vector marking saturated constraints in m-face    */
00561 /*      Sat : Saturation Matrix (row=constraints, col=rays)             */
00562 /*       ws : working space size                                        */
00563 /*       nr : (NbRays-1)/32 + 1                                         */
00564 /*                                                                      */
00565 /* Recursive function to find the rays and vertices of each m-face      */
00566 /*----------------------------------------------------------------------*/
00567 static void scan_m_face(int pos,int nb_un,Polyhedron *D,unsigned int *mf) {
00568   /* pos   - the next candidate constraint position */
00569   /* nb_un - the number of constraints needed to finish a face */
00570   /* D     - the source polyhedron */
00571   /* mf    - (bit vector) marks rays that are saturated so far */
00572 
00573   unsigned int *new_mf;
00574 
00575 #ifdef DEBUGPP4
00576   fprintf(stderr,"Start scan_m_face(pos=%d, nb_un=%d, n=%d, m=%d\n",
00577           pos,nb_un,n,m);
00578   fprintf(stderr,"mf = ");
00579   {
00580     int i;
00581     for(i=0;i<nr;i++)
00582       fprintf(stderr,"%08X", mf[i]);
00583     fprintf(stderr,"\nequality = [");
00584     for(i=0;i<D->NbConstraints;i++)
00585       fprintf(stderr," %1d",egalite[i]);
00586     fprintf(stderr,"]\n");
00587   }
00588 #endif
00589 
00590   if(nb_un == 0) {      /* Base case */   
00591     int i,j;
00592     
00593     /*********** ELIMINATION OF REDUNDANT FACES ***********/
00594     /* if all these vertices also verify a previous constraint */
00595     /* which is NOT already selected, we eliminate this face */
00596     /* This keeps the lexicographically greatest selection */
00597         for(i=0;i<pos-1;i++)
00598         {
00599                 if(egalite[i])
00600                         continue;       /* already selected */
00601       
00602                 /* if Sat[i] & mf == mf then it's redundant */
00603                 for (j=0;j<nr;j++)
00604                 {
00605         
00606 #ifdef DEBUGPP4
00607                         fprintf(stderr,"mf=%08X Sat[%d]=%08X &=%08X\n",mf[j],i,Sat->p[i][j],
00608                                 (mf[j] & Sat->p[i][j]) );
00609 #endif
00610 
00611                         if (((mf[j]) & (Sat->p[i][j])) != mf[j])
00612                                 break;  /* it's not redundant */
00613                 }
00614       
00615 #ifdef DEBUGPP4
00616                 if (j==nr) fprintf(stderr, "Redundant with constraint %d\n", i);
00617 #endif
00618     
00619                 if (j==nr) return;      /* it is redundant */
00620         }
00621     /********* END OF ELIMINATION OF DEGENERATE FACES *********/    
00622     /* if we haven't found a constraint verified by all */
00623     /* the rays, its OK, it's a new face. */
00624     traite_m_face(D,mf);
00625     return;
00626   }
00627 
00628   /* See if there are enough constraints left to finish */
00629   if((pos+nb_un)>D->NbConstraints) return;
00630   
00631   /* Recurring part of the procedure */
00632   /* Add the pos'th constraint, compute new saturation vector */
00633   {     
00634     int k;
00635     new_mf  = (unsigned int *)malloc(nr*sizeof(unsigned int));
00636     for (k=0; k<nr; k++)
00637       new_mf[k] = mf[k] & Sat->p[pos][k];
00638   }
00639 #ifdef DEBUGPP4
00640 fprintf(stderr,"new_mf = ");
00641  { 
00642    int i;
00643    for(i=0;i<nr;i++) {
00644      fprintf(stderr,"%08X", new_mf[i]);
00645    }
00646    fprintf(stderr,"\ncount(new_mf) = %d\n",count_sat(new_mf));
00647  }
00648 #endif
00649 
00650   {
00651         int c;
00652         c = count_sat(new_mf);
00653         /* optimization : at least m_dim+1 rays must be saturated to add this constraint */
00654         if (c>m_dim )
00655         {
00656                 int redundant = 0;
00657 
00658                 egalite[pos]=1;         /* Try it with the pos-th constraint */
00659 
00660                 /* If this constraint does not change anything,
00661                  * it is redundant with respect to the selected
00662                  * equalities and the remaining inequalities.
00663                  * Check whether it is redundant with respect
00664                  * to just the selected equalities.
00665                  */
00666                 if( c==count_sat(mf) ) {
00667                     int i, c, j;
00668 
00669                     for (i = 0, c = 0; i < D->NbConstraints; ++i) {
00670                         if (egalite[i] == 0 || egalite[i] == -1)
00671                             continue;
00672                         for (j = 0; j < D->Dimension+1; ++j)
00673                             value_assign(CTest->p[j][c], 
00674                                          D->Constraint[i][j+1]);
00675                         ++c;
00676                     }
00677                     CTest->NbColumns = c;
00678 #ifdef DEBUGPP41
00679                     Matrix_Print(stderr,P_VALUE_FMT,CTest);
00680 #endif
00681                     redundant = !TestRank(CTest);
00682                 }
00683 
00684                 /* Do not decrement nb_un if equality is redundant. */
00685                 if( redundant )
00686                 {
00687                    egalite[pos]=-1;     /* Don't use in further redundance test
00688                                          */
00689                    scan_m_face(pos+1,nb_un,D,new_mf);
00690                 }
00691                 else
00692                 {
00693                    scan_m_face(pos+1,nb_un-1,D,new_mf);
00694                 }
00695         }
00696   }
00697  free(new_mf);
00698  egalite[pos]=0;                /* Try it without the pos-th constraint */
00699  if ((pos+nb_un)>=D->NbConstraints) return;
00700  scan_m_face(pos+1,nb_un,D,mf);
00701  return;
00702 } /* scan_m_face */
00703 
00704 /*
00705  * Create a saturation matrix with rows correspond to the constraints and 
00706  * columns correspond to the rays of the polyhedron 'Pol'. Global variable 
00707  * 'nr' is set in the function.             
00708  */
00709 static SatMatrix *Poly2Sat(Polyhedron *Pol,unsigned int **L) { 
00710   
00711   SatMatrix *Sat;
00712   int i, j, k, kx;
00713   unsigned int *Temp;
00714   Value *p1, *p2, p3,tmp;
00715   unsigned Dimension, NbRay, NbCon, bx;
00716   
00717   /* Initialize all the 'Value' variables */
00718   value_init(p3); value_init(tmp);
00719   
00720   NbRay = Pol->NbRays;
00721   NbCon = Pol->NbConstraints;
00722   Dimension = Pol->Dimension+1;                /* Homogeneous Dimension */
00723   
00724   /* Build the Sat matrix */
00725   nr      = (NbRay - 1)/(sizeof(int)*8) + 1;   /* Set globally */
00726   Sat     = SMAlloc(NbCon,nr);
00727   Temp     = (unsigned int *)malloc(nr*sizeof(unsigned int));
00728   memset(Sat->p_init,0,nr*NbCon*sizeof(int));
00729   memset(Temp,0,nr*sizeof(unsigned int));
00730   kx=0; bx=MSB;
00731   for (k=0; k<NbRay; k++) { 
00732     for (i=0; i<NbCon; i++) {
00733       p1 = &Pol->Constraint[i][1];
00734       p2 = &Pol->Ray[k][1];
00735       value_set_si(p3,0);
00736       for (j=0;j<Dimension;j++) {
00737         value_multiply(tmp,*p1,*p2);
00738         value_addto(p3,p3,tmp);
00739         p1++; p2++;
00740       }
00741       if (value_zero_p(p3))
00742         Sat->p[i][kx]|=bx;
00743     }
00744     Temp[kx] |= bx;
00745     NEXT(kx, bx);
00746   }
00747   
00748   /* Set 'L' to an array containing ones in every bit position of its */
00749   /* elements.                                                        */
00750   *L = Temp;
00751   
00752   /* Clear all the 'Value' variables */
00753   value_clear(p3); value_clear(tmp);
00754   
00755   return Sat;
00756 } /* Poly2Sat */
00757 
00758 /*
00759  * Create a parametrized polyhedron with zero parameters. This function was 
00760  * first written by Xavier Redon, and was later modified by others.
00761  */
00762 Param_Polyhedron *GenParamPolyhedron(Polyhedron *Pol) {
00763   
00764   Param_Polyhedron *result;
00765   int nbRows, nbColumns;
00766   int i, size, rays;
00767   
00768   nbRows=Pol->NbRays;
00769   nbColumns=Pol->Dimension+2;
00770   
00771   /* Count the number of rays */
00772   for(i=0, rays=0; i<nbRows; i++)
00773     if(value_notone_p(Pol->Ray[i][0]) ||
00774        value_zero_p(Pol->Ray[i][nbColumns-1]))
00775       ++rays;
00776   
00777   /* Initialize the result */
00778   result=(Param_Polyhedron *)malloc(sizeof(Param_Polyhedron));
00779   result->nbV=nbRows-rays;
00780   result->V=NULL;
00781   
00782   /* Build the parametric vertices */
00783   for(i=0;i<nbRows;i++) {
00784     Matrix *vertex;
00785     Param_Vertices *paramVertex;
00786     int j;
00787 
00788     if (value_notone_p(Pol->Ray[i][0]) ||
00789         value_zero_p(Pol->Ray[i][nbColumns-1]))
00790       continue;
00791 
00792     vertex=Matrix_Alloc(nbColumns-2,2);
00793     for(j=1;j<nbColumns-1;j++) {
00794       value_assign(vertex->p[j-1][0],Pol->Ray[i][j]);
00795       value_assign(vertex->p[j-1][1],Pol->Ray[i][nbColumns-1]);
00796     }
00797     paramVertex=(Param_Vertices *)malloc(sizeof(Param_Vertices));
00798     paramVertex->Vertex=vertex;
00799     
00800     /* There is one validity domain : universe of dimension 0 */
00801     paramVertex->Domain=Matrix_Alloc(1,2);
00802     value_set_si(paramVertex->Domain->p[0][0],1);
00803     value_set_si(paramVertex->Domain->p[0][1],1);    
00804     paramVertex->next=result->V;
00805     result->V=paramVertex;
00806   }
00807   
00808   /* Build the parametric domains (only one here) */
00809   if (nbRows > 1)
00810     size=(nbRows-1)/(8*sizeof(int))+1;
00811   else
00812     size = 1;
00813   result->D=(Param_Domain *)malloc(sizeof(Param_Domain));
00814   result->D->next=NULL;
00815   result->D->Domain=Universe_Polyhedron(0);
00816   result->D->F=(unsigned int *)malloc(size*sizeof(int));
00817   memset(&result->D->F[0],0xFF,size*sizeof(int));
00818   
00819   return result;
00820 } /* GenParamPolyhedron */
00821 
00822 
00823 /*----------------------------------------------------------------------*/
00824 /* PreElim_Columns                                                      */
00825 /* function being called before Elim_Columns                            */
00826 /* Equalities in E are analysed to initialize ref and p.                */
00827 /* These two vectors are used to construct the new constraint matrix    */
00828 /* PreElim_Columns returns the transformation matrix to re-convert the  */
00829 /* resulting domains in the same format (by adding empty columns)       */
00830 /* in the parameter space                                               */
00831 /*----------------------------------------------------------------------*/
00832 Matrix *PreElim_Columns(Polyhedron *E,int *p,int *ref,int m) {
00833         
00834   int i,j,l;
00835   Matrix *T;
00836   
00837   /* find which columns to eliminate */
00838   /* p contains, for each line in E, the column to eliminate */
00839   /* (i.e. the corresponding parameter index to eliminate) */
00840   /* 0 <= i <= E->NbEq, and  1 <= p[i] <= E->Dimension */
00841   memset(p,0,sizeof(int)*(E->NbEq));
00842 
00843 #ifdef DEBUGPP32
00844   fprintf(stderr,"\n\nPreElim_Columns starting\n");
00845   fprintf(stderr,"E =\n");
00846   Polyhedron_Print(stderr,P_VALUE_FMT,E);
00847 #endif
00848   
00849   for(l=0;l<E->NbEq;++l) {
00850     if(value_notzero_p(E->Constraint[l][0])) {
00851       fprintf(stderr,"Internal error: Elim_Columns (polyparam.c), expecting equalities first in E.\n");
00852       free(p);
00853       return(NULL);
00854     }
00855     for(i=1;value_zero_p(E->Constraint[l][i]);++i) {
00856       if(i==E->Dimension+1) {
00857         fprintf(stderr,"Internal error: Elim_Columns (polyparam.c), expecting non-empty constraint in E.\n");
00858         free(p);
00859         return( NULL );
00860       }
00861     }
00862     p[l] = i;
00863     
00864 #ifdef DEBUGPP32
00865     fprintf(stderr,"p[%d] = %d,",l,p[l]);
00866 #endif
00867   }
00868 
00869   /* Reference vector: column ref[i] in A corresponds to column i in M */
00870   for(i=0;i<E->Dimension+2-E->NbEq;++i) {
00871     ref[i]=i;
00872     for(j=0;j<E->NbEq;++j)
00873       if(p[j]<=ref[i])
00874         ref[i]++;
00875     
00876 #ifdef DEBUGPP32
00877     fprintf(stderr,"ref[%d] = %d,",i,ref[i]);
00878 #endif
00879   }
00880   
00881   /* Size of T : phdim-nbEq * phdim */
00882   T = Matrix_Alloc(m+1-E->NbEq,m+1);
00883   for(i=0;i<T->NbColumns;i++)
00884     for(j=0;j<T->NbRows;j++)
00885       if(ref[E->Dimension-m+j+1] == E->Dimension-m+i+1)
00886         value_set_si(T->p[j][i],1);
00887       else
00888         value_set_si(T->p[j][i],0);
00889   
00890 #ifdef DEBUGPP32
00891   fprintf(stderr,"\nTransMatrix =\n");
00892   Matrix_Print(stderr,P_VALUE_FMT,T);
00893 #endif
00894   
00895   return(T);
00896 
00897 } /* PreElim_Columns */
00898 
00899 /*----------------------------------------------------------------------*/
00900 /* Elim_Columns                                                         */
00901 /* Eliminate columns from A, using the equalities in E.                 */
00902 /* ref and p are precalculated by PreElim_Columns, using E;             */
00903 /* these two vectors are used to construct the new constraint matrix    */
00904 /*----------------------------------------------------------------------*/
00905 Polyhedron *Elim_Columns(Polyhedron *A,Polyhedron *E,int *p,int *ref) {
00906   
00907   int i,l,c;
00908   Matrix *M, *C;
00909   Polyhedron *R;
00910   Value tmp1,tmp2;
00911   
00912   /* Initialize all the 'Value' variables */
00913   value_init(tmp1); value_init(tmp2);
00914   
00915 #ifdef DEBUGPP32
00916   fprintf(stderr,"\nElim_Columns starting\n");
00917   fprintf(stderr,"A =\n" );
00918   Polyhedron_Print(stderr,P_VALUE_FMT,A);
00919 #endif
00920   
00921   /* Builds M = constraint matrix of A, useless columns zeroed */
00922   M = Polyhedron2Constraints(A);
00923   for(l=0;l<E->NbEq;++l) {    
00924     for(c=0;c<M->NbRows;++c) {
00925       if(value_notzero_p(M->p[c][p[l]])) {
00926         
00927         /* A parameter to eliminate here ! */
00928         for(i=1;i<M->NbColumns;++i) {
00929           value_multiply(tmp1,M->p[c][i],E->Constraint[l][p[l]]);
00930           value_multiply(tmp2,E->Constraint[l][i],M->p[c][p[l]]);
00931           value_subtract(M->p[c][i],tmp1,tmp2);
00932         }
00933       }
00934     }
00935   } 
00936   
00937 #ifdef DEBUGPP32
00938   fprintf(stderr,"\nElim_Columns after zeroing columns of A.\n");
00939   fprintf(stderr,"M =\n");
00940   Matrix_Print(stderr,P_VALUE_FMT,M);
00941 #endif
00942   
00943   /* Builds C = constraint matrix, useless columns eliminated */
00944   C = Matrix_Alloc(M->NbRows,M->NbColumns - E->NbEq);
00945   for(l=0;l<C->NbRows;++l)
00946     for(c=0;c<C->NbColumns;++c) {
00947       value_assign(C->p[l][c],M->p[l][ref[c]]);
00948     }
00949     
00950 #ifdef DEBUGPP32
00951   fprintf(stderr,"\nElim_Columns after eliminating columns of A.\n");
00952   fprintf(stderr,"C =\n");
00953   Matrix_Print(stderr,P_VALUE_FMT,C);
00954 #endif
00955     
00956   R = Constraints2Polyhedron(C,ws);
00957   Matrix_Free(C);
00958   Matrix_Free(M);
00959   value_clear(tmp1); value_clear(tmp2);
00960   return(R);
00961 } /* Elim_Columns */
00962 
00963 /* 
00964  * Given a polyhedron 'Di' in combined data and parameter space and a context 
00965  * polyhedron 'C' representing the constraints on the parameter space, create
00966  * a list of parameterized vertices and assign values to global variables: 
00967  * m,n,ws,Sat,egalite,mf,Xi,Pi,PiInv,RaysDi,CEqualities. 
00968  */
00969 Param_Polyhedron *Find_m_faces(Polyhedron **Di,Polyhedron *C,int keep_dom,int working_space,Polyhedron **CEq,Matrix **CT) {     
00970   
00971   unsigned int *mf;
00972   int i, j;
00973   Polyhedron *D=*Di,
00974              *C1,         /* true context */
00975              *D1;         /* the combined polyhedron, including context C */
00976   Matrix *M;
00977   Param_Polyhedron *res;
00978   int *p, *ref;
00979 
00980   CEqualities = NULL;
00981 
00982   if(CT) {
00983     *CEq = NULL;
00984     *CT = NULL;
00985   }
00986   
00987   if(!D || !C) 
00988     return (Param_Polyhedron *) 0;
00989 
00990   ws = working_space;
00991   m = C->Dimension;
00992   n = D->Dimension - m;
00993   if(n<0) {
00994     fprintf(stderr,
00995             "Find_m_faces: ?%d parameters of a %d-polyhedron !\n",m,n);
00996     return (Param_Polyhedron *) 0;
00997   }
00998   if (m==0)
00999     return GenParamPolyhedron(D);
01000   
01001   /* Add constraints from Context to D -> result in D1 */
01002   C1 = align_context(C,D->Dimension,ws);
01003 
01004 #ifdef DEBUGPP31
01005   fprintf(stderr,"m = %d\n",m);
01006   fprintf(stderr, "D = ");
01007   Polyhedron_Print(stderr,P_VALUE_FMT,D);
01008   fprintf(stderr,"C1 = ");
01009   Polyhedron_Print(stderr,P_VALUE_FMT,C1);
01010 #endif
01011   
01012   D1 = DomainIntersection(D,C1,ws);
01013 
01014 #ifdef DEBUGPP31
01015   fprintf(stderr,"D1 = ");
01016   Polyhedron_Print(stderr,P_VALUE_FMT,D1);
01017 #endif
01018   
01019   Domain_Free(C1);
01020 
01021   if(!D1 || emptyQ(D1))
01022     return(NULL);
01023   
01024   /* Compute the true context C1 */
01025   /* M : lines in the direction of the first n indices (index space) */
01026   M   = Matrix_Alloc(n, D1->Dimension+2);
01027   for (i=0; i<n; i++)
01028     value_set_si(M->p[i][i+1],1);
01029   C1 = DomainAddRays(D1,M,ws);
01030   Matrix_Free(M);
01031   
01032 #ifdef DEBUGPP31
01033   fprintf(stderr,"True context C1 = ");
01034   Polyhedron_Print(stderr,P_VALUE_FMT,C1);
01035 #endif
01036   
01037   /* CEqualities contains the constraints (to be added again later) */
01038   /* *CT is the transformation matrix to add the removed parameters */
01039   if(!CT) {
01040     if (C1->NbEq == 0) {
01041       Polyhedron_Free(C1);
01042     } else {
01043       Polyhedron *CEq1, /* CEqualities, in homogeneous dim */
01044                  *C2,   /* C1 (temporary) simplified */
01045                  *D2;   /* D1, (temporary) simplified */
01046       
01047       /* Remove equalities from true context C1 and from D1             */     
01048       /* Compute CEqualities = matrix of equalities in C1, projected in */
01049       /* the parameter space                                            */
01050       M = Matrix_Alloc(C1->NbEq,m+2);
01051       for(j=0,i=0;i<C1->NbEq;++i,++j) {
01052         while(value_notzero_p(C1->Constraint[j][0]))
01053           ++j;
01054         value_assign(M->p[i][0],C1->Constraint[j][0]);
01055         Vector_Copy(&C1->Constraint[j][D->Dimension-m+1],&M->p[i][1],(m+1));
01056       }
01057       CEqualities = Constraints2Polyhedron(M,ws);
01058       Matrix_Free(M);
01059       CEq1 = align_context(CEqualities,D->Dimension,ws);
01060 
01061       /* Simplify D1 and C1 (remove the equalities) */
01062       D2 = DomainSimplify(D1,CEq1,ws);
01063       Polyhedron_Free(D1);
01064       Polyhedron_Free(C1);
01065       Polyhedron_Free(CEq1);
01066       D1 = D2;
01067       C1 = NULL;
01068     }
01069   }
01070   else { /* if( CT  ) */
01071     Polyhedron *CEq1,   /* CEqualities */
01072                *C2,     /* C1 (temporary) simplified */
01073                *D2;     /* D1, (temporary) simplified */
01074 
01075     /* Suppress all useless constraints in parameter domain */
01076     /* when CT is not NULL (ehrhart) */
01077     /* Vin100, march 01 */
01078     CEq1 = C1;
01079     M = Matrix_Alloc(C1->NbConstraints,m+2);
01080     for(i=0;i<C1->NbConstraints;++i) {
01081       value_assign(M->p[i][0],C1->Constraint[i][0]);
01082       Vector_Copy(&C1->Constraint[i][D->Dimension-m+1],&M->p[i][1],(m+1));
01083     }
01084     CEqualities = Constraints2Polyhedron( M, ws );
01085     Matrix_Free(M);
01086 
01087     D2 = DomainSimplify(D1,CEq1,ws);
01088     Polyhedron_Free(D1);
01089     D1 = D2;
01090     C1 = Universe_Polyhedron(D2->Dimension);
01091     
01092     /* if CT is not NULL, the constraints are eliminated                */
01093     /* *CT will contain the transformation matrix to come back to the   */
01094     /* original dimension (for a polyhedron, in the parameter space)    */
01095     if( CEq1->NbEq )
01096     {
01097       m -= CEq1->NbEq;
01098       p = (int *)malloc(sizeof(int)*(CEq1->NbEq));
01099     }
01100     else
01101       p = NULL;
01102     ref = (int*) malloc(sizeof(int)*
01103                         (CEq1->Dimension+2-CEq1->NbEq));
01104     *CT = PreElim_Columns(CEq1,p,ref,CEqualities->Dimension);
01105     D2 = Elim_Columns(D1,CEq1,p,ref);
01106     if (p)
01107       free(p);
01108     free(ref);
01109     
01110 #ifdef DEBUGPP3
01111     fprintf(stderr,"D2\t Dim = %3d\tNbEq = %3d\tLines = %3d\n",
01112             D2->Dimension,D2->NbEq,D2->NbBid);
01113     C2 = Elim_Columns(C1,CEq1,p,ref);
01114     fprintf(stderr,"C2\t Dim = %3d\tNbEq = %3d\tLines = %3d\n",
01115             C2->Dimension,C2->NbEq,C2->NbBid);
01116     Polyhedron_Free(C2);
01117 #endif
01118     
01119     Polyhedron_Free(D1);
01120     Polyhedron_Free(C1);
01121     D1 = D2;
01122     C1 = NULL;
01123     *CEq = CEqualities;
01124     
01125 #ifdef DEBUGPP3
01126     fprintf(stderr,"Polyhedron CEq = ");
01127     Polyhedron_Print(stderr,P_VALUE_FMT,*CEq);
01128     fprintf(stderr,"Matrix CT = ");
01129     Matrix_Print(stderr,P_VALUE_FMT,*CT);
01130 #endif
01131     
01132     Polyhedron_Free(CEq1);
01133     CEqualities = NULL; /* don't simplify ! */
01134 
01135     /* m changed !!! */
01136     if(m==0) {
01137       /* return the new D1 too */
01138       *Di = D1;
01139 
01140       return GenParamPolyhedron(D1);
01141     }
01142   }
01143 
01144 #ifdef DEBUGPP3
01145   fprintf(stderr,"Polyhedron D1 (D AND C) = ");
01146   Polyhedron_Print(stderr,P_VALUE_FMT, D1);
01147   fprintf(stderr,"Polyhedron CEqualities = ");
01148   if(CEqualities) Polyhedron_Print(stderr,P_VALUE_FMT, CEqualities);
01149   else fprintf(stderr,"NULL\n");
01150 #endif
01151   
01152   KD = keep_dom;
01153   PDomains = NULL;
01154   PV_Result = NULL;
01155   nbPV = 0;
01156   
01157   if (D1->NbRays==0) return 0;
01158   
01159   /* mf : a bit array indicating which rays are part of the m-face */
01160   /* Poly2Sat initializes mf to all ones */
01161   /* set global variable nr to size (number of words) of mf */
01162   Sat = Poly2Sat(D1,&mf);
01163 
01164 #ifdef DEBUGPP4
01165     fprintf(stderr,"Sat = ");
01166     SMPrint(Sat);
01167 
01168   fprintf(stderr,"mf = ");
01169   for (i=0; i<nr; i++)
01170     fprintf(stderr,"%08X", mf[i]);
01171   fprintf(stderr, "\n");
01172 #endif
01173   
01174   /* A boolean array saying which constraints are part of the m-face */
01175   egalite = (int *)malloc(sizeof(int)*D1->NbConstraints );
01176   memset(egalite,0, sizeof(int)*D1->NbConstraints);
01177 
01178   for (i=0; i<D1->NbEq; i++)
01179     egalite[i] = 1;
01180 
01181   Xi     = Matrix_Alloc(n+1,m+1);
01182   Pi     = Matrix_Alloc(m+1,m+1);
01183   PiTest = Matrix_Alloc(m+1,m+1);
01184   CTest  = Matrix_Alloc(D->Dimension+1,D->NbConstraints);
01185   PiInv  = Matrix_Alloc(m+1,m+2);
01186   RaysDi = Matrix_Alloc(D1->NbRays,m+2);
01187   m_dim = m;
01188   
01189 #ifdef DEBUGPP
01190   nbfaces=0;
01191 #endif
01192 #ifdef DEBUGPP3
01193   fprintf(stderr,
01194           "Target: find faces that saturate %d constraints and %d rays/lines\n",
01195           D1->Dimension - m_dim,m_dim+1);
01196 #endif
01197         
01198   /* D1->NbEq constraints already saturated ! */
01199   scan_m_face(D1->NbEq,(D1->Dimension - m_dim - D1->NbEq),D1,mf);
01200 
01201   /* pos, number of constraints needed     */
01202 
01203 #ifdef DEBUGPP
01204   fprintf( stderr, "Number of m-faces: %d\n", nbfaces );
01205 #endif
01206   
01207   Matrix_Free(RaysDi);
01208   Matrix_Free(PiInv);
01209   Matrix_Free(PiTest);
01210   Matrix_Free(CTest);
01211   Matrix_Free(Pi);
01212   Matrix_Free(Xi);
01213   free(egalite);
01214   free(mf);
01215   SMFree(Sat);
01216   
01217   /*    if(CEqualities && keep_dom==0) {
01218            Domain_Free(CEqualities);
01219         }
01220   */
01221 
01222   if(CT)                /* return the new D1 too ! */
01223     *Di = D1;
01224   else
01225     Domain_Free(D1);
01226 
01227   res = (Param_Polyhedron *) malloc (sizeof(Param_Polyhedron));
01228   res->nbV = nbPV;
01229   res->V = PV_Result;
01230   res->D = PDomains;
01231   return(res);
01232 } /* Find_m_faces */
01233 
01234 /*
01235  * Given parametric domain 'PD' and number of parametric vertices 'nb_domains',
01236  * find the vertices that belong to distinct sub-domains. 
01237  */
01238 void Compute_PDomains(Param_Domain *PD,int nb_domains,int working_space) {
01239   
01240   unsigned bx;
01241   int i, ix, nv;
01242   Polyhedron *dx, *d1, *d2;
01243   Param_Domain *p1, *p2, *p2prev, *PDNew;
01244   
01245   if (nb_domains==0) {
01246     
01247 #ifdef DEBUGPP5
01248     fprintf(stderr,"No domains\n");
01249 #endif
01250     
01251     return;
01252   }
01253 
01254   /* Already filled out by GenParamPolyhedron */
01255   if (!PD->next && PD->F)
01256     return;
01257 
01258    /* Initialization */
01259    nv = (nb_domains - 1)/(8*sizeof(int)) + 1;
01260 
01261 #ifdef DEBUGPP5
01262    fprintf(stderr,"nv = %d\n",nv);
01263 #endif
01264 
01265    for(p1=PD,i=0,ix=0,bx=MSB;p1;p1=p1->next,i++) {
01266      
01267      /* Assign a bit array 'p1->F' of suitable size to include the vertices */
01268      p1->F = (unsigned *) malloc (nv * sizeof(unsigned));
01269      
01270      /* Set the bit array to zeros */
01271      memset(p1->F,0,nv * sizeof(unsigned));
01272      p1->F[ix] |= bx;      /* Set i'th bit to one */
01273      NEXT(ix, bx);
01274    }
01275 
01276 #ifdef DEBUGPP5
01277    fprintf(stderr,"nb of vertices=%d\n",i);
01278 #endif
01279 
01280    /* Walk the PD list with two pointers */
01281    ix = 0; bx=MSB;
01282    for (p1=PD;p1;p1=p1->next) {
01283      for (p2prev=p1,p2=p1->next;p2;p2prev=p2,p2=p2->next) {
01284         
01285        /* Find intersection */
01286        dx = PDomainIntersection(p1->Domain,p2->Domain,working_space);
01287        
01288        if (!dx || emptyQ(dx)) {
01289          
01290 #ifdef DEBUGPP5
01291          fprintf( stderr, "Empty dx (p1 inter p2). Continuing\n");
01292 #endif
01293          if(dx)
01294            Domain_Free(dx);
01295          continue;
01296        }
01297 
01298 #ifdef DEBUGPP5      
01299        fprintf(stderr,"Begin PDomainDifference\n");
01300        fprintf(stderr, "p1=");
01301        Polyhedron_Print(stderr,P_VALUE_FMT,p1->Domain);
01302        fprintf(stderr,"p2=");
01303        Polyhedron_Print(stderr,P_VALUE_FMT,p2->Domain);
01304 #endif
01305        d1 = PDomainDifference(p1->Domain,p2->Domain,working_space);
01306        d2 = PDomainDifference(p2->Domain,p1->Domain,working_space);       
01307 
01308 #ifdef DEBUGPP5       
01309        fprintf(stderr,"p1\\p2=");
01310        Polyhedron_Print(stderr,P_VALUE_FMT,d1);
01311        fprintf(stderr,"p2\\p1=");
01312        Polyhedron_Print(stderr,P_VALUE_FMT,d2);
01313        fprintf(stderr,"END PDomainDifference\n\n");       
01314 #endif
01315        if (!d1 || emptyQ(d1) || d1->NbEq!=0) {
01316 
01317 #ifdef DEBUGPP5
01318          fprintf(stderr,"Empty d1\n");
01319 #endif
01320          if (d1) 
01321            Domain_Free(d1);
01322          Domain_Free(dx);
01323          
01324          if (!d2 || emptyQ(d2) || d2->NbEq!=0) {
01325            
01326 #ifdef DEBUGPP5
01327            fprintf( stderr, "Empty d2 (deleting)\n");
01328 #endif
01329            /* dx = p1->Domain = p2->Domain */
01330            if (d2) Domain_Free(d2);
01331            
01332            /* Update p1 */
01333            for (i=0;i<nv;i++)
01334              p1->F[i] |= p2->F[i];
01335            
01336            /* Delete p2 */
01337            p2prev->next = p2->next;
01338            Domain_Free(p2->Domain);
01339            free(p2->F);
01340            free(p2);
01341            p2 = p2prev;
01342          }
01343          else {  /* d2 is not empty --> dx==p1->domain */
01344            
01345 #ifdef DEBUGPP5
01346            fprintf( stderr, "p2 replaced by d2\n");
01347 #endif
01348            /* Update p1 */
01349            for(i=0;i<nv;i++)
01350              p1->F[i] |= p2->F[i];
01351            
01352            /* Replace p2 with d2 */
01353            Domain_Free( p2->Domain );
01354            p2->Domain = d2;
01355          }
01356        }
01357        else { /* d1 is not empty */         
01358          if (!d2 || emptyQ(d2) || d2->NbEq!=0) {
01359            
01360 #ifdef DEBUGPP5
01361            fprintf( stderr, "p1 replaced by d1\n");
01362 #endif
01363            if (d2) Domain_Free(d2);
01364            
01365            /* dx = p2->domain */
01366            Domain_Free(dx);
01367            
01368            /* Update p2 */
01369            for(i=0;i<nv;i++)
01370              p2->F[i] |= p1->F[i];
01371 
01372            /* Replace p1 with d1 */
01373            Domain_Free(p1->Domain);
01374            p1->Domain = d1;
01375          }
01376          else { /*d2 is not empty-->d1,d2,dx are distinct */
01377            
01378 #ifdef DEBUGPP5
01379            fprintf(stderr,"Non-empty d1 and d2\nNew node created\n");
01380 #endif
01381            /* Create a new node for dx */
01382            PDNew = (Param_Domain *) malloc( sizeof(Param_Domain) );
01383            PDNew->F = (unsigned int *)malloc( nv*sizeof(int) );
01384            memset(PDNew->F,0,nv*sizeof(int));
01385            PDNew->Domain = dx;
01386            
01387            for (i=0;i<nv;i++)
01388              PDNew->F[i] = p1->F[i] | p2->F[i];
01389            
01390            /* Replace p1 with d1 */
01391            Domain_Free( p1->Domain );
01392            p1->Domain = d1;
01393            
01394            /* Replace p2 with d2 */
01395            Domain_Free( p2->Domain );
01396            p2->Domain = d2;
01397            
01398            /* Insert new node after p1 */
01399            PDNew->next = p1->next;
01400            p1->next = PDNew;
01401          }
01402        }
01403      }  /* end of p2 scan */
01404      if (p1->Domain->next) {
01405         Polyhedron *C = DomainConvex(p1->Domain, working_space);
01406         Domain_Free(p1->Domain);
01407         p1->Domain = C;
01408      }
01409    } /* end of p1 scan */
01410 } /* Compute_PDomains */
01411                                         
01412 /* 
01413  * Given a polyhedron 'Din' in combined data and parametre space, a context
01414  * polyhedron 'Cin' representing the constraints on the parameter space and 
01415  * a working space size 'working_space', return a parametric polyhedron with
01416  * a list of parametric vertices and their defining domains. 
01417  */
01418 Param_Polyhedron *Polyhedron2Param_Vertices(Polyhedron *Din,Polyhedron *Cin,int working_space) {
01419   
01420   Param_Polyhedron *result;
01421   
01422   POL_ENSURE_FACETS(Din);
01423   POL_ENSURE_VERTICES(Din);
01424   POL_ENSURE_FACETS(Cin);
01425   POL_ENSURE_VERTICES(Cin);
01426  
01427 #ifdef DEBUGPP
01428   fprintf(stderr,"Polyhedron2Param_Vertices algorithm starting at : %.2fs\n",
01429           (float)clock()/CLOCKS_PER_SEC);
01430 #endif
01431   
01432   /***************** Scan the m-faces ****************/
01433   result = Find_m_faces(&Din,Cin,0,working_space,NULL,NULL);
01434   
01435 #ifdef DEBUGPP
01436   fprintf(stderr, "nb of points : %d\n",result->nbV);
01437 #endif
01438   
01439 #ifdef DEBUGPP
01440   fprintf(stderr, "end main loop : %.2fs\n", (float)clock()/CLOCKS_PER_SEC);
01441 #endif
01442   
01443   return(result);
01444 } /* Polyhedron2Param_Vertices */
01445 
01446 /*
01447  * Free the memory allocated to a list of parametrized vertices  
01448  */
01449 void Param_Vertices_Free(Param_Vertices *PV) {
01450   
01451   Param_Vertices *next_pv;
01452   
01453   while(PV) {
01454     next_pv = PV->next;
01455     if (PV->Vertex) Matrix_Free(PV->Vertex);
01456     if (PV->Domain) Matrix_Free(PV->Domain);
01457     free(PV);  
01458     PV = next_pv;
01459   }
01460 } /* Param_Vertices_Free */
01461 
01462 /*
01463  * Print a list of parametrized vertices *
01464  */
01465 void Print_Vertex(FILE *DST,Matrix *V,char **param_names){
01466   
01467   int l, v;
01468   int first;
01469   Value gcd,tmp;
01470   
01471   value_init(gcd); value_init(tmp);
01472   
01473   fprintf(DST, "[" );
01474   for(l=0;l<V->NbRows;++l){
01475     
01476     /* Variables */
01477     first=1;
01478     fprintf(DST, " " );
01479     for(v=0;v < V->NbColumns-2;++v) {
01480       if(value_notzero_p(V->p[l][v])) {
01481         Gcd(V->p[l][v],V->p[l][V->NbColumns-1],&gcd);
01482         value_absolute(gcd,gcd);
01483         value_division(tmp,V->p[l][v],gcd);
01484         if(value_posz_p(tmp)) {
01485           if(!first) 
01486             fprintf(DST, "+");
01487           value_division(tmp,V->p[l][v],gcd);
01488           if(value_notone_p(tmp)) { 
01489             value_print(DST,VALUE_FMT,tmp);
01490           }  
01491         }
01492         else { /* V->p[l][v]/gcd<0 */
01493           value_division(tmp,V->p[l][v],gcd);
01494           if(value_mone_p(tmp))
01495             fprintf(DST, "-" );
01496           else {
01497             value_print(DST,VALUE_FMT,tmp);
01498           }
01499         }
01500         value_division(tmp,V->p[l][V->NbColumns-1],gcd);
01501         if(value_notone_p(tmp)) {
01502           fprintf(DST, "%s/", param_names[v]);
01503           value_print(DST,VALUE_FMT,tmp);
01504         }
01505         else
01506           fprintf(DST, "%s", param_names[v]);
01507         first=0;
01508       }
01509     }
01510 
01511     /* Constant */
01512     if(value_notzero_p(V->p[l][v]) || first) {
01513       if(value_posz_p(V->p[l][v]) && !first)
01514         fprintf(DST,"+");
01515         Gcd(V->p[l][v],V->p[l][V->NbColumns-1],&gcd);
01516       value_absolute(gcd,gcd);
01517       value_division(tmp,V->p[l][v],gcd);
01518       value_print(DST,VALUE_FMT,tmp);
01519       value_division(tmp,V->p[l][V->NbColumns-1],gcd);
01520       if(value_notone_p(tmp)) {
01521         fprintf(DST,"/");
01522         value_print(DST,VALUE_FMT,tmp);
01523         fprintf(DST," ");
01524       }
01525     }
01526     if (l<V->NbRows-1) 
01527       fprintf(DST, ", ");
01528   }
01529   fprintf(DST, " ]");
01530   value_clear(gcd); value_clear(tmp);
01531   return;
01532 } /* Print_Vertex */
01533 
01534 /*----------------------------------------------------------------------*/
01535 /* VertexCT                                                             */
01536 /* convert a paramvertex from reduced space to normal m-space           */
01537 /*----------------------------------------------------------------------*/
01538 Matrix *VertexCT(Matrix *V,Matrix *CT) {
01539   
01540   Matrix *Vt;
01541   int i,j,k;
01542   
01543   if(CT) {
01544     
01545     /* Have to transform the vertices to original dimension */
01546     Vt = Matrix_Alloc(V->NbRows,CT->NbColumns+1);
01547     for(i=0;i<V->NbRows;++i) {
01548       value_assign(Vt->p[i][CT->NbColumns],V->p[i][V->NbColumns-1]);
01549       for(j=0;j<CT->NbColumns;j++) {
01550         for(k=0;k<CT->NbRows;k++)
01551           if(value_notzero_p(CT->p[k][j]))
01552             break;
01553         if(k<CT->NbRows)
01554           value_assign(Vt->p[i][j],V->p[i][k]);
01555         else
01556           value_set_si(Vt->p[i][j],0);
01557       }
01558     }
01559     return(Vt);
01560   }
01561   else
01562     return(NULL);
01563 } /* VertexCT */
01564 
01565 /*
01566  * Print the validity Domain 'D' of a parametric polyhedron 
01567  */ 
01568 void Print_Domain(FILE *DST,Polyhedron *D,char **pname) {
01569   
01570   int l, v;
01571   int first;
01572   
01573   POL_ENSURE_FACETS(D);
01574   POL_ENSURE_VERTICES(D);
01575  
01576   for(l=0;l<D->NbConstraints;++l) {
01577     fprintf(DST, "         ");
01578     first = 1;
01579     for(v=1;v<=D->Dimension;++v) {
01580       if(value_notzero_p(D->Constraint[l][v])) {
01581         if(value_one_p(D->Constraint[l][v])) {
01582           if(first)
01583             fprintf(DST, "%s ", pname[v-1]);
01584           else
01585             fprintf(DST, "+ %s ", pname[v-1] );
01586         }
01587         else if(value_mone_p(D->Constraint[l][v]))
01588           fprintf(DST, "- %s ", pname[v-1] );
01589         else {
01590           if(value_pos_p(D->Constraint[l][v]) && !first )
01591             fprintf(DST, "+ " );
01592           value_print(DST,VALUE_FMT,D->Constraint[l][v]);
01593           fprintf(DST,"%s ",pname[v-1]);
01594         }
01595         first = 0;
01596       }
01597     }
01598     if(value_notzero_p(D->Constraint[l][v])) {
01599       if(value_pos_p(D->Constraint[l][v]) && !first)
01600         fprintf(DST,"+");
01601       fprintf(DST," ");
01602       value_print(DST,VALUE_FMT,D->Constraint[l][v]);
01603     }
01604     fprintf(DST,(value_notzero_p(D->Constraint[l][0])) ?" >= 0":" = 0");
01605     fprintf(DST, "\n" );
01606   }
01607   fprintf(DST, "\n");
01608 
01609         if( D->next )
01610         {
01611                 fprintf( DST, "UNION\n" );
01612                 Print_Domain( DST, D->next, pname );
01613         }
01614   return;
01615 } /* Print_Domain */
01616 
01617 /* 
01618  * Given a list of parametrized vertices and an array of parameter names, Print
01619  * a list of parametrized vertices in a comprehensible format. 
01620  */
01621 void Param_Vertices_Print(FILE *DST,Param_Vertices *PV,char **param_names) {
01622    
01623   Polyhedron *poly;
01624   
01625   while(PV) {
01626     fprintf(DST, "Vertex :\n" );
01627     Print_Vertex(DST,PV->Vertex,param_names);
01628     
01629     /* Pour le domaine : */
01630     fprintf(DST, "   If :\n" );
01631     poly = Constraints2Polyhedron(PV->Domain,200);
01632     Print_Domain(DST,poly,param_names);
01633     Domain_Free(poly);   
01634     PV = PV->next;
01635   }
01636   return;
01637 } /* Param_Vertices_Print */
01638 
01639 /* 
01640  * Given a polyhedron 'Din' in combined data and parametre space, a context
01641  * polyhedron 'Cin' representing the constraints on the parameter space and 
01642  * a working space size 'working_space', return a parametric polyhedron with
01643  * a list of distinct validity domains and a complete list of valid vertices 
01644  * associated to each validity domain. 
01645  */
01646 Param_Polyhedron *Polyhedron2Param_Domain(Polyhedron *Din,Polyhedron *Cin,int working_space) {
01647                 
01648   Param_Polyhedron *result;
01649   Param_Domain *D;
01650 
01651   POL_ENSURE_FACETS(Din);
01652   POL_ENSURE_VERTICES(Din);
01653   POL_ENSURE_FACETS(Cin);
01654   POL_ENSURE_VERTICES(Cin);
01655  
01656 #ifdef DEBUGPP
01657   fprintf(stderr,"Polyhedron2Param_Polyhedron algorithm starting at : %.2fs\n",
01658           (float)clock()/CLOCKS_PER_SEC);
01659 #endif
01660   
01661   /* Find the m-faces, keeping the corresponding domains */
01662   /* in the linked list PDomains */
01663   result = Find_m_faces(&Din,Cin,1,working_space,NULL,NULL);
01664   
01665 #ifdef DEBUGPP
01666   if(result) fprintf(stderr, "Number of vertices : %d\n",result->nbV);
01667   fprintf(stderr,"Vertices found at : %.2fs\n",(float)clock()/CLOCKS_PER_SEC);
01668 #endif
01669   
01670   /* Processing of PVResult and PDomains */
01671   if(result && Cin->Dimension>0)                /* at least 1 parameter */
01672     Compute_PDomains(result->D,result->nbV,working_space);
01673   if(result && CEqualities)
01674     for(D=result->D;D;D=D->next)
01675       D->Domain = Add_CEqualities(D->Domain);
01676   Polyhedron_Free(CEqualities); 
01677   
01678 #ifdef DEBUGPP
01679   fprintf(stderr, "domains found at : %.2fs\n", (float)clock()/CLOCKS_PER_SEC);
01680 #endif
01681 
01682   return(result);
01683 } /* Polyhedon2Param_Domain */
01684 
01685 /*
01686  *
01687  */
01688 Param_Polyhedron *Polyhedron2Param_SimplifiedDomain(Polyhedron **Din,Polyhedron *Cin,int working_space,Polyhedron **CEq,Matrix **CT) {
01689                                                      
01690   Param_Polyhedron *result;
01691 
01692   assert(CEq != NULL);
01693   assert(CT != NULL);
01694 
01695   POL_ENSURE_FACETS(*Din);
01696   POL_ENSURE_VERTICES(*Din);
01697   POL_ENSURE_FACETS(Cin);
01698   POL_ENSURE_VERTICES(Cin);
01699  
01700 #ifdef DEBUGPP
01701   fprintf(stderr,"Polyhedron2Param_Polyhedron algorithm starting at : %.2fs\n",
01702           (float)clock()/CLOCKS_PER_SEC);
01703 #endif
01704   
01705   /* Find the m-faces, keeping the corresponding domains */
01706   /* in the linked list PDomains */
01707   result = Find_m_faces(Din,Cin,1,working_space,CEq,CT);
01708   
01709 #ifdef DEBUGPP
01710   if(result) fprintf(stderr, "Number of vertices : %d\n",result->nbV);
01711   fprintf(stderr,"Vertices found at : %.2fs\n",(float)clock()/CLOCKS_PER_SEC);
01712 #endif
01713 
01714   /* Processing of PVResult and PDomains */
01715   if(result && Cin->Dimension>0)                /* at least 1 parameter */
01716     Compute_PDomains(result->D,result->nbV,working_space);
01717   
01718   /* Removed this, Vin100, March 01 */
01719   /*    if(result && CEqualities )
01720         for(D=result->D;D;D=D->next)
01721         D->Domain = Add_CEqualities(D->Domain);
01722   */
01723   
01724 #ifdef DEBUGPP
01725   fprintf(stderr, "domains found at : %.2fs\n", (float)clock()/CLOCKS_PER_SEC);
01726 #endif
01727   
01728   return(result);
01729 } /* Polyhedron2Param_SimplifiedDomain */
01730 
01731 /*
01732  * Free the memory allocated to a list of validity domain of a parametrized 
01733  * polyhedron.
01734  */
01735 void Param_Domain_Free(Param_Domain *PD) {
01736         
01737   Param_Domain *next_pd;
01738   
01739   while(PD) {
01740     free(PD->F);
01741     Domain_Free(PD->Domain);
01742     next_pd = PD->next;
01743     free(PD);
01744     PD = next_pd;
01745   }
01746   return;
01747 } /* Param_Domain_Free */
01748 
01749 /*
01750  * Free the memory allocated to a parametric polyhedron 'P' 
01751  */
01752 void Param_Polyhedron_Free(Param_Polyhedron *P) {
01753   
01754   if (!P) return;
01755   Param_Vertices_Free(P->V);
01756   Param_Domain_Free(P->D);
01757   free(P);
01758   return;
01759 } /* Param_Polyhedron_Free */
01760 
01761 /*
01762  * Scales the parametric polyhedron such that all vertices are integer.
01763  */
01764 void Param_Polyhedron_Scale_Integer(Param_Polyhedron *PP, Polyhedron **P,
01765                                     Value *det, unsigned MaxRays)
01766 {
01767   int i;
01768   int nb_param, nb_vars;
01769   Vector *denoms;
01770   Param_Vertices *V;
01771   Value global_var_lcm;
01772   Matrix *expansion;
01773 
01774   value_set_si(*det, 1);
01775   if (!PP->nbV)
01776     return;
01777 
01778   nb_param = PP->D->Domain->Dimension;
01779   nb_vars = PP->V->Vertex->NbRows;
01780 
01781   /* Scan the vertices and make an orthogonal expansion of the variable
01782      space */
01783   /* a- prepare the array of common denominators */
01784   denoms = Vector_Alloc(nb_vars);
01785   value_init(global_var_lcm);
01786 
01787   /* b- scan the vertices and compute the variables' global lcms */
01788   for (V = PP->V; V; V = V->next)
01789     for (i = 0; i < nb_vars; i++)
01790       Lcm3(denoms->p[i], V->Vertex->p[i][nb_param+1], &denoms->p[i]);
01791 
01792   value_set_si(global_var_lcm, 1);
01793   for (i = 0; i < nb_vars; i++) {
01794     value_multiply(*det, *det, denoms->p[i]);
01795     Lcm3(global_var_lcm, denoms->p[i], &global_var_lcm);
01796   }
01797 
01798   /* scale vertices */
01799   for (V = PP->V; V; V = V->next)
01800     for (i = 0; i < nb_vars; i++) {
01801       Vector_Scale(V->Vertex->p[i], V->Vertex->p[i], denoms->p[i], nb_param+1);
01802       Vector_Normalize(V->Vertex->p[i], nb_param+2);
01803     }
01804 
01805   /* the expansion can be actually writen as global_var_lcm.L^{-1} */
01806   /* this is equivalent to multiply the rows of P by denoms_det */
01807   for (i = 0; i < nb_vars; i++)
01808     value_division(denoms->p[i], global_var_lcm, denoms->p[i]);
01809 
01810   /* OPT : we could use a vector instead of a diagonal matrix here (c- and d-).*/
01811   /* c- make the quick expansion matrix */
01812   expansion = Matrix_Alloc(nb_vars+nb_param+1, nb_vars+nb_param+1);
01813   for (i = 0; i < nb_vars; i++)
01814     value_assign(expansion->p[i][i], denoms->p[i]);
01815   for (i = nb_vars; i < nb_vars+nb_param+1; i++)
01816     value_assign(expansion->p[i][i], global_var_lcm);
01817 
01818   /* d- apply the variable expansion to the polyhedron */
01819   if (P)
01820     *P = Polyhedron_Preimage(*P, expansion, MaxRays);
01821 
01822   Matrix_Free(expansion);
01823   value_clear(global_var_lcm);
01824   Vector_Free(denoms);
01825 }

Generated on Mon Apr 23 19:23:53 2007 for polylib by doxygen 1.3.5