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

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