Main Page   Compound List   File List   Compound 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 
00020 
00021 /*! \class Ehrhart
00022 
00023 The following are mainly for debug purposes. You shouldn't need to
00024 change anything for daily usage...
00025 
00026 <p>
00027 
00028 you may define each macro independently 
00029 <ol>
00030 <li> #define EDEBUG minimal debug 
00031 <li> #define EDEBUG1 prints enumeration points
00032 <li> #define EDEBUG11 prints number of points
00033 <li> #define EDEBUG2 prints domains
00034 <li> #define EDEBUG21 prints more domains
00035 <li> #define EDEBUG3 prints systems of equations that are solved
00036 <li> #define EDEBUG4 prints message for degree reduction
00037 <li> #define EDEBUG5 prints result before simplification 
00038 <li> #define EDEBUG6 prints domains in Preprocess 
00039 <li> #define EDEBUG61 prints even more in Preprocess
00040 <li> #define EDEBUG62 prints domains in Preprocess2
00041 </ol>
00042 */
00043 
00044 
00045 /** 
00046     
00047 define this to print all constraints on the validity domains if not
00048 defined, only new constraints (not in validity domain given by the
00049 user) are printed
00050 
00051 */
00052 #define EPRINT_ALL_VALIDITY_CONSTRAINTS
00053 
00054 /* #define EDEBUG       */              /* minimal debug */
00055 /* #define EDEBUG1      */              /* prints enumeration points */
00056 /* #define EDEBUG11     */              /* prints number of points */
00057 /* #define EDEBUG2      */              /* prints domains */
00058 /* #define EDEBUG21     */              /* prints more domains */
00059 /* #define EDEBUG3      */              /* prints systems of equations that are solved */
00060 /* #define EDEBUG4      */              /* prints message for degree reduction */
00061 /* #define EDEBUG5      */              /* prints result before simplification */
00062 /* #define EDEBUG6      */              /* prints domains in Preprocess */
00063 /* #define EDEBUG61     */              /* prints even more in Preprocess */
00064 /* #define EDEBUG62     */              /* prints domains in Preprocess2 */
00065 
00066 
00067 /**
00068  Reduce the degree of resulting polynomials
00069 */
00070 #define REDUCE_DEGREE
00071 
00072 /** 
00073 define this to print one warning message per domain overflow these
00074 overflows should no longer happen since version 4.20
00075 */
00076 #define ALL_OVERFLOW_WARNINGS
00077 
00078 /******************* -----------END USER #DEFS-------- *********************/
00079 
00080 int overflow_warning_flag = 1;
00081 
00082 /*-------------------------------------------------------------------*/
00083 /* EHRHART POLYNOMIAL SYMBOLIC ALGEBRA SYSTEM                        */
00084 /*-------------------------------------------------------------------*/ 
00085 /** 
00086 
00087 EHRHART POLYNOMIAL SYMBOLIC ALGEBRA SYSTEM. The newly allocated enode
00088 can be freed with a simple free(x)
00089 
00090 @param type : enode type
00091 @param size : degree+1 for polynomial, period for periodic
00092 @param pos  : 1..nb_param, position of parameter            
00093 @return a newly allocated enode 
00094 
00095 */
00096 enode *new_enode(enode_type type,int size,int pos) {
00097   
00098   enode *res;
00099   int i;
00100   
00101   if(size == 0) {
00102     fprintf(stderr, "Allocating enode of size 0 !\n" );
00103     return NULL;
00104   }
00105   res = (enode *) malloc(sizeof(enode) + (size-1)*sizeof(evalue));
00106   res->type = type;
00107   res->size = size;
00108   res->pos = pos;
00109   for(i=0; i<size; i++) {
00110     value_init(res->arr[i].d);
00111     value_set_si(res->arr[i].d,0);
00112     res->arr[i].x.p = 0;
00113   }
00114   return res;
00115 } /* new_enode */
00116 
00117 /**
00118 releases all memory referenced by e.  (recursive)        
00119 @param e pointer to an evalue
00120 */
00121 void free_evalue_refs(evalue *e) {
00122   
00123   enode *p;
00124   int i;
00125   
00126   if (value_notzero_p(e->d)) {
00127     
00128     /* 'e' stores a constant */
00129     value_clear(e->d);
00130     value_clear(e->x.n);
00131     return; 
00132   }  
00133   value_clear(e->d);
00134   p = e->x.p;
00135   if (!p) return;       /* null pointer */
00136   for (i=0; i<p->size; i++) {
00137     free_evalue_refs(&(p->arr[i]));
00138   }
00139   free(p);
00140   return;
00141 } /* free_evalue_refs */
00142 
00143 /**
00144 
00145 @param e pointer to an evalue 
00146 @return description
00147 
00148 */
00149 enode *ecopy(enode *e) {
00150   
00151   enode *res;
00152   int i;
00153   
00154   res = new_enode(e->type,e->size,e->pos);
00155   for(i=0;i<e->size;++i) {
00156     value_assign(res->arr[i].d,e->arr[i].d);
00157     if(value_zero_p(res->arr[i].d))
00158       res->arr[i].x.p = ecopy(e->arr[i].x.p);
00159     else {
00160       value_init(res->arr[i].x.n);
00161       value_assign(res->arr[i].x.n,e->arr[i].x.n);
00162     }
00163   }
00164   return(res);
00165 } /* ecopy */
00166 
00167 /**
00168 
00169 @param DST destination file
00170 @param e pointer to evalue to be printed
00171 
00172 */
00173 void print_evalue(FILE *DST,evalue *e,char **pname) {
00174   
00175   if(value_notzero_p(e->d)) {    
00176     if(value_notone_p(e->d)) {
00177       value_print(DST,VALUE_FMT,e->x.n);
00178       fprintf(DST,"/");
00179       value_print(DST,VALUE_FMT,e->d);
00180     }  
00181     else {
00182       value_print(DST,VALUE_FMT,e->x.n);
00183     }
00184   }  
00185   else
00186     print_enode(DST,e->x.p,pname);
00187   return;
00188 } /* print_evalue */
00189 
00190 /** prints the enode  to DST  
00191 
00192 @param DST destination file 
00193 @param p pointer to enode  to be printed 
00194 @param pname array of strings, name of the parameters
00195 
00196 */
00197 void print_enode(FILE *DST,enode *p,char **pname) {
00198   
00199   int i;
00200   
00201   if (!p) {
00202     fprintf(DST, "NULL");
00203     return;
00204   }
00205   if (p->type == evector) {
00206     fprintf(DST, "{ ");
00207     for (i=0; i<p->size; i++) {
00208       print_evalue(DST, &p->arr[i], pname);
00209       if (i!=(p->size-1))
00210         fprintf(DST, ", ");
00211     }
00212     fprintf(DST, " }\n");
00213   }
00214   else if (p->type == polynomial) {
00215     fprintf(DST, "( ");
00216     for (i=p->size-1; i>=0; i--) {
00217       print_evalue(DST, &p->arr[i], pname);
00218       if (i==1) fprintf(DST, " * %s + ", pname[p->pos-1]);
00219       else if (i>1) 
00220         fprintf(DST, " * %s^%d + ", pname[p->pos-1], i);
00221     }
00222     fprintf(DST, " )\n");
00223   }
00224   else if (p->type == periodic) {
00225     fprintf(DST, "[ ");
00226     for (i=0; i<p->size; i++) {
00227       print_evalue(DST, &p->arr[i], pname);
00228       if (i!=(p->size-1)) fprintf(DST, ", ");
00229     }
00230     fprintf(DST," ]_%s", pname[p->pos-1]);
00231   }
00232   return;
00233 } /* print_enode */ 
00234 
00235 /**
00236 
00237 @param  e1 pointers to evalues
00238 @param  e2 pointers to evalues
00239 @return 1 (true) if they are equal, 0 (false) if not       
00240 
00241 */
00242 static int eequal(evalue *e1,evalue *e2) { 
00243  
00244     int i;
00245     enode *p1, *p2;
00246   
00247     if (value_ne(e1->d,e2->d))
00248         return 0;
00249   
00250     /* e1->d == e2->d */
00251     if (value_notzero_p(e1->d)) {    
00252         if (value_ne(e1->x.n,e2->x.n))
00253             return 0;
00254     
00255         /* e1->d == e2->d != 0  AND e1->n == e2->n */
00256         return 1;
00257     }
00258   
00259     /* e1->d == e2->d == 0 */
00260     p1 = e1->x.p;
00261     p2 = e2->x.p;
00262     if (p1->type != p2->type) return 0;
00263     if (p1->size != p2->size) return 0;
00264     if (p1->pos  != p2->pos) return 0;
00265     for (i=0; i<p1->size; i++)
00266         if (!eequal(&p1->arr[i], &p2->arr[i]) ) 
00267             return 0;
00268     return 1;
00269 } /* eequal */
00270 
00271 /** 
00272 
00273 @param e pointer to an evalue
00274 
00275 */
00276 void reduce_evalue (evalue *e) {
00277   
00278     enode *p;
00279     int i, j, k;
00280   
00281     if (value_notzero_p(e->d))
00282         return; /* a rational number, its already reduced */
00283     if(!(p = e->x.p))
00284         return; /* hum... an overflow probably occured */
00285   
00286     /* First reduce the components of p */
00287     for (i=0; i<p->size; i++)
00288         reduce_evalue(&p->arr[i]);
00289 
00290     if (p->type==periodic) {
00291     
00292         /* Try to reduce the period */
00293         for (i=1; i<=(p->size)/2; i++) {
00294             if ((p->size % i)==0) {
00295         
00296                 /* Can we reduce the size to i ? */
00297                 for (j=0; j<i; j++)
00298                     for (k=j+i; k<e->x.p->size; k+=i)
00299                         if (!eequal(&p->arr[j], &p->arr[k])) goto you_lose;
00300 
00301                 /* OK, lets do it */
00302                 for (j=i; j<p->size; j++) free_evalue_refs(&p->arr[j]);
00303                 p->size = i;
00304                 break;
00305 
00306             you_lose:   /* OK, lets not do it */
00307                 continue;
00308             }
00309         }
00310 
00311         /* Try to reduce its strength */
00312         if (p->size == 1) {
00313             value_clear(e->d);
00314             memcpy(e,&p->arr[0],sizeof(evalue));
00315             free(p);
00316         }
00317     }
00318     else if (p->type==polynomial) {
00319           
00320         /* Try to reduce the degree */
00321         for (i=p->size-1;i>=0;i--) {
00322             if (value_one_p(p->arr[i].d) && value_zero_p(p->arr[i].x.n))
00323         
00324                 /* Zero coefficient */
00325                 continue;
00326             else
00327                 break;
00328         }
00329         if (i==-1) p->size = 1;
00330         else if (i+1<p->size) 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         value_init(tmp.x.n);
00535      
00536         /* res = res + v1[i]*v2[i] */
00537         emul(&v1->arr[i],&v2->arr[i],&tmp);
00538         eadd(&tmp,res);
00539         free_evalue_refs(&tmp);
00540     }
00541     return;
00542 } /* edot */
00543 
00544 /**
00545 
00546 local recursive function used in the following ref contains the new
00547 position for each old index position
00548 
00549 @param e pointer to an evalue
00550 @param ref transformation Matrix
00551 
00552 */
00553 static void aep_evalue(evalue *e, int *ref) {
00554   
00555     enode *p;
00556     int i;
00557   
00558     if (value_notzero_p(e->d))
00559         return;         /* a rational number, its already reduced */
00560     if(!(p = e->x.p))
00561         return;         /* hum... an overflow probably occured */
00562   
00563     /* First check the components of p */
00564     for (i=0;i<p->size;i++)
00565         aep_evalue(&p->arr[i],ref);
00566   
00567     /* Then p itself */
00568     p->pos = ref[p->pos-1]+1;
00569     return;
00570 } /* aep_evalue */
00571 
00572 /** Comments */
00573 static void addeliminatedparams_evalue(evalue *e,Matrix *CT) {
00574         
00575     enode *p;
00576     int i, j;
00577     int *ref;
00578 
00579     if (value_notzero_p(e->d))
00580         return;          /* a rational number, its already reduced */
00581     if(!(p = e->x.p))
00582         return;          /* hum... an overflow probably occured */
00583   
00584     /* Compute ref */
00585     ref = (int *)malloc(sizeof(int)*(CT->NbRows-1));
00586     for(i=0;i<CT->NbRows-1;i++)
00587         for(j=0;j<CT->NbColumns;j++)
00588             if(value_notzero_p(CT->p[i][j])) {
00589                 ref[i] = j;
00590                 break;
00591             }
00592   
00593     /* Transform the references in e, using ref */
00594     aep_evalue(e,ref);
00595     free( ref );
00596     return;
00597 } /* addeliminatedparams_evalue */
00598 
00599 /** 
00600 
00601 This procedure finds an integer point contained in polyhedron D /
00602 first checks for positive values, then for negative values returns
00603 TRUE on success. Result is in min.  returns FALSE if no integer point
00604 is found
00605 
00606 <p>
00607 
00608 This is the maximum number of iterations for a given parameter to find
00609 a integer point inside the context. Kind of weird. cherche_min should
00610 
00611 <p>
00612 
00613 @param min
00614 @param D
00615 @param pos
00616 
00617 */
00618  //FIXME: needs to be rewritten !
00619 #define MAXITER 100
00620 int cherche_min(Value *min,Polyhedron *D,int pos) {
00621         
00622     Value binf, bsup;   /* upper & lower bound */
00623     Value i;
00624     int flag, maxiter;
00625   
00626     if(!D)
00627         return(1);
00628     if(pos > D->Dimension)
00629         return(1);
00630   
00631     value_init(binf); value_init(bsup);
00632     value_init(i);
00633   
00634 #ifdef EDEBUG61
00635     fprintf(stderr,"Entering Cherche min --> \n");
00636     fprintf(stderr,"LowerUpperBounds :\n");
00637     fprintf(stderr,"pos = %d\n",pos);
00638     fprintf(stderr,"current min = (");
00639     value_print(stderr,P_VALUE_FMT,min[0]);
00640     {int j;
00641     for(j=1;j<=D->Dimension ; j++) {
00642         fprintf(stderr,", ");
00643         value_print(stderr,P_VALUE_FMT,min[j]);
00644     }  
00645     }
00646     fprintf(stderr,")\n");
00647 #endif
00648         
00649     flag = lower_upper_bounds(pos,D,min,&binf,&bsup);
00650   
00651 #ifdef EDEBUG61
00652     fprintf(stderr, "flag = %d\n", flag);
00653     fprintf(stderr,"binf = ");
00654     value_print(stderr,P_VALUE_FMT,binf);
00655     fprintf(stderr,"\n");
00656     fprintf(stderr,"bsup = ");
00657     value_print(stderr,P_VALUE_FMT,bsup);
00658     fprintf(stderr,"\n");
00659 #endif
00660 
00661     if(flag&LB_INFINITY)
00662         value_set_si(binf,0);
00663   
00664     /* Loop from 0 (or binf if positive) to bsup */
00665     for(maxiter=0,(((flag&LB_INFINITY) || value_neg_p(binf)) ? 
00666             value_set_si(i,0) : value_assign(i,binf));
00667         ((flag&UB_INFINITY) || value_le(i,bsup)) && maxiter<MAXITER ;
00668         value_increment(i,i),maxiter++) {
00669     
00670         value_assign(min[pos],i);
00671         if(cherche_min(min,D->next,pos+1)) {
00672             value_clear(binf); value_clear(bsup);
00673             value_clear(i);
00674             return(1);
00675         }  
00676     }
00677   
00678     /* Descending loop from -1 (or bsup if negative) to binf */
00679     if((flag&LB_INFINITY) || value_neg_p(binf))
00680         for(maxiter=0,(((flag&UB_INFINITY) || value_pos_p(bsup))?
00681                 value_set_si(i,-1)
00682                 :value_assign(i,bsup));
00683             ((flag&LB_INFINITY) || value_ge(i,binf)) && maxiter<MAXITER  ;
00684             value_decrement(i,i),maxiter++) {
00685 
00686             value_assign(min[pos],i);
00687             if(cherche_min(min,D->next,pos+1)) {
00688                 value_clear(binf); value_clear(bsup);
00689                 value_clear(i);
00690                 return(1);
00691             }   
00692         }
00693     value_clear(binf); value_clear(bsup);
00694     value_clear(i);
00695 
00696     value_set_si(min[pos],0);
00697     return(0);       /* not found :-( */
00698 } /* cherche_min */
00699 
00700 /** 
00701 
00702 This procedure finds the smallest parallelepiped of size
00703 '<i>size[i]</i>' for every dimension i, contained in polyhedron D If
00704 this is not possible, an empty polyhedron is returned
00705 
00706 <p>
00707 
00708 <pre>
00709 written by vin100, 2000, for version 4.19
00710 modified 2002, version 5.10
00711 </pre>
00712 
00713 <p>
00714 
00715 It first finds the coordinates of the lexicographically smallest edge
00716 of the hypercube, obtained by transforming the constraints of D (by
00717 adding 'size' as many times as there are negative coeficients in each
00718 constraint), and finding the lexicographical min of this
00719 polyhedron. Then it builds the hypercube and returns it.
00720 
00721 <p>
00722 @param D
00723 @param size
00724 @param MAXRAYS
00725 
00726 */
00727 
00728 Polyhedron *Polyhedron_Preprocess(Polyhedron *D,Value *size,unsigned MAXRAYS)
00729 {
00730     Matrix *M;
00731     int i, j, d;
00732     Polyhedron *T, *S, *H, *C;
00733     Value *min,tmp;
00734   
00735     value_init(tmp);
00736     d = D->Dimension;
00737     M = Matrix_Alloc(MAXRAYS, D->Dimension+2);
00738     M->NbRows = D->NbConstraints;
00739   
00740     /* Original constraints */
00741     for(i=0;i<D->NbConstraints;i++)
00742         Vector_Copy(D->Constraint[i],M->p[i],(d+2));
00743 
00744 #ifdef EDEBUG6
00745     fprintf(stderr,"M for PreProcess : ");
00746     Matrix_Print(stderr,P_VALUE_FMT,M);
00747     fprintf(stderr,"\nsize == ");
00748     for( i=0 ; i<d ; i++ )
00749         value_print(stderr,P_VALUE_FMT,size[i]);
00750     fprintf(stderr,"\n");
00751 #endif
00752 
00753     /* Additionnal constraints */
00754     for(i=0;i<D->NbConstraints;i++) {
00755         if(value_zero_p(D->Constraint[i][0])) {
00756             fprintf(stderr,"Polyhedron_Preprocess: ");
00757             fprintf(stderr,"an equality was found where I did expect an inequality.\n");
00758             fprintf(stderr,"Trying to continue...\n");
00759             continue;
00760         }
00761         Vector_Copy(D->Constraint[i],M->p[M->NbRows],(d+2));
00762         for(j=1;j<=d;j++)
00763             if(value_neg_p(D->Constraint[i][j])) {
00764                 value_multiply(tmp,D->Constraint[i][j],size[j-1]);
00765                 value_addto(M->p[M->NbRows][d+1],M->p[M->NbRows][d+1],tmp);
00766             }
00767     
00768         /* If anything changed, add this new constraint */
00769         if(value_ne(M->p[M->NbRows][d+1],D->Constraint[i][d+1]))
00770             M->NbRows ++ ;
00771     }
00772   
00773 #ifdef EDEBUG6
00774     fprintf(stderr,"M used to find min : ");
00775     Matrix_Print(stderr,P_VALUE_FMT,M);
00776 #endif
00777   
00778     T = Constraints2Polyhedron(M,MAXRAYS);
00779     Matrix_Free(M);
00780     if (!T || emptyQ(T)) {
00781         if(T)
00782             Polyhedron_Free(T);
00783         value_clear(tmp);
00784         return(NULL);
00785     }
00786   
00787     /* Ok, now find the lexicographical min of T */
00788     min = (Value *) malloc(sizeof(Value) * (d+2));
00789     for(i=0;i<=d;i++) {
00790         value_init(min[i]);
00791         value_set_si(min[i],0);
00792     }  
00793     value_init(min[i]);
00794     value_set_si(min[i],1);
00795     C = Universe_Polyhedron(0);
00796     S = Polyhedron_Scan(T,C,MAXRAYS);
00797     Polyhedron_Free(C);
00798     Polyhedron_Free(T);
00799 
00800 #ifdef EDEBUG6
00801     for(i=0;i<=(d+1);i++) {
00802         value_print(stderr,P_VALUE_FMT,min[i]);
00803         fprintf(stderr," ,");
00804     }
00805     fprintf(stderr,"\n");
00806     Polyhedron_Print(stderr,P_VALUE_FMT,S);
00807     fprintf(stderr,"\n");
00808 #endif
00809     
00810     if (!cherche_min(min,S,1))
00811         {
00812             for(i=0;i<=(d+1);i++)
00813                 value_clear(min[i]);
00814             value_clear(tmp);
00815             return(NULL);
00816         }
00817     Domain_Free(S);
00818   
00819 #ifdef EDEBUG6
00820     fprintf(stderr,"min = ( ");
00821     value_print(stderr,P_VALUE_FMT,min[1]);
00822     for(i=2;i<=d;i++) {
00823         fprintf(stderr,", ");
00824         value_print(stderr,P_VALUE_FMT,min[i]);
00825     }  
00826     fprintf(stderr,")\n");
00827 #endif
00828   
00829     /* Min is the point from which we can construct the hypercube */
00830     M = Matrix_Alloc(d*2,d+2);
00831     for(i=0;i<d;i++) {
00832     
00833         /* Creates inequality  1 0..0 1 0..0 -min[i+1] */
00834         value_set_si(M->p[2*i][0],1);
00835         for(j=1;j<=d;j++)
00836             value_set_si(M->p[2*i][j],0);
00837         value_set_si(M->p[2*i][i+1],1);
00838         value_oppose(M->p[2*i][d+1],min[i+1]);
00839     
00840         /* Creates inequality  1 0..0 -1 0..0 min[i+1]+size -1 */
00841         value_set_si(M->p[2*i+1][0],1);
00842         for(j=1;j<=d;j++)
00843             value_set_si(M->p[2*i+1][j],0);
00844         value_set_si(M->p[2*i+1][i+1],-1);
00845         value_addto(M->p[2*i+1][d+1],min[i+1],size[i]);
00846         value_sub_int(M->p[2*i+1][d+1],M->p[2*i+1][d+1],1);
00847     }
00848   
00849 #ifdef EDEBUG6
00850     fprintf(stderr,"PolyhedronPreprocess: constraints H = ");
00851     Matrix_Print(stderr,P_VALUE_FMT,M);
00852 #endif
00853   
00854     H = Constraints2Polyhedron(M,MAXRAYS);
00855   
00856 #ifdef EDEBUG6
00857     Polyhedron_Print(stderr,P_VALUE_FMT,H);
00858     fprintf(stderr,"\n");
00859 #endif
00860   
00861     Matrix_Free(M);
00862     for(i=0;i<=(d+1);i++)
00863         value_clear(min[i]);
00864     free(min);
00865     value_clear(tmp);
00866     return(H);
00867 } /* Polyhedron_Preprocess */
00868 
00869 /** This procedure finds an hypercube of size 'size', containing
00870 polyhedron D increases size and lcm if necessary (and not "too big")
00871 If this is not possible, an empty polyhedron is returned
00872 
00873 <p>
00874 
00875 <pre> written by vin100, 2001, for version 4.19</pre>
00876 
00877 @param D
00878 @param size
00879 @param lcm
00880 @param MAXRAYS
00881 
00882 */
00883 Polyhedron *Polyhedron_Preprocess2(Polyhedron *D,Value *size,Value *lcm,unsigned MAXRAYS) {
00884   
00885     Matrix *c;
00886     Polyhedron *H;
00887     int i,j,r;
00888     Value n;      /* smallest/biggest value */
00889     Value s;    /* size in this dimension */
00890     Value tmp1,tmp2;
00891 
00892 #ifdef EDEBUG62
00893     int np;
00894 #endif
00895 
00896     value_init(n); value_init(s);
00897     value_init(tmp1); value_init(tmp2);
00898     c = Matrix_Alloc(D->Dimension*2,D->Dimension+2);
00899   
00900 #ifdef EDEBUG62
00901     fprintf(stderr,"\nPreProcess2 : starting\n");
00902     fprintf(stderr,"lcm = ");
00903     for( np=0 ; np<D->Dimension; np++ )
00904         value_print(stderr,VALUE_FMT,lcm[np]);
00905     fprintf(stderr,", size = ");
00906     for( np=0 ; np<D->Dimension; np++ )
00907         value_print(stderr,VALUE_FMT,size[np]);
00908     fprintf(stderr,"\n");
00909 #endif
00910   
00911     for(i=0;i<D->Dimension;i++) {
00912     
00913         /* Create constraint 1 0..0 1 0..0 -min */
00914         value_set_si(c->p[2*i][0],1);
00915         for(j=0;j<D->Dimension;j++)
00916             value_set_si(c->p[2*i][1+j],0);
00917         value_division(n,D->Ray[0][i+1],D->Ray[0][D->Dimension+1]);
00918         for(r=1;r<D->NbRays;r++) {
00919             value_division(tmp1,D->Ray[r][i+1],D->Ray[r][D->Dimension+1]);
00920             if(value_gt(n,tmp1)) {
00921         
00922                 /* New min */
00923                 value_division(n,D->Ray[r][i+1],D->Ray[r][D->Dimension+1]);
00924             }
00925         }
00926         value_set_si(c->p[2*i][i+1],1);
00927         value_oppose(c->p[2*i][D->Dimension+1],n);
00928     
00929         /* Create constraint 1 0..0 -1 0..0 max */
00930         value_set_si(c->p[2*i+1][0],1);
00931         for(j=0;j<D->Dimension;j++)
00932             value_set_si(c->p[2*i+1][1+j],0);
00933     
00934         /* n = (num+den-1)/den */
00935         value_addto(tmp1,D->Ray[0][i+1],D->Ray[0][D->Dimension+1]);
00936         value_sub_int(tmp1,tmp1,1);
00937         value_division(n,tmp1,D->Ray[0][D->Dimension+1]);
00938         for(r=1;r<D->NbRays;r++) {
00939             value_addto(tmp1,D->Ray[r][i+1],D->Ray[r][D->Dimension+1]);
00940             value_sub_int(tmp1,tmp1,1);
00941             value_division(tmp1,tmp1,D->Ray[r][D->Dimension+1]);
00942             if (value_lt(n,tmp1)) {
00943         
00944                 /* New max */
00945                 value_addto(tmp1,D->Ray[r][i+1],D->Ray[r][D->Dimension+1]);
00946                 value_sub_int(tmp1,tmp1,1);
00947                 value_division(n,tmp1,D->Ray[r][D->Dimension+1]);
00948             }
00949         }
00950         value_set_si(c->p[2*i+1][i+1],-1);
00951         value_assign(c->p[2*i+1][D->Dimension+1],n);
00952         value_addto(s,c->p[2*i+1][D->Dimension+1],c->p[2*i][D->Dimension+1]);
00953     
00954         /* Now test if the dimension of the cube is greater than the size */
00955         if(value_gt(s,size[i])) {
00956       
00957 #ifdef EDEBUG62
00958             fprintf(stderr,"size on dimension %d\n",i);
00959             fprintf(stderr,"lcm = ");
00960             for( np=0 ; np<D->Dimension; np++ )
00961                 value_print(stderr,VALUE_FMT,lcm[np]);
00962             fprintf(stderr,", size = ");
00963             for( np=0 ; np<D->Dimension; np++ )
00964                 value_print(stderr,VALUE_FMT,size[np]);
00965             fprintf(stderr,"\n");
00966             fprintf(stderr,"required size (s) = ");
00967             value_print(stderr,VALUE_FMT,s);
00968             fprintf(stderr,"\n");
00969 #endif
00970       
00971             /* If the needed size is "small enough"(<=20 or less than twice *size) */
00972             /* then increase *size, and artificially increase lcm too !*/
00973             value_set_si(tmp1,20);
00974             value_addto(tmp2,size[i],size[i]);
00975             if(value_le(s,tmp1)
00976                     || value_le(s,tmp2)) {
00977 
00978                 if( value_zero_p(lcm[i]) )
00979                     value_set_si(lcm[i],1);
00980                 /* lcm divides size... */
00981                 value_division(tmp1,size[i],lcm[i]);
00982         
00983                 /* lcm = ceil(s/h) */
00984                 value_addto(tmp2,s,tmp1);
00985                 value_add_int(tmp2,tmp2,1);
00986                 value_division(lcm[i],tmp2,tmp1);
00987         
00988                 /* new size = lcm*h */
00989                 value_multiply(size[i],lcm[i],tmp1);
00990         
00991 #ifdef EDEBUG62
00992                 fprintf(stderr,"new size = ");
00993                 for( np=0 ; np<D->Dimension; np++ )
00994                     value_print(stderr,VALUE_FMT,size[np]);
00995                 fprintf(stderr,", new lcm = ");
00996                 for( np=0 ; np<D->Dimension; np++ )
00997                     value_print(stderr,VALUE_FMT,lcm[np]);
00998                 fprintf(stderr,"\n");
00999 #endif
01000 
01001             }
01002             else {
01003         
01004 #ifdef EDEBUG62
01005                 fprintf(stderr,"Failed on dimension %d.\n",i);
01006 #endif
01007                 break;
01008             }
01009         }
01010     }
01011     if(i!=D->Dimension) {
01012         Matrix_Free(c);
01013         value_clear(n); value_clear(s);
01014         value_clear(tmp1); value_clear(tmp2);
01015         return(NULL);
01016     }
01017     for(i=0;i<D->Dimension;i++) {
01018         value_substract(c->p[2*i+1][D->Dimension+1],size[i], 
01019                 c->p[2*i][D->Dimension+1]);
01020     }
01021   
01022 #ifdef EDEBUG62
01023     fprintf(stderr,"PreProcess2 : c =");
01024     Matrix_Print(stderr,P_VALUE_FMT,c);
01025 #endif
01026 
01027     H = Constraints2Polyhedron(c,MAXRAYS);
01028     Matrix_Free(c);
01029     value_clear(n); value_clear(s);
01030     value_clear(tmp1); value_clear(tmp2);
01031     return(H);
01032 } /* Polyhedron_Preprocess2 */
01033 
01034 /**  
01035 
01036 This procedure adds additional constraints to D so that as each
01037 parameter is scanned, it will have a minimum of 'size' points If this
01038 is not possible, an empty polyhedron is returned
01039 
01040 @param D
01041 @param size
01042 @param MAXRAYS
01043 
01044 */
01045 Polyhedron *old_Polyhedron_Preprocess(Polyhedron *D,Value size,unsigned MAXRAYS) {
01046   
01047     int p, p1, ub, lb;
01048     Value a, a1, b, b1, g, aa;
01049     Value abs_a, abs_b, size_copy;
01050     int dim, con, new, needed;
01051     Value **C;
01052     Matrix *M;
01053     Polyhedron *D1;
01054   
01055     value_init(a); value_init(a1); value_init(b);
01056     value_init(b1); value_init(g); value_init(aa);
01057     value_init(abs_a); value_init(abs_b); value_init(size_copy);
01058   
01059     dim = D->Dimension;
01060     con = D->NbConstraints;
01061     M = Matrix_Alloc(MAXRAYS,dim+2);
01062     new = 0;
01063     value_assign(size_copy,size);
01064     C = D->Constraint;
01065     for (p=1; p<=dim; p++) {
01066         for (ub=0; ub<con; ub++) {
01067             value_assign(a,C[ub][p]);
01068             if (value_posz_p(a))        /* a >= 0 */
01069                 continue;               /* not an upper bound */
01070             for (lb=0;lb<con;lb++) {
01071                 value_assign(b,C[lb][p]);
01072                 if (value_negz_p(b))
01073                     continue;   /* not a lower bound */
01074         
01075                 /* Check if a new constraint is needed for this (ub,lb) pair */
01076                 /* a constraint is only needed if a previously scanned */
01077                 /* parameter (1..p-1) constrains this parameter (p) */
01078                 needed=0;
01079                 for (p1=1; p1<p; p1++) {
01080                     if (value_notzero_p(C[ub][p1]) || value_notzero_p(C[lb][p1])) {
01081                         needed=1; 
01082                         break;
01083                     }
01084                 }
01085                 if (!needed) continue;  
01086                 value_absolute(abs_a,a);
01087                 value_absolute(abs_b,b);
01088 
01089                 /* Create new constraint: b*UB-a*LB >= a*b*size */
01090                 Gcd(abs_a,abs_b,&g);
01091                 value_division(a1,a,g);
01092                 value_division(b1,b,g);
01093                 value_set_si(M->p[new][0],1);
01094                 value_oppose(abs_a,a1);           /* abs_a = -a1 */
01095                 Vector_Combine(&(C[ub][1]),&(C[lb][1]),&(M->p[new][1]),
01096                         b1,abs_a,dim+1);
01097                 value_multiply(aa,a1,b1);
01098                 value_multiply(abs_a,aa,size_copy);
01099                 value_addto(M->p[new][dim+1],M->p[new][dim+1],abs_a);
01100                 Vector_Normalize(&(M->p[new][1]),(dim+1));
01101                 new++;
01102             }
01103         }
01104     }
01105     D1 = AddConstraints(M->p_Init,new,D,MAXRAYS);
01106     Matrix_Free(M);
01107   
01108     value_clear(a); value_clear(a1); value_clear(b);
01109     value_clear(b1); value_clear(g); value_clear(aa);
01110     value_clear(abs_a); value_clear(abs_b); value_clear(size_copy);
01111     return D1;
01112 } /* old_Polyhedron_Preprocess */
01113 
01114 /** 
01115 
01116 PROCEDURES TO COMPUTE ENUMERATION. recursive procedure, recurse for
01117 each imbriquation
01118 
01119 @param pos index position of current loop index (1..hdim-1)
01120 @param P loop domain
01121 @param context context values for fixed indices 
01122 @return the number of integer points in this
01123 polyhedron 
01124 
01125 */
01126 void count_points (int pos,Polyhedron *P,Value *context, Value *res) {
01127    
01128     Value LB, UB, k, c;
01129 
01130     if (emptyQ(P)) {
01131         value_set_si(*res, 0);
01132         return;
01133     }
01134 
01135     value_init(LB); value_init(UB); value_init(k);
01136     value_set_si(LB,0);
01137     value_set_si(UB,0);
01138 
01139     if (lower_upper_bounds(pos,P,context,&LB,&UB) !=0) {
01140     
01141         /* Problem if UB or LB is INFINITY */
01142         fprintf(stderr, "count_points: ? infinite domain\n");
01143         value_clear(LB); value_clear(UB); value_clear(k);
01144         value_set_si(*res, -1);
01145         return;
01146     }
01147   
01148 #ifdef EDEBUG1
01149     if (!P->next) {
01150         int i;
01151         for (value_assign(k,LB); value_le(k,UB); value_increment(k,k)) {
01152             fprintf(stderr, "(");
01153             for (i=1; i<pos; i++) {
01154                 value_print(stderr,P_VALUE_FMT,context[i]);
01155                 fprintf(stderr,",");
01156             }
01157             value_print(stderr,P_VALUE_FMT,k);
01158             fprintf(stderr,")\n");
01159         }
01160     }
01161 #endif
01162   
01163     value_set_si(context[pos],0);
01164     if (value_lt(UB,LB)) {
01165         value_clear(LB); value_clear(UB); value_clear(k);
01166         value_set_si(*res, 0);
01167         return;  
01168     }  
01169     if (!P->next) {
01170         value_substract(k,UB,LB);
01171         value_add_int(k,k,1);
01172         value_assign(*res, k);
01173         value_clear(LB); value_clear(UB); value_clear(k);
01174         return;
01175     } 
01176 
01177     /*-----------------------------------------------------------------*/
01178     /* Optimization idea                                               */
01179     /*   If inner loops are not a function of k (the current index)    */
01180     /*   i.e. if P->Constraint[i][pos]==0 for all P following this and */
01181     /*        for all i,                                               */
01182     /*   Then CNT = (UB-LB+1)*count_points(pos+1, P->next, context)    */
01183     /*   (skip the for loop)                                           */
01184     /*-----------------------------------------------------------------*/
01185   
01186     value_init(c);
01187     value_set_si(*res, 0);
01188     for (value_assign(k,LB);value_le(k,UB);value_increment(k,k)) {
01189         /* Insert k in context */
01190         value_assign(context[pos],k);
01191         count_points(pos+1,P->next,context,&c);
01192         if(value_notmone_p(c))
01193             value_addto(*res, *res, c);
01194         else {
01195             value_set_si(*res, 0);
01196             break;
01197         }
01198     }
01199     value_clear(c);
01200   
01201 #ifdef EDEBUG11
01202     fprintf(stderr,"%d\n",CNT);
01203 #endif
01204   
01205     /* Reset context */
01206     value_set_si(context[pos],0);
01207     value_clear(LB); value_clear(UB); value_clear(k);
01208     return;
01209 } /* count_points */
01210 
01211 /*-------------------------------------------------------------------*/
01212 /* enode *P_Enum(L, LQ, context, pos, nb_param, dim, lcm,param_name) */
01213 /*     L : list of polyhedra for the loop nest                       */
01214 /*     LQ : list of polyhedra for the parameter loop nest            */
01215 /*     pos : 1..nb_param, position of the parameter                  */
01216 /*     nb_param : number of parameters total                         */
01217 /*     dim : total dimension of the polyhedron, param incl.          */
01218 /*     lcm : denominator array [0..dim-1] of the polyhedron          */
01219 /*     param_name : name of the parameters                           */
01220 /* Returns an enode tree representing the pseudo polynomial          */
01221 /*   expression for the enumeration of the polyhedron.               */
01222 /* A recursive procedure.                                            */
01223 /*-------------------------------------------------------------------*/
01224 static enode *P_Enum(Polyhedron *L,Polyhedron *LQ,Value *context,int pos,int nb_param,int dim,Value *lcm,char **param_name) {
01225 
01226   enode *res,*B,*C;
01227   int hdim,i,j,rank,flag;
01228   Value n,g,nLB,nUB,nlcm,noff,nexp,k1,nm,hdv,k,lcm_copy;
01229   Value tmp;
01230   Matrix *A;
01231 
01232 #ifdef EDEBUG
01233   fprintf(stderr,"-------------------- begin P_Enum -------------------\n");
01234   fprintf(stderr,"Calling P_Enum with pos = %d\n",pos);
01235 #endif
01236   
01237   /* Xavier Redon modification: handle the case when there is no parameter */
01238   if(nb_param==0) {
01239     res=new_enode(polynomial,1,0);
01240     value_set_si(res->arr[0].d,1);
01241     value_init(res->arr[0].x.n);
01242     count_points(1,L,context,&res->arr[0].x.n);
01243     return res;
01244   }
01245   
01246   /* Initialize all the 'Value' variables */
01247   value_init(n); value_init(g); value_init(nLB);
01248   value_init(nUB); value_init(nlcm); value_init(noff);
01249   value_init(nexp); value_init(k1); value_init(nm);
01250   value_init(hdv); value_init(k); value_init(tmp);
01251   value_init(lcm_copy);
01252 
01253   if( value_zero_p(lcm[pos-1]) )
01254   {
01255                 hdim = 1;
01256                 value_set_si( lcm_copy, 1 );
01257   }
01258   else
01259   {
01260           /* hdim is the degree of the polynomial + 1 */
01261                 hdim = dim-nb_param+1;          /* homogenous dim w/o parameters */
01262                 value_assign( lcm_copy, lcm[pos-1] );
01263   }  
01264 
01265   /* code to limit generation of equations to valid parameters only */
01266   /*----------------------------------------------------------------*/
01267   flag = lower_upper_bounds(pos,LQ,&context[dim-nb_param],&nLB,&nUB);
01268   if (flag & LB_INFINITY) {
01269     if (!(flag & UB_INFINITY)) {
01270       
01271       /* Only an upper limit: set lower limit */
01272       /* Compute nLB such that (nUB-nLB+1) >= (hdim*lcm) */
01273       value_sub_int(nLB,nUB,1);
01274       value_set_si(hdv,hdim);
01275       value_multiply(tmp,hdv,lcm_copy);
01276       value_substract(nLB,nLB,tmp);
01277       if(value_pos_p(nLB))
01278         value_set_si(nLB,0);
01279     }
01280     else {
01281       value_set_si(nLB,0);
01282       
01283       /* No upper nor lower limit: set lower limit to 0 */
01284       value_set_si(hdv,hdim);
01285       value_multiply(nUB,hdv,lcm_copy);
01286       value_add_int(nUB,nUB,1);
01287     }
01288   }
01289 
01290   /* if (nUB-nLB+1) < (hdim*lcm) then we have more unknowns than equations */
01291   /* We can: 1. Find more equations by changing the context parameters, or */
01292   /* 2. Assign extra unknowns values in such a way as to simplify result.  */
01293   /* Think about ways to scan parameter space to get as much info out of it*/
01294   /* as possible.                                                          */
01295   
01296 #ifdef REDUCE_DEGREE
01297   if (pos==1 && (flag & UB_INFINITY)==0) {
01298     /* only for finite upper bound on first parameter */
01299     /* NOTE: only first parameter because subsequent parameters may
01300        be artificially limited by the choice of the first parameter */
01301    
01302 #ifdef EDEBUG
01303     fprintf(stderr,"*************** n **********\n");
01304     value_print(stderr,VALUE_FMT,n);
01305     fprintf(stderr,"\n");
01306 #endif
01307 
01308     value_substract(n,nUB,nLB);
01309     value_increment(n,n);
01310     
01311 #ifdef EDEBUG 
01312     value_print(stderr,VALUE_FMT,n);
01313     fprintf(stderr,"\n*************** n ************\n");
01314 #endif 
01315 
01316     /* Total number of samples>0 */
01317     if(value_neg_p(n))
01318       i=0;
01319     else {
01320       value_modulus(tmp,n,lcm_copy);
01321       if(value_notzero_p(tmp)) {
01322                   value_division(tmp,n,lcm_copy);
01323                   value_increment(tmp,tmp);
01324                   i = VALUE_TO_INT(tmp);
01325       }
01326       else {
01327                   value_division(tmp,n,lcm_copy);
01328                   i =   VALUE_TO_INT(tmp);      /* ceiling of n/lcm */
01329       }
01330     }
01331 
01332 #ifdef EDEBUG 
01333     value_print(stderr,VALUE_FMT,n);
01334     fprintf(stderr,"\n*************** n ************\n");
01335 #endif 
01336     
01337     /* Reduce degree of polynomial based on number of sample points */
01338     if (i < hdim){
01339       hdim=i;
01340       
01341 #ifdef EDEBUG4
01342       fprintf(stdout,"Parameter #%d: LB=",pos);
01343       value_print(stdout,VALUE_FMT,nLB);
01344       fprintf(stdout," UB=");
01345       value_print(stdout,VALUE_FMT,nUB);
01346       fprintf(stdout," lcm=");
01347       value_print(stdout,VALUE_FMT,lcm_copy);
01348       fprintf(stdout," degree reduced to %d\n",hdim-1);
01349 #endif
01350       
01351     }
01352   }
01353 #endif /* REDUCE_DEGREE */
01354   
01355   /* hdim is now set */  
01356   /* allocate result structure */
01357   res = new_enode(polynomial,hdim,pos);
01358   for (i=0;i<hdim;i++) {
01359     int l;
01360     l = VALUE_TO_INT(lcm_copy);
01361     res->arr[i].x.p = new_enode(periodic,l,pos);
01362   }
01363   
01364   /* Utility arrays */
01365   A = Matrix_Alloc(hdim, 2*hdim+1);                     /* used for Gauss */
01366   B = new_enode(evector, hdim, 0);
01367   C = new_enode(evector, hdim, 0);
01368   
01369   /*----------------------------------------------------------------*/
01370   /*                                                                */
01371   /*                                0<-----+---k--------->          */
01372   /* |---------noff----------------->-nlcm->-------lcm---->         */
01373   /* |--- . . . -----|--------------|------+-------|------+-------|-*/
01374   /* 0          (q-1)*lcm         q*lcm    |  (q+1)*lcm   |         */
01375   /*                                      nLB          nLB+lcm      */
01376   /*                                                                */
01377   /*----------------------------------------------------------------*/
01378   if(value_neg_p(nLB)) {
01379     value_modulus(nlcm,nLB,lcm_copy);
01380     value_addto(nlcm,nlcm,lcm_copy);
01381   }
01382   else {
01383     value_modulus(nlcm,nLB,lcm_copy);
01384   }
01385   
01386   /* noff is a multiple of lcm */
01387   value_substract(noff,nLB,nlcm);
01388   value_addto(tmp,lcm_copy,nlcm);
01389   for (value_assign(k,nlcm);value_lt(k,tmp);value_increment(k,k)) {
01390  
01391 #ifdef EDEBUG
01392     fprintf(stderr,"Finding ");
01393     value_print(stderr,VALUE_FMT,k);
01394     fprintf(stderr,"-th elements of periodic coefficients\n");
01395 #endif
01396 
01397     value_set_si(hdv,hdim);
01398     value_multiply(nm,hdv,lcm_copy);
01399     value_addto(nm,nm,nLB);
01400     i=0;
01401     for (value_addto(n,k,noff); value_lt(n,nm); value_addto(n,n,lcm_copy),i++) {
01402       
01403       /* n == i*lcm + k + noff;   */
01404       /* nlcm <= k < nlcm+lcm     */
01405       /* n mod lcm == k1 */
01406       
01407 #ifdef ALL_OVERFLOW_WARNINGS
01408       if (((flag & UB_INFINITY)==0) && value_gt(n,nUB)) {
01409         fprintf(stdout,"Domain Overflow: Parameter #%d:",pos);
01410         fprintf(stdout,"nLB=");
01411         value_print(stdout,VALUE_FMT,nLB);
01412         fprintf(stdout," n=");
01413         value_print(stdout,VALUE_FMT,n);
01414         fprintf(stdout," nUB=");
01415         value_print(stdout,VALUE_FMT,nUB);
01416         fprintf(stdout,"\n");
01417       }
01418 #else
01419       if (overflow_warning_flag && ((flag & UB_INFINITY)==0) &&
01420           value_gt(n,nUB)) {
01421         fprintf(stdout,"\nWARNING: Parameter Domain Overflow.");
01422         fprintf(stdout," Result may be incorrect on this domain.\n");
01423         overflow_warning_flag = 0;
01424       }
01425 #endif
01426       
01427       /* Set parameter to n */
01428       value_assign(context[dim-nb_param+pos],n);
01429       
01430 #ifdef EDEBUG1
01431         if( param_name )
01432         {
01433       fprintf(stderr,"%s = ",param_name[pos-1]);
01434       value_print(stderr,VALUE_FMT,n);
01435       fprintf(stderr," (hdim=%d, lcm[%d]=",hdim,pos-1);
01436       value_print(stderr,VALUE_FMT,lcm_copy);
01437       fprintf(stderr,")\n");
01438         }
01439         else
01440         {
01441       fprintf(stderr,"P%d = ",pos);
01442       value_print(stderr,VALUE_FMT,n);
01443       fprintf(stderr," (hdim=%d, lcm[%d]=",hdim,pos-1);
01444       value_print(stderr,VALUE_FMT,lcm_copy);
01445       fprintf(stderr,")\n");      
01446         }
01447 #endif
01448       
01449       /* Setup B vector */
01450       if (pos==nb_param) {
01451         
01452 #ifdef EDEBUG   
01453         fprintf(stderr,"Yes\n");
01454 #endif 
01455         
01456         /* call count */
01457         /* count can only be called when the context is fully specified */
01458         value_set_si(B->arr[i].d,1);
01459         value_init(B->arr[i].x.n);
01460         count_points(1,L,context,&B->arr[i].x.n);
01461         
01462 #ifdef EDEBUG3
01463         for (j=1; j<pos; j++) fputs("   ",stdout);
01464         fprintf(stdout, "E(");
01465         for (j=1; j<nb_param; j++) {
01466           value_print(stdout,VALUE_FMT,context[dim-nb_param+j]);
01467           fprintf(stdout,",");
01468         }  
01469         value_print(stdout,VALUE_FMT,n);
01470         fprintf(stdout,") = ");
01471         value_print(stdout,VALUE_FMT,B->arr[i].x.n);
01472         fprintf(stdout," =");
01473 #endif
01474         
01475       }
01476       else {    /* count is a function of other parameters */
01477         /* call P_Enum recursively */
01478         value_set_si(B->arr[i].d,0);
01479         B->arr[i].x.p = P_Enum(L,LQ->next,context,pos+1,nb_param,dim,lcm,param_name);
01480         
01481 #ifdef EDEBUG3
01482         if( param_name )
01483         {
01484                 for (j=1; j<pos; j++)
01485                   fputs("   ", stdout);
01486                 fprintf(stdout, "E(");
01487                 for (j=1; j<=pos; j++) {
01488                   value_print(stdout,VALUE_FMT,context[dim-nb_param+j]);
01489                   fprintf(stdout,",");
01490                 }         
01491                 for (j=pos+1; j<nb_param; j++)
01492                   fprintf(stdout,"%s,",param_name[j]);
01493                 fprintf(stdout,"%s) = ",param_name[j]);
01494                 print_enode(stdout,B->arr[i].x.p,param_name);
01495                 fprintf(stdout," =");
01496         }
01497 #endif
01498         
01499       }
01500       
01501       /* Create i-th equation*/
01502       /* K_0 + K_1 * n**1 + ... + K_dim * n**dim | Identity Matrix */
01503       
01504       value_set_si(A->p[i][0],0);  /* status bit = equality */
01505       value_set_si(nexp,1);
01506       for (j=1;j<=hdim;j++) {
01507         value_assign(A->p[i][j],nexp);
01508         value_set_si(A->p[i][j+hdim],0);
01509         
01510 #ifdef EDEBUG3
01511         fprintf(stdout," + ");
01512         value_print(stdout,VALUE_FMT,nexp);
01513         fprintf(stdout," c%d",j);
01514 #endif  
01515         value_multiply(nexp,nexp,n);
01516       }
01517       
01518 #ifdef EDEBUG3
01519       fprintf(stdout, "\n");
01520 #endif
01521       
01522       value_set_si(A->p[i][i+1+hdim],1);      
01523     }
01524     
01525     /* Assertion check */
01526     if (i!=hdim)
01527       fprintf(stderr, "P_Enum: ?expecting i==hdim\n");
01528     
01529 #ifdef EDEBUG
01530         if( param_name )
01531         {
01532     fprintf(stderr,"B (enode) =\n");
01533     print_enode(stderr,B,param_name);
01534         }
01535     fprintf(stderr,"A (Before Gauss) =\n");
01536     Matrix_Print(stderr,P_VALUE_FMT,A);
01537 #endif
01538     
01539     /* Solve hdim (=dim+1) equations with hdim unknowns, result in CNT */
01540     rank = Gauss(A,hdim,2*hdim);
01541     
01542 #ifdef EDEBUG
01543     fprintf(stderr,"A (After Gauss) =\n");
01544     Matrix_Print(stderr,P_VALUE_FMT,A);
01545 #endif
01546     
01547     /* Assertion check */
01548     if (rank!=hdim) {
01549       fprintf(stderr, "P_Enum: ?expecting rank==hdim\n");
01550     }
01551     
01552     /* if (rank < hdim) then set the last hdim-rank coefficients to ? */
01553     /* if (rank == 0) then set all coefficients to 0 */    
01554     /* copy result as k1-th element of periodic numbers */
01555     if(value_lt(k,lcm_copy))
01556       value_assign(k1,k);
01557     else
01558       value_substract(k1,k,lcm_copy);
01559     
01560     for (i=0; i<rank; i++) {
01561       
01562       /* Set up coefficient vector C from i-th row of inverted matrix */
01563       for (j=0; j<rank; j++) {
01564         Gcd(A->p[i][i+1],A->p[i][j+1+hdim],&g);
01565         value_division(C->arr[j].d,A->p[i][i+1],g);
01566         value_init(C->arr[j].x.n);
01567         value_division(C->arr[j].x.n,A->p[i][j+1+hdim],g);
01568       }
01569       
01570 #ifdef EDEBUG
01571         if( param_name )
01572         {
01573       fprintf(stderr, "C (enode) =\n");
01574       print_enode(stderr, C, param_name);
01575         }
01576 #endif
01577       
01578       /* The i-th enode is the lcm-periodic coefficient of term n**i */
01579       edot(B,C,&(res->arr[i].x.p->arr[VALUE_TO_INT(k1)]));
01580       
01581 #ifdef EDEBUG
01582         if( param_name )
01583         {
01584       fprintf(stderr, "B.C (evalue)=\n");
01585       print_evalue(stderr,&(res->arr[i].x.p->arr[VALUE_TO_INT(k1)]),param_name );
01586       fprintf(stderr,"\n");
01587         }
01588 #endif
01589       
01590     }
01591     value_addto(tmp,lcm_copy,nlcm);
01592   }
01593   
01594 #ifdef EDEBUG
01595         if( param_name )
01596         {
01597           fprintf(stderr,"res (enode) =\n");
01598           print_enode(stderr,res,param_name);
01599         }
01600   fprintf(stderr, "-------------------- end P_Enum -----------------------\n");
01601 #endif
01602   
01603   /* Reset context */
01604   value_set_si(context[dim-nb_param+pos],0);
01605   
01606   /* Release memory */
01607   Matrix_Free(A);
01608   free(B);
01609   free(C);
01610   
01611   /* Clear all the 'Value' variables */
01612   value_clear(n); value_clear(g); value_clear(nLB);
01613   value_clear(nUB); value_clear(nlcm); value_clear(noff);
01614   value_clear(nexp); value_clear(k1); value_clear(nm);
01615   value_clear(hdv); value_clear(k); value_clear(tmp);
01616   value_clear(lcm_copy);
01617   return res;
01618 } /* P_Enum */
01619 
01620 /*----------------------------------------------------------------*/
01621 /* Scan_Vertices(PP, Q, CT)                                       */
01622 /*    PP : ParamPolyhedron                                        */
01623 /*    Q : Domain                                                  */
01624 /*    CT : Context transformation matrix                          */
01625 /*    lcm : lcm array (output)                                    */
01626 /*    nbp : number of parameters                                  */
01627 /*    param_name : name of the parameters                         */
01628 /*----------------------------------------------------------------*/
01629 static void Scan_Vertices(Param_Polyhedron *PP,Param_Domain *Q,Matrix *CT,
01630    Value *lcm, int nbp, char **param_name )
01631 {
01632   Param_Vertices *V;
01633   int i, j, ix, l, np;
01634   unsigned bx;
01635   Value k,m1;
01636 
01637   /* Compute the denominator of P */
01638   /* lcm = Least Common Multiple of the denominators of the vertices of P */
01639   /* and print the vertices */  
01640 
01641   value_init(k); value_init(m1);
01642   for( np=0 ; np<nbp ; np++ )
01643     value_set_si( lcm[np], 0 );
01644 
01645         if( param_name )
01646           fprintf(stdout,"Vertices:\n");
01647 
01648   for(i=0,ix=0,bx=MSB,V=PP->V; V && i<PP->nbV; i++,V=V->next) {
01649     if (Q->F[ix] & bx) {
01650                 if( param_name )
01651                 {
01652         if(CT) {
01653                                 Matrix *v;
01654                                 v = VertexCT(V->Vertex,CT);
01655                                 Print_Vertex(stdout,v,param_name);
01656                                 Matrix_Free(v);
01657         }
01658         else
01659                                 Print_Vertex(stdout,V->Vertex,param_name);
01660                 fprintf(stdout,"\n");
01661                 }
01662 
01663       for(j=0;j<V->Vertex->NbRows;j++) {
01664                         /* A matrix */
01665                         for( l=0 ; l<V->Vertex->NbColumns-2 ; l++ )
01666                         {
01667                                 if( value_notzero_p(V->Vertex->p[j][l]) )
01668                                 {
01669                                         Gcd(V->Vertex->p[j][V->Vertex->NbColumns-1],V->Vertex->p[j][l], &m1);
01670                                         value_division(k,V->Vertex->p[j][V->Vertex->NbColumns-1],m1);
01671                                         if( value_notzero_p(lcm[l]) )
01672                                         {
01673                                                 /* lcm[l] = lcm[l] * k / gcd(k,lcm[l]) */
01674                                                 if (value_notzero_p(k) && value_notone_p(k))
01675                                                 {
01676                                                   Gcd(lcm[l],k,&m1);
01677                                                   value_division(k,k,m1);
01678                                                   value_multiply(lcm[l],lcm[l],k);
01679                                                 }
01680                                         }
01681                                         else
01682                                         {
01683                                                 value_assign(lcm[l],k);
01684                                         }
01685                                 }
01686                         }
01687       }
01688     }
01689     NEXT(ix,bx);
01690   }
01691   value_clear(k); value_clear(m1);
01692 } /* Scan_Vertices */
01693 
01694 /**
01695 
01696 Procedure to count points in a non-parameterized polytope.
01697 
01698 @param P       Polyhedron to count
01699 @param C       Parameter Context domain
01700 @param CT      Matrix to transform context to original
01701 @parma CEq     additionnal equalities in context
01702 @param MAXRAYS workspace size
01703 @param param_name parameter names
01704 
01705 */
01706 Enumeration *Enumerate_NoParameters(Polyhedron *P,Polyhedron *C,Matrix *CT,Polyhedron *CEq,unsigned MAXRAYS,char **param_name) {
01707   
01708     Polyhedron *L;
01709     Enumeration *res;
01710     Value *context,tmp;
01711     int j;
01712     int hdim = P->Dimension + 1;
01713     int r,i;
01714   
01715     /* Create a context vector size dim+2 */
01716     context = (Value *) malloc((hdim+1)*sizeof(Value));
01717     for (j=0;j<= hdim;j++) 
01718         value_init(context[j]);
01719     value_init(tmp);
01720   
01721     res = (Enumeration *)malloc(sizeof(Enumeration));
01722     res->next = NULL;
01723     res->ValidityDomain = Universe_Polyhedron(0);  /* no parameters */
01724     value_init(res->EP.d);
01725     value_set_si(res->EP.d,0);  
01726     L = Polyhedron_Scan(P,res->ValidityDomain,MAXRAYS);
01727   
01728 #ifdef EDEBUG2
01729     fprintf(stderr, "L = \n");
01730     Polyhedron_Print(stderr, P_VALUE_FMT, L);
01731 #endif
01732   
01733     if(CT) {
01734         Polyhedron *Dt;
01735     
01736         /* Add parameters to validity domain */
01737         Dt = Polyhedron_Preimage(res->ValidityDomain,CT,MAXRAYS);
01738         Polyhedron_Free(res->ValidityDomain);
01739         res->ValidityDomain = DomainIntersection(Dt,CEq,MAXRAYS);
01740         Polyhedron_Free(Dt);
01741     }
01742   
01743         if( param_name )
01744         {
01745     fprintf(stdout,"---------------------------------------\n");
01746     fprintf(stdout,"Domain:\n");
01747     Print_Domain(stdout,res->ValidityDomain, param_name);
01748   
01749     /* Print the vertices */
01750     printf("Vertices:\n");
01751     for(r=0;r<P->NbRays;++r) {
01752         if(value_zero_p(P->Ray[r][0]))
01753             printf("(line) ");
01754         printf("[");
01755         if (P->Dimension > 0)
01756             value_print(stdout,P_VALUE_FMT,P->Ray[r][1]);
01757         for(i=1;i<P->Dimension;i++) {
01758             printf(", ");
01759             value_print(stdout,P_VALUE_FMT,P->Ray[r][i+1]);
01760         }  
01761         printf("]");
01762         if(value_notone_p(P->Ray[r][P->Dimension+1])) {
01763             printf("/");
01764             value_print(stdout,P_VALUE_FMT, P->Ray[r][P->Dimension+1]);
01765         }
01766         printf("\n");
01767     }
01768         }
01769   if (emptyQ(P)) {
01770     res->EP.x.p = new_enode(polynomial,1,0);;
01771     value_set_si(res->EP.x.p->arr[0].d, 1);
01772     value_init(res->EP.x.p->arr[0].x.n);
01773     value_set_si(res->EP.x.p->arr[0].x.n, 0);
01774   } else if (!L) {
01775     /* Non-empty zero-dimensional domain */
01776     res->EP.x.p = new_enode(polynomial,1,0);;
01777     value_set_si(res->EP.x.p->arr[0].d, 1);
01778     value_init(res->EP.x.p->arr[0].x.n);
01779     value_set_si(res->EP.x.p->arr[0].x.n, 1);
01780   } else {
01781     CATCH(overflow_error) {
01782         fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
01783         fprintf(stderr,"You should rebuild PolyLib using GNU-MP or increasing the size of integers.\n");
01784         overflow_warning_flag = 0;
01785         assert(overflow_warning_flag);
01786     }
01787     TRY {
01788     
01789         Vector_Set(context,0,(hdim+1));
01790     
01791         /* Set context[hdim] = 1  (the constant) */
01792         value_set_si(context[hdim],1);
01793         value_set_si(tmp,1);
01794         res->EP.x.p = P_Enum(L,NULL,context,1,0,hdim-1,&tmp,param_name);
01795         UNCATCH(overflow_error);
01796     }
01797   }
01798   
01799     Domain_Free(L);
01800   
01801     /*  **USELESS, there are no references to parameters in res**
01802         if( CT )
01803         addeliminatedparams_evalue(&res->EP, CT);
01804     */
01805   
01806         if( param_name )
01807         {
01808     fprintf(stdout,"\nEhrhart Polynomial:\n");
01809     print_evalue(stdout,&res->EP,param_name);
01810     fprintf(stdout, "\n");
01811         }
01812 
01813     value_clear(tmp);
01814     for (j=0;j<= hdim;j++) 
01815         value_clear(context[j]);  
01816     free(context);
01817     return(res);
01818 } /* Enumerate_NoParameters */
01819 
01820 /**  Procedure to count points in a parameterized polytope.
01821 
01822 @param P Polyhedron to enumerate
01823 @param C Context Domain
01824 @param MAXRAYS size of workspace
01825 @param param_name parameter names (array of strings), may be NULL
01826 @return a list of validity domains + evalues EP
01827 
01828 */
01829 Enumeration *Polyhedron_Enumerate(Polyhedron *Pi,Polyhedron *C,unsigned MAXRAYS,char **param_name)
01830 {
01831   Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P;
01832   Matrix *CT;
01833   Param_Polyhedron *PP;
01834   Param_Domain   *Q;
01835   int i,hdim, dim, nb_param, np;
01836   Value *lcm, *m1, hdv;
01837   Value *context;
01838   Enumeration *en, *res;
01839 
01840   res = NULL;
01841   P = Pi;
01842 
01843 #ifdef EDEBUG2
01844   fprintf(stderr,"C = \n");
01845   Polyhedron_Print(stderr,P_VALUE_FMT,C);
01846   fprintf(stderr,"P = \n");
01847   Polyhedron_Print(stderr,P_VALUE_FMT,P);
01848 #endif
01849 
01850   hdim          = P->Dimension + 1;
01851   dim           = P->Dimension;
01852   nb_param      = C->Dimension;
01853 
01854   /* Don't call Polyhedron2Param_Domain if there are no parameters */
01855   if(nb_param == 0) {
01856     
01857     return(Enumerate_NoParameters(P,C,NULL,NULL,MAXRAYS,param_name));  
01858   }
01859   PP = Polyhedron2Param_SimplifiedDomain(&P,C,MAXRAYS,&CEq,&CT);
01860   if(!PP) {
01861         if( param_name )
01862     fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
01863 
01864     return(NULL);
01865   }
01866   
01867   /* CT : transformation matrix to eliminate useless ("false") parameters */
01868   if(CT) {
01869     nb_param -= CT->NbColumns-CT->NbRows;
01870     dim  -= CT->NbColumns-CT->NbRows;
01871     hdim -= CT->NbColumns-CT->NbRows;
01872     
01873     /* Don't call Polyhedron2Param_Domain if there are no parameters */
01874     if(nb_param == 0)
01875     {
01876             res = Enumerate_NoParameters(P,C,CT,CEq,MAXRAYS,param_name);
01877             if( P != Pi )
01878                     Polyhedron_Free( P );
01879             return( res );
01880     }  
01881   }
01882 
01883   /* get memory for Values */
01884   lcm = (Value *)malloc( nb_param * sizeof(Value));
01885   m1  = (Value *)malloc( nb_param * sizeof(Value));
01886   /* Initialize all the 'Value' variables */
01887   for( np=0 ; np<nb_param ; np++ )
01888   {
01889     value_init(lcm[np]); value_init(m1[np]);
01890   }
01891   value_init(hdv);
01892 
01893   for(Q=PP->D;Q;Q=Q->next) {
01894     if(CT) {
01895       Polyhedron *Dt;
01896       CQ = Q->Domain;      
01897       Dt = Polyhedron_Preimage(Q->Domain,CT,MAXRAYS);
01898       rVD = DomainIntersection(Dt,CEq,MAXRAYS);
01899       
01900       /* if rVD is empty or too small in geometric dimension */
01901       if(!rVD || emptyQ(rVD) ||
01902          (rVD->Dimension-rVD->NbEq < Dt->Dimension-Dt->NbEq-CEq->NbEq)) {
01903         if(rVD)
01904           Polyhedron_Free(rVD);
01905         Polyhedron_Free(Dt);
01906         continue;               /* empty validity domain */
01907       }
01908       Polyhedron_Free(Dt);
01909     }
01910     else
01911       rVD = CQ = Q->Domain;    
01912     en = (Enumeration *)malloc(sizeof(Enumeration));
01913     en->next = res;
01914     res = en;
01915     res->ValidityDomain = rVD;
01916     
01917         if( param_name )
01918    {
01919          fprintf(stdout,"---------------------------------------\n");
01920     fprintf(stdout,"Domain:\n");
01921     
01922 #ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
01923     Print_Domain(stdout,res->ValidityDomain,param_name);
01924 #else    
01925     {
01926       Polyhedron *VD;
01927       VD = DomainSimplify(res->ValidityDomain,C,MAXRAYS);
01928       Print_Domain(stdout,VD,param_name);
01929       Domain_Free(VD);
01930     }
01931 #endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
01932         }
01933     
01934     overflow_warning_flag = 1;
01935     
01936     /* Scan the vertices and compute lcm */
01937     Scan_Vertices(PP,Q,CT,lcm,nb_param,param_name);
01938     
01939 #ifdef EDEBUG2
01940     fprintf(stderr,"Denominator = ");
01941     for( np=0;np<nb_param;np++)
01942       value_print(stderr,P_VALUE_FMT,lcm[np]);
01943     fprintf(stderr," and hdim == %d \n",hdim);
01944 #endif
01945     
01946 #ifdef EDEBUG2
01947     fprintf(stderr,"CQ = \n");
01948     Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
01949 #endif
01950 
01951     /* Before scanning, add constraints to ensure at least hdim*lcm */
01952     /* points in every dimension */
01953     value_set_si(hdv,hdim-nb_param);
01954 
01955     for( np=0;np<nb_param;np++)
01956     {
01957                 if( value_notzero_p(lcm[np]) )
01958                         value_multiply(m1[np],hdv,lcm[np]);
01959                 else
01960                         value_set_si(m1[np],1);
01961     }
01962 
01963 #ifdef EDEBUG2 
01964     fprintf(stderr,"m1 == ");
01965     for( np=0;np<nb_param;np++)
01966       value_print(stderr,P_VALUE_FMT,m1[np]);
01967     fprintf(stderr,"\n");
01968 #endif 
01969 
01970     CATCH(overflow_error) {
01971       fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
01972       CQ2 = NULL;
01973     }
01974     TRY {      
01975       CQ2 = Polyhedron_Preprocess(CQ,m1,MAXRAYS);
01976 
01977 #ifdef EDEBUG2
01978       fprintf(stderr,"After preprocess, CQ2 = ");
01979       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
01980 #endif
01981       
01982       UNCATCH(overflow_error);
01983     }
01984     
01985     /* Vin100, Feb 2001 */
01986     /* in case of degenerate, try to find a domain _containing_ CQ */
01987     if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid==0) {
01988       int r;
01989       
01990 #ifdef EDEBUG2
01991       fprintf(stderr,"Trying to call Polyhedron_Preprocess2 : CQ = \n");
01992       Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
01993 #endif
01994       
01995       /* Check if CQ is bounded */
01996       for(r=0;r<CQ->NbRays;r++) {
01997         if(value_zero_p(CQ->Ray[r][0]) ||
01998            value_zero_p(CQ->Ray[r][CQ->Dimension+1]))
01999           break;
02000       }
02001       if(r==CQ->NbRays) {
02002         
02003         /* ok, CQ is bounded */
02004         /* now find if CQ is contained in a hypercube of size m1 */
02005         CQ2 = Polyhedron_Preprocess2(CQ,m1,lcm,MAXRAYS);
02006       }
02007     }
02008     if (!CQ2 || emptyQ(CQ2)) {
02009 #ifdef EDEBUG2
02010       fprintf(stderr,"Degenerate.\n");
02011 #endif
02012       fprintf(stdout,"Degenerate Domain. Can not continue.\n");
02013       value_init(res->EP.d);
02014       value_init(res->EP.x.n);
02015       value_set_si(res->EP.d,1);
02016       value_set_si(res->EP.x.n,-1);
02017     }
02018     else {
02019       
02020 #ifdef EDEBUG2
02021       fprintf(stderr,"CQ2 = \n");
02022       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
02023       if( ! PolyhedronIncludes(CQ, CQ2) )
02024         fprintf( stderr,"CQ does not include CQ2 !\n");
02025       else
02026         fprintf( stderr,"CQ includes CQ2.\n");
02027       if( ! PolyhedronIncludes(res->ValidityDomain, CQ2) )
02028         fprintf( stderr,"CQ2 is *not* included in validity domain !\n");
02029       else
02030         fprintf( stderr,"CQ2 is included in validity domain.\n");
02031 #endif
02032       
02033       /* L is used in counting the number of points in the base cases */
02034       L = Polyhedron_Scan(P,CQ,MAXRAYS);
02035       U = Universe_Polyhedron(0);
02036       
02037       /* LQ is used to scan the parameter space */
02038       LQ = Polyhedron_Scan(CQ2,U,MAXRAYS); /* bounds on parameters */
02039       Domain_Free(U);
02040       if(CT)    /* we did compute another Q->Domain */
02041         Domain_Free(CQ);
02042       
02043       /* Else, CQ was Q->Domain (used in res) */
02044       Domain_Free(CQ2);
02045       
02046 #ifdef EDEBUG2
02047       fprintf(stderr,"L = \n");
02048       Polyhedron_Print(stderr,P_VALUE_FMT,L);
02049       fprintf(stderr,"LQ = \n");
02050       Polyhedron_Print(stderr,P_VALUE_FMT,LQ);
02051 #endif
02052 #ifdef EDEBUG3
02053       fprintf(stdout,"\nSystem of Equations:\n");
02054 #endif
02055       
02056       value_init(res->EP.d);
02057       value_set_si(res->EP.d,0);
02058       
02059       /* Create a context vector size dim+2 */
02060       context = (Value *) malloc ((hdim+1)*sizeof(Value));  
02061       for(i=0;i<=(hdim);i++)
02062         value_init(context[i]);
02063       Vector_Set(context,0,(hdim+1));
02064       
02065       /* Set context[hdim] = 1  (the constant) */
02066       value_set_si(context[hdim],1);
02067       
02068       CATCH(overflow_error) {
02069                         fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
02070                         fprintf(stderr,"You should rebuild PolyLib using GNU-MP or increasing the size of integers.\n");
02071                         overflow_warning_flag = 0;
02072                         assert(overflow_warning_flag);
02073         
02074       }
02075       TRY {
02076                         res->EP.x.p = P_Enum(L,LQ,context,1,nb_param,dim,lcm,param_name);
02077                         UNCATCH(overflow_error);        
02078       }
02079       
02080       for(i=0;i<=(hdim);i++)
02081         value_clear(context[i]);
02082       free(context);
02083       Domain_Free(L);
02084       Domain_Free(LQ);
02085       
02086 #ifdef EDEBUG5
02087         if( param_name )
02088    {
02089       fprintf(stdout,"\nEhrhart Polynomial (before simplification):\n");
02090       print_evalue(stdout,&res->EP,param_name);
02091         }
02092 #endif
02093 
02094       /* Try to simplify the result */
02095       reduce_evalue(&res->EP);
02096       
02097       /* Put back the original parameters into result */
02098       /* (equalities have been eliminated)            */
02099       if(CT) 
02100           addeliminatedparams_evalue(&res->EP,CT);
02101       
02102         if( param_name )
02103         {
02104       fprintf(stdout,"\nEhrhart Polynomial:\n");
02105       print_evalue(stdout,&res->EP, param_name);
02106       fprintf(stdout,"\n");
02107       /* sometimes the final \n lacks (when a single constant is printed) */
02108         }
02109       
02110     }
02111   }
02112 
02113   if( P != Pi )
02114         Polyhedron_Free( P );
02115   /* Clear all the 'Value' variables */
02116   for( np=0; np<nb_param ; np++ )
02117   {
02118     value_clear(lcm[np]); value_clear(m1[np]);
02119   }
02120   value_clear(hdv);
02121 
02122   return res;
02123 } /* Polyhedron_Enumerate */ 
02124 
02125 void Enumeration_Free(Enumeration *en)
02126 {
02127   Enumeration *ee;
02128 
02129   while( en )
02130   {
02131           free_evalue_refs( &(en->EP) );
02132           Polyhedron_Free( en->ValidityDomain );
02133           ee = en ->next;
02134           free( en );
02135           en = ee;
02136   }
02137 }
02138 
02139 
02140 

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