polylib: polyparam.c Source File

- Main Page
- Classes
- Files

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