polylib: polyparam.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# polyparam.c

Go to the documentation of this file.

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