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

ehrhart.c

Go to the documentation of this file.
00001 /***********************************************************************/
00002 /*                Ehrhart V4.20                                        */
00003 /*                copyright 1997, Doran Wilde                          */
00004 /*                copyright 1997-2000, Vincent Loechner                */
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 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <ctype.h>
00014 #include <string.h>
00015 #include <unistd.h>
00016 #include <assert.h>
00017 
00018 #include <polylib/polylib.h>
00019 #include <polylib/homogenization.h>
00020 
00021 
00022 /*! \class Ehrhart
00023 
00024 The following are mainly for debug purposes. You shouldn't need to
00025 change anything for daily usage...
00026 
00027 <p>
00028 
00029 you may define each macro independently 
00030 <ol>
00031 <li> #define EDEBUG minimal debug 
00032 <li> #define EDEBUG1 prints enumeration points
00033 <li> #define EDEBUG11 prints number of points
00034 <li> #define EDEBUG2 prints domains
00035 <li> #define EDEBUG21 prints more domains
00036 <li> #define EDEBUG3 prints systems of equations that are solved
00037 <li> #define EDEBUG4 prints message for degree reduction
00038 <li> #define EDEBUG5 prints result before simplification 
00039 <li> #define EDEBUG6 prints domains in Preprocess 
00040 <li> #define EDEBUG61 prints even more in Preprocess
00041 <li> #define EDEBUG62 prints domains in Preprocess2
00042 </ol>
00043 */
00044 
00045 
00046 /** 
00047     
00048 define this to print all constraints on the validity domains if not
00049 defined, only new constraints (not in validity domain given by the
00050 user) are printed
00051 
00052 */
00053 #define EPRINT_ALL_VALIDITY_CONSTRAINTS
00054 
00055 /* #define EDEBUG       */              /* minimal debug */
00056 /* #define EDEBUG1      */              /* prints enumeration points */
00057 /* #define EDEBUG11     */              /* prints number of points */
00058 /* #define EDEBUG2      */              /* prints domains */
00059 /* #define EDEBUG21     */              /* prints more domains */
00060 /* #define EDEBUG3      */              /* prints systems of equations that are solved */
00061 /* #define EDEBUG4      */              /* prints message for degree reduction */
00062 /* #define EDEBUG5      */              /* prints result before simplification */
00063 /* #define EDEBUG6      */              /* prints domains in Preprocess */
00064 /* #define EDEBUG61     */              /* prints even more in Preprocess */
00065 /* #define EDEBUG62     */              /* prints domains in Preprocess2 */
00066 
00067 
00068 /**
00069  Reduce the degree of resulting polynomials
00070 */
00071 #define REDUCE_DEGREE
00072 
00073 /** 
00074 define this to print one warning message per domain overflow these
00075 overflows should no longer happen since version 4.20
00076 */
00077 #define ALL_OVERFLOW_WARNINGS
00078 
00079 /******************* -----------END USER #DEFS-------- *********************/
00080 
00081 int overflow_warning_flag = 1;
00082 
00083 /*-------------------------------------------------------------------*/
00084 /* EHRHART POLYNOMIAL SYMBOLIC ALGEBRA SYSTEM                        */
00085 /*-------------------------------------------------------------------*/ 
00086 /** 
00087 
00088 EHRHART POLYNOMIAL SYMBOLIC ALGEBRA SYSTEM. The newly allocated enode
00089 can be freed with a simple free(x)
00090 
00091 @param type : enode type
00092 @param size : degree+1 for polynomial, period for periodic
00093 @param pos  : 1..nb_param, position of parameter            
00094 @return a newly allocated enode 
00095 
00096 */
00097 enode *new_enode(enode_type type,int size,int pos) {
00098   
00099   enode *res;
00100   int i;
00101   
00102   if(size == 0) {
00103     fprintf(stderr, "Allocating enode of size 0 !\n" );
00104     return NULL;
00105   }
00106   res = (enode *) malloc(sizeof(enode) + (size-1)*sizeof(evalue));
00107   res->type = type;
00108   res->size = size;
00109   res->pos = pos;
00110   for(i=0; i<size; i++) {
00111     value_init(res->arr[i].d);
00112     value_set_si(res->arr[i].d,0);
00113     res->arr[i].x.p = 0;
00114   }
00115   return res;
00116 } /* new_enode */
00117 
00118 /**
00119 releases all memory referenced by e.  (recursive)        
00120 @param e pointer to an evalue
00121 */
00122 void free_evalue_refs(evalue *e) {
00123   
00124   enode *p;
00125   int i;
00126   
00127   if (value_notzero_p(e->d)) {
00128     
00129     /* 'e' stores a constant */
00130     value_clear(e->d);
00131     value_clear(e->x.n);
00132     return; 
00133   }  
00134   value_clear(e->d);
00135   p = e->x.p;
00136   if (!p) return;       /* null pointer */
00137   for (i=0; i<p->size; i++) {
00138     free_evalue_refs(&(p->arr[i]));
00139   }
00140   free(p);
00141   return;
00142 } /* free_evalue_refs */
00143 
00144 /**
00145 
00146 @param e pointer to an evalue 
00147 @return description
00148 
00149 */
00150 enode *ecopy(enode *e) {
00151   
00152   enode *res;
00153   int i;
00154   
00155   res = new_enode(e->type,e->size,e->pos);
00156   for(i=0;i<e->size;++i) {
00157     value_assign(res->arr[i].d,e->arr[i].d);
00158     if(value_zero_p(res->arr[i].d))
00159       res->arr[i].x.p = ecopy(e->arr[i].x.p);
00160     else {
00161       value_init(res->arr[i].x.n);
00162       value_assign(res->arr[i].x.n,e->arr[i].x.n);
00163     }
00164   }
00165   return(res);
00166 } /* ecopy */
00167 
00168 /**
00169 
00170 @param DST destination file
00171 @param e pointer to evalue to be printed
00172 @param pname array of strings, name of the parameters
00173 
00174 */
00175 void print_evalue(FILE *DST,evalue *e,char **pname) {
00176   
00177   if(value_notzero_p(e->d)) {    
00178     if(value_notone_p(e->d)) {
00179       value_print(DST,VALUE_FMT,e->x.n);
00180       fprintf(DST,"/");
00181       value_print(DST,VALUE_FMT,e->d);
00182     }  
00183     else {
00184       value_print(DST,VALUE_FMT,e->x.n);
00185     }
00186   }  
00187   else
00188     print_enode(DST,e->x.p,pname);
00189   return;
00190 } /* print_evalue */
00191 
00192 /** prints the enode  to DST  
00193 
00194 @param DST destination file 
00195 @param p pointer to enode  to be printed 
00196 @param pname array of strings, name of the parameters
00197 
00198 */
00199 void print_enode(FILE *DST,enode *p,char **pname) {
00200   
00201   int i;
00202   
00203   if (!p) {
00204     fprintf(DST, "NULL");
00205     return;
00206   }
00207   if (p->type == evector) {
00208     fprintf(DST, "{ ");
00209     for (i=0; i<p->size; i++) {
00210       print_evalue(DST, &p->arr[i], pname);
00211       if (i!=(p->size-1))
00212         fprintf(DST, ", ");
00213     }
00214     fprintf(DST, " }\n");
00215   }
00216   else if (p->type == polynomial) {
00217     fprintf(DST, "( ");
00218     for (i=p->size-1; i>=0; i--) {
00219       print_evalue(DST, &p->arr[i], pname);
00220       if (i==1) fprintf(DST, " * %s + ", pname[p->pos-1]);
00221       else if (i>1) 
00222         fprintf(DST, " * %s^%d + ", pname[p->pos-1], i);
00223     }
00224     fprintf(DST, " )\n");
00225   }
00226   else if (p->type == periodic) {
00227     fprintf(DST, "[ ");
00228     for (i=0; i<p->size; i++) {
00229       print_evalue(DST, &p->arr[i], pname);
00230       if (i!=(p->size-1)) fprintf(DST, ", ");
00231     }
00232     fprintf(DST," ]_%s", pname[p->pos-1]);
00233   }
00234   return;
00235 } /* print_enode */ 
00236 
00237 /**
00238 
00239 @param  e1 pointers to evalues
00240 @param  e2 pointers to evalues
00241 @return 1 (true) if they are equal, 0 (false) if not       
00242 
00243 */
00244 static int eequal(evalue *e1,evalue *e2) { 
00245  
00246     int i;
00247     enode *p1, *p2;
00248   
00249     if (value_ne(e1->d,e2->d))
00250         return 0;
00251   
00252     /* e1->d == e2->d */
00253     if (value_notzero_p(e1->d)) {    
00254         if (value_ne(e1->x.n,e2->x.n))
00255             return 0;
00256     
00257         /* e1->d == e2->d != 0  AND e1->n == e2->n */
00258         return 1;
00259     }
00260   
00261     /* e1->d == e2->d == 0 */
00262     p1 = e1->x.p;
00263     p2 = e2->x.p;
00264     if (p1->type != p2->type) return 0;
00265     if (p1->size != p2->size) return 0;
00266     if (p1->pos  != p2->pos) return 0;
00267     for (i=0; i<p1->size; i++)
00268         if (!eequal(&p1->arr[i], &p2->arr[i]) ) 
00269             return 0;
00270     return 1;
00271 } /* eequal */
00272 
00273 /** 
00274 
00275 @param e pointer to an evalue
00276 
00277 */
00278 void reduce_evalue (evalue *e) {
00279   
00280     enode *p;
00281     int i, j, k;
00282   
00283     if (value_notzero_p(e->d))
00284         return; /* a rational number, its already reduced */
00285     if(!(p = e->x.p))
00286         return; /* hum... an overflow probably occured */
00287   
00288     /* First reduce the components of p */
00289     for (i=0; i<p->size; i++)
00290         reduce_evalue(&p->arr[i]);
00291 
00292     if (p->type==periodic) {
00293     
00294         /* Try to reduce the period */
00295         for (i=1; i<=(p->size)/2; i++) {
00296             if ((p->size % i)==0) {
00297         
00298                 /* Can we reduce the size to i ? */
00299                 for (j=0; j<i; j++)
00300                     for (k=j+i; k<e->x.p->size; k+=i)
00301                         if (!eequal(&p->arr[j], &p->arr[k])) goto you_lose;
00302 
00303                 /* OK, lets do it */
00304                 for (j=i; j<p->size; j++) free_evalue_refs(&p->arr[j]);
00305                 p->size = i;
00306                 break;
00307 
00308             you_lose:   /* OK, lets not do it */
00309                 continue;
00310             }
00311         }
00312 
00313         /* Try to reduce its strength */
00314         if (p->size == 1) {
00315             value_clear(e->d);
00316             memcpy(e,&p->arr[0],sizeof(evalue));
00317             free(p);
00318         }
00319     }
00320     else if (p->type==polynomial) {
00321           
00322         /* Try to reduce the degree */
00323         for (i=p->size-1;i>=1;i--) {
00324             if (!(value_one_p(p->arr[i].d) && value_zero_p(p->arr[i].x.n)))
00325                 break;
00326             /* Zero coefficient */
00327             free_evalue_refs(&p->arr[i]);
00328         }
00329         if (i+1<p->size)
00330             p->size = i+1;
00331 
00332         /* Try to reduce its strength */
00333         if (p->size == 1) {
00334             value_clear(e->d);
00335             memcpy(e,&p->arr[0],sizeof(evalue));
00336             free(p);
00337         }
00338     }
00339 } /* reduce_evalue */
00340 
00341 
00342 /**
00343 
00344 multiplies two evalues and puts the result in res
00345 
00346 @param e1 pointer to an evalue
00347 @param e2 pointer to a constant evalue
00348 @param res  pointer to result evalue = e1 * e2
00349 
00350 */
00351 static void emul (evalue *e1,evalue *e2,evalue *res) {
00352   
00353     enode *p;
00354     int i;
00355     Value g;
00356 
00357     if (value_zero_p(e2->d)) {
00358         fprintf(stderr, "emul: ?expecting constant value\n");
00359         return;
00360     }  
00361     value_init(g);
00362     if (value_notzero_p(e1->d)) {
00363     
00364         value_init(res->x.n);
00365         /* Product of two rational numbers */
00366         value_multiply(res->d,e1->d,e2->d);
00367         value_multiply(res->x.n,e1->x.n,e2->x.n );
00368         Gcd(res->x.n, res->d,&g);
00369         if (value_notone_p(g)) {
00370             value_division(res->d,res->d,g);
00371             value_division(res->x.n,res->x.n,g);
00372         }
00373     }
00374     else { /* e1 is an expression */    
00375         value_set_si(res->d,0);
00376         p = e1->x.p;
00377         res->x.p = new_enode(p->type, p->size, p->pos);
00378         for (i=0; i<p->size; i++) {
00379             emul(&p->arr[i], e2, &(res->x.p->arr[i]) ); 
00380         }
00381     }
00382     value_clear(g);
00383     return;
00384 } /* emul */
00385 
00386 /**
00387 adds one evalue to evalue 'res. result = res + e1 
00388 
00389 @param e1 an evalue 
00390 @param res 
00391 
00392 */
00393 void eadd(evalue *e1,evalue *res) {
00394 
00395   int i;
00396   Value g,m1,m2;
00397  
00398   value_init(g);
00399   value_init(m1);
00400   value_init(m2);
00401   
00402   if (value_notzero_p(e1->d) && value_notzero_p(res->d)) {
00403     
00404     /* Add two rational numbers*/
00405     value_multiply(m1,e1->x.n,res->d);
00406     value_multiply(m2,res->x.n,e1->d);
00407     value_addto(res->x.n,m1,m2);
00408     value_multiply(res->d,e1->d,res->d);  
00409     Gcd(res->x.n,res->d,&g);
00410     if (value_notone_p(g)) {  
00411       value_division(res->d,res->d,g);
00412       value_division(res->x.n,res->x.n,g);
00413     }
00414     value_clear(g); value_clear(m1); value_clear(m2);
00415     return;
00416   }
00417   else if (value_notzero_p(e1->d) && value_zero_p(res->d)) {
00418     if (res->x.p->type==polynomial) {
00419       
00420       /* Add the constant to the constant term */
00421       eadd(e1, &res->x.p->arr[0]);
00422       value_clear(g); value_clear(m1); value_clear(m2);
00423       return;
00424     }
00425     else if (res->x.p->type==periodic) {
00426       
00427       /* Add the constant to all elements of periodic number */
00428       for (i=0; i<res->x.p->size; i++) { 
00429         eadd(e1, &res->x.p->arr[i]);
00430       }
00431       value_clear(g); value_clear(m1); value_clear(m2);
00432       return;
00433     }
00434     else {
00435       fprintf(stderr, "eadd: cannot add const with vector\n");
00436       value_clear(g); value_clear(m1); value_clear(m2);
00437       return;
00438     }
00439   }
00440   else if (value_zero_p(e1->d) && value_notzero_p(res->d)) {
00441     fprintf(stderr,"eadd: cannot add evalue to const\n");
00442     value_clear(g); value_clear(m1); value_clear(m2);
00443     return;
00444   }
00445   else {    /* ((e1->d==0) && (res->d==0)) */  
00446     if ((e1->x.p->type != res->x.p->type) ||
00447         (e1->x.p->pos  != res->x.p->pos )) {
00448       fprintf(stderr, "eadd: ?cannot add, incompatible types\n");
00449       value_clear(g); value_clear(m1); value_clear(m2);
00450       return;
00451     }
00452     if (e1->x.p->size == res->x.p->size) {
00453       for (i=0; i<res->x.p->size; i++) {
00454         eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
00455       }
00456       value_clear(g); value_clear(m1); value_clear(m2);
00457       return;
00458     }
00459     
00460     /* Sizes are different */
00461     if (res->x.p->type==polynomial) { 
00462       
00463       /* VIN100: if e1-size > res-size you have to copy e1 in a   */
00464       /* new enode and add res to that new node. If you do not do */
00465       /* that, you lose the the upper weight part of e1 !         */
00466       
00467       if(e1->x.p->size > res->x.p->size) {
00468         enode *tmp;
00469         tmp = ecopy(e1->x.p);
00470         for(i=0;i<res->x.p->size;++i) {
00471           eadd(&res->x.p->arr[i], &tmp->arr[i]);
00472           free_evalue_refs(&res->x.p->arr[i]);
00473         }
00474         res->x.p = tmp;
00475       }
00476       else {
00477         for (i=0; i<e1->x.p->size ; i++) {
00478           eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
00479         }
00480         value_clear(g); value_clear(m1); value_clear(m2);
00481         return;
00482       }
00483     }
00484     else if (res->x.p->type==periodic) {
00485       fprintf(stderr, "eadd: ?addition of different sized periodic nos\n");
00486       value_clear(g); value_clear(m1); value_clear(m2);
00487       return;
00488     }
00489     else { /* evector */
00490       fprintf(stderr, "eadd: ?cannot add vectors of different length\n");
00491       value_clear(g); value_clear(m1); value_clear(m2);
00492       return;
00493     }
00494   }
00495   value_clear(g); value_clear(m1); value_clear(m2);
00496   return;
00497 } /* eadd */
00498 
00499 /** 
00500 
00501 computes the inner product of two vectors. Result = result (evalue) =
00502 v1.v2 (dot product)
00503 
00504 @param  v1 an enode (vector)
00505 @param  v2 an enode (vector of constants)
00506 @param res result (evalue)
00507 
00508 */
00509 void edot(enode *v1,enode *v2,evalue *res) {
00510   
00511     int i;
00512     evalue tmp;
00513   
00514     if ((v1->type != evector) || (v2->type != evector)) {
00515         fprintf(stderr, "edot: ?expecting vectors\n");
00516         return;
00517     }
00518     if (v1->size != v2->size) {
00519         fprintf(stderr, "edot: ? vector lengths do not agree\n");
00520         return;
00521     }
00522     if (v1->size<=0) {
00523         value_set_si(res->d,1); /* set result to 0/1 */
00524         value_init(res->x.n);
00525         value_set_si(res->x.n,0);
00526         return;
00527     }
00528   
00529     /* vector v2 is expected to have only rational numbers in */
00530     /* the array.  No pointers. */  
00531     emul(&v1->arr[0],&v2->arr[0],res);
00532     for (i=1; i<v1->size; i++) {
00533         value_init(tmp.d);
00534      
00535         /* res = res + v1[i]*v2[i] */
00536         emul(&v1->arr[i],&v2->arr[i],&tmp);
00537         eadd(&tmp,res);
00538         free_evalue_refs(&tmp);
00539     }
00540     return;
00541 } /* edot */
00542 
00543 /**
00544 
00545 local recursive function used in the following ref contains the new
00546 position for each old index position
00547 
00548 @param e pointer to an evalue
00549 @param ref transformation Matrix
00550 
00551 */
00552 static void aep_evalue(evalue *e, int *ref) {
00553   
00554     enode *p;
00555     int i;
00556   
00557     if (value_notzero_p(e->d))
00558         return;         /* a rational number, its already reduced */
00559     if(!(p = e->x.p))
00560         return;         /* hum... an overflow probably occured */
00561   
00562     /* First check the components of p */
00563     for (i=0;i<p->size;i++)
00564         aep_evalue(&p->arr[i],ref);
00565   
00566     /* Then p itself */
00567     p->pos = ref[p->pos-1]+1;
00568     return;
00569 } /* aep_evalue */
00570 
00571 /** Comments */
00572 static void addeliminatedparams_evalue(evalue *e,Matrix *CT) {
00573         
00574     enode *p;
00575     int i, j;
00576     int *ref;
00577 
00578     if (value_notzero_p(e->d))
00579         return;          /* a rational number, its already reduced */
00580     if(!(p = e->x.p))
00581         return;          /* hum... an overflow probably occured */
00582   
00583     /* Compute ref */
00584     ref = (int *)malloc(sizeof(int)*(CT->NbRows-1));
00585     for(i=0;i<CT->NbRows-1;i++)
00586         for(j=0;j<CT->NbColumns;j++)
00587             if(value_notzero_p(CT->p[i][j])) {
00588                 ref[i] = j;
00589                 break;
00590             }
00591   
00592     /* Transform the references in e, using ref */
00593     aep_evalue(e,ref);
00594     free( ref );
00595     return;
00596 } /* addeliminatedparams_evalue */
00597 
00598 /** 
00599 
00600 This procedure finds an integer point contained in polyhedron D /
00601 first checks for positive values, then for negative values returns
00602 TRUE on success. Result is in min.  returns FALSE if no integer point
00603 is found
00604 
00605 <p>
00606 
00607 This is the maximum number of iterations for a given parameter to find
00608 a integer point inside the context. Kind of weird. cherche_min should
00609 
00610 <p>
00611 
00612 @param min
00613 @param D
00614 @param pos
00615 
00616 */
00617  //FIXME: needs to be rewritten !
00618 #define MAXITER 100
00619 int cherche_min(Value *min,Polyhedron *D,int pos) {
00620         
00621     Value binf, bsup;   /* upper & lower bound */
00622     Value i;
00623     int flag, maxiter;
00624   
00625     if(!D)
00626         return(1);
00627     if(pos > D->Dimension)
00628         return(1);
00629   
00630     value_init(binf); value_init(bsup);
00631     value_init(i);
00632   
00633 #ifdef EDEBUG61
00634     fprintf(stderr,"Entering Cherche min --> \n");
00635     fprintf(stderr,"LowerUpperBounds :\n");
00636     fprintf(stderr,"pos = %d\n",pos);
00637     fprintf(stderr,"current min = (");
00638     value_print(stderr,P_VALUE_FMT,min[1]);
00639     {int j;
00640     for(j=2;j<=D->Dimension ; j++) {
00641         fprintf(stderr,", ");
00642         value_print(stderr,P_VALUE_FMT,min[j]);
00643     }  
00644     }
00645     fprintf(stderr,")\n");
00646 #endif
00647         
00648     flag = lower_upper_bounds(pos,D,min,&binf,&bsup);
00649   
00650 #ifdef EDEBUG61
00651     fprintf(stderr, "flag = %d\n", flag);
00652     fprintf(stderr,"binf = ");
00653     value_print(stderr,P_VALUE_FMT,binf);
00654     fprintf(stderr,"\n");
00655     fprintf(stderr,"bsup = ");
00656     value_print(stderr,P_VALUE_FMT,bsup);
00657     fprintf(stderr,"\n");
00658 #endif
00659 
00660     if(flag&LB_INFINITY)
00661         value_set_si(binf,0);
00662   
00663     /* Loop from 0 (or binf if positive) to bsup */
00664     for(maxiter=0,(((flag&LB_INFINITY) || value_neg_p(binf)) ? 
00665             value_set_si(i,0) : value_assign(i,binf));
00666         ((flag&UB_INFINITY) || value_le(i,bsup)) && maxiter<MAXITER ;
00667         value_increment(i,i),maxiter++) {
00668     
00669         value_assign(min[pos],i);
00670         if(cherche_min(min,D->next,pos+1)) {
00671             value_clear(binf); value_clear(bsup);
00672             value_clear(i);
00673             return(1);
00674         }  
00675     }
00676   
00677     /* Descending loop from -1 (or bsup if negative) to binf */
00678     if((flag&LB_INFINITY) || value_neg_p(binf))
00679         for(maxiter=0,(((flag&UB_INFINITY) || value_pos_p(bsup))?
00680                 value_set_si(i,-1)
00681                 :value_assign(i,bsup));
00682             ((flag&LB_INFINITY) || value_ge(i,binf)) && maxiter<MAXITER  ;
00683             value_decrement(i,i),maxiter++) {
00684 
00685             value_assign(min[pos],i);
00686             if(cherche_min(min,D->next,pos+1)) {
00687                 value_clear(binf); value_clear(bsup);
00688                 value_clear(i);
00689                 return(1);
00690             }   
00691         }
00692     value_clear(binf); value_clear(bsup);
00693     value_clear(i);
00694 
00695     value_set_si(min[pos],0);
00696     return(0);       /* not found :-( */
00697 } /* cherche_min */
00698 
00699 /** 
00700 
00701 This procedure finds the smallest parallelepiped of size
00702 '<i>size[i]</i>' for every dimension i, contained in polyhedron D.
00703 If this is not possible, NULL is returned
00704 
00705 <p>
00706 
00707 <pre>
00708 written by vin100, 2000, for version 4.19
00709 modified 2002, version 5.10
00710 </pre>
00711 
00712 <p>
00713 
00714 It first finds the coordinates of the lexicographically smallest edge
00715 of the hypercube, obtained by transforming the constraints of D (by
00716 adding 'size' as many times as there are negative coeficients in each
00717 constraint), and finding the lexicographical min of this
00718 polyhedron. Then it builds the hypercube and returns it.
00719 
00720 <p>
00721 @param D
00722 @param size
00723 @param MAXRAYS
00724 
00725 */
00726 
00727 Polyhedron *Polyhedron_Preprocess(Polyhedron *D,Value *size,unsigned MAXRAYS)
00728 {
00729     Matrix *M;
00730     int i, j, d;
00731     Polyhedron *T, *S, *H, *C;
00732     Value *min;
00733     //, tmp;
00734   
00735     // value_init(tmp);
00736     d = D->Dimension;
00737     if (MAXRAYS < 2*D->NbConstraints)
00738         MAXRAYS = 2*D->NbConstraints;
00739     M = Matrix_Alloc(MAXRAYS, D->Dimension+2);
00740     M->NbRows = D->NbConstraints;
00741   
00742     /* Original constraints */
00743     for(i=0;i<D->NbConstraints;i++)
00744         Vector_Copy(D->Constraint[i],M->p[i],(d+2));
00745 
00746 #ifdef EDEBUG6
00747     fprintf(stderr,"M for PreProcess : ");
00748     Matrix_Print(stderr,P_VALUE_FMT,M);
00749     fprintf(stderr,"\nsize == ");
00750     for( i=0 ; i<d ; i++ )
00751         value_print(stderr,P_VALUE_FMT,size[i]);
00752     fprintf(stderr,"\n");
00753 #endif
00754 
00755     /* Additionnal constraints */
00756     for(i=0;i<D->NbConstraints;i++) {
00757         if(value_zero_p(D->Constraint[i][0])) {
00758             fprintf(stderr,"Polyhedron_Preprocess: ");
00759             fprintf(stderr,"an equality was found where I did expect an inequality.\n");
00760             fprintf(stderr,"Trying to continue...\n");
00761             continue;
00762         }
00763         Vector_Copy(D->Constraint[i],M->p[M->NbRows],(d+2));
00764         for(j=1;j<=d;j++)
00765             if(value_neg_p(D->Constraint[i][j])) {
00766               // value_multiply(tmp,D->Constraint[i][j],size[j-1]);
00767               // value_addto(M->p[M->NbRows][d+1],M->p[M->NbRows][d+1],tmp);
00768               value_addmul(M->p[M->NbRows][d+1], D->Constraint[i][j], size[j-1]);
00769             }
00770     
00771         /* If anything changed, add this new constraint */
00772         if(value_ne(M->p[M->NbRows][d+1],D->Constraint[i][d+1]))
00773             M->NbRows ++ ;
00774     }
00775   
00776 #ifdef EDEBUG6
00777     fprintf(stderr,"M used to find min : ");
00778     Matrix_Print(stderr,P_VALUE_FMT,M);
00779 #endif
00780   
00781     T = Constraints2Polyhedron(M,MAXRAYS);
00782     Matrix_Free(M);
00783     if (!T || emptyQ(T)) {
00784         if(T)
00785             Polyhedron_Free(T);
00786         // value_clear(tmp);
00787         return(NULL);
00788     }
00789   
00790     /* Ok, now find the lexicographical min of T */
00791     min = (Value *) malloc(sizeof(Value) * (d+2));
00792     for(i=0;i<=d;i++) {
00793         value_init(min[i]);
00794         value_set_si(min[i],0);
00795     }  
00796     value_init(min[i]);
00797     value_set_si(min[i],1);
00798     C = Universe_Polyhedron(0);
00799     S = Polyhedron_Scan(T,C,MAXRAYS);
00800     Polyhedron_Free(C);
00801     Polyhedron_Free(T);
00802 
00803 #ifdef EDEBUG6
00804     for(i=0;i<=(d+1);i++) {
00805         value_print(stderr,P_VALUE_FMT,min[i]);
00806         fprintf(stderr," ,");
00807     }
00808     fprintf(stderr,"\n");
00809     Polyhedron_Print(stderr,P_VALUE_FMT,S);
00810     fprintf(stderr,"\n");
00811 #endif
00812     
00813     if (!cherche_min(min,S,1))
00814         {
00815             for(i=0;i<=(d+1);i++)
00816                 value_clear(min[i]);
00817             // value_clear(tmp);
00818             return(NULL);
00819         }
00820     Domain_Free(S);
00821   
00822 #ifdef EDEBUG6
00823     fprintf(stderr,"min = ( ");
00824     value_print(stderr,P_VALUE_FMT,min[1]);
00825     for(i=2;i<=d;i++) {
00826         fprintf(stderr,", ");
00827         value_print(stderr,P_VALUE_FMT,min[i]);
00828     }  
00829     fprintf(stderr,")\n");
00830 #endif
00831   
00832     /* Min is the point from which we can construct the hypercube */
00833     M = Matrix_Alloc(d*2,d+2);
00834     for(i=0;i<d;i++) {
00835     
00836         /* Creates inequality  1 0..0 1 0..0 -min[i+1] */
00837         value_set_si(M->p[2*i][0],1);
00838         for(j=1;j<=d;j++)
00839             value_set_si(M->p[2*i][j],0);
00840         value_set_si(M->p[2*i][i+1],1);
00841         value_oppose(M->p[2*i][d+1],min[i+1]);
00842     
00843         /* Creates inequality  1 0..0 -1 0..0 min[i+1]+size -1 */
00844         value_set_si(M->p[2*i+1][0],1);
00845         for(j=1;j<=d;j++)
00846             value_set_si(M->p[2*i+1][j],0);
00847         value_set_si(M->p[2*i+1][i+1],-1);
00848         value_addto(M->p[2*i+1][d+1],min[i+1],size[i]);
00849         value_sub_int(M->p[2*i+1][d+1],M->p[2*i+1][d+1],1);
00850     }
00851   
00852 #ifdef EDEBUG6
00853     fprintf(stderr,"PolyhedronPreprocess: constraints H = ");
00854     Matrix_Print(stderr,P_VALUE_FMT,M);
00855 #endif
00856   
00857     H = Constraints2Polyhedron(M,MAXRAYS);
00858   
00859 #ifdef EDEBUG6
00860     Polyhedron_Print(stderr,P_VALUE_FMT,H);
00861     fprintf(stderr,"\n");
00862 #endif
00863   
00864     Matrix_Free(M);
00865     for(i=0;i<=(d+1);i++)
00866         value_clear(min[i]);
00867     free(min);
00868     // value_clear(tmp);
00869     assert(!emptyQ(H));
00870     return(H);
00871 } /* Polyhedron_Preprocess */
00872 
00873 /** This procedure finds an hypercube of size 'size', containing
00874 polyhedron D increases size and lcm if necessary (and not "too big")
00875 If this is not possible, an empty polyhedron is returned
00876 
00877 <p>
00878 
00879 <pre> written by vin100, 2001, for version 4.19</pre>
00880 
00881 @param D
00882 @param size
00883 @param lcm
00884 @param MAXRAYS
00885 
00886 */
00887 Polyhedron *Polyhedron_Preprocess2(Polyhedron *D,Value *size,Value *lcm,unsigned MAXRAYS) {
00888   
00889     Matrix *c;
00890     Polyhedron *H;
00891     int i,j,r;
00892     Value n;      /* smallest/biggest value */
00893     Value s;    /* size in this dimension */
00894     Value tmp1,tmp2;
00895 
00896 #ifdef EDEBUG62
00897     int np;
00898 #endif
00899 
00900     value_init(n); value_init(s);
00901     value_init(tmp1); value_init(tmp2);
00902     c = Matrix_Alloc(D->Dimension*2,D->Dimension+2);
00903   
00904 #ifdef EDEBUG62
00905     fprintf(stderr,"\nPreProcess2 : starting\n");
00906     fprintf(stderr,"lcm = ");
00907     for( np=0 ; np<D->Dimension; np++ )
00908         value_print(stderr,VALUE_FMT,lcm[np]);
00909     fprintf(stderr,", size = ");
00910     for( np=0 ; np<D->Dimension; np++ )
00911         value_print(stderr,VALUE_FMT,size[np]);
00912     fprintf(stderr,"\n");
00913 #endif
00914   
00915     for(i=0;i<D->Dimension;i++) {
00916     
00917         /* Create constraint 1 0..0 1 0..0 -min */
00918         value_set_si(c->p[2*i][0],1);
00919         for(j=0;j<D->Dimension;j++)
00920             value_set_si(c->p[2*i][1+j],0);
00921         value_division(n,D->Ray[0][i+1],D->Ray[0][D->Dimension+1]);
00922         for(r=1;r<D->NbRays;r++) {
00923             value_division(tmp1,D->Ray[r][i+1],D->Ray[r][D->Dimension+1]);
00924             if(value_gt(n,tmp1)) {
00925         
00926                 /* New min */
00927                 value_division(n,D->Ray[r][i+1],D->Ray[r][D->Dimension+1]);
00928             }
00929         }
00930         value_set_si(c->p[2*i][i+1],1);
00931         value_oppose(c->p[2*i][D->Dimension+1],n);
00932     
00933         /* Create constraint 1 0..0 -1 0..0 max */
00934         value_set_si(c->p[2*i+1][0],1);
00935         for(j=0;j<D->Dimension;j++)
00936             value_set_si(c->p[2*i+1][1+j],0);
00937     
00938         /* n = (num+den-1)/den */
00939         value_addto(tmp1,D->Ray[0][i+1],D->Ray[0][D->Dimension+1]);
00940         value_sub_int(tmp1,tmp1,1);
00941         value_division(n,tmp1,D->Ray[0][D->Dimension+1]);
00942         for(r=1;r<D->NbRays;r++) {
00943             value_addto(tmp1,D->Ray[r][i+1],D->Ray[r][D->Dimension+1]);
00944             value_sub_int(tmp1,tmp1,1);
00945             value_division(tmp1,tmp1,D->Ray[r][D->Dimension+1]);
00946             if (value_lt(n,tmp1)) {
00947         
00948                 /* New max */
00949                 value_addto(tmp1,D->Ray[r][i+1],D->Ray[r][D->Dimension+1]);
00950                 value_sub_int(tmp1,tmp1,1);
00951                 value_division(n,tmp1,D->Ray[r][D->Dimension+1]);
00952             }
00953         }
00954         value_set_si(c->p[2*i+1][i+1],-1);
00955         value_assign(c->p[2*i+1][D->Dimension+1],n);
00956         value_addto(s,c->p[2*i+1][D->Dimension+1],c->p[2*i][D->Dimension+1]);
00957     
00958         /* Now test if the dimension of the cube is greater than the size */
00959         if(value_gt(s,size[i])) {
00960       
00961 #ifdef EDEBUG62
00962             fprintf(stderr,"size on dimension %d\n",i);
00963             fprintf(stderr,"lcm = ");
00964             for( np=0 ; np<D->Dimension; np++ )
00965                 value_print(stderr,VALUE_FMT,lcm[np]);
00966             fprintf(stderr,", size = ");
00967             for( np=0 ; np<D->Dimension; np++ )
00968                 value_print(stderr,VALUE_FMT,size[np]);
00969             fprintf(stderr,"\n");
00970             fprintf(stderr,"required size (s) = ");
00971             value_print(stderr,VALUE_FMT,s);
00972             fprintf(stderr,"\n");
00973 #endif
00974       
00975             /* If the needed size is "small enough"(<=20 or less than twice *size) */
00976             /* then increase *size, and artificially increase lcm too !*/
00977             value_set_si(tmp1,20);
00978             value_addto(tmp2,size[i],size[i]);
00979             if(value_le(s,tmp1)
00980                     || value_le(s,tmp2)) {
00981 
00982                 if( value_zero_p(lcm[i]) )
00983                     value_set_si(lcm[i],1);
00984                 /* lcm divides size... */
00985                 value_division(tmp1,size[i],lcm[i]);
00986         
00987                 /* lcm = ceil(s/h) */
00988                 value_addto(tmp2,s,tmp1);
00989                 value_add_int(tmp2,tmp2,1);
00990                 value_division(lcm[i],tmp2,tmp1);
00991         
00992                 /* new size = lcm*h */
00993                 value_multiply(size[i],lcm[i],tmp1);
00994         
00995 #ifdef EDEBUG62
00996                 fprintf(stderr,"new size = ");
00997                 for( np=0 ; np<D->Dimension; np++ )
00998                     value_print(stderr,VALUE_FMT,size[np]);
00999                 fprintf(stderr,", new lcm = ");
01000                 for( np=0 ; np<D->Dimension; np++ )
01001                     value_print(stderr,VALUE_FMT,lcm[np]);
01002                 fprintf(stderr,"\n");
01003 #endif
01004 
01005             }
01006             else {
01007         
01008 #ifdef EDEBUG62
01009                 fprintf(stderr,"Failed on dimension %d.\n",i);
01010 #endif
01011                 break;
01012             }
01013         }
01014     }
01015     if(i!=D->Dimension) {
01016         Matrix_Free(c);
01017         value_clear(n); value_clear(s);
01018         value_clear(tmp1); value_clear(tmp2);
01019         return(NULL);
01020     }
01021     for(i=0;i<D->Dimension;i++) {
01022         value_subtract(c->p[2*i+1][D->Dimension+1],size[i], 
01023                 c->p[2*i][D->Dimension+1]);
01024     }
01025   
01026 #ifdef EDEBUG62
01027     fprintf(stderr,"PreProcess2 : c =");
01028     Matrix_Print(stderr,P_VALUE_FMT,c);
01029 #endif
01030 
01031     H = Constraints2Polyhedron(c,MAXRAYS);
01032     Matrix_Free(c);
01033     value_clear(n); value_clear(s);
01034     value_clear(tmp1); value_clear(tmp2);
01035     return(H);
01036 } /* Polyhedron_Preprocess2 */
01037 
01038 /**  
01039 
01040 This procedure adds additional constraints to D so that as each
01041 parameter is scanned, it will have a minimum of 'size' points If this
01042 is not possible, an empty polyhedron is returned
01043 
01044 @param D
01045 @param size
01046 @param MAXRAYS
01047 
01048 */
01049 Polyhedron *old_Polyhedron_Preprocess(Polyhedron *D,Value size,unsigned MAXRAYS) {
01050   
01051     int p, p1, ub, lb;
01052     Value a, a1, b, b1, g, aa;
01053     Value abs_a, abs_b, size_copy;
01054     int dim, con, new, needed;
01055     Value **C;
01056     Matrix *M;
01057     Polyhedron *D1;
01058   
01059     value_init(a); value_init(a1); value_init(b);
01060     value_init(b1); value_init(g); value_init(aa);
01061     value_init(abs_a); value_init(abs_b); value_init(size_copy);
01062   
01063     dim = D->Dimension;
01064     con = D->NbConstraints;
01065     M = Matrix_Alloc(MAXRAYS,dim+2);
01066     new = 0;
01067     value_assign(size_copy,size);
01068     C = D->Constraint;
01069     for (p=1; p<=dim; p++) {
01070         for (ub=0; ub<con; ub++) {
01071             value_assign(a,C[ub][p]);
01072             if (value_posz_p(a))        /* a >= 0 */
01073                 continue;               /* not an upper bound */
01074             for (lb=0;lb<con;lb++) {
01075                 value_assign(b,C[lb][p]);
01076                 if (value_negz_p(b))
01077                     continue;   /* not a lower bound */
01078         
01079                 /* Check if a new constraint is needed for this (ub,lb) pair */
01080                 /* a constraint is only needed if a previously scanned */
01081                 /* parameter (1..p-1) constrains this parameter (p) */
01082                 needed=0;
01083                 for (p1=1; p1<p; p1++) {
01084                     if (value_notzero_p(C[ub][p1]) || value_notzero_p(C[lb][p1])) {
01085                         needed=1; 
01086                         break;
01087                     }
01088                 }
01089                 if (!needed) continue;  
01090                 value_absolute(abs_a,a);
01091                 value_absolute(abs_b,b);
01092 
01093                 /* Create new constraint: b*UB-a*LB >= a*b*size */
01094                 Gcd(abs_a,abs_b,&g);
01095                 value_division(a1,a,g);
01096                 value_division(b1,b,g);
01097                 value_set_si(M->p[new][0],1);
01098                 value_oppose(abs_a,a1);           /* abs_a = -a1 */
01099                 Vector_Combine(&(C[ub][1]),&(C[lb][1]),&(M->p[new][1]),
01100                         b1,abs_a,dim+1);
01101                 value_multiply(aa,a1,b1);
01102                 // value_multiply(abs_a,aa,size_copy);
01103                 // value_addto(M->p[new][dim+1],M->p[new][dim+1],abs_a);
01104                 value_addmul(M->p[new][dim+1], aa, size_copy);
01105                 Vector_Normalize(&(M->p[new][1]),(dim+1));
01106                 new++;
01107             }
01108         }
01109     }
01110     D1 = AddConstraints(M->p_Init,new,D,MAXRAYS);
01111     Matrix_Free(M);
01112   
01113     value_clear(a); value_clear(a1); value_clear(b);
01114     value_clear(b1); value_clear(g); value_clear(aa);
01115     value_clear(abs_a); value_clear(abs_b); value_clear(size_copy);
01116     return D1;
01117 } /* old_Polyhedron_Preprocess */
01118 
01119 /** 
01120 
01121 PROCEDURES TO COMPUTE ENUMERATION. recursive procedure, recurse for
01122 each imbriquation
01123 
01124 @param pos index position of current loop index (1..hdim-1)
01125 @param P loop domain
01126 @param context context values for fixed indices 
01127 @param res the number of integer points in this
01128 polyhedron 
01129 
01130 */
01131 void count_points (int pos,Polyhedron *P,Value *context, Value *res) {
01132    
01133     Value LB, UB, k, c;
01134 
01135     POL_ENSURE_FACETS(P);
01136     POL_ENSURE_VERTICES(P);
01137 
01138     if (emptyQ(P)) {
01139         value_set_si(*res, 0);
01140         return;
01141     }
01142 
01143     value_init(LB); value_init(UB); value_init(k);
01144     value_set_si(LB,0);
01145     value_set_si(UB,0);
01146 
01147     if (lower_upper_bounds(pos,P,context,&LB,&UB) !=0) {
01148     
01149         /* Problem if UB or LB is INFINITY */
01150         fprintf(stderr, "count_points: ? infinite domain\n");
01151         value_clear(LB); value_clear(UB); value_clear(k);
01152         value_set_si(*res, -1);
01153         return;
01154     }
01155   
01156 #ifdef EDEBUG1
01157     if (!P->next) {
01158         int i;
01159         for (value_assign(k,LB); value_le(k,UB); value_increment(k,k)) {
01160             fprintf(stderr, "(");
01161             for (i=1; i<pos; i++) {
01162                 value_print(stderr,P_VALUE_FMT,context[i]);
01163                 fprintf(stderr,",");
01164             }
01165             value_print(stderr,P_VALUE_FMT,k);
01166             fprintf(stderr,")\n");
01167         }
01168     }
01169 #endif
01170   
01171     value_set_si(context[pos],0);
01172     if (value_lt(UB,LB)) {
01173         value_clear(LB); value_clear(UB); value_clear(k);
01174         value_set_si(*res, 0);
01175         return;  
01176     }  
01177     if (!P->next) {
01178         value_subtract(k,UB,LB);
01179         value_add_int(k,k,1);
01180         value_assign(*res, k);
01181         value_clear(LB); value_clear(UB); value_clear(k);
01182         return;
01183     } 
01184 
01185     /*-----------------------------------------------------------------*/
01186     /* Optimization idea                                               */
01187     /*   If inner loops are not a function of k (the current index)    */
01188     /*   i.e. if P->Constraint[i][pos]==0 for all P following this and */
01189     /*        for all i,                                               */
01190     /*   Then CNT = (UB-LB+1)*count_points(pos+1, P->next, context)    */
01191     /*   (skip the for loop)                                           */
01192     /*-----------------------------------------------------------------*/
01193   
01194     value_init(c);
01195     value_set_si(*res, 0);
01196     for (value_assign(k,LB);value_le(k,UB);value_increment(k,k)) {
01197         /* Insert k in context */
01198         value_assign(context[pos],k);
01199         count_points(pos+1,P->next,context,&c);
01200         if(value_notmone_p(c))
01201             value_addto(*res, *res, c);
01202         else {
01203             value_set_si(*res, -1);
01204             break;
01205         }
01206     }
01207     value_clear(c);
01208   
01209 #ifdef EDEBUG11
01210     fprintf(stderr,"%d\n",CNT);
01211 #endif
01212   
01213     /* Reset context */
01214     value_set_si(context[pos],0);
01215     value_clear(LB); value_clear(UB); value_clear(k);
01216     return;
01217 } /* count_points */
01218 
01219 /*-------------------------------------------------------------------*/
01220 /* enode *P_Enum(L, LQ, context, pos, nb_param, dim, lcm,param_name) */
01221 /*     L : list of polyhedra for the loop nest                       */
01222 /*     LQ : list of polyhedra for the parameter loop nest            */
01223 /*     pos : 1..nb_param, position of the parameter                  */
01224 /*     nb_param : number of parameters total                         */
01225 /*     dim : total dimension of the polyhedron, param incl.          */
01226 /*     lcm : denominator array [0..dim-1] of the polyhedron          */
01227 /*     param_name : name of the parameters                           */
01228 /* Returns an enode tree representing the pseudo polynomial          */
01229 /*   expression for the enumeration of the polyhedron.               */
01230 /* A recursive procedure.                                            */
01231 /*-------------------------------------------------------------------*/
01232 static enode *P_Enum(Polyhedron *L,Polyhedron *LQ,Value *context,int pos,int nb_param,int dim,Value *lcm,char **param_name) {
01233 
01234   enode *res,*B,*C;
01235   int hdim,i,j,rank,flag;
01236   Value n,g,nLB,nUB,nlcm,noff,nexp,k1,nm,hdv,k,lcm_copy;
01237   Value tmp;
01238   Matrix *A;
01239 
01240 #ifdef EDEBUG
01241   fprintf(stderr,"-------------------- begin P_Enum -------------------\n");
01242   fprintf(stderr,"Calling P_Enum with pos = %d\n",pos);
01243 #endif
01244   
01245   /* Initialize all the 'Value' variables */
01246   value_init(n); value_init(g); value_init(nLB);
01247   value_init(nUB); value_init(nlcm); value_init(noff);
01248   value_init(nexp); value_init(k1); value_init(nm);
01249   value_init(hdv); value_init(k); value_init(tmp);
01250   value_init(lcm_copy);
01251 
01252   if( value_zero_p(lcm[pos-1]) )
01253   {
01254                 hdim = 1;
01255                 value_set_si( lcm_copy, 1 );
01256   }
01257   else
01258   {
01259           /* hdim is the degree of the polynomial + 1 */
01260                 hdim = dim-nb_param+1;          /* homogenous dim w/o parameters */
01261                 value_assign( lcm_copy, lcm[pos-1] );
01262   }  
01263 
01264   /* code to limit generation of equations to valid parameters only */
01265   /*----------------------------------------------------------------*/
01266   flag = lower_upper_bounds(pos,LQ,&context[dim-nb_param],&nLB,&nUB);
01267   if (flag & LB_INFINITY) {
01268     if (!(flag & UB_INFINITY)) {
01269       
01270       /* Only an upper limit: set lower limit */
01271       /* Compute nLB such that (nUB-nLB+1) >= (hdim*lcm) */
01272       value_sub_int(nLB,nUB,1);
01273       value_set_si(hdv,hdim);
01274       value_multiply(tmp,hdv,lcm_copy);
01275       value_subtract(nLB,nLB,tmp);
01276       if(value_pos_p(nLB))
01277         value_set_si(nLB,0);
01278     }
01279     else {
01280       value_set_si(nLB,0);
01281       
01282       /* No upper nor lower limit: set lower limit to 0 */
01283       value_set_si(hdv,hdim);
01284       value_multiply(nUB,hdv,lcm_copy);
01285       value_add_int(nUB,nUB,1);
01286     }
01287   }
01288 
01289   /* if (nUB-nLB+1) < (hdim*lcm) then we have more unknowns than equations */
01290   /* We can: 1. Find more equations by changing the context parameters, or */
01291   /* 2. Assign extra unknowns values in such a way as to simplify result.  */
01292   /* Think about ways to scan parameter space to get as much info out of it*/
01293   /* as possible.                                                          */
01294   
01295 #ifdef REDUCE_DEGREE
01296   if (pos==1 && (flag & UB_INFINITY)==0) {
01297     /* only for finite upper bound on first parameter */
01298     /* NOTE: only first parameter because subsequent parameters may
01299        be artificially limited by the choice of the first parameter */
01300    
01301 #ifdef EDEBUG
01302     fprintf(stderr,"*************** n **********\n");
01303     value_print(stderr,VALUE_FMT,n);
01304     fprintf(stderr,"\n");
01305 #endif
01306 
01307     value_subtract(n,nUB,nLB);
01308     value_increment(n,n);
01309     
01310 #ifdef EDEBUG 
01311     value_print(stderr,VALUE_FMT,n);
01312     fprintf(stderr,"\n*************** n ************\n");
01313 #endif 
01314 
01315     /* Total number of samples>0 */
01316     if(value_neg_p(n))
01317       i=0;
01318     else {
01319       value_modulus(tmp,n,lcm_copy);
01320       if(value_notzero_p(tmp)) {
01321                   value_division(tmp,n,lcm_copy);
01322                   value_increment(tmp,tmp);
01323                   i = VALUE_TO_INT(tmp);
01324       }
01325       else {
01326                   value_division(tmp,n,lcm_copy);
01327                   i =   VALUE_TO_INT(tmp);      /* ceiling of n/lcm */
01328       }
01329     }
01330 
01331 #ifdef EDEBUG 
01332     value_print(stderr,VALUE_FMT,n);
01333     fprintf(stderr,"\n*************** n ************\n");
01334 #endif 
01335     
01336     /* Reduce degree of polynomial based on number of sample points */
01337     if (i < hdim){
01338       hdim=i;
01339       
01340 #ifdef EDEBUG4
01341       fprintf(stdout,"Parameter #%d: LB=",pos);
01342       value_print(stdout,VALUE_FMT,nLB);
01343       fprintf(stdout," UB=");
01344       value_print(stdout,VALUE_FMT,nUB);
01345       fprintf(stdout," lcm=");
01346       value_print(stdout,VALUE_FMT,lcm_copy);
01347       fprintf(stdout," degree reduced to %d\n",hdim-1);
01348 #endif
01349       
01350     }
01351   }
01352 #endif /* REDUCE_DEGREE */
01353   
01354   /* hdim is now set */  
01355   /* allocate result structure */
01356   res = new_enode(polynomial,hdim,pos);
01357   for (i=0;i<hdim;i++) {
01358     int l;
01359     l = VALUE_TO_INT(lcm_copy);
01360     res->arr[i].x.p = new_enode(periodic,l,pos);
01361   }
01362   
01363   /* Utility arrays */
01364   A = Matrix_Alloc(hdim, 2*hdim+1);                     /* used for Gauss */
01365   B = new_enode(evector, hdim, 0);
01366   C = new_enode(evector, hdim, 0);
01367 
01368   /* We'll create these again when we need them */
01369   for (j = 0; j < hdim; ++j)
01370     free_evalue_refs(&C->arr[j]);
01371   
01372   /*----------------------------------------------------------------*/
01373   /*                                                                */
01374   /*                                0<-----+---k--------->          */
01375   /* |---------noff----------------->-nlcm->-------lcm---->         */
01376   /* |--- . . . -----|--------------|------+-------|------+-------|-*/
01377   /* 0          (q-1)*lcm         q*lcm    |  (q+1)*lcm   |         */
01378   /*                                      nLB          nLB+lcm      */
01379   /*                                                                */
01380   /*----------------------------------------------------------------*/
01381   if(value_neg_p(nLB)) {
01382     value_modulus(nlcm,nLB,lcm_copy);
01383     value_addto(nlcm,nlcm,lcm_copy);
01384   }
01385   else {
01386     value_modulus(nlcm,nLB,lcm_copy);
01387   }
01388   
01389   /* noff is a multiple of lcm */
01390   value_subtract(noff,nLB,nlcm);
01391   value_addto(tmp,lcm_copy,nlcm);
01392   for (value_assign(k,nlcm);value_lt(k,tmp);) {
01393  
01394 #ifdef EDEBUG
01395     fprintf(stderr,"Finding ");
01396     value_print(stderr,VALUE_FMT,k);
01397     fprintf(stderr,"-th elements of periodic coefficients\n");
01398 #endif
01399 
01400     value_set_si(hdv,hdim);
01401     value_multiply(nm,hdv,lcm_copy);
01402     value_addto(nm,nm,nLB);
01403     i=0;
01404     for (value_addto(n,k,noff); value_lt(n,nm); value_addto(n,n,lcm_copy),i++) {
01405       
01406       /* n == i*lcm + k + noff;   */
01407       /* nlcm <= k < nlcm+lcm     */
01408       /* n mod lcm == k1 */
01409       
01410 #ifdef ALL_OVERFLOW_WARNINGS
01411       if (((flag & UB_INFINITY)==0) && value_gt(n,nUB)) {
01412         fprintf(stdout,"Domain Overflow: Parameter #%d:",pos);
01413         fprintf(stdout,"nLB=");
01414         value_print(stdout,VALUE_FMT,nLB);
01415         fprintf(stdout," n=");
01416         value_print(stdout,VALUE_FMT,n);
01417         fprintf(stdout," nUB=");
01418         value_print(stdout,VALUE_FMT,nUB);
01419         fprintf(stdout,"\n");
01420       }
01421 #else
01422       if (overflow_warning_flag && ((flag & UB_INFINITY)==0) &&
01423           value_gt(n,nUB)) {
01424         fprintf(stdout,"\nWARNING: Parameter Domain Overflow.");
01425         fprintf(stdout," Result may be incorrect on this domain.\n");
01426         overflow_warning_flag = 0;
01427       }
01428 #endif
01429       
01430       /* Set parameter to n */
01431       value_assign(context[dim-nb_param+pos],n);
01432       
01433 #ifdef EDEBUG1
01434         if( param_name )
01435         {
01436       fprintf(stderr,"%s = ",param_name[pos-1]);
01437       value_print(stderr,VALUE_FMT,n);
01438       fprintf(stderr," (hdim=%d, lcm[%d]=",hdim,pos-1);
01439       value_print(stderr,VALUE_FMT,lcm_copy);
01440       fprintf(stderr,")\n");
01441         }
01442         else
01443         {
01444       fprintf(stderr,"P%d = ",pos);
01445       value_print(stderr,VALUE_FMT,n);
01446       fprintf(stderr," (hdim=%d, lcm[%d]=",hdim,pos-1);
01447       value_print(stderr,VALUE_FMT,lcm_copy);
01448       fprintf(stderr,")\n");      
01449         }
01450 #endif
01451       
01452       /* Setup B vector */
01453       if (pos==nb_param) {
01454         
01455 #ifdef EDEBUG   
01456         fprintf(stderr,"Yes\n");
01457 #endif 
01458         
01459         /* call count */
01460         /* count can only be called when the context is fully specified */
01461         value_set_si(B->arr[i].d,1);
01462         value_init(B->arr[i].x.n);
01463         count_points(1,L,context,&B->arr[i].x.n);
01464         
01465 #ifdef EDEBUG3
01466         for (j=1; j<pos; j++) fputs("   ",stdout);
01467         fprintf(stdout, "E(");
01468         for (j=1; j<nb_param; j++) {
01469           value_print(stdout,VALUE_FMT,context[dim-nb_param+j]);
01470           fprintf(stdout,",");
01471         }  
01472         value_print(stdout,VALUE_FMT,n);
01473         fprintf(stdout,") = ");
01474         value_print(stdout,VALUE_FMT,B->arr[i].x.n);
01475         fprintf(stdout," =");
01476 #endif
01477         
01478       }
01479       else {    /* count is a function of other parameters */
01480         /* call P_Enum recursively */
01481         value_set_si(B->arr[i].d,0);
01482         B->arr[i].x.p = P_Enum(L,LQ->next,context,pos+1,nb_param,dim,lcm,param_name);
01483         
01484 #ifdef EDEBUG3
01485         if( param_name )
01486         {
01487                 for (j=1; j<pos; j++)
01488                   fputs("   ", stdout);
01489                 fprintf(stdout, "E(");
01490                 for (j=1; j<=pos; j++) {
01491                   value_print(stdout,VALUE_FMT,context[dim-nb_param+j]);
01492                   fprintf(stdout,",");
01493                 }         
01494                 for (j=pos+1; j<nb_param; j++)
01495                   fprintf(stdout,"%s,",param_name[j]);
01496                 fprintf(stdout,"%s) = ",param_name[j]);
01497                 print_enode(stdout,B->arr[i].x.p,param_name);
01498                 fprintf(stdout," =");
01499         }
01500 #endif
01501         
01502       }
01503       
01504       /* Create i-th equation*/
01505       /* K_0 + K_1 * n**1 + ... + K_dim * n**dim | Identity Matrix */
01506       
01507       value_set_si(A->p[i][0],0);  /* status bit = equality */
01508       value_set_si(nexp,1);
01509       for (j=1;j<=hdim;j++) {
01510         value_assign(A->p[i][j],nexp);
01511         value_set_si(A->p[i][j+hdim],0);
01512         
01513 #ifdef EDEBUG3
01514         fprintf(stdout," + ");
01515         value_print(stdout,VALUE_FMT,nexp);
01516         fprintf(stdout," c%d",j);
01517 #endif  
01518         value_multiply(nexp,nexp,n);
01519       }
01520       
01521 #ifdef EDEBUG3
01522       fprintf(stdout, "\n");
01523 #endif
01524       
01525       value_set_si(A->p[i][i+1+hdim],1);      
01526     }
01527     
01528     /* Assertion check */
01529     if (i!=hdim)
01530       fprintf(stderr, "P_Enum: ?expecting i==hdim\n");
01531     
01532 #ifdef EDEBUG
01533         if( param_name )
01534         {
01535     fprintf(stderr,"B (enode) =\n");
01536     print_enode(stderr,B,param_name);
01537         }
01538     fprintf(stderr,"A (Before Gauss) =\n");
01539     Matrix_Print(stderr,P_VALUE_FMT,A);
01540 #endif
01541     
01542     /* Solve hdim (=dim+1) equations with hdim unknowns, result in CNT */
01543     rank = Gauss(A,hdim,2*hdim);
01544     
01545 #ifdef EDEBUG
01546     fprintf(stderr,"A (After Gauss) =\n");
01547     Matrix_Print(stderr,P_VALUE_FMT,A);
01548 #endif
01549     
01550     /* Assertion check */
01551     if (rank!=hdim) {
01552       fprintf(stderr, "P_Enum: ?expecting rank==hdim\n");
01553     }
01554     
01555     /* if (rank < hdim) then set the last hdim-rank coefficients to ? */
01556     /* if (rank == 0) then set all coefficients to 0 */    
01557     /* copy result as k1-th element of periodic numbers */
01558     if(value_lt(k,lcm_copy))
01559       value_assign(k1,k);
01560     else
01561       value_subtract(k1,k,lcm_copy);
01562     
01563     for (i=0; i<rank; i++) {
01564       
01565       /* Set up coefficient vector C from i-th row of inverted matrix */
01566       for (j=0; j<rank; j++) {
01567         Gcd(A->p[i][i+1],A->p[i][j+1+hdim],&g);
01568         value_init(C->arr[j].d);
01569         value_division(C->arr[j].d,A->p[i][i+1],g);
01570         value_init(C->arr[j].x.n);
01571         value_division(C->arr[j].x.n,A->p[i][j+1+hdim],g);
01572       }
01573       
01574 #ifdef EDEBUG
01575         if( param_name )
01576         {
01577       fprintf(stderr, "C (enode) =\n");
01578       print_enode(stderr, C, param_name);
01579         }
01580 #endif
01581       
01582       /* The i-th enode is the lcm-periodic coefficient of term n**i */
01583       edot(B,C,&(res->arr[i].x.p->arr[VALUE_TO_INT(k1)]));
01584       
01585 #ifdef EDEBUG
01586         if( param_name )
01587         {
01588       fprintf(stderr, "B.C (evalue)=\n");
01589       print_evalue(stderr,&(res->arr[i].x.p->arr[VALUE_TO_INT(k1)]),param_name );
01590       fprintf(stderr,"\n");
01591         }
01592 #endif
01593       
01594       for (j = 0; j < rank; ++j)
01595         free_evalue_refs(&C->arr[j]);
01596     }
01597     value_addto(tmp,lcm_copy,nlcm);
01598 
01599     value_increment(k,k);
01600     for (i = 0; i < hdim; ++i) {
01601       free_evalue_refs(&B->arr[i]);
01602       if (value_lt(k,tmp))
01603         value_init(B->arr[i].d);
01604     }
01605   }
01606   
01607 #ifdef EDEBUG
01608         if( param_name )
01609         {
01610           fprintf(stderr,"res (enode) =\n");
01611           print_enode(stderr,res,param_name);
01612         }
01613   fprintf(stderr, "-------------------- end P_Enum -----------------------\n");
01614 #endif
01615   
01616   /* Reset context */
01617   value_set_si(context[dim-nb_param+pos],0);
01618   
01619   /* Release memory */
01620   Matrix_Free(A);
01621   free(B);
01622   free(C);
01623   
01624   /* Clear all the 'Value' variables */
01625   value_clear(n); value_clear(g); value_clear(nLB);
01626   value_clear(nUB); value_clear(nlcm); value_clear(noff);
01627   value_clear(nexp); value_clear(k1); value_clear(nm);
01628   value_clear(hdv); value_clear(k); value_clear(tmp);
01629   value_clear(lcm_copy);
01630   return res;
01631 } /* P_Enum */
01632 
01633 /*----------------------------------------------------------------*/
01634 /* Scan_Vertices(PP, Q, CT)                                       */
01635 /*    PP : ParamPolyhedron                                        */
01636 /*    Q : Domain                                                  */
01637 /*    CT : Context transformation matrix                          */
01638 /*    lcm : lcm array (output)                                    */
01639 /*    nbp : number of parameters                                  */
01640 /*    param_name : name of the parameters                         */
01641 /*----------------------------------------------------------------*/
01642 static void Scan_Vertices(Param_Polyhedron *PP,Param_Domain *Q,Matrix *CT,
01643    Value *lcm, int nbp, char **param_name )
01644 {
01645   Param_Vertices *V;
01646   int i, j, ix, l, np;
01647   unsigned bx;
01648   Value k,m1;
01649 
01650   /* Compute the denominator of P */
01651   /* lcm = Least Common Multiple of the denominators of the vertices of P */
01652   /* and print the vertices */  
01653 
01654   value_init(k); value_init(m1);
01655   for( np=0 ; np<nbp ; np++ )
01656     value_set_si( lcm[np], 0 );
01657 
01658         if( param_name )
01659           fprintf(stdout,"Vertices:\n");
01660 
01661   for(i=0,ix=0,bx=MSB,V=PP->V; V && i<PP->nbV; i++,V=V->next) {
01662     if (Q->F[ix] & bx) {
01663                 if( param_name )
01664                 {
01665         if(CT) {
01666                                 Matrix *v;
01667                                 v = VertexCT(V->Vertex,CT);
01668                                 Print_Vertex(stdout,v,param_name);
01669                                 Matrix_Free(v);
01670         }
01671         else
01672                                 Print_Vertex(stdout,V->Vertex,param_name);
01673                 fprintf(stdout,"\n");
01674                 }
01675 
01676       for(j=0;j<V->Vertex->NbRows;j++) {
01677                         /* A matrix */
01678                         for( l=0 ; l<V->Vertex->NbColumns-1 ; l++ )
01679                         {
01680                                 if( value_notzero_p(V->Vertex->p[j][l]) )
01681                                 {
01682                                         Gcd(V->Vertex->p[j][V->Vertex->NbColumns-1],V->Vertex->p[j][l], &m1);
01683                                         value_division(k,V->Vertex->p[j][V->Vertex->NbColumns-1],m1);
01684                                         if( value_notzero_p(lcm[l]) )
01685                                         {
01686                                                 /* lcm[l] = lcm[l] * k / gcd(k,lcm[l]) */
01687                                                 if (value_notzero_p(k) && value_notone_p(k))
01688                                                 {
01689                                                   Gcd(lcm[l],k,&m1);
01690                                                   value_division(k,k,m1);
01691                                                   value_multiply(lcm[l],lcm[l],k);
01692                                                 }
01693                                         }
01694                                         else
01695                                         {
01696                                                 value_assign(lcm[l],k);
01697                                         }
01698                                 }
01699                         }
01700       }
01701     }
01702     NEXT(ix,bx);
01703   }
01704   value_clear(k); value_clear(m1);
01705 } /* Scan_Vertices */
01706 
01707 /**
01708 
01709 Procedure to count points in a non-parameterized polytope.
01710 
01711 @param P       Polyhedron to count
01712 @param C       Parameter Context domain
01713 @param CT      Matrix to transform context to original
01714 @param CEq     additionnal equalities in context
01715 @param MAXRAYS workspace size
01716 @param param_name parameter names
01717 
01718 */
01719 Enumeration *Enumerate_NoParameters(Polyhedron *P,Polyhedron *C,Matrix *CT,Polyhedron *CEq,unsigned MAXRAYS,char **param_name) {
01720   
01721     Polyhedron *L;
01722     Enumeration *res;
01723     Value *context;
01724     int j;
01725     int hdim = P->Dimension + 1;
01726     int r,i;
01727   
01728     /* Create a context vector size dim+2 */
01729     context = (Value *) malloc((hdim+1)*sizeof(Value));
01730     for (j=0;j<= hdim;j++) 
01731         value_init(context[j]);
01732   
01733     res = (Enumeration *)malloc(sizeof(Enumeration));
01734     res->next = NULL;
01735     res->ValidityDomain = Universe_Polyhedron(0);  /* no parameters */
01736     value_init(res->EP.d);
01737     value_set_si(res->EP.d,0);  
01738     L = Polyhedron_Scan(P,res->ValidityDomain,MAXRAYS);
01739   
01740 #ifdef EDEBUG2
01741     fprintf(stderr, "L = \n");
01742     Polyhedron_Print(stderr, P_VALUE_FMT, L);
01743 #endif
01744   
01745     if(CT) {
01746         Polyhedron *Dt;
01747     
01748         /* Add parameters to validity domain */
01749         Dt = Polyhedron_Preimage(res->ValidityDomain,CT,MAXRAYS);
01750         Polyhedron_Free(res->ValidityDomain);
01751         res->ValidityDomain = DomainIntersection(Dt,CEq,MAXRAYS);
01752         Polyhedron_Free(Dt);
01753     }
01754   
01755         if( param_name )
01756         {
01757     fprintf(stdout,"---------------------------------------\n");
01758     fprintf(stdout,"Domain:\n");
01759     Print_Domain(stdout,res->ValidityDomain, param_name);
01760   
01761     /* Print the vertices */
01762     printf("Vertices:\n");
01763     for(r=0;r<P->NbRays;++r) {
01764         if(value_zero_p(P->Ray[r][0]))
01765             printf("(line) ");
01766         printf("[");
01767         if (P->Dimension > 0)
01768             value_print(stdout,P_VALUE_FMT,P->Ray[r][1]);
01769         for(i=1;i<P->Dimension;i++) {
01770             printf(", ");
01771             value_print(stdout,P_VALUE_FMT,P->Ray[r][i+1]);
01772         }  
01773         printf("]");
01774         if(value_notone_p(P->Ray[r][P->Dimension+1])) {
01775             printf("/");
01776             value_print(stdout,P_VALUE_FMT, P->Ray[r][P->Dimension+1]);
01777         }
01778         printf("\n");
01779     }
01780         }
01781 
01782   res->EP.x.p = new_enode(polynomial,1,0);;
01783   value_set_si(res->EP.x.p->arr[0].d, 1);
01784   value_init(res->EP.x.p->arr[0].x.n);
01785 
01786   if (emptyQ(P)) {
01787     value_set_si(res->EP.x.p->arr[0].x.n, 0);
01788   } else if (!L) {
01789     /* Non-empty zero-dimensional domain */
01790     value_set_si(res->EP.x.p->arr[0].x.n, 1);
01791   } else {
01792     CATCH(overflow_error) {
01793         fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
01794         fprintf(stderr,"You should rebuild PolyLib using GNU-MP or increasing the size of integers.\n");
01795         overflow_warning_flag = 0;
01796         assert(overflow_warning_flag);
01797     }
01798     TRY {
01799     
01800         Vector_Set(context,0,(hdim+1));
01801     
01802         /* Set context[hdim] = 1  (the constant) */
01803         value_set_si(context[hdim],1);
01804         count_points(1, L, context, &res->EP.x.p->arr[0].x.n);
01805         UNCATCH(overflow_error);
01806     }
01807   }
01808   
01809     Domain_Free(L);
01810   
01811     /*  **USELESS, there are no references to parameters in res**
01812         if( CT )
01813         addeliminatedparams_evalue(&res->EP, CT);
01814     */
01815   
01816         if( param_name )
01817         {
01818     fprintf(stdout,"\nEhrhart Polynomial:\n");
01819     print_evalue(stdout,&res->EP,param_name);
01820     fprintf(stdout, "\n");
01821         }
01822 
01823     for (j=0;j<= hdim;j++) 
01824         value_clear(context[j]);  
01825     free(context);
01826     return(res);
01827 } /* Enumerate_NoParameters */
01828 
01829 /**  Procedure to count points in a parameterized polytope.
01830 
01831 @param Pi Polyhedron to enumerate
01832 @param C Context Domain
01833 @param MAXRAYS size of workspace
01834 @param param_name parameter names (array of strings), may be NULL
01835 @return a list of validity domains + evalues EP
01836 
01837 */
01838 Enumeration *Polyhedron_Enumerate(Polyhedron *Pi,Polyhedron *C,unsigned MAXRAYS,char **param_name)
01839 {
01840   Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P, *Ph = NULL;
01841   Matrix *CT;
01842   Param_Polyhedron *PP;
01843   Param_Domain   *Q;
01844   int i,hdim, dim, nb_param, np;
01845   Value *lcm, *m1, hdv;
01846   Value *context;
01847   Enumeration *en, *res;
01848 
01849   if (MAXRAYS == POL_NO_DUAL)
01850     MAXRAYS = 0;
01851 
01852   POL_ENSURE_FACETS(Pi);
01853   POL_ENSURE_VERTICES(Pi);
01854   POL_ENSURE_FACETS(C);
01855   POL_ENSURE_VERTICES(C);
01856 
01857   res = NULL;
01858   P = Pi;
01859 
01860 #ifdef EDEBUG2
01861   fprintf(stderr,"C = \n");
01862   Polyhedron_Print(stderr,P_VALUE_FMT,C);
01863   fprintf(stderr,"P = \n");
01864   Polyhedron_Print(stderr,P_VALUE_FMT,P);
01865 #endif
01866 
01867   hdim          = P->Dimension + 1;
01868   dim           = P->Dimension;
01869   nb_param      = C->Dimension;
01870 
01871   /* Don't call Polyhedron2Param_Domain if there are no parameters */
01872   if(nb_param == 0) {
01873     
01874     return(Enumerate_NoParameters(P,C,NULL,NULL,MAXRAYS,param_name));  
01875   }
01876   if(nb_param == dim) {
01877     res = (Enumeration *)malloc(sizeof(Enumeration));
01878     res->next = 0;
01879     res->ValidityDomain = DomainIntersection(P,C,MAXRAYS);
01880     value_init(res->EP.d);
01881     value_init(res->EP.x.n);
01882     value_set_si(res->EP.d,1);
01883     value_set_si(res->EP.x.n,1);
01884     if( param_name ) {
01885       fprintf(stdout,"---------------------------------------\n");
01886       fprintf(stdout,"Domain:\n");
01887       Print_Domain(stdout,res->ValidityDomain, param_name);
01888       fprintf(stdout,"\nEhrhart Polynomial:\n");
01889       print_evalue(stdout,&res->EP,param_name);
01890       fprintf(stdout, "\n");
01891     }
01892     return res;
01893   }
01894   PP = Polyhedron2Param_SimplifiedDomain(&P,C,MAXRAYS,&CEq,&CT);
01895   if(!PP) {
01896         if( param_name )
01897     fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
01898 
01899     return(NULL);
01900   }
01901   
01902   /* CT : transformation matrix to eliminate useless ("false") parameters */
01903   if(CT) {
01904     nb_param -= CT->NbColumns-CT->NbRows;
01905     dim  -= CT->NbColumns-CT->NbRows;
01906     hdim -= CT->NbColumns-CT->NbRows;
01907     
01908     /* Don't call Polyhedron2Param_Domain if there are no parameters */
01909     if(nb_param == 0) {
01910         res = Enumerate_NoParameters(P,C,CT,CEq,MAXRAYS,param_name);
01911         goto out;
01912     }  
01913   }
01914 
01915   /* get memory for Values */
01916   lcm = (Value *)malloc((nb_param+1) * sizeof(Value));
01917   m1  = (Value *)malloc((nb_param+1) * sizeof(Value));
01918   /* Initialize all the 'Value' variables */
01919   for( np=0 ; np < nb_param+1; np++ )
01920   {
01921     value_init(lcm[np]); value_init(m1[np]);
01922   }
01923   value_init(hdv);
01924 
01925   for(Q=PP->D;Q;Q=Q->next) {
01926     int hom = 0;
01927     if(CT) {
01928       Polyhedron *Dt;
01929       CQ = Q->Domain;      
01930       Dt = Polyhedron_Preimage(Q->Domain,CT,MAXRAYS);
01931       rVD = DomainIntersection(Dt,CEq,MAXRAYS);
01932       
01933       /* if rVD is empty or too small in geometric dimension */
01934       if(!rVD || emptyQ(rVD) ||
01935          (rVD->Dimension-rVD->NbEq < Dt->Dimension-Dt->NbEq-CEq->NbEq)) {
01936         if(rVD)
01937           Polyhedron_Free(rVD);
01938         Polyhedron_Free(Dt);
01939         continue;               /* empty validity domain */
01940       }
01941       Polyhedron_Free(Dt);
01942     }
01943     else
01944       rVD = CQ = Q->Domain;    
01945     en = (Enumeration *)malloc(sizeof(Enumeration));
01946     en->next = res;
01947     res = en;
01948     res->ValidityDomain = rVD;
01949     
01950     if( param_name ) {
01951       fprintf(stdout,"---------------------------------------\n");
01952       fprintf(stdout,"Domain:\n");
01953     
01954 #ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
01955       Print_Domain(stdout,res->ValidityDomain,param_name);
01956 #else    
01957       {
01958         Polyhedron *VD;
01959         VD = DomainSimplify(res->ValidityDomain,C,MAXRAYS);
01960         Print_Domain(stdout,VD,param_name);
01961         Domain_Free(VD);
01962       }
01963 #endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
01964     }
01965     
01966     overflow_warning_flag = 1;
01967     
01968     /* Scan the vertices and compute lcm */
01969     Scan_Vertices(PP,Q,CT,lcm,nb_param,param_name);
01970     
01971 #ifdef EDEBUG2
01972     fprintf(stderr,"Denominator = ");
01973     for( np=0;np<nb_param;np++)
01974       value_print(stderr,P_VALUE_FMT,lcm[np]);
01975     fprintf(stderr," and hdim == %d \n",hdim);
01976 #endif
01977     
01978 #ifdef EDEBUG2
01979     fprintf(stderr,"CQ = \n");
01980     Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
01981 #endif
01982 
01983     /* Before scanning, add constraints to ensure at least hdim*lcm */
01984     /* points in every dimension */
01985     value_set_si(hdv,hdim-nb_param);
01986 
01987     for( np=0;np<nb_param+1;np++) {
01988         if( value_notzero_p(lcm[np]) )
01989             value_multiply(m1[np],hdv,lcm[np]);
01990         else
01991             value_set_si(m1[np],1);
01992     }
01993 
01994 #ifdef EDEBUG2 
01995     fprintf(stderr,"m1 == ");
01996     for( np=0;np<nb_param;np++)
01997       value_print(stderr,P_VALUE_FMT,m1[np]);
01998     fprintf(stderr,"\n");
01999 #endif 
02000 
02001     CATCH(overflow_error) {
02002       fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
02003       CQ2 = NULL;
02004     }
02005     TRY {      
02006       CQ2 = Polyhedron_Preprocess(CQ,m1,MAXRAYS);
02007 
02008 #ifdef EDEBUG2
02009       fprintf(stderr,"After preprocess, CQ2 = ");
02010       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
02011 #endif
02012       
02013       UNCATCH(overflow_error);
02014     }
02015 
02016     /* Vin100, Feb 2001 */
02017     /* in case of degenerate, try to find a domain _containing_ CQ */
02018     if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid==0) {
02019       int r;
02020       
02021 #ifdef EDEBUG2
02022       fprintf(stderr,"Trying to call Polyhedron_Preprocess2 : CQ = \n");
02023       Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
02024 #endif
02025       
02026       /* Check if CQ is bounded */
02027       for(r=0;r<CQ->NbRays;r++) {
02028         if(value_zero_p(CQ->Ray[r][0]) ||
02029            value_zero_p(CQ->Ray[r][CQ->Dimension+1]))
02030           break;
02031       }
02032       if(r==CQ->NbRays) {
02033         
02034         /* ok, CQ is bounded */
02035         /* now find if CQ is contained in a hypercube of size m1 */
02036         CQ2 = Polyhedron_Preprocess2(CQ,m1,lcm,MAXRAYS);
02037       }
02038     }
02039 
02040     if (!CQ2) {
02041 #ifdef EDEBUG2
02042       fprintf(stderr,"Homogenize.\n");
02043 #endif
02044       hom = 1;
02045       Polyhedron *tmp = homogenize(CQ, MAXRAYS);
02046       CQ2 = Polyhedron_Preprocess(tmp,m1,MAXRAYS);
02047       Polyhedron_Free(tmp);
02048       if (!Ph)
02049         Ph = homogenize(P, MAXRAYS);
02050       for (np=0; np < nb_param+1; np++)
02051           if (value_notzero_p(lcm[np]))
02052               value_addto(m1[np],m1[np],lcm[np]);
02053     }
02054     
02055     if (!CQ2 || emptyQ(CQ2)) {
02056 #ifdef EDEBUG2
02057       fprintf(stderr,"Degenerate.\n");
02058 #endif
02059       fprintf(stdout,"Degenerate Domain. Can not continue.\n");
02060       value_init(res->EP.d);
02061       value_init(res->EP.x.n);
02062       value_set_si(res->EP.d,1);
02063       value_set_si(res->EP.x.n,-1);
02064     }
02065     else {
02066       
02067 #ifdef EDEBUG2
02068       fprintf(stderr,"CQ2 = \n");
02069       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
02070       if( ! PolyhedronIncludes(CQ, CQ2) )
02071         fprintf( stderr,"CQ does not include CQ2 !\n");
02072       else
02073         fprintf( stderr,"CQ includes CQ2.\n");
02074       if( ! PolyhedronIncludes(res->ValidityDomain, CQ2) )
02075         fprintf( stderr,"CQ2 is *not* included in validity domain !\n");
02076       else
02077         fprintf( stderr,"CQ2 is included in validity domain.\n");
02078 #endif
02079       
02080       /* L is used in counting the number of points in the base cases */
02081       L = Polyhedron_Scan(hom ? Ph : P,CQ2,MAXRAYS);
02082       U = Universe_Polyhedron(0);
02083       
02084       /* LQ is used to scan the parameter space */
02085       LQ = Polyhedron_Scan(CQ2,U,MAXRAYS); /* bounds on parameters */
02086       Domain_Free(U);
02087       if(CT)    /* we did compute another Q->Domain */
02088         Domain_Free(CQ);
02089       
02090       /* Else, CQ was Q->Domain (used in res) */
02091       Domain_Free(CQ2);
02092       
02093 #ifdef EDEBUG2
02094       fprintf(stderr,"L = \n");
02095       Polyhedron_Print(stderr,P_VALUE_FMT,L);
02096       fprintf(stderr,"LQ = \n");
02097       Polyhedron_Print(stderr,P_VALUE_FMT,LQ);
02098 #endif
02099 #ifdef EDEBUG3
02100       fprintf(stdout,"\nSystem of Equations:\n");
02101 #endif
02102       
02103       value_init(res->EP.d);
02104       value_set_si(res->EP.d,0);
02105       
02106       /* Create a context vector size dim+2 */
02107       context = (Value *) malloc ((hdim+1+hom)*sizeof(Value));  
02108       for(i=0;i<=(hdim+hom);i++)
02109         value_init(context[i]);
02110       Vector_Set(context,0,(hdim+1+hom));
02111       
02112       /* Set context[hdim] = 1  (the constant) */
02113       value_set_si(context[hdim+hom],1);
02114       
02115       CATCH(overflow_error) {
02116           fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
02117           fprintf(stderr,"You should rebuild PolyLib using GNU-MP or increasing the size of integers.\n");
02118           overflow_warning_flag = 0;
02119           assert(overflow_warning_flag);
02120         
02121       }
02122       TRY {
02123           res->EP.x.p = P_Enum(L,LQ,context,1,nb_param+hom,dim+hom,lcm,param_name);
02124           UNCATCH(overflow_error);      
02125       }
02126       if (hom)
02127           dehomogenize_evalue(&res->EP, nb_param+1);
02128       
02129       for(i=0;i<=(hdim+hom);i++)
02130         value_clear(context[i]);
02131       free(context);
02132       Domain_Free(L);
02133       Domain_Free(LQ);
02134       
02135 #ifdef EDEBUG5
02136         if( param_name )
02137    {
02138       fprintf(stdout,"\nEhrhart Polynomial (before simplification):\n");
02139       print_evalue(stdout,&res->EP,param_name);
02140         }
02141 #endif
02142 
02143       /* Try to simplify the result */
02144       reduce_evalue(&res->EP);
02145       
02146       /* Put back the original parameters into result */
02147       /* (equalities have been eliminated)            */
02148       if(CT) 
02149           addeliminatedparams_evalue(&res->EP,CT);
02150       
02151       if (param_name) {
02152         fprintf(stdout,"\nEhrhart Polynomial:\n");
02153         print_evalue(stdout,&res->EP, param_name);
02154         fprintf(stdout,"\n");
02155         /* sometimes the final \n lacks (when a single constant is printed) */
02156       }
02157       
02158     }
02159   }
02160 
02161   if (Ph)
02162     Polyhedron_Free(Ph);
02163   /* Clear all the 'Value' variables */
02164   for (np=0; np < nb_param+1; np++)
02165   {
02166     value_clear(lcm[np]); value_clear(m1[np]);
02167   }
02168   value_clear(hdv);
02169   free(lcm);
02170   free(m1);
02171 
02172 out:
02173   if (CEq)
02174     Polyhedron_Free(CEq);
02175   if (CT)
02176     Matrix_Free(CT);
02177   free(PP);
02178   if( P != Pi )
02179     Polyhedron_Free( P );
02180 
02181   return res;
02182 } /* Polyhedron_Enumerate */ 
02183 
02184 void Enumeration_Free(Enumeration *en)
02185 {
02186   Enumeration *ee;
02187 
02188   while( en )
02189   {
02190           free_evalue_refs( &(en->EP) );
02191           Domain_Free( en->ValidityDomain );
02192           ee = en ->next;
02193           free( en );
02194           en = ee;
02195   }
02196 }
02197 
02198 // adds by B. Meister for Ehrhart Polynomial approximation
02199 
02200 /**
02201 
02202 void evalue_div (e, n)                                    
02203 divides the evalue e by the integer n
02204 recursive function
02205 Warning :  modifies e
02206 
02207 @param e an evalue (to be divided by n)
02208 @param n
02209 
02210 */
02211 
02212 void evalue_div(evalue * e, Value n) {
02213   int i;
02214   Value gc;
02215   value_init(gc);
02216   if (value_zero_p(e->d)) {
02217     for (i=0; i< e->x.p->size; i++) {
02218       evalue_div(&(e->x.p->arr[i]), n);
02219     }
02220   }
02221   else {
02222     value_multiply(e->d, e->d, n);
02223     /* simplify the new rational if needed */
02224     Gcd(e->x.n, e->d, &gc);
02225     if (value_notone_p(gc)&&(value_notzero_p(gc))) {
02226       value_division(e->d, e->d, gc);
02227       value_division(e->x.n, e->x.n, gc);
02228     }
02229   }
02230   value_clear(gc);
02231 } /* evalue_div */
02232 
02233 
02234 /** 
02235 
02236 Ehrhart_Quick_Apx_Full_Dim(P, C, MAXRAYS, param_names)
02237 
02238 Procedure to estimate the nubmer of points in a parameterized polytope.
02239 Returns a list of validity domains + evalues EP
02240 B.M.
02241 The most rough and quick approximation by variables expansion  
02242 Deals with the full-dimensional case.                          
02243 @param Pi : Polyhedron to enumerate (approximatively)
02244 @param C : Context Domain
02245 @param MAXRAYS : size of workspace
02246 @param param_name : names for the parameters (char strings)
02247 
02248 */
02249 Enumeration *Ehrhart_Quick_Apx_Full_Dim(Polyhedron *Pi,Polyhedron *C,unsigned MAXRAYS, char ** param_name)
02250 {
02251   Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P;
02252   Matrix *CT;
02253   Param_Polyhedron *PP;
02254   Param_Domain   *Q;
02255   int i,j,hdim, dim, nb_param, np;
02256   Value *lcm, *m1, hdv;
02257   Value *context;
02258   Enumeration *en, *res;
02259   unsigned int nb_vars;
02260   Matrix * denoms;
02261   Value expansion_det;
02262   Value global_var_lcm;
02263   Matrix * expansion;
02264   Polyhedron * Expanded;
02265 
02266   // BM : used to scan the vertices
02267   Param_Vertices * V_tmp;
02268 
02269   res = NULL;
02270   P = Pi;
02271 
02272 
02273   value_init(expansion_det);
02274   value_init(global_var_lcm);
02275 
02276 #ifdef EDEBUG2
02277   fprintf(stderr,"C = \n");
02278   Polyhedron_Print(stderr,P_VALUE_FMT,C);
02279   fprintf(stderr,"P = \n");
02280   Polyhedron_Print(stderr,P_VALUE_FMT,P);
02281 #endif
02282 
02283   hdim          = P->Dimension + 1;
02284   dim           = P->Dimension;
02285   nb_param      = C->Dimension;
02286 
02287   /* Don't call Polyhedron2Param_Domain if there are no parameters */
02288   if(nb_param == 0) {
02289     
02290     return(Enumerate_NoParameters(P,C,NULL,NULL,MAXRAYS, param_name));  
02291   }
02292 
02293 #if EDEBUG2
02294   printf("Enumerating polyhedron : \n");
02295   Polyhedron_Print(stdout, P_VALUE_FMT, P);
02296 #endif
02297 
02298   PP = Polyhedron2Param_SimplifiedDomain(&P,C,MAXRAYS,&CEq,&CT);
02299   if(!PP) {
02300     if( param_name )
02301       fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
02302 
02303     return(NULL);
02304   }
02305   
02306   /* CT : transformation matrix to eliminate useless ("false") parameters */
02307   if(CT) {
02308     nb_param -= CT->NbColumns-CT->NbRows;
02309     dim  -= CT->NbColumns-CT->NbRows;
02310     hdim -= CT->NbColumns-CT->NbRows;
02311     
02312     /* Don't call Polyhedron2Param_Domain if there are no parameters */
02313     if(nb_param == 0)
02314     {
02315             res = Enumerate_NoParameters(P,C,CT,CEq,MAXRAYS,param_name);
02316             if( P != Pi )
02317                     Polyhedron_Free( P );
02318             return( res );
02319     }  
02320   }
02321 
02322   /* get memory for Values */
02323   lcm = (Value *)malloc( nb_param * sizeof(Value));
02324   m1  = (Value *)malloc( nb_param * sizeof(Value));
02325   /* Initialize all the 'Value' variables */
02326   for( np=0 ; np<nb_param ; np++ )
02327   {
02328     value_init(lcm[np]); value_init(m1[np]);
02329   }
02330   value_init(hdv);
02331 
02332   /* BM: Scan the vertices and make an orthogonal expansion of the variable space */
02333   /* a- prepare the array of common denominators */
02334   if (!PP->nbV) return 0;
02335   else {
02336     nb_vars = P->Dimension-nb_param;
02337     denoms = Matrix_Alloc(1, nb_vars);
02338     for (i=0; i< nb_vars; i++) value_set_si(denoms->p[0][i], 0);
02339   }
02340   
02341   /* b- scan the vertices and compute the global variable lcms */
02342   for (V_tmp = PP->V; V_tmp; V_tmp=V_tmp->next)
02343     for (i=0; i< nb_vars; i++) 
02344       Lcm3(denoms->p[0][i],V_tmp->Vertex->p[i][nb_param+1], &(denoms->p[0][i]));
02345   printf("denoms = \n");
02346   Matrix_Print(stderr, P_VALUE_FMT, denoms);
02347   value_set_si(expansion_det, 1);
02348   value_set_si(global_var_lcm, 1);
02349   for (i=0; i< nb_vars;i++) {
02350     value_multiply(expansion_det, expansion_det, denoms->p[0][i]);
02351     Lcm3(global_var_lcm, denoms->p[0][i], &global_var_lcm);
02352   }
02353   printf("expansion_det:\n");
02354   value_print(stderr, P_VALUE_FMT, expansion_det);
02355   printf("\n");
02356   
02357   
02358   /* the expansion can be actually writen as denoms_det.L^{-1} */
02359   /* this is equivalent to multiply the rows of P by denoms_det */
02360   for (i=0; i< nb_vars; i++) value_division(denoms->p[0][i], global_var_lcm, denoms->p[0][i]);
02361   
02362   // OPT : we could use a vector instead of a diagonal matrix here (c- and d-).
02363   /* c- make the quick expansion matrix */
02364   printf("nb vars = %d, nb param = %d", nb_vars, nb_param);
02365   expansion = Matrix_Alloc(nb_vars+nb_param+1, nb_vars+nb_param+1);
02366   for (i=0; i< nb_vars; i++) {
02367     for (j=0; j< nb_vars+nb_param+1; j++) {
02368       if (i==j) value_assign(expansion->p[i][j], denoms->p[0][i]);
02369       else value_set_si(expansion->p[i][j], 0);
02370     }
02371   }
02372   for (i=nb_vars; i< nb_vars+nb_param+1; i++) {
02373     for (j=0; j< nb_vars+nb_param+1; j++) {
02374       if (i==j) value_assign(expansion->p[i][j], global_var_lcm);
02375       else value_set_si(expansion->p[i][j], 0);
02376     }
02377   }
02378   value_clear(global_var_lcm);
02379   printf("expansion = \n");
02380   Matrix_Print(stderr, P_VALUE_FMT, expansion);
02381   
02382   /* d- apply the variable expansion to the polyhedron */
02383 #if EDEBUG2 
02384   Polyhedron_Print(stderr, P_VALUE_FMT, P);
02385 #endif
02386 
02387   Expanded = Polyhedron_Preimage(P, expansion, MAXRAYS);
02388   
02389 #if EDEBUG2
02390   Polyhedron_Print(stderr, P_VALUE_FMT, Expanded);
02391 #endif
02392 
02393   Polyhedron_Free(P);
02394   P = Expanded;
02395   /* formerly : Scan the vertices and compute lcm 
02396      Scan_Vertices_Quick_Apx(PP,Q,CT,lcm,nb_param); */
02397   /* now : lcm = 1 (by construction) */
02398   // OPT : A lot among what happens after this point can be simplified by knowing that lcm[i] = 1
02399   // for now, we just conservatively fool the rest of the function with lcm = 1
02400   // to do after a first debugging
02401   for (i=0; i< nb_param; i++) value_set_si(lcm[i], 1);
02402   
02403   for(Q=PP->D;Q;Q=Q->next) {
02404     if(CT) {
02405       Polyhedron *Dt;
02406       CQ = Q->Domain;      
02407       Dt = Polyhedron_Preimage(Q->Domain,CT,MAXRAYS);
02408       rVD = DomainIntersection(Dt,CEq,MAXRAYS);
02409       
02410       /* if rVD is empty or too small in geometric dimension */
02411       if(!rVD || emptyQ(rVD) ||
02412          (rVD->Dimension-rVD->NbEq < Dt->Dimension-Dt->NbEq-CEq->NbEq)) {
02413         if(rVD)
02414           Polyhedron_Free(rVD);
02415         Polyhedron_Free(Dt);
02416         continue;               /* empty validity domain */
02417       }
02418       Polyhedron_Free(Dt);
02419     }
02420     else
02421       rVD = CQ = Q->Domain;
02422     en = (Enumeration *)malloc(sizeof(Enumeration));
02423     en->next = res;
02424     res = en;
02425     res->ValidityDomain = rVD;
02426         
02427     if( param_name )
02428       {    
02429         fprintf(stdout,"---------------------------------------\n");
02430         fprintf(stdout,"Domain:\n");
02431     
02432 #ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
02433         Print_Domain(stdout,res->ValidityDomain,param_name);
02434 #else    
02435         {
02436           Polyhedron *VD;
02437           VD = DomainSimplify(res->ValidityDomain,C,MAXRAYS);
02438           Print_Domain(stdout,VD,param_name);
02439           Domain_Free(VD);
02440         }
02441 #endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
02442       }
02443     
02444     overflow_warning_flag = 1;
02445 
02446     // BM : expansion formerly here.
02447     
02448 #ifdef EDEBUG2
02449     fprintf(stderr,"Denominator = ");
02450     for( np=0;np<nb_param;np++)
02451       value_print(stderr,P_VALUE_FMT,lcm[np]);
02452     fprintf(stderr," and hdim == %d \n",hdim);
02453 #endif
02454     
02455 #ifdef EDEBUG2
02456     fprintf(stderr,"CQ = \n");
02457     Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
02458 #endif
02459 
02460     /* Before scanning, add constraints to ensure at least hdim*lcm */
02461     /* points in every dimension */
02462     value_set_si(hdv,hdim-nb_param);
02463 
02464     for( np=0;np<nb_param;np++)
02465     {
02466                 if( value_notzero_p(lcm[np]) )
02467                         value_multiply(m1[np],hdv,lcm[np]);
02468                 else
02469                         value_set_si(m1[np],1);
02470     }
02471 
02472 #ifdef EDEBUG2 
02473     fprintf(stderr,"m1 == ");
02474     for( np=0;np<nb_param;np++)
02475       value_print(stderr,P_VALUE_FMT,m1[np]);
02476     fprintf(stderr,"\n");
02477 #endif 
02478 
02479     CATCH(overflow_error) {
02480       fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
02481       CQ2 = NULL;
02482     }
02483     TRY {      
02484       CQ2 = Polyhedron_Preprocess(CQ,m1,MAXRAYS);
02485 
02486 #ifdef EDEBUG2
02487       fprintf(stderr,"After preprocess, CQ2 = ");
02488       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
02489 #endif
02490       
02491       UNCATCH(overflow_error);
02492     }
02493     
02494     /* Vin100, Feb 2001 */
02495     /* in case of degenerate, try to find a domain _containing_ CQ */
02496     if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid==0) {
02497       int r;
02498       
02499 #ifdef EDEBUG2
02500       fprintf(stderr,"Trying to call Polyhedron_Preprocess2 : CQ = \n");
02501       Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
02502 #endif
02503       
02504       /* Check if CQ is bounded */
02505       for(r=0;r<CQ->NbRays;r++) {
02506         if(value_zero_p(CQ->Ray[r][0]) ||
02507            value_zero_p(CQ->Ray[r][CQ->Dimension+1]))
02508           break;
02509       }
02510       if(r==CQ->NbRays) {
02511         
02512         /* ok, CQ is bounded */
02513         /* now find if CQ is contained in a hypercube of size m1 */
02514         CQ2 = Polyhedron_Preprocess2(CQ,m1,lcm,MAXRAYS);
02515       }
02516     }
02517     if (!CQ2 || emptyQ(CQ2)) {
02518 #ifdef EDEBUG2
02519       fprintf(stderr,"Degenerate.\n");
02520 #endif
02521       fprintf(stdout,"Degenerate Domain. Can not continue.\n");
02522       value_init(res->EP.d);
02523       value_init(res->EP.x.n);
02524       value_set_si(res->EP.d,1);
02525       value_set_si(res->EP.x.n,-1);
02526     }
02527     else {
02528       
02529 #ifdef EDEBUG2
02530       fprintf(stderr,"CQ2 = \n");
02531       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
02532       if( ! PolyhedronIncludes(CQ, CQ2) )
02533         fprintf( stderr,"CQ does not include CQ2 !\n");
02534       else
02535         fprintf( stderr,"CQ includes CQ2.\n");
02536       if( ! PolyhedronIncludes(res->ValidityDomain, CQ2) )
02537         fprintf( stderr,"CQ2 is *not* included in validity domain !\n");
02538       else
02539         fprintf( stderr,"CQ2 is included in validity domain.\n");
02540 #endif
02541       
02542       /* L is used in counting the number of points in the base cases */
02543       L = Polyhedron_Scan(P,CQ,MAXRAYS);
02544       U = Universe_Polyhedron(0);
02545       
02546       /* LQ is used to scan the parameter space */
02547       LQ = Polyhedron_Scan(CQ2,U,MAXRAYS); /* bounds on parameters */
02548       Domain_Free(U);
02549       if(CT)    /* we did compute another Q->Domain */
02550         Domain_Free(CQ);
02551       
02552       /* Else, CQ was Q->Domain (used in res) */
02553       Domain_Free(CQ2);
02554       
02555 #ifdef EDEBUG2
02556       fprintf(stderr,"L = \n");
02557       Polyhedron_Print(stderr,P_VALUE_FMT,L);
02558       fprintf(stderr,"LQ = \n");
02559       Polyhedron_Print(stderr,P_VALUE_FMT,LQ);
02560 #endif
02561 #ifdef EDEBUG3
02562       fprintf(stdout,"\nSystem of Equations:\n");
02563 #endif
02564       
02565       value_init(res->EP.d);
02566       value_set_si(res->EP.d,0);
02567       
02568       /* Create a context vector size dim+2 */
02569       context = (Value *) malloc ((hdim+1)*sizeof(Value));  
02570       for(i=0;i<=(hdim);i++)
02571         value_init(context[i]);
02572       Vector_Set(context,0,(hdim+1));
02573       
02574       /* Set context[hdim] = 1  (the constant) */
02575       value_set_si(context[hdim],1);
02576       
02577       CATCH(overflow_error) {
02578                         fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
02579                         fprintf(stderr,"You should rebuild PolyLib using GNU-MP or increasing the size of integers.\n");
02580                         overflow_warning_flag = 0;
02581                         assert(overflow_warning_flag);
02582         
02583       }
02584       TRY {
02585                         res->EP.x.p = P_Enum(L,LQ,context,1,nb_param,dim,lcm, param_name);
02586                         UNCATCH(overflow_error);        
02587       }
02588       
02589       for(i=0;i<=(hdim);i++)
02590         value_clear(context[i]);
02591       free(context);
02592       Domain_Free(L);
02593       Domain_Free(LQ);
02594       
02595 #ifdef EDEBUG5
02596       if( param_name )
02597         {
02598           fprintf(stdout,"\nEhrhart Polynomial (before simplification):\n");
02599           print_evalue(stdout,&res->EP,param_name);
02600         }
02601 
02602       /* BM: divide EP by denom_det, the expansion factor */
02603       fprintf(stdout,"\nEhrhart Polynomial (before division):\n");
02604       print_evalue(stdout,&(res->EP),param_name);
02605 #endif
02606 
02607       evalue_div(&(res->EP), expansion_det);
02608 
02609 
02610       /* Try to simplify the result */
02611       reduce_evalue(&res->EP);
02612       
02613       /* Put back the original parameters into result */
02614       /* (equalities have been eliminated)            */
02615       if(CT) 
02616           addeliminatedparams_evalue(&res->EP,CT);
02617       
02618       if( param_name )
02619         {
02620           fprintf(stdout,"\nEhrhart Polynomial:\n");
02621           print_evalue(stdout,&res->EP, param_name);
02622           fprintf(stdout,"\n");
02623           /* sometimes the final \n lacks (when a single constant is printed) */
02624         }
02625       
02626     }
02627   }
02628   value_clear(expansion_det);
02629 
02630   if( P != Pi )
02631         Polyhedron_Free( P );
02632   /* Clear all the 'Value' variables */
02633   for( np=0; np<nb_param ; np++ )
02634   {
02635     value_clear(lcm[np]); value_clear(m1[np]);
02636   }
02637   value_clear(hdv);
02638 
02639   return res;
02640 } /* Ehrhart_Quick_Apx_Full_Dim */ 
02641 
02642 
02643 /** 
02644 
02645 Ehrhart_Quick_Apx
02646 
02647 computes the approximation of the Ehrhart polynomial of a polyhedron (implicit form -> matrix), treating the non-full-dimensional case.
02648 
02649 @param M a Matrix (polyhedron under implicit form)
02650 @param C a Matrix (context under implicit form)
02651 @param Validity_Lattice a pointer to a Matrix (returned : the parameter's validity lattice)
02652 @param MAXRAYS (the needed "working space" for other polylib functions used here)
02653 @param param_name (the names of the parameters)
02654 
02655 */
02656 Enumeration *Ehrhart_Quick_Apx(Matrix * M, Matrix * C, Matrix ** Validity_Lattice, unsigned MAXRAYS, char ** param_name) {
02657 
02658   // 0- compute a full-dimensional polyhedron with the same number of points,
02659   // and its parameter's validity lattice
02660   Matrix * M_full;
02661   Polyhedron * P, * PC;
02662   Enumeration *en;
02663   
02664   M_full = full_dimensionize(M, C->NbColumns-2, Validity_Lattice);
02665   // 1- apply the same tranformation to the context that what has been applied to the parameters space of the polyhedron.
02666   mpolyhedron_compress_last_vars(C, *Validity_Lattice);
02667   show_matrix(M_full);
02668   P = Constraints2Polyhedron(M_full, MAXRAYS);
02669   PC = Constraints2Polyhedron(C, MAXRAYS);
02670   Matrix_Free(M_full);
02671   // compute the Ehrhart polynomial of the "equivalent" polyhedron
02672   en = Ehrhart_Quick_Apx_Full_Dim(P, PC, MAXRAYS, param_name);
02673 
02674   // clean up
02675   Polyhedron_Free(P);
02676   Polyhedron_Free(PC);
02677   return en;
02678 } /* Ehrhart_Quick_Apx */
02679 
02680 
02681 

Generated on Mon Sep 12 15:15:10 2005 for polylib by doxygen 1.3.5