polylib: ehrhart.c Source File

- Main Page
- Classes
- Files

# 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, const 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, const 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         value_gcd(g, res->x.n, res->d);
    00369         if (value_notone_p(g)) {
    00370             value_divexact(res->d, res->d, g);
    00371             value_divexact(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     value_gcd(g, res->x.n, res->d);
    00410     if (value_notone_p(g)) {
    00411       value_divexact(res->d, res->d, g);
    00412       value_divexact(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
    00734     d = D->Dimension;
    00735     if (MAXRAYS < 2*D->NbConstraints)
    00736         MAXRAYS = 2*D->NbConstraints;
    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,
    00758                     "an equality was found where I did expect an inequality.\n");
    00759             fprintf(stderr,"Trying to continue...\n");
    00760             continue;
    00761         }
    00762         Vector_Copy(D->Constraint[i],M->p[M->NbRows],(d+2));
    00763         for(j=1;j<=d;j++)
    00764             if(value_neg_p(D->Constraint[i][j])) {
    00765               value_addmul(M->p[M->NbRows][d+1], D->Constraint[i][j], size[j-1]);
    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         return(NULL);
    00784     }
    00785
    00786     /* Ok, now find the lexicographical min of T */
    00787     min = (Value *) malloc(sizeof(Value) * (d+2));
    00788     for(i=0;i<=d;i++) {
    00789         value_init(min[i]);
    00790         value_set_si(min[i],0);
    00791     }
    00792     value_init(min[i]);
    00793     value_set_si(min[i],1);
    00794     C = Universe_Polyhedron(0);
    00795     S = Polyhedron_Scan(T,C,MAXRAYS);
    00796     Polyhedron_Free(C);
    00797     Polyhedron_Free(T);
    00798
    00799 #ifdef EDEBUG6
    00800     for(i=0;i<=(d+1);i++) {
    00801         value_print(stderr,P_VALUE_FMT,min[i]);
    00802         fprintf(stderr," ,");
    00803     }
    00804     fprintf(stderr,"\n");
    00805     Polyhedron_Print(stderr,P_VALUE_FMT,S);
    00806     fprintf(stderr,"\n");
    00807 #endif
    00808
    00809     if (!cherche_min(min,S,1))
    00810         {
    00811             for(i=0;i<=(d+1);i++)
    00812                 value_clear(min[i]);
    00813             return(NULL);
    00814         }
    00815     Domain_Free(S);
    00816
    00817 #ifdef EDEBUG6
    00818     fprintf(stderr,"min = ( ");
    00819     value_print(stderr,P_VALUE_FMT,min[1]);
    00820     for(i=2;i<=d;i++) {
    00821         fprintf(stderr,", ");
    00822         value_print(stderr,P_VALUE_FMT,min[i]);
    00823     }
    00824     fprintf(stderr,")\n");
    00825 #endif
    00826
    00827     /* Min is the point from which we can construct the hypercube */
    00828     M = Matrix_Alloc(d*2,d+2);
    00829     for(i=0;i<d;i++) {
    00830
    00831         /* Creates inequality  1 0..0 1 0..0 -min[i+1] */
    00832         value_set_si(M->p[2*i][0],1);
    00833         for(j=1;j<=d;j++)
    00834             value_set_si(M->p[2*i][j],0);
    00835         value_set_si(M->p[2*i][i+1],1);
    00836         value_oppose(M->p[2*i][d+1],min[i+1]);
    00837
    00838         /* Creates inequality  1 0..0 -1 0..0 min[i+1]+size -1 */
    00839         value_set_si(M->p[2*i+1][0],1);
    00840         for(j=1;j<=d;j++)
    00841             value_set_si(M->p[2*i+1][j],0);
    00842         value_set_si(M->p[2*i+1][i+1],-1);
    00843         value_addto(M->p[2*i+1][d+1],min[i+1],size[i]);
    00844         value_sub_int(M->p[2*i+1][d+1],M->p[2*i+1][d+1],1);
    00845     }
    00846
    00847 #ifdef EDEBUG6
    00848     fprintf(stderr,"PolyhedronPreprocess: constraints H = ");
    00849     Matrix_Print(stderr,P_VALUE_FMT,M);
    00850 #endif
    00851
    00852     H = Constraints2Polyhedron(M,MAXRAYS);
    00853
    00854 #ifdef EDEBUG6
    00855     Polyhedron_Print(stderr,P_VALUE_FMT,H);
    00856     fprintf(stderr,"\n");
    00857 #endif
    00858
    00859     Matrix_Free(M);
    00860     for(i=0;i<=(d+1);i++)
    00861         value_clear(min[i]);
    00862     free(min);
    00863     assert(!emptyQ(H));
    00864     return(H);
    00865 } /* Polyhedron_Preprocess */
    00866
    00867
    00868 /** This procedure finds an hypercube of size 'size', containing
    00869 polyhedron D increases size and lcm if necessary (and not "too big")
    00870 If this is not possible, an empty polyhedron is returned
    00871
    00872 <p>
    00873
    00874 <pre> written by vin100, 2001, for version 4.19</pre>
    00875
    00876 @param D
    00877 @param size
    00878 @param lcm
    00879 @param MAXRAYS
    00880
    00881 */
    00882 Polyhedron *Polyhedron_Preprocess2(Polyhedron *D,Value *size,
    00883                                    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
    00972                twice *size),
    00973                then increase *size, and artificially increase lcm too !*/
    00974             value_set_si(tmp1,20);
    00975             value_addto(tmp2,size[i],size[i]);
    00976             if(value_le(s,tmp1)
    00977                     || value_le(s,tmp2)) {
    00978
    00979                 if( value_zero_p(lcm[i]) )
    00980                     value_set_si(lcm[i],1);
    00981                 /* lcm divides size... */
    00982                 value_division(tmp1,size[i],lcm[i]);
    00983
    00984                 /* lcm = ceil(s/h) */
    00985                 value_addto(tmp2,s,tmp1);
    00986                 value_add_int(tmp2,tmp2,1);
    00987                 value_division(lcm[i],tmp2,tmp1);
    00988
    00989                 /* new size = lcm*h */
    00990                 value_multiply(size[i],lcm[i],tmp1);
    00991
    00992 #ifdef EDEBUG62
    00993                 fprintf(stderr,"new size = ");
    00994                 for( np=0 ; np<D->Dimension; np++ )
    00995                     value_print(stderr,VALUE_FMT,size[np]);
    00996                 fprintf(stderr,", new lcm = ");
    00997                 for( np=0 ; np<D->Dimension; np++ )
    00998                     value_print(stderr,VALUE_FMT,lcm[np]);
    00999                 fprintf(stderr,"\n");
    01000 #endif
    01001
    01002             }
    01003             else {
    01004
    01005 #ifdef EDEBUG62
    01006                 fprintf(stderr,"Failed on dimension %d.\n",i);
    01007 #endif
    01008                 break;
    01009             }
    01010         }
    01011     }
    01012     if(i!=D->Dimension) {
    01013         Matrix_Free(c);
    01014         value_clear(n); value_clear(s);
    01015         value_clear(tmp1); value_clear(tmp2);
    01016         return(NULL);
    01017     }
    01018     for(i=0;i<D->Dimension;i++) {
    01019         value_subtract(c->p[2*i+1][D->Dimension+1],size[i],
    01020                 c->p[2*i][D->Dimension+1]);
    01021     }
    01022
    01023 #ifdef EDEBUG62
    01024     fprintf(stderr,"PreProcess2 : c =");
    01025     Matrix_Print(stderr,P_VALUE_FMT,c);
    01026 #endif
    01027
    01028     H = Constraints2Polyhedron(c,MAXRAYS);
    01029     Matrix_Free(c);
    01030     value_clear(n); value_clear(s);
    01031     value_clear(tmp1); value_clear(tmp2);
    01032     return(H);
    01033 } /* Polyhedron_Preprocess2 */
    01034
    01035 /**
    01036
    01037 This procedure adds additional constraints to D so that as each
    01038 parameter is scanned, it will have a minimum of 'size' points If this
    01039 is not possible, an empty polyhedron is returned
    01040
    01041 @param D
    01042 @param size
    01043 @param MAXRAYS
    01044
    01045 */
    01046 Polyhedron *old_Polyhedron_Preprocess(Polyhedron *D,Value size,
    01047                                       unsigned MAXRAYS) {
    01048
    01049     int p, p1, ub, lb;
    01050     Value a, a1, b, b1, g, aa;
    01051     Value abs_a, abs_b, size_copy;
    01052     int dim, con, newi, needed;
    01053     Value **C;
    01054     Matrix *M;
    01055     Polyhedron *D1;
    01056
    01057     value_init(a); value_init(a1); value_init(b);
    01058     value_init(b1); value_init(g); value_init(aa);
    01059     value_init(abs_a); value_init(abs_b); value_init(size_copy);
    01060
    01061     dim = D->Dimension;
    01062     con = D->NbConstraints;
    01063     M = Matrix_Alloc(MAXRAYS,dim+2);
    01064     newi = 0;
    01065     value_assign(size_copy,size);
    01066     C = D->Constraint;
    01067     for (p=1; p<=dim; p++) {
    01068         for (ub=0; ub<con; ub++) {
    01069             value_assign(a,C[ub][p]);
    01070             if (value_posz_p(a))        /* a >= 0 */
    01071                 continue;               /* not an upper bound */
    01072             for (lb=0;lb<con;lb++) {
    01073                 value_assign(b,C[lb][p]);
    01074                 if (value_negz_p(b))
    01075                     continue;   /* not a lower bound */
    01076
    01077                 /* Check if a new constraint is needed for this (ub,lb) pair */
    01078                 /* a constraint is only needed if a previously scanned */
    01079                 /* parameter (1..p-1) constrains this parameter (p) */
    01080                 needed=0;
    01081                 for (p1=1; p1<p; p1++) {
    01082                     if (value_notzero_p(C[ub][p1]) ||
    01083                         value_notzero_p(C[lb][p1])) {
    01084                         needed=1;
    01085                         break;
    01086                     }
    01087                 }
    01088                 if (!needed) continue;
    01089                 value_absolute(abs_a,a);
    01090                 value_absolute(abs_b,b);
    01091
    01092                 /* Create new constraint: b*UB-a*LB >= a*b*size */
    01093                 value_gcd(g, abs_a, abs_b);
    01094                 value_divexact(a1, a, g);
    01095                 value_divexact(b1, b, g);
    01096                 value_set_si(M->p[newi][0],1);
    01097                 value_oppose(abs_a,a1);           /* abs_a = -a1 */
    01098                 Vector_Combine(&(C[ub][1]),&(C[lb][1]),&(M->p[newi][1]),
    01099                         b1,abs_a,dim+1);
    01100                 value_multiply(aa,a1,b1);
    01101                 value_addmul(M->p[newi][dim+1], aa, size_copy);
    01102                 Vector_Normalize(&(M->p[newi][1]),(dim+1));
    01103                 newi++;
    01104             }
    01105         }
    01106     }
    01107     D1 = AddConstraints(M->p_Init,newi,D,MAXRAYS);
    01108     Matrix_Free(M);
    01109
    01110     value_clear(a); value_clear(a1); value_clear(b);
    01111     value_clear(b1); value_clear(g); value_clear(aa);
    01112     value_clear(abs_a); value_clear(abs_b); value_clear(size_copy);
    01113     return D1;
    01114 } /* old_Polyhedron_Preprocess */
    01115
    01116 /**
    01117
    01118 PROCEDURES TO COMPUTE ENUMERATION. recursive procedure, recurse for
    01119 each imbriquation
    01120
    01121 @param pos index position of current loop index (1..hdim-1)
    01122 @param P loop domain
    01123 @param context context values for fixed indices
    01124 @param res the number of integer points in this
    01125 polyhedron
    01126
    01127 */
    01128 void count_points (int pos,Polyhedron *P,Value *context, Value *res) {
    01129
    01130     Value LB, UB, k, c;
    01131
    01132     POL_ENSURE_FACETS(P);
    01133     POL_ENSURE_VERTICES(P);
    01134
    01135     if (emptyQ(P)) {
    01136         value_set_si(*res, 0);
    01137         return;
    01138     }
    01139
    01140     value_init(LB); value_init(UB); value_init(k);
    01141     value_set_si(LB,0);
    01142     value_set_si(UB,0);
    01143
    01144     if (lower_upper_bounds(pos,P,context,&LB,&UB) !=0) {
    01145
    01146         /* Problem if UB or LB is INFINITY */
    01147         fprintf(stderr, "count_points: ? infinite domain\n");
    01148         value_clear(LB); value_clear(UB); value_clear(k);
    01149         value_set_si(*res, -1);
    01150         return;
    01151     }
    01152
    01153 #ifdef EDEBUG1
    01154     if (!P->next) {
    01155         int i;
    01156         for (value_assign(k,LB); value_le(k,UB); value_increment(k,k)) {
    01157             fprintf(stderr, "(");
    01158             for (i=1; i<pos; i++) {
    01159                 value_print(stderr,P_VALUE_FMT,context[i]);
    01160                 fprintf(stderr,",");
    01161             }
    01162             value_print(stderr,P_VALUE_FMT,k);
    01163             fprintf(stderr,")\n");
    01164         }
    01165     }
    01166 #endif
    01167
    01168     value_set_si(context[pos],0);
    01169     if (value_lt(UB,LB)) {
    01170         value_clear(LB); value_clear(UB); value_clear(k);
    01171         value_set_si(*res, 0);
    01172         return;
    01173     }
    01174     if (!P->next) {
    01175         value_subtract(k,UB,LB);
    01176         value_add_int(k,k,1);
    01177         value_assign(*res, k);
    01178         value_clear(LB); value_clear(UB); value_clear(k);
    01179         return;
    01180     }
    01181
    01182     /*-----------------------------------------------------------------*/
    01183     /* Optimization idea                                               */
    01184     /*   If inner loops are not a function of k (the current index)    */
    01185     /*   i.e. if P->Constraint[i][pos]==0 for all P following this and */
    01186     /*        for all i,                                               */
    01187     /*   Then CNT = (UB-LB+1)*count_points(pos+1, P->next, context)    */
    01188     /*   (skip the for loop)                                           */
    01189     /*-----------------------------------------------------------------*/
    01190
    01191     value_init(c);
    01192     value_set_si(*res, 0);
    01193     for (value_assign(k,LB);value_le(k,UB);value_increment(k,k)) {
    01194         /* Insert k in context */
    01195         value_assign(context[pos],k);
    01196         count_points(pos+1,P->next,context,&c);
    01197         if(value_notmone_p(c))
    01198             value_addto(*res, *res, c);
    01199         else {
    01200             value_set_si(*res, -1);
    01201             break;
    01202         }
    01203     }
    01204     value_clear(c);
    01205
    01206 #ifdef EDEBUG11
    01207     fprintf(stderr,"%d\n",CNT);
    01208 #endif
    01209
    01210     /* Reset context */
    01211     value_set_si(context[pos],0);
    01212     value_clear(LB); value_clear(UB); value_clear(k);
    01213     return;
    01214 } /* count_points */
    01215
    01216 /*-------------------------------------------------------------------*/
    01217 /* enode *P_Enum(L, LQ, context, pos, nb_param, dim, lcm,param_name) */
    01218 /*     L : list of polyhedra for the loop nest                       */
    01219 /*     LQ : list of polyhedra for the parameter loop nest            */
    01220 /*     pos : 1..nb_param, position of the parameter                  */
    01221 /*     nb_param : number of parameters total                         */
    01222 /*     dim : total dimension of the polyhedron, param incl.          */
    01223 /*     lcm : denominator array [0..dim-1] of the polyhedron          */
    01224 /*     param_name : name of the parameters                           */
    01225 /* Returns an enode tree representing the pseudo polynomial          */
    01226 /*   expression for the enumeration of the polyhedron.               */
    01227 /* A recursive procedure.                                            */
    01228 /*-------------------------------------------------------------------*/
    01229 static enode *P_Enum(Polyhedron *L,Polyhedron *LQ,Value *context,int pos,
    01230                      int nb_param,int dim,Value *lcm, const char **param_name)
    01231 {
    01232   enode *res,*B,*C;
    01233   int hdim,i,j,rank,flag;
    01234   Value n,g,nLB,nUB,nlcm,noff,nexp,k1,nm,hdv,k,lcm_copy;
    01235   Value tmp;
    01236   Matrix *A;
    01237
    01238 #ifdef EDEBUG
    01239   fprintf(stderr,"-------------------- begin P_Enum -------------------\n");
    01240   fprintf(stderr,"Calling P_Enum with pos = %d\n",pos);
    01241 #endif
    01242
    01243   /* Initialize all the 'Value' variables */
    01244   value_init(n); value_init(g); value_init(nLB);
    01245   value_init(nUB); value_init(nlcm); value_init(noff);
    01246   value_init(nexp); value_init(k1); value_init(nm);
    01247   value_init(hdv); value_init(k); value_init(tmp);
    01248   value_init(lcm_copy);
    01249
    01250   if( value_zero_p(lcm[pos-1]) )
    01251   {
    01252                 hdim = 1;
    01253                 value_set_si( lcm_copy, 1 );
    01254   }
    01255   else
    01256   {
    01257           /* hdim is the degree of the polynomial + 1 */
    01258                 hdim = dim-nb_param+1; /* homogenous dim w/o parameters */
    01259                 value_assign( lcm_copy, lcm[pos-1] );
    01260   }
    01261
    01262   /* code to limit generation of equations to valid parameters only */
    01263   /*----------------------------------------------------------------*/
    01264   flag = lower_upper_bounds(pos,LQ,&context[dim-nb_param],&nLB,&nUB);
    01265   if (flag & LB_INFINITY) {
    01266     if (!(flag & UB_INFINITY)) {
    01267
    01268       /* Only an upper limit: set lower limit */
    01269       /* Compute nLB such that (nUB-nLB+1) >= (hdim*lcm) */
    01270       value_sub_int(nLB,nUB,1);
    01271       value_set_si(hdv,hdim);
    01272       value_multiply(tmp,hdv,lcm_copy);
    01273       value_subtract(nLB,nLB,tmp);
    01274       if(value_pos_p(nLB))
    01275         value_set_si(nLB,0);
    01276     }
    01277     else {
    01278       value_set_si(nLB,0);
    01279
    01280       /* No upper nor lower limit: set lower limit to 0 */
    01281       value_set_si(hdv,hdim);
    01282       value_multiply(nUB,hdv,lcm_copy);
    01283       value_add_int(nUB,nUB,1);
    01284     }
    01285   }
    01286
    01287   /* if (nUB-nLB+1) < (hdim*lcm) then we have more unknowns than equations */
    01288   /* We can: 1. Find more equations by changing the context parameters, or */
    01289   /* 2. Assign extra unknowns values in such a way as to simplify result.  */
    01290   /* Think about ways to scan parameter space to get as much info out of it*/
    01291   /* as possible.                                                          */
    01292
    01293 #ifdef REDUCE_DEGREE
    01294   if (pos==1 && (flag & UB_INFINITY)==0) {
    01295     /* only for finite upper bound on first parameter */
    01296     /* NOTE: only first parameter because subsequent parameters may
    01297        be artificially limited by the choice of the first parameter */
    01298
    01299 #ifdef EDEBUG
    01300     fprintf(stderr,"*************** n **********\n");
    01301     value_print(stderr,VALUE_FMT,n);
    01302     fprintf(stderr,"\n");
    01303 #endif
    01304
    01305     value_subtract(n,nUB,nLB);
    01306     value_increment(n,n);
    01307
    01308 #ifdef EDEBUG
    01309     value_print(stderr,VALUE_FMT,n);
    01310     fprintf(stderr,"\n*************** n ************\n");
    01311 #endif
    01312
    01313     /* Total number of samples>0 */
    01314     if(value_neg_p(n))
    01315       i=0;
    01316     else {
    01317       value_modulus(tmp,n,lcm_copy);
    01318       if(value_notzero_p(tmp)) {
    01319                   value_division(tmp,n,lcm_copy);
    01320                   value_increment(tmp,tmp);
    01321                   i = VALUE_TO_INT(tmp);
    01322       }
    01323       else {
    01324                   value_division(tmp,n,lcm_copy);
    01325                   i =   VALUE_TO_INT(tmp);      /* ceiling of n/lcm */
    01326       }
    01327     }
    01328
    01329 #ifdef EDEBUG
    01330     value_print(stderr,VALUE_FMT,n);
    01331     fprintf(stderr,"\n*************** n ************\n");
    01332 #endif
    01333
    01334     /* Reduce degree of polynomial based on number of sample points */
    01335     if (i < hdim){
    01336       hdim=i;
    01337
    01338 #ifdef EDEBUG4
    01339       fprintf(stdout,"Parameter #%d: LB=",pos);
    01340       value_print(stdout,VALUE_FMT,nLB);
    01341       fprintf(stdout," UB=");
    01342       value_print(stdout,VALUE_FMT,nUB);
    01343       fprintf(stdout," lcm=");
    01344       value_print(stdout,VALUE_FMT,lcm_copy);
    01345       fprintf(stdout," degree reduced to %d\n",hdim-1);
    01346 #endif
    01347
    01348     }
    01349   }
    01350 #endif /* REDUCE_DEGREE */
    01351
    01352   /* hdim is now set */
    01353   /* allocate result structure */
    01354   res = new_enode(polynomial,hdim,pos);
    01355   for (i=0;i<hdim;i++) {
    01356     int l;
    01357     l = VALUE_TO_INT(lcm_copy);
    01358     res->arr[i].x.p = new_enode(periodic,l,pos);
    01359   }
    01360
    01361   /* Utility arrays */
    01362   A = Matrix_Alloc(hdim, 2*hdim+1);               /* used for Gauss */
    01363   B = new_enode(evector, hdim, 0);
    01364   C = new_enode(evector, hdim, 0);
    01365
    01366   /* We'll create these again when we need them */
    01367   for (j = 0; j < hdim; ++j)
    01368     free_evalue_refs(&C->arr[j]);
    01369
    01370   /*----------------------------------------------------------------*/
    01371   /*                                                                */
    01372   /*                                0<-----+---k--------->          */
    01373   /* |---------noff----------------->-nlcm->-------lcm---->         */
    01374   /* |--- . . . -----|--------------|------+-------|------+-------|-*/
    01375   /* 0          (q-1)*lcm         q*lcm    |  (q+1)*lcm   |         */
    01376   /*                                      nLB          nLB+lcm      */
    01377   /*                                                                */
    01378   /*----------------------------------------------------------------*/
    01379   if(value_neg_p(nLB)) {
    01380     value_modulus(nlcm,nLB,lcm_copy);
    01381     value_addto(nlcm,nlcm,lcm_copy);
    01382   }
    01383   else {
    01384     value_modulus(nlcm,nLB,lcm_copy);
    01385   }
    01386
    01387   /* noff is a multiple of lcm */
    01388   value_subtract(noff,nLB,nlcm);
    01389   value_addto(tmp,lcm_copy,nlcm);
    01390   for (value_assign(k,nlcm);value_lt(k,tmp);) {
    01391
    01392 #ifdef EDEBUG
    01393     fprintf(stderr,"Finding ");
    01394     value_print(stderr,VALUE_FMT,k);
    01395     fprintf(stderr,"-th elements of periodic coefficients\n");
    01396 #endif
    01397
    01398     value_set_si(hdv,hdim);
    01399     value_multiply(nm,hdv,lcm_copy);
    01400     value_addto(nm,nm,nLB);
    01401     i=0;
    01402     for (value_addto(n,k,noff); value_lt(n,nm);
    01403          value_addto(n,n,lcm_copy),i++) {
    01404
    01405       /* n == i*lcm + k + noff;   */
    01406       /* nlcm <= k < nlcm+lcm     */
    01407       /* n mod lcm == k1 */
    01408
    01409 #ifdef ALL_OVERFLOW_WARNINGS
    01410       if (((flag & UB_INFINITY)==0) && value_gt(n,nUB)) {
    01411         fprintf(stdout,"Domain Overflow: Parameter #%d:",pos);
    01412         fprintf(stdout,"nLB=");
    01413         value_print(stdout,VALUE_FMT,nLB);
    01414         fprintf(stdout," n=");
    01415         value_print(stdout,VALUE_FMT,n);
    01416         fprintf(stdout," nUB=");
    01417         value_print(stdout,VALUE_FMT,nUB);
    01418         fprintf(stdout,"\n");
    01419       }
    01420 #else
    01421       if (overflow_warning_flag && ((flag & UB_INFINITY)==0) &&
    01422           value_gt(n,nUB)) {
    01423         fprintf(stdout,"\nWARNING: Parameter Domain Overflow.");
    01424         fprintf(stdout," Result may be incorrect on this domain.\n");
    01425         overflow_warning_flag = 0;
    01426       }
    01427 #endif
    01428
    01429       /* Set parameter to n */
    01430       value_assign(context[dim-nb_param+pos],n);
    01431
    01432 #ifdef EDEBUG1
    01433         if( param_name )
    01434         {
    01435       fprintf(stderr,"%s = ",param_name[pos-1]);
    01436       value_print(stderr,VALUE_FMT,n);
    01437       fprintf(stderr," (hdim=%d, lcm[%d]=",hdim,pos-1);
    01438       value_print(stderr,VALUE_FMT,lcm_copy);
    01439       fprintf(stderr,")\n");
    01440         }
    01441         else
    01442         {
    01443       fprintf(stderr,"P%d = ",pos);
    01444       value_print(stderr,VALUE_FMT,n);
    01445       fprintf(stderr," (hdim=%d, lcm[%d]=",hdim,pos-1);
    01446       value_print(stderr,VALUE_FMT,lcm_copy);
    01447       fprintf(stderr,")\n");
    01448         }
    01449 #endif
    01450
    01451       /* Setup B vector */
    01452       if (pos==nb_param) {
    01453
    01454 #ifdef EDEBUG
    01455         fprintf(stderr,"Yes\n");
    01456 #endif
    01457
    01458         /* call count */
    01459         /* count can only be called when the context is fully specified */
    01460         value_set_si(B->arr[i].d,1);
    01461         value_init(B->arr[i].x.n);
    01462         count_points(1,L,context,&B->arr[i].x.n);
    01463
    01464 #ifdef EDEBUG3
    01465         for (j=1; j<pos; j++) fputs("   ",stdout);
    01466         fprintf(stdout, "E(");
    01467         for (j=1; j<nb_param; j++) {
    01468           value_print(stdout,VALUE_FMT,context[dim-nb_param+j]);
    01469           fprintf(stdout,",");
    01470         }
    01471         value_print(stdout,VALUE_FMT,n);
    01472         fprintf(stdout,") = ");
    01473         value_print(stdout,VALUE_FMT,B->arr[i].x.n);
    01474         fprintf(stdout," =");
    01475 #endif
    01476
    01477       }
    01478       else {    /* count is a function of other parameters */
    01479         /* call P_Enum recursively */
    01480         value_set_si(B->arr[i].d,0);
    01481         B->arr[i].x.p = P_Enum(L,LQ->next,context,pos+1,
    01482                                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         value_gcd(g, A->p[i][i+1], A->p[i][j+1+hdim]);
    01568         value_init(C->arr[j].d);
    01569         value_divexact(C->arr[j].d, A->p[i][i+1], g);
    01570         value_init(C->arr[j].x.n);
    01571         value_divexact(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)]),
    01590                    param_name);
    01591       fprintf(stderr,"\n");
    01592         }
    01593 #endif
    01594
    01595       for (j = 0; j < rank; ++j)
    01596         free_evalue_refs(&C->arr[j]);
    01597     }
    01598     value_addto(tmp,lcm_copy,nlcm);
    01599
    01600     value_increment(k,k);
    01601     for (i = 0; i < hdim; ++i) {
    01602       free_evalue_refs(&B->arr[i]);
    01603       if (value_lt(k,tmp))
    01604         value_init(B->arr[i].d);
    01605     }
    01606   }
    01607
    01608 #ifdef EDEBUG
    01609         if( param_name )
    01610         {
    01611           fprintf(stderr,"res (enode) =\n");
    01612           print_enode(stderr,res,param_name);
    01613         }
    01614   fprintf(stderr, "-------------------- end P_Enum -----------------------\n");
    01615 #endif
    01616
    01617   /* Reset context */
    01618   value_set_si(context[dim-nb_param+pos],0);
    01619
    01620   /* Release memory */
    01621   Matrix_Free(A);
    01622   free(B);
    01623   free(C);
    01624
    01625   /* Clear all the 'Value' variables */
    01626   value_clear(n); value_clear(g); value_clear(nLB);
    01627   value_clear(nUB); value_clear(nlcm); value_clear(noff);
    01628   value_clear(nexp); value_clear(k1); value_clear(nm);
    01629   value_clear(hdv); value_clear(k); value_clear(tmp);
    01630   value_clear(lcm_copy);
    01631   return res;
    01632 } /* P_Enum */
    01633
    01634 /*----------------------------------------------------------------*/
    01635 /* Scan_Vertices(PP, Q, CT)                                       */
    01636 /*    PP : ParamPolyhedron                                        */
    01637 /*    Q : Domain                                                  */
    01638 /*    CT : Context transformation matrix                          */
    01639 /*    lcm : lcm array (output)                                    */
    01640 /*    nbp : number of parameters                                  */
    01641 /*    param_name : name of the parameters                         */
    01642 /*----------------------------------------------------------------*/
    01643 static void Scan_Vertices(Param_Polyhedron *PP,Param_Domain *Q,Matrix *CT,
    01644    Value *lcm, int nbp, const char **param_name)
    01645 {
    01646   Param_Vertices *V;
    01647   int i, j, ix, l, np;
    01648   unsigned bx;
    01649   Value k,m1;
    01650
    01651   /* Compute the denominator of P */
    01652   /* lcm = Least Common Multiple of the denominators of the vertices of P */
    01653   /* and print the vertices */
    01654
    01655   value_init(k); value_init(m1);
    01656   for( np=0 ; np<nbp ; np++ )
    01657     value_set_si( lcm[np], 0 );
    01658
    01659         if( param_name )
    01660           fprintf(stdout,"Vertices:\n");
    01661
    01662   for(i=0,ix=0,bx=MSB,V=PP->V; V && i<PP->nbV; i++,V=V->next) {
    01663     if (Q->F[ix] & bx) {
    01664       if( param_name )
    01665         {
    01666           if(CT) {
    01667             Matrix *v;
    01668             v = VertexCT(V->Vertex,CT);
    01669             Print_Vertex(stdout,v,param_name);
    01670             Matrix_Free(v);
    01671           }
    01672           else
    01673             Print_Vertex(stdout,V->Vertex,param_name);
    01674           fprintf(stdout,"\n");
    01675         }
    01676
    01677       for(j=0;j<V->Vertex->NbRows;j++) {
    01678         /* A matrix */
    01679         for( l=0 ; l<V->Vertex->NbColumns-1 ; l++ )
    01680           {
    01681             if( value_notzero_p(V->Vertex->p[j][l]) )
    01682               {
    01683                 value_gcd(m1, V->Vertex->p[j][V->Vertex->NbColumns-1],
    01684                           V->Vertex->p[j][l]);
    01685                 value_divexact(k, V->Vertex->p[j][V->Vertex->NbColumns-1], m1);
    01686                 if( value_notzero_p(lcm[l]) )
    01687                   {
    01688                     /* lcm[l] = lcm[l] * k / gcd(k,lcm[l]) */
    01689                     if (value_notzero_p(k) && value_notone_p(k))
    01690                       {
    01691                         value_gcd(m1, lcm[l], k);
    01692                         value_divexact(k, k, m1);
    01693                         value_multiply(lcm[l],lcm[l],k);
    01694                       }
    01695                   }
    01696                 else
    01697                   {
    01698                     value_assign(lcm[l],k);
    01699                   }
    01700               }
    01701           }
    01702       }
    01703     }
    01704     NEXT(ix,bx);
    01705   }
    01706   value_clear(k); value_clear(m1);
    01707 } /* Scan_Vertices */
    01708
    01709 /**
    01710
    01711 Procedure to count points in a non-parameterized polytope.
    01712
    01713 @param P       Polyhedron to count
    01714 @param C       Parameter Context domain
    01715 @param CT      Matrix to transform context to original
    01716 @param CEq     additionnal equalities in context
    01717 @param MAXRAYS workspace size
    01718 @param param_name parameter names
    01719
    01720 */
    01721 Enumeration *Enumerate_NoParameters(Polyhedron *P,Polyhedron *C,
    01722                                     Matrix *CT,Polyhedron *CEq,
    01723                                     unsigned MAXRAYS, const char **param_name)
    01724 {
    01725     Polyhedron *L;
    01726     Enumeration *res;
    01727     Value *context;
    01728     int j;
    01729     int hdim = P->Dimension + 1;
    01730     int r,i;
    01731
    01732     /* Create a context vector size dim+2 */
    01733     context = (Value *) malloc((hdim+1)*sizeof(Value));
    01734     for (j=0;j<= hdim;j++)
    01735         value_init(context[j]);
    01736
    01737     res = (Enumeration *)malloc(sizeof(Enumeration));
    01738     res->next = NULL;
    01739     res->ValidityDomain = Universe_Polyhedron(0);  /* no parameters */
    01740     value_init(res->EP.d);
    01741     value_set_si(res->EP.d,0);
    01742     L = Polyhedron_Scan(P,res->ValidityDomain,MAXRAYS);
    01743
    01744 #ifdef EDEBUG2
    01745     fprintf(stderr, "L = \n");
    01746     Polyhedron_Print(stderr, P_VALUE_FMT, L);
    01747 #endif
    01748
    01749     if(CT) {
    01750         Polyhedron *Dt;
    01751
    01752         /* Add parameters to validity domain */
    01753         Dt = Polyhedron_Preimage(res->ValidityDomain,CT,MAXRAYS);
    01754         Polyhedron_Free(res->ValidityDomain);
    01755         res->ValidityDomain = DomainIntersection(Dt,CEq,MAXRAYS);
    01756         Polyhedron_Free(Dt);
    01757     }
    01758
    01759         if( param_name )
    01760         {
    01761     fprintf(stdout,"---------------------------------------\n");
    01762     fprintf(stdout,"Domain:\n");
    01763     Print_Domain(stdout,res->ValidityDomain, param_name);
    01764
    01765     /* Print the vertices */
    01766     printf("Vertices:\n");
    01767     for(r=0;r<P->NbRays;++r) {
    01768         if(value_zero_p(P->Ray[r][0]))
    01769             printf("(line) ");
    01770         printf("[");
    01771         if (P->Dimension > 0)
    01772             value_print(stdout,P_VALUE_FMT,P->Ray[r][1]);
    01773         for(i=1;i<P->Dimension;i++) {
    01774             printf(", ");
    01775             value_print(stdout,P_VALUE_FMT,P->Ray[r][i+1]);
    01776         }
    01777         printf("]");
    01778         if(value_notone_p(P->Ray[r][P->Dimension+1])) {
    01779             printf("/");
    01780             value_print(stdout,P_VALUE_FMT, P->Ray[r][P->Dimension+1]);
    01781         }
    01782         printf("\n");
    01783     }
    01784         }
    01785
    01786   res->EP.x.p = new_enode(polynomial,1,0);;
    01787   value_set_si(res->EP.x.p->arr[0].d, 1);
    01788   value_init(res->EP.x.p->arr[0].x.n);
    01789
    01790   if (emptyQ(P)) {
    01791     value_set_si(res->EP.x.p->arr[0].x.n, 0);
    01792   } else if (!L) {
    01793     /* Non-empty zero-dimensional domain */
    01794     value_set_si(res->EP.x.p->arr[0].x.n, 1);
    01795   } else {
    01796     CATCH(overflow_error) {
    01797         fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
    01798         fprintf(stderr,"You should rebuild PolyLib using GNU-MP"
    01799                 " or increasing the size of integers.\n");
    01800         overflow_warning_flag = 0;
    01801         assert(overflow_warning_flag);
    01802     }
    01803     TRY {
    01804
    01805         Vector_Set(context,0,(hdim+1));
    01806
    01807         /* Set context[hdim] = 1  (the constant) */
    01808         value_set_si(context[hdim],1);
    01809         count_points(1, L, context, &res->EP.x.p->arr[0].x.n);
    01810         UNCATCH(overflow_error);
    01811     }
    01812   }
    01813
    01814     Domain_Free(L);
    01815
    01816     /*  **USELESS, there are no references to parameters in res**
    01817         if( CT )
    01818         addeliminatedparams_evalue(&res->EP, CT);
    01819     */
    01820
    01821         if( param_name )
    01822         {
    01823     fprintf(stdout,"\nEhrhart Polynomial:\n");
    01824     print_evalue(stdout,&res->EP,param_name);
    01825     fprintf(stdout, "\n");
    01826         }
    01827
    01828     for (j=0;j<= hdim;j++)
    01829         value_clear(context[j]);
    01830     free(context);
    01831     return(res);
    01832 } /* Enumerate_NoParameters */
    01833
    01834 /**  Procedure to count points in a parameterized polytope.
    01835
    01836 @param Pi Polyhedron to enumerate
    01837 @param C Context Domain
    01838 @param MAXRAYS size of workspace
    01839 @param param_name parameter names (array of strings), may be NULL
    01840 @return a list of validity domains + evalues EP
    01841
    01842 */
    01843 Enumeration *Polyhedron_Enumerate(Polyhedron *Pi,Polyhedron *C,
    01844                                   unsigned MAXRAYS, const char **param_name)
    01845 {
    01846   Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P, *Ph = NULL;
    01847   Matrix *CT;
    01848   Param_Polyhedron *PP;
    01849   Param_Domain   *Q;
    01850   int i,hdim, dim, nb_param, np;
    01851   Value *lcm, *m1, hdv;
    01852   Value *context;
    01853   Enumeration *en, *res;
    01854
    01855   if (POL_ISSET(MAXRAYS, POL_NO_DUAL))
    01856     MAXRAYS = 0;
    01857
    01858   POL_ENSURE_FACETS(Pi);
    01859   POL_ENSURE_VERTICES(Pi);
    01860   POL_ENSURE_FACETS(C);
    01861   POL_ENSURE_VERTICES(C);
    01862
    01863   res = NULL;
    01864   P = Pi;
    01865
    01866 #ifdef EDEBUG2
    01867   fprintf(stderr,"C = \n");
    01868   Polyhedron_Print(stderr,P_VALUE_FMT,C);
    01869   fprintf(stderr,"P = \n");
    01870   Polyhedron_Print(stderr,P_VALUE_FMT,P);
    01871 #endif
    01872
    01873   hdim          = P->Dimension + 1;
    01874   dim           = P->Dimension;
    01875   nb_param      = C->Dimension;
    01876
    01877   /* Don't call Polyhedron2Param_Domain if there are no parameters */
    01878   if(nb_param == 0) {
    01879
    01880     return(Enumerate_NoParameters(P,C,NULL,NULL,MAXRAYS,param_name));
    01881   }
    01882   if(nb_param == dim) {
    01883     res = (Enumeration *)malloc(sizeof(Enumeration));
    01884     res->next = 0;
    01885     res->ValidityDomain = DomainIntersection(P,C,MAXRAYS);
    01886     value_init(res->EP.d);
    01887     value_init(res->EP.x.n);
    01888     value_set_si(res->EP.d,1);
    01889     value_set_si(res->EP.x.n,1);
    01890     if( param_name ) {
    01891       fprintf(stdout,"---------------------------------------\n");
    01892       fprintf(stdout,"Domain:\n");
    01893       Print_Domain(stdout,res->ValidityDomain, param_name);
    01894       fprintf(stdout,"\nEhrhart Polynomial:\n");
    01895       print_evalue(stdout,&res->EP,param_name);
    01896       fprintf(stdout, "\n");
    01897     }
    01898     return res;
    01899   }
    01900   PP = Polyhedron2Param_SimplifiedDomain(&P,C,MAXRAYS,&CEq,&CT);
    01901   if(!PP) {
    01902         if( param_name )
    01903     fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
    01904
    01905     return(NULL);
    01906   }
    01907
    01908   /* CT : transformation matrix to eliminate useless ("false") parameters */
    01909   if(CT) {
    01910     nb_param -= CT->NbColumns-CT->NbRows;
    01911     dim  -= CT->NbColumns-CT->NbRows;
    01912     hdim -= CT->NbColumns-CT->NbRows;
    01913
    01914     /* Don't call Polyhedron2Param_Domain if there are no parameters */
    01915     if(nb_param == 0) {
    01916         res = Enumerate_NoParameters(P,C,CT,CEq,MAXRAYS,param_name);
    01917         Param_Polyhedron_Free(PP);
    01918         goto out;
    01919     }
    01920   }
    01921
    01922   /* get memory for Values */
    01923   lcm = (Value *)malloc((nb_param+1) * sizeof(Value));
    01924   m1  = (Value *)malloc((nb_param+1) * sizeof(Value));
    01925   /* Initialize all the 'Value' variables */
    01926   for( np=0 ; np < nb_param+1; np++ )
    01927   {
    01928     value_init(lcm[np]); value_init(m1[np]);
    01929   }
    01930   value_init(hdv);
    01931
    01932   for(Q=PP->D;Q;Q=Q->next) {
    01933     int hom = 0;
    01934     if(CT) {
    01935       Polyhedron *Dt;
    01936       CQ = Q->Domain;
    01937       Dt = Polyhedron_Preimage(Q->Domain,CT,MAXRAYS);
    01938       rVD = DomainIntersection(Dt,CEq,MAXRAYS);
    01939
    01940       /* if rVD is empty or too small in geometric dimension */
    01941       if(!rVD || emptyQ(rVD) ||
    01942          (rVD->Dimension-rVD->NbEq < Dt->Dimension-Dt->NbEq-CEq->NbEq)) {
    01943         if(rVD)
    01944           Polyhedron_Free(rVD);
    01945         Polyhedron_Free(Dt);
    01946         Polyhedron_Free(CQ);
    01947         continue;               /* empty validity domain */
    01948       }
    01949       Polyhedron_Free(Dt);
    01950     }
    01951     else
    01952       rVD = CQ = Q->Domain;
    01953     en = (Enumeration *)malloc(sizeof(Enumeration));
    01954     en->next = res;
    01955     res = en;
    01956     res->ValidityDomain = rVD;
    01957
    01958     if( param_name ) {
    01959       fprintf(stdout,"---------------------------------------\n");
    01960       fprintf(stdout,"Domain:\n");
    01961
    01962 #ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
    01963       Print_Domain(stdout,res->ValidityDomain,param_name);
    01964 #else
    01965       {
    01966         Polyhedron *VD;
    01967         VD = DomainSimplify(res->ValidityDomain,C,MAXRAYS);
    01968         Print_Domain(stdout,VD,param_name);
    01969         Domain_Free(VD);
    01970       }
    01971 #endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
    01972     }
    01973
    01974     overflow_warning_flag = 1;
    01975
    01976     /* Scan the vertices and compute lcm */
    01977     Scan_Vertices(PP,Q,CT,lcm,nb_param,param_name);
    01978
    01979 #ifdef EDEBUG2
    01980     fprintf(stderr,"Denominator = ");
    01981     for( np=0;np<nb_param;np++)
    01982       value_print(stderr,P_VALUE_FMT,lcm[np]);
    01983     fprintf(stderr," and hdim == %d \n",hdim);
    01984 #endif
    01985
    01986 #ifdef EDEBUG2
    01987     fprintf(stderr,"CQ = \n");
    01988     Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
    01989 #endif
    01990
    01991     /* Before scanning, add constraints to ensure at least hdim*lcm */
    01992     /* points in every dimension */
    01993     value_set_si(hdv,hdim-nb_param);
    01994
    01995     for( np=0;np<nb_param+1;np++) {
    01996         if( value_notzero_p(lcm[np]) )
    01997             value_multiply(m1[np],hdv,lcm[np]);
    01998         else
    01999             value_set_si(m1[np],1);
    02000     }
    02001
    02002 #ifdef EDEBUG2
    02003     fprintf(stderr,"m1 == ");
    02004     for( np=0;np<nb_param;np++)
    02005       value_print(stderr,P_VALUE_FMT,m1[np]);
    02006     fprintf(stderr,"\n");
    02007 #endif
    02008
    02009     CATCH(overflow_error) {
    02010       fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
    02011       CQ2 = NULL;
    02012     }
    02013     TRY {
    02014       CQ2 = Polyhedron_Preprocess(CQ,m1,MAXRAYS);
    02015
    02016 #ifdef EDEBUG2
    02017       fprintf(stderr,"After preprocess, CQ2 = ");
    02018       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
    02019 #endif
    02020
    02021       UNCATCH(overflow_error);
    02022     }
    02023
    02024     /* Vin100, Feb 2001 */
    02025     /* in case of degenerate, try to find a domain _containing_ CQ */
    02026     if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid==0) {
    02027       int r;
    02028
    02029 #ifdef EDEBUG2
    02030       fprintf(stderr,"Trying to call Polyhedron_Preprocess2 : CQ = \n");
    02031       Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
    02032 #endif
    02033
    02034       /* Check if CQ is bounded */
    02035       for(r=0;r<CQ->NbRays;r++) {
    02036         if(value_zero_p(CQ->Ray[r][0]) ||
    02037            value_zero_p(CQ->Ray[r][CQ->Dimension+1]))
    02038           break;
    02039       }
    02040       if(r==CQ->NbRays) {
    02041
    02042         /* ok, CQ is bounded */
    02043         /* now find if CQ is contained in a hypercube of size m1 */
    02044         CQ2 = Polyhedron_Preprocess2(CQ,m1,lcm,MAXRAYS);
    02045       }
    02046     }
    02047
    02048     if (!CQ2) {
    02049       Polyhedron *tmp;
    02050 #ifdef EDEBUG2
    02051       fprintf(stderr,"Homogenize.\n");
    02052 #endif
    02053       hom = 1;
    02054       tmp = homogenize(CQ, MAXRAYS);
    02055       CQ2 = Polyhedron_Preprocess(tmp,m1,MAXRAYS);
    02056       Polyhedron_Free(tmp);
    02057       if (!Ph)
    02058         Ph = homogenize(P, MAXRAYS);
    02059       for (np=0; np < nb_param+1; np++)
    02060           if (value_notzero_p(lcm[np]))
    02061               value_addto(m1[np],m1[np],lcm[np]);
    02062     }
    02063
    02064     if (!CQ2 || emptyQ(CQ2)) {
    02065 #ifdef EDEBUG2
    02066       fprintf(stderr,"Degenerate.\n");
    02067 #endif
    02068       fprintf(stdout,"Degenerate Domain. Can not continue.\n");
    02069       value_init(res->EP.d);
    02070       value_init(res->EP.x.n);
    02071       value_set_si(res->EP.d,1);
    02072       value_set_si(res->EP.x.n,-1);
    02073     }
    02074     else {
    02075
    02076 #ifdef EDEBUG2
    02077       fprintf(stderr,"CQ2 = \n");
    02078       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
    02079       if( ! PolyhedronIncludes(CQ, CQ2) )
    02080         fprintf( stderr,"CQ does not include CQ2 !\n");
    02081       else
    02082         fprintf( stderr,"CQ includes CQ2.\n");
    02083       if( ! PolyhedronIncludes(res->ValidityDomain, CQ2) )
    02084         fprintf( stderr,"CQ2 is *not* included in validity domain !\n");
    02085       else
    02086         fprintf( stderr,"CQ2 is included in validity domain.\n");
    02087 #endif
    02088
    02089       /* L is used in counting the number of points in the base cases */
    02090       L = Polyhedron_Scan(hom ? Ph : P,CQ2,MAXRAYS);
    02091       U = Universe_Polyhedron(0);
    02092
    02093       /* LQ is used to scan the parameter space */
    02094       LQ = Polyhedron_Scan(CQ2,U,MAXRAYS); /* bounds on parameters */
    02095       Domain_Free(U);
    02096       if(CT)    /* we did compute another Q->Domain */
    02097         Domain_Free(CQ);
    02098
    02099       /* Else, CQ was Q->Domain (used in res) */
    02100       Domain_Free(CQ2);
    02101
    02102 #ifdef EDEBUG2
    02103       fprintf(stderr,"L = \n");
    02104       Polyhedron_Print(stderr,P_VALUE_FMT,L);
    02105       fprintf(stderr,"LQ = \n");
    02106       Polyhedron_Print(stderr,P_VALUE_FMT,LQ);
    02107 #endif
    02108 #ifdef EDEBUG3
    02109       fprintf(stdout,"\nSystem of Equations:\n");
    02110 #endif
    02111
    02112       value_init(res->EP.d);
    02113       value_set_si(res->EP.d,0);
    02114
    02115       /* Create a context vector size dim+2 */
    02116       context = (Value *) malloc ((hdim+1+hom)*sizeof(Value));
    02117       for(i=0;i<=(hdim+hom);i++)
    02118         value_init(context[i]);
    02119       Vector_Set(context,0,(hdim+1+hom));
    02120
    02121       /* Set context[hdim] = 1  (the constant) */
    02122       value_set_si(context[hdim+hom],1);
    02123
    02124       CATCH(overflow_error) {
    02125           fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
    02126           fprintf(stderr,"You should rebuild PolyLib using GNU-MP "
    02127                   "or increasing the size of integers.\n");
    02128           overflow_warning_flag = 0;
    02129           assert(overflow_warning_flag);
    02130
    02131       }
    02132       TRY {
    02133           res->EP.x.p = P_Enum(L,LQ,context,1,nb_param+hom,
    02134                                dim+hom,lcm,param_name);
    02135           UNCATCH(overflow_error);
    02136       }
    02137       if (hom)
    02138           dehomogenize_evalue(&res->EP, nb_param+1);
    02139
    02140       for(i=0;i<=(hdim+hom);i++)
    02141         value_clear(context[i]);
    02142       free(context);
    02143       Domain_Free(L);
    02144       Domain_Free(LQ);
    02145
    02146 #ifdef EDEBUG5
    02147         if( param_name )
    02148    {
    02149       fprintf(stdout,"\nEhrhart Polynomial (before simplification):\n");
    02150       print_evalue(stdout,&res->EP,param_name);
    02151         }
    02152 #endif
    02153
    02154       /* Try to simplify the result */
    02155       reduce_evalue(&res->EP);
    02156
    02157       /* Put back the original parameters into result */
    02158       /* (equalities have been eliminated)            */
    02159       if(CT)
    02160           addeliminatedparams_evalue(&res->EP,CT);
    02161
    02162       if (param_name) {
    02163         fprintf(stdout,"\nEhrhart Polynomial:\n");
    02164         print_evalue(stdout,&res->EP, param_name);
    02165         fprintf(stdout,"\n");
    02166         /* sometimes the final \n lacks (when a single constant is printed) */
    02167       }
    02168
    02169     }
    02170   }
    02171
    02172   if (Ph)
    02173     Polyhedron_Free(Ph);
    02174   /* Clear all the 'Value' variables */
    02175   for (np=0; np < nb_param+1; np++)
    02176   {
    02177     value_clear(lcm[np]); value_clear(m1[np]);
    02178   }
    02179   value_clear(hdv);
    02180   free(lcm);
    02181   free(m1);
    02182   /* We can't simply call Param_Polyhedron_Free because we've reused the domains */
    02183   Param_Vertices_Free(PP->V);
    02184   while (PP->D) {
    02185     Q = PP->D;
    02186     PP->D = PP->D->next;
    02187     free(Q->F);
    02188     free(Q);
    02189   }
    02190   free(PP);
    02191
    02192 out:
    02193   if (CEq)
    02194     Polyhedron_Free(CEq);
    02195   if (CT)
    02196     Matrix_Free(CT);
    02197   if( P != Pi )
    02198     Polyhedron_Free( P );
    02199
    02200   return res;
    02201 } /* Polyhedron_Enumerate */
    02202
    02203 void Enumeration_Free(Enumeration *en)
    02204 {
    02205   Enumeration *ee;
    02206
    02207   while( en )
    02208   {
    02209           free_evalue_refs( &(en->EP) );
    02210           Domain_Free( en->ValidityDomain );
    02211           ee = en ->next;
    02212           free( en );
    02213           en = ee;
    02214   }
    02215 }
    02216
    02217 /* adds by B. Meister for Ehrhart Polynomial approximation */
    02218
    02219 /**
    02220  * Divides the evalue e by the integer n<br/>
    02221  * recursive function<br/>
    02222  * Warning :  modifies e
    02223  * @param e an evalue (to be divided by n)
    02224  * @param n
    02225  */
    02226
    02227 void evalue_div(evalue * e, Value n) {
    02228   int i;
    02229   Value gc;
    02230   value_init(gc);
    02231   if (value_zero_p(e->d)) {
    02232     for (i=0; i< e->x.p->size; i++) {
    02233       evalue_div(&(e->x.p->arr[i]), n);
    02234     }
    02235   }
    02236   else {
    02237     value_multiply(e->d, e->d, n);
    02238     /* simplify the new rational if needed */
    02239     value_gcd(gc, e->x.n, e->d);
    02240     if (value_notone_p(gc)) {
    02241       value_divexact(e->d, e->d, gc);
    02242       value_divexact(e->x.n, e->x.n, gc);
    02243     }
    02244   }
    02245   value_clear(gc);
    02246 } /* evalue_div */
    02247
    02248
    02249 /**
    02250
    02251 Ehrhart_Quick_Apx_Full_Dim(P, C, MAXRAYS, param_names)
    02252
    02253 Procedure to estimate the number of points in a parameterized polytope.
    02254 Returns a list of validity domains + evalues EP
    02255 B.M.
    02256 The most rough and quick approximation by variables expansion
    02257 Deals with the full-dimensional case.
    02258 @param Pi : Polyhedron to enumerate (approximatively)
    02259 @param C : Context Domain
    02260 @param MAXRAYS : size of workspace
    02261 @param param_name : names for the parameters (char strings)
    02262
    02263 */
    02264 Enumeration *Ehrhart_Quick_Apx_Full_Dim(Polyhedron *Pi,Polyhedron *C,
    02265                                         unsigned MAXRAYS, const char **param_name)
    02266 {
    02267   Polyhedron *L, *CQ, *CQ2, *LQ, *U, *CEq, *rVD, *P;
    02268   Matrix *CT;
    02269   Param_Polyhedron *PP;
    02270   Param_Domain   *Q;
    02271   int i,j,hdim, dim, nb_param, np;
    02272   Value *lcm, *m1, hdv;
    02273   Value *context;
    02274   Enumeration *en, *res;
    02275   Value expansion_det;
    02276   Polyhedron * Expanded;
    02277
    02278   /* used to scan the vertices */
    02279   Param_Vertices * V_tmp;
    02280
    02281   res = NULL;
    02282   P = Pi;
    02283
    02284   value_init(expansion_det);
    02285
    02286 #ifdef EDEBUG2
    02287   fprintf(stderr,"C = \n");
    02288   Polyhedron_Print(stderr,P_VALUE_FMT,C);
    02289   fprintf(stderr,"P = \n");
    02290   Polyhedron_Print(stderr,P_VALUE_FMT,P);
    02291 #endif
    02292
    02293   hdim          = P->Dimension + 1;
    02294   dim           = P->Dimension;
    02295   nb_param      = C->Dimension;
    02296
    02297   /* Don't call Polyhedron2Param_Domain if there are no parameters */
    02298   if(nb_param == 0) {
    02299
    02300     return(Enumerate_NoParameters(P,C,NULL,NULL,MAXRAYS, param_name));
    02301   }
    02302
    02303 #if EDEBUG2
    02304   printf("Enumerating polyhedron : \n");
    02305   Polyhedron_Print(stdout, P_VALUE_FMT, P);
    02306 #endif
    02307
    02308   PP = Polyhedron2Param_SimplifiedDomain(&P,C,MAXRAYS,&CEq,&CT);
    02309   if(!PP) {
    02310     if( param_name )
    02311       fprintf(stdout, "\nEhrhart Polynomial:\nNULL\n");
    02312
    02313     return(NULL);
    02314   }
    02315
    02316   /* CT : transformation matrix to eliminate useless ("false") parameters */
    02317   if(CT) {
    02318     nb_param -= CT->NbColumns-CT->NbRows;
    02319     dim  -= CT->NbColumns-CT->NbRows;
    02320     hdim -= CT->NbColumns-CT->NbRows;
    02321
    02322     /* Don't call Polyhedron2Param_Domain if there are no parameters */
    02323     if(nb_param == 0)
    02324     {
    02325             res = Enumerate_NoParameters(P,C,CT,CEq,MAXRAYS,param_name);
    02326             if( P != Pi )
    02327                     Polyhedron_Free( P );
    02328             return( res );
    02329     }
    02330   }
    02331
    02332   if (!PP->nbV)
    02333     /* Leaks memory */
    02334     return NULL;
    02335
    02336   /* get memory for Values */
    02337   lcm = (Value *)malloc( nb_param * sizeof(Value));
    02338   m1  = (Value *)malloc( nb_param * sizeof(Value));
    02339   /* Initialize all the 'Value' variables */
    02340   for( np=0 ; np<nb_param ; np++ )
    02341   {
    02342     value_init(lcm[np]); value_init(m1[np]);
    02343   }
    02344   value_init(hdv);
    02345
    02346 #if EDEBUG2
    02347   Polyhedron_Print(stderr, P_VALUE_FMT, P);
    02348 #endif
    02349
    02350   Expanded = P;
    02351   Param_Polyhedron_Scale_Integer(PP, &Expanded, &expansion_det, MAXRAYS);
    02352
    02353 #if EDEBUG2
    02354   Polyhedron_Print(stderr, P_VALUE_FMT, Expanded);
    02355 #endif
    02356
    02357   if (P != Expanded)
    02358     Polyhedron_Free(P);
    02359   P = Expanded;
    02360
    02361   /* formerly : Scan the vertices and compute lcm
    02362      Scan_Vertices_Quick_Apx(PP,Q,CT,lcm,nb_param); */
    02363   /* now : lcm = 1 (by construction) */
    02364   /* OPT : A lot among what happens after this point can be simplified by
    02365      knowing that lcm[i] = 1 for now, we just conservatively fool the rest of
    02366      the function with lcm = 1 */
    02367   for (i=0; i< nb_param; i++) value_set_si(lcm[i], 1);
    02368
    02369   for(Q=PP->D;Q;Q=Q->next) {
    02370     if(CT) {
    02371       Polyhedron *Dt;
    02372       CQ = Q->Domain;
    02373       Dt = Polyhedron_Preimage(Q->Domain,CT,MAXRAYS);
    02374       rVD = DomainIntersection(Dt,CEq,MAXRAYS);
    02375
    02376       /* if rVD is empty or too small in geometric dimension */
    02377       if(!rVD || emptyQ(rVD) ||
    02378          (rVD->Dimension-rVD->NbEq < Dt->Dimension-Dt->NbEq-CEq->NbEq)) {
    02379         if(rVD)
    02380           Polyhedron_Free(rVD);
    02381         Polyhedron_Free(Dt);
    02382         continue;               /* empty validity domain */
    02383       }
    02384       Polyhedron_Free(Dt);
    02385     }
    02386     else
    02387       rVD = CQ = Q->Domain;
    02388     en = (Enumeration *)malloc(sizeof(Enumeration));
    02389     en->next = res;
    02390     res = en;
    02391     res->ValidityDomain = rVD;
    02392
    02393     if( param_name )
    02394       {
    02395         fprintf(stdout,"---------------------------------------\n");
    02396         fprintf(stdout,"Domain:\n");
    02397
    02398 #ifdef EPRINT_ALL_VALIDITY_CONSTRAINTS
    02399         Print_Domain(stdout,res->ValidityDomain,param_name);
    02400 #else
    02401         {
    02402           Polyhedron *VD;
    02403           VD = DomainSimplify(res->ValidityDomain,C,MAXRAYS);
    02404           Print_Domain(stdout,VD,param_name);
    02405           Domain_Free(VD);
    02406         }
    02407 #endif /* EPRINT_ALL_VALIDITY_CONSTRAINTS */
    02408       }
    02409
    02410     overflow_warning_flag = 1;
    02411
    02412 #ifdef EDEBUG2
    02413     fprintf(stderr,"Denominator = ");
    02414     for( np=0;np<nb_param;np++)
    02415       value_print(stderr,P_VALUE_FMT,lcm[np]);
    02416     fprintf(stderr," and hdim == %d \n",hdim);
    02417 #endif
    02418
    02419 #ifdef EDEBUG2
    02420     fprintf(stderr,"CQ = \n");
    02421     Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
    02422 #endif
    02423
    02424     /* Before scanning, add constraints to ensure at least hdim*lcm */
    02425     /* points in every dimension */
    02426     value_set_si(hdv,hdim-nb_param);
    02427
    02428     for( np=0;np<nb_param;np++)
    02429     {
    02430                 if( value_notzero_p(lcm[np]) )
    02431                         value_multiply(m1[np],hdv,lcm[np]);
    02432                 else
    02433                         value_set_si(m1[np],1);
    02434     }
    02435
    02436 #ifdef EDEBUG2
    02437     fprintf(stderr,"m1 == ");
    02438     for( np=0;np<nb_param;np++)
    02439       value_print(stderr,P_VALUE_FMT,m1[np]);
    02440     fprintf(stderr,"\n");
    02441 #endif
    02442
    02443     CATCH(overflow_error) {
    02444       fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
    02445       CQ2 = NULL;
    02446     }
    02447     TRY {
    02448       CQ2 = Polyhedron_Preprocess(CQ,m1,MAXRAYS);
    02449
    02450 #ifdef EDEBUG2
    02451       fprintf(stderr,"After preprocess, CQ2 = ");
    02452       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
    02453 #endif
    02454
    02455       UNCATCH(overflow_error);
    02456     }
    02457
    02458     /* Vin100, Feb 2001 */
    02459     /* in case of degenerate, try to find a domain _containing_ CQ */
    02460     if ((!CQ2 || emptyQ(CQ2)) && CQ->NbBid==0) {
    02461       int r;
    02462
    02463 #ifdef EDEBUG2
    02464       fprintf(stderr,"Trying to call Polyhedron_Preprocess2 : CQ = \n");
    02465       Polyhedron_Print(stderr,P_VALUE_FMT,CQ);
    02466 #endif
    02467
    02468       /* Check if CQ is bounded */
    02469       for(r=0;r<CQ->NbRays;r++) {
    02470         if(value_zero_p(CQ->Ray[r][0]) ||
    02471            value_zero_p(CQ->Ray[r][CQ->Dimension+1]))
    02472           break;
    02473       }
    02474       if(r==CQ->NbRays) {
    02475
    02476         /* ok, CQ is bounded */
    02477         /* now find if CQ is contained in a hypercube of size m1 */
    02478         CQ2 = Polyhedron_Preprocess2(CQ,m1,lcm,MAXRAYS);
    02479       }
    02480     }
    02481     if (!CQ2 || emptyQ(CQ2)) {
    02482 #ifdef EDEBUG2
    02483       fprintf(stderr,"Degenerate.\n");
    02484 #endif
    02485       fprintf(stdout,"Degenerate Domain. Can not continue.\n");
    02486       value_init(res->EP.d);
    02487       value_init(res->EP.x.n);
    02488       value_set_si(res->EP.d,1);
    02489       value_set_si(res->EP.x.n,-1);
    02490     }
    02491     else {
    02492
    02493 #ifdef EDEBUG2
    02494       fprintf(stderr,"CQ2 = \n");
    02495       Polyhedron_Print(stderr,P_VALUE_FMT,CQ2);
    02496       if( ! PolyhedronIncludes(CQ, CQ2) )
    02497         fprintf( stderr,"CQ does not include CQ2 !\n");
    02498       else
    02499         fprintf( stderr,"CQ includes CQ2.\n");
    02500       if( ! PolyhedronIncludes(res->ValidityDomain, CQ2) )
    02501         fprintf( stderr,"CQ2 is *not* included in validity domain !\n");
    02502       else
    02503         fprintf( stderr,"CQ2 is included in validity domain.\n");
    02504 #endif
    02505
    02506       /* L is used in counting the number of points in the base cases */
    02507       L = Polyhedron_Scan(P,CQ,MAXRAYS);
    02508       U = Universe_Polyhedron(0);
    02509
    02510       /* LQ is used to scan the parameter space */
    02511       LQ = Polyhedron_Scan(CQ2,U,MAXRAYS); /* bounds on parameters */
    02512       Domain_Free(U);
    02513       if(CT)    /* we did compute another Q->Domain */
    02514         Domain_Free(CQ);
    02515
    02516       /* Else, CQ was Q->Domain (used in res) */
    02517       Domain_Free(CQ2);
    02518
    02519 #ifdef EDEBUG2
    02520       fprintf(stderr,"L = \n");
    02521       Polyhedron_Print(stderr,P_VALUE_FMT,L);
    02522       fprintf(stderr,"LQ = \n");
    02523       Polyhedron_Print(stderr,P_VALUE_FMT,LQ);
    02524 #endif
    02525 #ifdef EDEBUG3
    02526       fprintf(stdout,"\nSystem of Equations:\n");
    02527 #endif
    02528
    02529       value_init(res->EP.d);
    02530       value_set_si(res->EP.d,0);
    02531
    02532       /* Create a context vector size dim+2 */
    02533       context = (Value *) malloc ((hdim+1)*sizeof(Value));
    02534       for(i=0;i<=(hdim);i++)
    02535         value_init(context[i]);
    02536       Vector_Set(context,0,(hdim+1));
    02537
    02538       /* Set context[hdim] = 1  (the constant) */
    02539       value_set_si(context[hdim],1);
    02540
    02541       CATCH(overflow_error) {
    02542         fprintf(stderr,"Enumerate: arithmetic overflow error.\n");
    02543         fprintf(stderr,"You should rebuild PolyLib using GNU-MP "
    02544                 "or increasing the size of integers.\n");
    02545         overflow_warning_flag = 0;
    02546         assert(overflow_warning_flag);
    02547
    02548       }
    02549       TRY {
    02550         res->EP.x.p = P_Enum(L,LQ,context,1,nb_param,dim,lcm, param_name);
    02551         UNCATCH(overflow_error);
    02552       }
    02553
    02554       for(i=0;i<=(hdim);i++)
    02555         value_clear(context[i]);
    02556       free(context);
    02557       Domain_Free(L);
    02558       Domain_Free(LQ);
    02559
    02560 #ifdef EDEBUG5
    02561       if( param_name )
    02562         {
    02563           fprintf(stdout,"\nEhrhart Polynomial (before simplification):\n");
    02564           print_evalue(stdout,&res->EP,param_name);
    02565         }
    02566
    02567       /* BM: divide EP by denom_det, the expansion factor */
    02568       fprintf(stdout,"\nEhrhart Polynomial (before division):\n");
    02569       print_evalue(stdout,&(res->EP),param_name);
    02570 #endif
    02571
    02572       evalue_div(&(res->EP), expansion_det);
    02573
    02574
    02575       /* Try to simplify the result */
    02576       reduce_evalue(&res->EP);
    02577
    02578       /* Put back the original parameters into result */
    02579       /* (equalities have been eliminated)            */
    02580       if(CT)
    02581           addeliminatedparams_evalue(&res->EP,CT);
    02582
    02583       if( param_name )
    02584         {
    02585           fprintf(stdout,"\nEhrhart Polynomial:\n");
    02586           print_evalue(stdout,&res->EP, param_name);
    02587           fprintf(stdout,"\n");
    02588           /* sometimes the final \n lacks (when a single constant is printed)
    02589           */
    02590         }
    02591
    02592     }
    02593   }
    02594   value_clear(expansion_det);
    02595
    02596   if( P != Pi )
    02597         Polyhedron_Free( P );
    02598   /* Clear all the 'Value' variables */
    02599   for( np=0; np<nb_param ; np++ )
    02600   {
    02601     value_clear(lcm[np]); value_clear(m1[np]);
    02602   }
    02603   value_clear(hdv);
    02604
    02605   return res;
    02606 } /* Ehrhart_Quick_Apx_Full_Dim */
    02607
    02608
    02609 /**
    02610  * Computes the approximation of the Ehrhart polynomial of a polyhedron
    02611  * (implicit form -> matrix), treating the non-full-dimensional case.
    02612  * @param M a polyhedron under implicit form
    02613  * @param C  M's context under implicit form
    02614  * @param Validity_Lattice a pointer to the parameter's validity lattice
    02615  * @param MAXRAYS the needed "working space" for other polylib functions used here
    02616  * @param param_name the names of the parameters,
    02617  */
    02618 Enumeration *Ehrhart_Quick_Apx(Matrix * M, Matrix * C,
    02619                                Matrix **Validity_Lattice, unsigned maxRays) {
    02620                                /* char ** param_name) {*/
    02621
    02622   /* 0- compute a full-dimensional polyhedron with the same number of points,
    02623      and its parameter's validity lattice */
    02624   Matrix * M_full;
    02625   Polyhedron * P, * PC;
    02626   Enumeration *en;
    02627
    02628   M_full = full_dimensionize(M, C->NbColumns-2, Validity_Lattice);
    02629   /* 1- apply the same tranformation to the context that what has been applied
    02630      to the parameters space of the polyhedron. */
    02631   mpolyhedron_compress_last_vars(C, *Validity_Lattice);
    02632   show_matrix(M_full);
    02633   P = Constraints2Polyhedron(M_full, maxRays);
    02634   PC = Constraints2Polyhedron(C, maxRays);
    02635   Matrix_Free(M_full);
    02636   /* compute the Ehrhart polynomial of the "equivalent" polyhedron */
    02637   en = Ehrhart_Quick_Apx_Full_Dim(P, PC, maxRays, NULL);
    02638
    02639   /* clean up */
    02640   Polyhedron_Free(P);
    02641   Polyhedron_Free(PC);
    02642   return en;
    02643 } /* Ehrhart_Quick_Apx */
    02644
    02645
    02646
    02647 /**
    02648  * Computes the approximation of the Ehrhart polynomial of a polyhedron (implicit
    02649  * form -> matrix), treating the non-full-dimensional case.  If there are some
    02650  * equalities involving only parameters, these are used to eliminate useless
    02651  * parameters.
    02652  * @param M a polyhedron under implicit form
    02653  * @param C  M's context under implicit form
    02654  * @param validityLattice a pointer to the parameter's validity lattice
    02655  * (returned)
    02656  * @param parmsEqualities Equalities involving only the parameters
    02657  * @param maxRays the needed "working space" for other polylib functions used here
    02658  * @param elimParams  array of the indices of the eliminated parameters (returned)
    02659  */
    02660 Enumeration *Constraints_EhrhartQuickApx(Matrix const * M, Matrix const * C,
    02661                                          Matrix ** validityLattice,
    02662                                          Matrix ** parmEqualities,
    02663                                          unsigned int ** elimParms,
    02664                                          unsigned maxRays) {
    02665   Enumeration *EP;
    02666   Matrix * Mp = Matrix_Copy(M);
    02667   Matrix * Cp = Matrix_Copy(C);
    02668   /* remove useless equalities involving only parameters, using these
    02669      equalities to remove parameters. */
    02670   (*parmEqualities) = Constraints_Remove_parm_eqs(&Mp, &Cp, 0, elimParms);
    02671   if (Mp->NbRows>=0) {/* if there is no contradiction */
    02672     EP = Ehrhart_Quick_Apx(Mp, Cp, validityLattice, maxRays);
    02673     return EP;
    02674   }
    02675   else {
    02676     /* if there are contradictions, return a zero Ehrhart polynomial */
    02677     return NULL;
    02678   }
    02679
    02680 }
    02681
    02682
    02683 /**
    02684  * Returns the array of parameter names after some of them have been eliminated.
    02685  * @param parmNames the initial names of the parameters
    02686  * @param elimParms a list of parameters that have been eliminated from the
    02687  * original parameters. The first element of this array is the number of
    02688  * elements.
    02689  * <p> Note: does not copy the parameters names themselves. </p>
    02690  * @param nbParms the initial number of parameters
    02691 */
    02692 const char **parmsWithoutElim(char const **parmNames,
    02693                               unsigned int const *elimParms,
    02694                               unsigned int nbParms)
    02695 {
    02696   int i=0, j=0,k;
    02697   int newParmNb = nbParms - elimParms[0];
    02698   const char **newParmNames = (const char **)malloc(newParmNb * sizeof(char *));
    02699   for (k=1; k<= elimParms[0]; k++) {
    02700     while (i!=elimParms[k]) {
    02701       newParmNames[i-k+1] = parmNames[i];
    02702       i++;
    02703     }
    02704   }
    02705   return newParmNames;
    02706 }
    02707
    02708
    02709 /**
    02710  * returns a constant Ehrhart polynomial whose value is zero for any value of
    02711  * the parameters.
    02712  * @param nbParms the number of parameters, i.e., the number of arguments to
    02713  * the Ehrhart polynomial
    02714  */
    02715 Enumeration * Enumeration_zero(unsigned int nbParms, unsigned int maxRays) {
    02716   Matrix * Mz = Matrix_Alloc(1, nbParms+3);
    02717   Polyhedron * emptyP;
    02718   Polyhedron * universe;
    02719   Enumeration * zero;
    02720   /* 1- build an empty polyhedron with the right dimension */
    02721   /* here we choose to take 2i = -1 */
    02722   value_set_si(Mz->p[0][1], 2);
    02723   value_set_si(Mz->p[0][nbParms+2], 1);
    02724   emptyP = Constraints2Polyhedron(Mz, maxRays);
    02725   Matrix_Free(Mz);
    02726   universe = Universe_Polyhedron(nbParms);
    02727   zero = Polyhedron_Enumerate(emptyP, universe, maxRays, NULL);
    02728   Polyhedron_Free(emptyP);
    02729   Polyhedron_Free(universe);
    02730   return zero;
    02731 } /* Enumeration_zero() */
    02732