polylib: ext_ehrhart.c Source File

- Main Page
- Classes
- Files

# ext_ehrhart.c

Go to the documentation of this file.

    00001
    00002 #include <stdlib.h>
    00003 #include <polylib/polylib.h>
    00004 #define WS 200
    00005
    00006 /* #define UE_DEBUG */
    00007
    00008
    00009 typedef struct _Polyhedron_union {
    00010         Enumeration *pt;
    00011         struct _Polyhedron_union *next;} Polyhedron_union;
    00012
    00013 static int ppcm1 (int a, int b);
    00014 Matrix *CalcBase( Matrix *R);
    00015
    00016
    00017 /**** ker.c ****/
    00018
    00019 static void Soustraire_ligne(Matrix *R, int l1, int l2, int piv );
    00020 static int existepivot( Matrix *R, int l );
    00021 static void swap_line(Matrix *R, int l1, int l2);
    00022
    00023
    00024 /* Caclule une base du noyau de l'application definie
    00025 par la matrice _carree_ R (completee par des 0..0) */
    00026
    00027 /* /!\ R est alteree par cette fonction. */
    00028
    00029 Matrix *CalcBase( Matrix *R )
    00030 {
    00031         Matrix *B/*,*BTran*/;   /* matrice des vect. de la base */
    00032         int i, j;
    00033         Value p;
    00034         int l;          /* ligne en cours de `pivotage' */
    00035         int lnn;
    00036         int dimbase;
    00037         int u;          /* vecteur util en cours de calcul */
    00038         Value  som;
    00039         int c;
    00040         /* diagonalisation de R : algo du pivot */
    00041         /* avec conservation des pivots nuls */
    00042         for( l=0 ; l<R->NbRows ; ++l )
    00043         {
    00044                 /* cherche le prochain pivot non nul */
    00045                 if( (lnn=existepivot(R,l)) != -1 )
    00046                 {
    00047                         swap_line( R, l, lnn );
    00048
    00049                         /* met la colonne dessous a 0 */
    00050                         for( j=l+1 ; j<R->NbRows ; ++j )
    00051                                 if(value_notzero_p( R->p[j][l]) )
    00052                                         Soustraire_ligne( R, l, j, l );
    00053
    00054                         /* et celle dessus aussi */
    00055                         for( j=0 ; j<l ; ++j )
    00056                                 if( value_notzero_p(R->p[j][l]) )
    00057                                         Soustraire_ligne( R, l, j, l );
    00058
    00059                 }
    00060                 /* s'ils sont tous nuls on passe au suivant */
    00061                 /* en laissant cette ligne inchangee. */
    00062         }
    00063
    00064         dimbase = 0;
    00065         for( l=0 ; l<R->NbRows ; ++l )
    00066                 if( value_zero_p(R->p[l][l]) )
    00067                         ++dimbase;     /* = nb de 0 dans la diagonale */
    00068
    00069         B = Matrix_Alloc( dimbase, R->NbRows );
    00070
    00071         l=0;
    00072         for( u=0 ; u<dimbase ; ++u )
    00073         {
    00074                 while(value_notzero_p( R->p[l][l]) )
    00075                         ++l;
    00076
    00077         /* calcul effectif de ce vecteur : chaque coord en commencant par le bas */
    00078                 for( i=R->NbRows-1 ; i>l ; --i )
    00079                         value_set_si(B->p[u][i], 0);
    00080                 value_set_si(B->p[u][l], 1);
    00081                 for( i=l-1 ; i>=0 ; --i )       /* i=chaque coord du vecteur */
    00082                 {
    00083                         if(value_zero_p( R->p[i][i]) )
    00084                           /* on a deux 0... un seul dans */
    00085                           /* ce vect util suffit */
    00086                                 value_set_si(B->p[u][i],0);
    00087                         else
    00088                         {
    00089                                 /* somme des coef deja calcules * coef dans la matrice */
    00090                                 value_set_si(som,0);
    00091                                 for( c=l ; c>i ; --c )
    00092                                 {
    00093                                   value_addmul(som, R->p[i][c], B->p[u][c]);
    00094                                   value_multiply(B->p[u][c] ,B->p[u][c] , R->p[i][i]);
    00095                                 }
    00096                                 value_oppose(B->p[u][i] , som );
    00097                         }
    00098                 }
    00099                 /* reste a faire le pgcd du vecteur et a l'orienter */
    00100                 value_set_si(p,0);
    00101                 for( i=0 ; i<R->NbRows ; ++i )
    00102                         value_gcd(p, p, B->p[u][i]);
    00103                 if( value_zero_p(p))
    00104                         value_set_si(p,1);
    00105                 for( i=0 ; i<R->NbRows && value_zero_p(B->p[u][i]); ++i )
    00106                         ;
    00107                 if( i<R->NbRows )
    00108                         if( value_neg_p(B->p[u][i]) )
    00109                       value_oppose( p,p );
    00110
    00111                 for( i=0 ; i<R->NbRows ; ++i )
    00112                         value_divexact(B->p[u][i], B->p[u][i], p);
    00113
    00114                 /* incrementer le compteur de lignes */
    00115                 ++l;
    00116         }
    00117         return B;
    00118 }
    00119
    00120
    00121 /* fonction qui calcule les vect generateurs de l'espace vectoriel
    00122    contenant le polyhedre P */
    00123 /*
    00124 Matrix *CalcPolyhedronBase( Polyhedron *P )
    00125 {
    00126   Matrix *R;
    00127   Matrix *B;
    00128   int n, lines;
    00129
    00130   if( emptyQ(P) )
    00131     return( Matrix_Alloc( 0, P->Dimension ) ); */ /* pas de vect. gen */ /*
    00132
    00133   R = Matrix_Alloc( P->Dimension, P->Dimension );
    00134
    00135   */ /* recopie le 'lineality space' du polyedre dans la matrice R */ /*
    00136   for( lines=0,n=0 ; n<P->NbConstraints ; ++n )
    00137     {
    00138       if( P->Constraint[n][0]==0 )
    00139         */ /* c'est une direction definissant un ss-espace */ /*
    00140         {
    00141           memcpy( &R->p[lines][0], &P->Constraint[n][1],
    00142                   sizeof(int)*P->Dimension );
    00143           ++lines;
    00144         }
    00145     }
    00146   */ /* remplit le reste de 0..0 */ /*
    00147   for( ; lines<R->NbRows ; ++lines )
    00148     memset( &R->p[lines][0], 0, sizeof(int)*P->Dimension );
    00149
    00150   B = CalcBase( R );
    00151   Matrix_Free( R );
    00152
    00153   return( B );
    00154 }*/
    00155
    00156
    00157 /* fonction qui calcule l'espace vectoriel non parametre de dimension dim
    00158         contenant le polyhedre parametre P */
    00159 /* les _egalites_ sont stockees par la polylib sous forme triangulaire
    00160 superieure donc il suffit de prendre les premieres. */
    00161
    00162 /*Matrix *CalcEVPolyhedronNP( Polyhedron *P, int dim )
    00163 {
    00164         Matrix *R;
    00165         Matrix *B;
    00166         int n, lines;
    00167
    00168         if( emptyQ(P) ) */ /* pas de vect. gen */ /*
    00169         {
    00170           B = Matrix_Alloc( 1, dim );   */ /* on ne peut pas allouer 0 lignes ! */ /*
    00171                 B->NbRows = 0;
    00172                 return( B );
    00173         }
    00174
    00175         R = Matrix_Alloc( dim, dim );
    00176
    00177 */ /* recopie le 'lineality space' du polyedre dans la matrice R */ /*
    00178         for( lines=0,n=0 ; n<P->NbConstraints && lines<dim ; ++n )
    00179         {
    00180                 if( P->Constraint[n][0]==0 )
    00181                   */ /* c'est une direction definissant un ss-espace */ /*
    00182                 {
    00183                         memcpy( &R->p[lines][0], &P->Constraint[n][1],
    00184                                         sizeof(int)*P->Dimension );
    00185                         ++lines;
    00186                 }
    00187         }
    00188 */ /* remplit le reste de 0..0 */ /*
    00189         for( ; lines<R->NbRows ; ++lines )
    00190                 memset( &R->p[lines][0], 0, sizeof(int)*dim );
    00191
    00192         B = CalcBase( R );
    00193         Matrix_Free( R );
    00194
    00195         return( B );
    00196 }*/
    00197
    00198
    00199 /* renvoie la ligne sur laquelle on a trouve un coef non nul */
    00200 /* pareil mais cherche dans toutes les lignes */
    00201 /* et -1 s'il n'y en a pas. */
    00202 static int existepivot( Matrix *R, int l )
    00203 {
    00204         int j, c;
    00205
    00206         for( j=l ; j<R->NbRows ; ++j )
    00207                 if(value_notzero_p( R->p[j][l]) )
    00208                         return( j );
    00209
    00210         /* on ne l'a pas trouve pour l'instant... on cherche au dessus */
    00211         /* les lignes ayant que des 0 jusqu'a la position l */
    00212         for( j=0 ; j<l ; ++j )
    00213         {
    00214                 for( c=0 ; c<l && value_zero_p(R->p[j][c]) ; c++ )
    00215                         ;
    00216                 if( c==l && value_notzero_p(R->p[j][l]) )
    00217                         return( j );
    00218         }
    00219
    00220         return( -1 );
    00221 }
    00222
    00223
    00224 /* echange les lignes l1 et l2 dans la matrice R */
    00225 static void swap_line(Matrix *R, int l1, int l2)
    00226 {
    00227         int i;
    00228         Value  tmp;
    00229
    00230         if( l1 != l2 )
    00231                 for(i = 0;i < R->NbColumns;i ++)
    00232                 {
    00233                         value_assign(tmp , R->p[l1][i]);
    00234                         value_assign(R->p[l1][i] , R->p[l2][i]);
    00235                         value_assign(R->p[l2][i] , tmp);
    00236                 }
    00237 }
    00238
    00239
    00240
    00241 int pgcd1( int a, int b)
    00242 {
    00243  int r;
    00244  if( a== 0 )
    00245  return( abs(b) );
    00246   if(b==0 )
    00247   return(abs(a) );
    00248   do
    00249   {
    00250     r= a % b;
    00251     a= b;
    00252    b = r;
    00253    }
    00254    while ( r!=0 );
    00255  return(abs(a));
    00256 }
    00257
    00258
    00259
    00260
    00261 /* Soustraire la ligne l1 de l2 */
    00262 /* On effectue l2 = (l1[piv]/pgcd)*l2 - l1 * (l2[piv]/pgcd) */
    00263 static void Soustraire_ligne(Matrix *R, int l1, int l2, int piv )
    00264 {
    00265         int i;
    00266         Value  a, b, p, t;
    00267         /* l2 = a*l2 - b*l1 */
    00268
    00269         if (value_zero_p(R->p[l2][piv] ))               /* c'est deja fait ! */
    00270                 return;
    00271
    00272         value_init(a);
    00273         value_init(b);
    00274         value_init(p);
    00275         value_init(t);
    00276
    00277         value_gcd(p, R->p[l1][piv], R->p[l2][piv]);
    00278         value_divexact(a, R->p[l1][piv], p);
    00279         value_divexact(b, R->p[l2][piv], p);
    00280
    00281         value_set_si(R->p[l2][piv] , 0);
    00282         value_set_si(p,0);
    00283         for(i = piv + 1;i < R->NbColumns;i ++)
    00284         {
    00285                 value_multiply(t,b,R->p[l1][i]);
    00286                 value_multiply(R->p[l2][i],a,R->p[l2][i]);
    00287                 value_subtract(R->p[l2][i],R->p[l2][i],t);
    00288                 value_gcd(p, p, R->p[l2][i]);
    00289         }
    00290         /* Simplification par le pgcd de toute la ligne */
    00291         for( i=piv+1 ; i<R->NbColumns && p!=0 ; i++ )
    00292                 value_divexact(R->p[l2][i], R->p[l2][i], p);
    00293
    00294         value_clear(a);
    00295         value_clear(b);
    00296         value_clear(p);
    00297         value_clear(t);
    00298 }
    00299
    00300
    00301 /*** ext_ehrhart.c ****/
    00302
    00303
    00304 void new_eadd(evalue *e1,evalue *res) {
    00305 int i, p, x, y;
    00306
    00307 evalue *ne;
    00308 Value g,m1,m2;
    00309
    00310   value_init(g);
    00311   value_init(m1);
    00312   value_init(m2);
    00313     if (value_notzero_p(e1->d) && value_notzero_p(res->d)) {
    00314          /* Add two rational numbers*/
    00315          value_multiply(m1,e1->x.n,res->d);
    00316          value_multiply(m2,res->x.n,e1->d);
    00317          value_addto(res->x.n,m1,m2);
    00318          value_multiply(res->d,e1->d,res->d);
    00319          value_gcd(g, res->x.n,res->d);
    00320          if (value_notone_p(g)) {
    00321               value_divexact(res->d, res->d, g);
    00322               value_divexact(res->x.n, res->x.n, g);
    00323          }
    00324          value_clear(g); value_clear(m1); value_clear(m2);
    00325          return ;
    00326      }
    00327      else if (value_notzero_p(e1->d) && value_zero_p(res->d)) {
    00328               if (res->x.p->type==polynomial) {
    00329                   /* Add the constant to the constant term of a polynomial*/
    00330                    new_eadd(e1, &res->x.p->arr[0]);
    00331                    value_clear(g); value_clear(m1); value_clear(m2);
    00332                    return ;
    00333               }
    00334               else if (res->x.p->type==periodic) {
    00335                           /* Add the constant to all elements of a periodic number */
    00336                           for (i=0; i<res->x.p->size; i++) {
    00337                               new_eadd(e1, &res->x.p->arr[i]);
    00338                           }
    00339                           value_clear(g); value_clear(m1); value_clear(m2);
    00340
    00341                           return ;
    00342                     }
    00343                     else {
    00344                             fprintf(stderr, "eadd: cannot add const with vector\n");
    00345                             value_clear(g); value_clear(m1); value_clear(m2);
    00346
    00347                             return;
    00348                     }
    00349      }
    00350     /* ######### add polynomial or periodic to constant #############
    00351        you have to exchange e1 and res, before doing addition */
    00352
    00353      else if (value_zero_p(e1->d) && value_notzero_p(res->d)) {
    00354               enode *tmp;
    00355               evalue x;
    00356               x=*res;
    00357               tmp= ecopy(e1->x.p);
    00358               value_init(res->d);
    00359               value_set_si( res->d, 0 );
    00360               res->x.p=tmp;
    00361
    00362               new_eadd(&x,res);
    00363               value_clear(g); value_clear(m1); value_clear(m2);
    00364               return ;
    00365      }
    00366     else {   /* ((e1->d==0) && (res->d==0)) */
    00367                  if ((e1->x.p->type != res->x.p->type) ) {
    00368                    /* ##### adding to evalues of different type. two cases are possible  ####
    00369
    00370                    #### res is periodic and e1 is polynomial, you have to exchange
    00371                    e1 and res then to add e1 to the constant term of res  #### */
    00372                      if ((res->x.p->type == periodic)&&(e1->x.p->type == polynomial)) {
    00373
    00374                           evalue eval;
    00375                           value_set_si( eval.d, 0 );
    00376                           eval.x.p=ecopy(res->x.p);
    00377                           res->x.p= ecopy(e1->x.p);
    00378                           new_eadd(&eval,&res->x.p->arr[0]);
    00379
    00380                      }
    00381                      else if ((res->x.p->type == polynomial)&&(e1->x.p->type == periodic)) {
    00382                        /* #### res is polynomial and e1 is periodic,
    00383                           add e1 to the constant term of res  #### */
    00384
    00385                           new_eadd(e1,&res->x.p->arr[0]);
    00386                      }
    00387
    00388                      value_clear(g); value_clear(m1); value_clear(m2);
    00389                      return;
    00390                  }
    00391                  else if (e1->x.p->pos  != res->x.p->pos ) {
    00392                    /* ### adding evalues of different position (i.e function of different unknowns
    00393                       to case are possible  ### */
    00394
    00395                          if (res->x.p->type == polynomial) {/*  ### res and e1 are polynomials
    00396                                                                 add e1 to the constant term of res */
    00397
    00398                                new_eadd(e1,&res->x.p->arr[0]);
    00399                                value_clear(g); value_clear(m1); value_clear(m2);
    00400                                return;
    00401                           }
    00402                           else {  /* ### res and e1 are pointers to periodic numbers
    00403                                      add e1 to all elements of res */
    00404
    00405                                   for (i=0;i<res->x.p->size;i++) {
    00406                                        new_eadd(e1,&res->x.p->arr[i]);
    00407                                   }
    00408                                   value_clear(g); value_clear(m1); value_clear(m2);
    00409                                   return;
    00410                           }
    00411
    00412
    00413                  }  /* ### */
    00414
    00415
    00416                  /* same type , same pos  and same size */
    00417                  if (e1->x.p->size == res->x.p->size) {
    00418                    /* add any element in e1 to the corresponding element in res */
    00419                       for (i=0; i<res->x.p->size; i++) {
    00420                             new_eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
    00421                       }
    00422                       value_clear(g); value_clear(m1); value_clear(m2);
    00423                       return ;
    00424                 }
    00425
    00426                 /* Sizes are different */
    00427                 if (res->x.p->type==polynomial) {
    00428                     /* VIN100: if e1-size > res-size you have to copy e1 in a   */
    00429                     /* new enode and add res to that new node. If you do not do */
    00430                     /* that, you lose the the upper weight part of e1 !         */
    00431
    00432                      if(e1->x.p->size > res->x.p->size) {
    00433                           enode *tmp;
    00434                           tmp = ecopy(e1->x.p);
    00435                           for(i=0;i<res->x.p->size;++i) {
    00436                               new_eadd(&res->x.p->arr[i], &tmp->arr[i]);
    00437                               /*  free_evalue_refs(&res->x.p->arr[i]); */
    00438                           }
    00439                           res->x.p = tmp;
    00440
    00441                      }
    00442                      else {
    00443
    00444                         for (i=0; i<e1->x.p->size ; i++) {
    00445                              new_eadd(&e1->x.p->arr[i], &res->x.p->arr[i]);
    00446                         }
    00447                         value_clear(g); value_clear(m1); value_clear(m2);
    00448
    00449                         return ;
    00450                      }
    00451                 }
    00452
    00453                 /* ### add two periodics of the same pos (unknown) but whith different sizes (periods) ### */
    00454                 else if (res->x.p->type==periodic) {
    00455                       /* you have to create a new evalue 'ne' in whitch size equals to the scm
    00456                        of the sizes of e1 and res, then to copy res periodicaly in ne, after
    00457                        to add periodicaly elements of e1 to elements of ne, and finaly to
    00458                        return ne. */
    00459
    00460                        x=e1->x.p->size;
    00461                        y= res->x.p->size;
    00462                        p=ppcm1(x,y);
    00463                        ne= (evalue *) malloc (sizeof(evalue));
    00464                        value_init(ne->d);
    00465                        value_set_si( ne->d,0);
    00466
    00467                        ne->x.p=new_enode(res->x.p->type,p, res->x.p->pos);
    00468                        for(i=0;i<p;i++)  {
    00469                               value_assign(ne->x.p->arr[i].d, res->x.p->arr[i%y].d);
    00470                               if (value_notzero_p(ne->x.p->arr[i].d))   {
    00471                             value_init(ne->x.p->arr[i].x.n);
    00472                             value_assign(ne->x.p->arr[i].x.n, res->x.p->arr[i%y].x.n);
    00473                               }
    00474                               else {
    00475                                   ne->x.p->arr[i].x.p =ecopy(res->x.p->arr[i%y].x.p);
    00476                               }
    00477                        }
    00478                        for(i=0;i<p;i++)  {
    00479                             new_eadd(&e1->x.p->arr[i%x], &ne->x.p->arr[i]);
    00480                        }
    00481
    00482                        res=ne;
    00483
    00484                         value_clear(g); value_clear(m1); value_clear(m2);
    00485                         return ;
    00486                 }
    00487                 else { /* evector */
    00488                      fprintf(stderr, "eadd: ?cannot add vectors of different length\n");
    00489                      value_clear(g); value_clear(m1); value_clear(m2);
    00490                      return ;
    00491                 }
    00492      }
    00493      value_clear(g); value_clear(m1); value_clear(m2);
    00494      return ;
    00495  } /* new_eadd */
    00496
    00497 /* remove the last row and the last column of a matrix Mat */
    00498 Matrix *Reduce_Matrix (Matrix *Mat) {
    00499            int i;
    00500            Value *p;
    00501            p=*(Mat->p+(Mat->NbRows-1));
    00502            for (i=0;i<Mat->NbColumns; i++)  {
    00503                    value_clear(*p++);
    00504            }
    00505            for (i=0; i<Mat->NbRows-1; i++)  {
    00506                    p=*(Mat->p+i);
    00507                    value_clear(*(p+(Mat->NbColumns-1)));
    00508            }
    00509            Mat->NbRows--;
    00510            Mat->NbColumns--;
    00511            return Mat;
    00512    } /* Reduce_Matrix */
    00513
    00514
    00515   /* Computes the scalar product (in euclidien space) of two vectors */
    00516
    00517 void Scalar_product(Value *p1,Value *p2,unsigned length, Value *r) {
    00518         Value *cp1, *cp2;
    00519
    00520         int i;
    00521           cp1=p1;
    00522           cp2=p2;
    00523           value_set_si(*r,0);
    00524                for (i=0;i<length;i++) {
    00525                  value_addmul(*r, *cp1, *cp2);
    00526                   cp1++; cp2++;
    00527                }
    00528   } /* Scalar_product */
    00529
    00530     /* computes the scm of two integrals  */
    00531
    00532       int ppcm1 (int a, int b) {
    00533            int t;
    00534            t = (a*b)/ pgcd1(a,b);
    00535           return t;
    00536        } /* ppcm1 */
    00537
    00538
    00539 Matrix *Orthogonal_Base(Matrix *Mat)  {
    00540   Matrix *OrthMat;
    00541   Value a,b,c,d;
    00542   Vector *q,*p,*f;
    00543   unsigned length;
    00544   int i,j,k;
    00545   value_init(a);
    00546   value_init(b);
    00547   value_init(c);
    00548   value_init(d);
    00549   OrthMat= Matrix_Alloc(Mat->NbRows,Mat->NbColumns);
    00550   length=Mat->NbColumns;
    00551   for(k=0; k<length; k++)  {
    00552     value_assign(OrthMat->p[0][k],Mat->p[0][k]);
    00553   }
    00554   f=Vector_Alloc(length);
    00555   p=Vector_Alloc(length);
    00556   q=Vector_Alloc(length);
    00557   for(i=1; i<Mat->NbRows; i++)  {
    00558     for(k=0;k<length;k++)  {
    00559       value_assign(f->p[k],Mat->p[i][k]);
    00560       value_assign(q->p[k],Mat->p[i][k]);
    00561     }
    00562     value_set_si(d,1);
    00563     for(j=0; j<i; j++) {
    00564       for(k=0;k<length;k++)  {
    00565         value_assign(p->p[k],OrthMat->p[j][k]);
    00566       }
    00567
    00568       Scalar_product(p->p,f->p,length,&a);
    00569       Scalar_product(p->p,p->p,length,&b);
    00570       value_gcd(c, a, b);
    00571       value_divexact(a, a, c);
    00572       value_divexact(b, b, c);
    00573       for(k=0;k<length;k++) {
    00574         value_multiply(p->p[k],p->p[k],a);
    00575       }
    00576
    00577       if(value_notone_p(d)|value_notone_p(b))  {
    00578         value_lcm(c, d, b);
    00579         value_divexact(a, c, b);
    00580         value_divexact(b, c, d);
    00581         value_assign(d,c);
    00582         for(k=0;k<length;k++) {
    00583           value_multiply(p->p[k],p->p[k],a);
    00584           value_multiply(q->p[k],q->p[k],b);
    00585         }
    00586
    00587       }
    00588
    00589       for(k=0;k<length;k++) {
    00590         value_subtract(q->p[k],q->p[k],p->p[k]);
    00591       }
    00592
    00593     }
    00594     Vector_Gcd(q->p,length,&c);
    00595     Vector_AntiScale(q->p, OrthMat->p[i], c, length);
    00596   }
    00597   value_clear(a);
    00598   value_clear(b);
    00599   value_clear(c);
    00600   value_clear(d);
    00601   return OrthMat;
    00602 }  /* Orthogonal_Base  */
    00603
    00604
    00605 /* Remove an element of a list */
    00606 void  Remove_Element(Enumeration *en,Enumeration **re, Enumeration *prev)  {
    00607   if (en== *re)  {
    00608     *re= (*re)->next;
    00609   }
    00610   else {
    00611     prev->next=en->next;
    00612   }
    00613 } /* Remove_Element */
    00614
    00615  /* Remove validite domains and correspending ehrhart polynomials whitch are redundant after
    00616   the enumeration of a polyhedron */
    00617
    00618  void Remove_RedundantDomains (Enumeration  **Ures)  {
    00619         Enumeration *ren1, *ren2, *previous=NULL;
    00620         int red;
    00621         for (ren1=*Ures; ren1; ren1=ren1->next)  {
    00622                 red=0;
    00623                 for (ren2=*Ures; ren2; ren2=ren2->next)  {
    00624                         if (ren1!=ren2)  {
    00625
    00626                             if (PolyhedronIncludes(ren2->ValidityDomain, ren1->ValidityDomain)) {
    00627                                         red= 1;
    00628                                         break;
    00629
    00630                                 }
    00631
    00632                         }
    00633                 }
    00634                 if (red)  {
    00635                         Remove_Element(ren1,Ures,previous);
    00636                 }
    00637                 previous=ren1;
    00638         }
    00639  }/*Remove_RedendentDomains */
    00640
    00641
    00642 int IncludeInRes (Polyhedron *p, Enumeration *e, unsigned MR) {
    00643         Enumeration *en;
    00644            for (en=e; en; en=en->next)  {
    00645
    00646                 if (PolyhedronIncludes(e->ValidityDomain,p))
    00647                          return 1;
    00648            }
    00649         return 0;
    00650 }
    00651
    00652 Polyhedron *DMUnion(Enumeration *en, unsigned MR)  {
    00653         Enumeration *e1;
    00654         Polyhedron *d;
    00655         e1=en;
    00656         d=e1->ValidityDomain;
    00657          for (e1=en->next; e1; e1=e1->next) {
    00658            d= DomainUnion( d, e1->ValidityDomain, MR);
    00659          }
    00660          return d;
    00661   }
    00662
    00663
    00664 void AffConstraints(Polyhedron *Poldisj)
    00665 {
    00666         Polyhedron *p;
    00667
    00668         for(p=Poldisj;p;p=p->next)
    00669         {
    00670                 Polyhedron_PrintConstraints( stdout, P_VALUE_FMT, p);
    00671                 printf("\n");
    00672         }
    00673 }
    00674 int Degenerate (Enumeration *en) {
    00675         if(value_notzero_p(en->EP.d)) {
    00676
    00677            if(value_mone_p(en->EP.x.n )) {
    00678                return 1;
    00679            }
    00680         }
    00681    return 0;
    00682 }
    00683
    00684 /* Enumeration of a domain D */
    00685
    00686 Enumeration *Domain_Enumerate(Polyhedron *D, Polyhedron *C, unsigned MAXRAYS,
    00687                                 const char **pn)
    00688 {     Polyhedron_union *Polun,*pu;
    00689       Polyhedron  *lp, *lp1, *lp1next;
    00690       Polyhedron *d1,*d2,*d;
    00691       Enumeration *e,*pr,*en,*en1, *en2,*tmp, *res, *sen;
    00692       Polun=NULL;
    00693
    00694       for (d = D; d; d = d->next) {
    00695           POL_ENSURE_FACETS(d);
    00696           POL_ENSURE_VERTICES(d);
    00697       }
    00698       POL_ENSURE_FACETS(C);
    00699       POL_ENSURE_VERTICES(C);
    00700
    00701      lp = Disjoint_Domain( D, 0, MAXRAYS );
    00702
    00703 #ifdef UE_DEBUG
    00704      printf("##############################################################\n");
    00705      printf("\n###### DISJOINT UNION  ######\n\n");
    00706      AffConstraints(lp);
    00707      printf("##############################################################\n");
    00708 #endif
    00709
    00710         for (lp1=lp ; lp1; lp1=lp1->next)
    00711         {
    00712                 Enumeration *enext;
    00713                 lp1next = lp1->next;
    00714                 lp1->next = NULL;
    00715                 en= Polyhedron_Enumerate(lp1, C, MAXRAYS,NULL);
    00716                 lp1->next = lp1next;
    00717                 sen= NULL;
    00718                 for (e=en;e;e=enext) {
    00719                         enext = e->next;
    00720                         if (!Degenerate(e)) {
    00721                                 e->next = sen;
    00722                                 sen=e;
    00723                         } else {
    00724                                 free_evalue_refs(&e->EP);
    00725                                 Domain_Free(e->ValidityDomain);
    00726                                 free(e);
    00727                         }
    00728                 }
    00729
    00730                 if(sen!= NULL)
    00731                 {
    00732                         pu = (Polyhedron_union  *)malloc(sizeof(Polyhedron_union));
    00733                         pu->pt=sen;
    00734                         pu->next = Polun;
    00735                         Polun = pu;
    00736                 }
    00737         }
    00738         if(!Polun)
    00739         {
    00740 #ifdef UE_DEBUG
    00741                 fprintf(stdout,"Empty Polun\n");
    00742 #endif
    00743                 return ((Enumeration *) 0);
    00744         }
    00745
    00746         while(Polun->next != NULL)  {
    00747                 Enumeration *enext;
    00748                 res=NULL;
    00749                 en1=Polun->pt;
    00750                 en2=(Polun->next)->pt;
    00751
    00752                 d1=DMUnion(en1, MAXRAYS);
    00753                 d2=DMUnion(en2, MAXRAYS);
    00754
    00755                 for (en1=Polun->pt;en1;en1=enext) {
    00756                         enext = en1->next;
    00757                         for(en2=(Polun->next)->pt;en2;en2=en2->next)
    00758                         {
    00759                                 d = DomainIntersection(en1->ValidityDomain,en2->ValidityDomain,MAXRAYS);
    00760                                 if( d && !emptyQ(d)&&!IncludeInRes(d,res,MAXRAYS))  {
    00761                                         tmp = (Enumeration  *)malloc(sizeof(Enumeration));
    00762                                         value_init(tmp->EP.d);
    00763                                         value_assign( tmp->EP.d, en2->EP.d );
    00764                                         if(value_zero_p(tmp->EP.d))
    00765                                                 tmp->EP.x.p=ecopy(en2->EP.x.p);
    00766                                         else
    00767                                         {
    00768                                                 value_init(tmp->EP.x.n);
    00769                                                 value_assign( tmp->EP.x.n, en2->EP.x.n );
    00770                                         }
    00771
    00772                                         new_eadd(&en1->EP,&tmp->EP);
    00773                                         tmp->ValidityDomain =d;
    00774                                         tmp->next= res;
    00775                                         res=tmp;
    00776                                 }
    00777                         }
    00778                         d=DomainDifference(en1->ValidityDomain,d2 ,MAXRAYS);
    00779                         if (d && !emptyQ(d) && !IncludeInRes(d,res,MAXRAYS)) {
    00780                                 en1->ValidityDomain = d;
    00781                                 en1->next= res;
    00782                                 res=en1;
    00783                         } else {
    00784                                 free_evalue_refs(&en1->EP);
    00785                                 free(en1);
    00786                         }
    00787                 }
    00788                 for (en2=(Polun->next)->pt; en2; en2 = enext) {
    00789                         enext = en2->next;
    00790                         d= DomainDifference(en2->ValidityDomain,d1,MAXRAYS);
    00791                         if (d && !emptyQ(d)&&!IncludeInRes(d,res,MAXRAYS)) {
    00792                                 en2->ValidityDomain = d;
    00793                                 en2->next = res;
    00794                                 res = en2;
    00795                         } else {
    00796                                 free_evalue_refs(&en2->EP);
    00797                                 free(en2);
    00798                         }
    00799                 }
    00800                 Domain_Free(d1);
    00801                 Domain_Free(d2);
    00802
    00803                 Polun->pt=res;
    00804
    00805                 Polun->next= (Polun->next)->next;
    00806         }
    00807         res=Polun->pt;
    00808
    00809         Remove_RedundantDomains(&res);
    00810         return(res);
    00811 }
    00812
    00813
    00814 /**********
    00815  DO NOT USE THE FOLLOWING FUNCTION IT'S NOT WORKING PROPERLY YET.
    00816  **********/
    00817
    00818 /* Enumeration of the image by T of domain D */
    00819 Enumeration *Polyhedron_Image_Enumerate(Polyhedron *D,  Polyhedron *C, Matrix *T, unsigned MAXRAYS, const char **par_name)
    00820 {   Polyhedron *polun,*pol;
    00821     Enumeration *ee;
    00822     Matrix *TCopy,*Tred, *d1,*d;
    00823     Vector *v1,*v2;
    00824     Value h;
    00825     int i,j,k;
    00826
    00827   POL_ENSURE_FACETS(D);
    00828   POL_ENSURE_VERTICES(D);
    00829   POL_ENSURE_FACETS(C);
    00830   POL_ENSURE_VERTICES(C);
    00831
    00832    value_init(h);
    00833     if(!D) {
    00834          fprintf(stdout,"             Error: in reading input domain \n");
    00835          value_clear(h);
    00836            return ((Enumeration *) 0);
    00837     }
    00838     else {
    00839       printf("\n ################   INPUT  POLYHEDRON  #######################\n\n");
    00840       AffConstraints(D);
    00841      }
    00842
    00843 #ifdef DOMAIN_IMAGE
    00844        fpol=DomainImage(D,T,MAXRAYS);
    00845        printf("\n $$$$$$$$$$$$$  THE  DOMAIN IMAGE    $$$$$$$$$$$$$\n\n");
    00846          AffConstraints(fpol);
    00847           if(emptyQ(fpol)) {
    00848                   value_clear(h);
    00849                   return ((Enumeration *) 0);
    00850           }
    00851           ee = Domain_Enumerate(fpol,C,MAXRAYS,par_name);
    00852           value_clear(h);
    00853        return  (ee);
    00854 #endif
    00855
    00856      TCopy= Matrix_Copy(T);
    00857      Tred= Reduce_Matrix(TCopy);
    00858      printf("\n ##################  INPUT REDUCED TRANSFORMATION MATRIX ##################\n" );
    00859      Matrix_Print(stdout,P_VALUE_FMT,Tred);
    00860
    00861          if (Tred->NbRows <Tred->NbColumns) {
    00862                d1=(Matrix *) Matrix_Alloc(Tred->NbColumns,Tred->NbColumns);
    00863                for (i=0;i<Tred->NbRows;i++) {
    00864                     for (j=0; j<Tred->NbColumns;j++) {
    00865                                 value_assign( d1->p[i][j], Tred->p[i][j] );
    00866                     }
    00867                }
    00868                for(i=Tred->NbRows;i<Tred->NbColumns;i++) {
    00869                      for (j=0;j<Tred->NbColumns;j++) {
    00870                           value_set_si( d1->p[i][j], 0 );
    00871                      }
    00872                }
    00873                d= (Matrix *) CalcBase(d1);
    00874                Matrix_Free(Tred);
    00875                Matrix_Free(d1);
    00876
    00877          }
    00878          else {
    00879               d=(Matrix *) CalcBase(Tred);
    00880               Matrix_Free(Tred);
    00881          }
    00882     if(d->NbRows==0) {
    00883         if(emptyQ(D)) {
    00884                 value_clear(h);
    00885                 return ((Enumeration *) 0);
    00886         }
    00887         else {
    00888            printf( "        Ker(A)=0  implys directly Enumeration on input polyhedron\n\n");
    00889            ee=Domain_Enumerate(D,C,MAXRAYS,par_name);
    00890            value_clear(h);
    00891            return ee;
    00892         }
    00893    }
    00894
    00895    d1=Transpose(d);
    00896    Matrix_Free(d);
    00897
    00898    if(d1->NbRows!=D->Dimension) {
    00899       fprintf(stdout,"      \n Error: incompatible dimension \n");
    00900       value_clear(h);
    00901       return ((Enumeration *) 0);
    00902    }
    00903    if(d1->NbColumns > 1) {
    00904  fprintf(stdout,"   \n Error: Can not compute intégral points : More then vector in ker(A)! \n");
    00905     value_clear(h);
    00906     return ((Enumeration *) 0);
    00907
    00908     }
    00909    printf( "           \n Ker(A)=1  implys adding constraints befor Enumeration\n");
    00910    v1=Vector_Alloc(d1->NbRows);
    00911    v2=Vector_Alloc(d1->NbRows);
    00912
    00913           polun=(Polyhedron *) NULL;
    00914             for (k=0;k<d1->NbRows;k++) {
    00915                   value_assign(v1->p[k],d1->p[k][0]) ;
    00916             }
    00917           /* adding a new constraint for all constraints of D in which the scalar product of the*/
    00918           /* normal whith vector v1 is greter then zero*/
    00919
    00920           for (j=0;j<D->NbConstraints;j++)  {
    00921                  for (k=0;k<=D->Dimension-1;k++) {
    00922                         value_assign(v2->p[k],D->Constraint[j][k+1]) ;
    00923                   }
    00924                   Scalar_product(v1->p,v2->p,D->Dimension,&h);
    00925
    00926                   if(value_pos_p(h)&&!value_zero_p(D->Constraint[j][0])) {
    00927                        Vector *NCont;
    00928                        Value val;
    00929                        value_init( val );
    00930                        /* Create a new contraint whitch is added to the polyhedron*/
    00931
    00932                        NCont=Vector_Alloc(d1->NbRows+2);
    00933                        value_set_si( NCont->p[0],1); /* the constraint is an inequality */
    00934
    00935                        for (k=1;k<=D->Dimension;k++) {
    00936                             value_oppose( NCont->p[k], D->Constraint[j][k]);
    00937                                         }
    00938                        value_decrement(val,h);
    00939                        value_subtract(val,val,D->Constraint[j][D->Dimension+1]);
    00940                        value_assign (NCont->p[D->Dimension+1],val);
    00941                        value_clear(val);
    00942                        /* add the new constraint to polyhedron D */
    00943                        pol=AddConstraints(NCont->p,1,D,MAXRAYS);
    00944                        POL_ENSURE_VERTICES(pol);
    00945                        polun=AddPolyToDomain(Polyhedron_Copy(pol),polun);
    00946                        Polyhedron_Free(pol);
    00947                        Vector_Free(NCont);
    00948                                  value_clear( val );
    00949                     }
    00950            }
    00951           if(polun==NULL) { /*  No constraint is added to input polyhedron */
    00952               if(emptyQ(D)) {
    00953                       value_clear(h);
    00954                       return ((Enumeration *) 0);
    00955               }
    00956               else {
    00957                  ee= Domain_Enumerate(D,C,MAXRAYS,par_name);
    00958               }
    00959           }
    00960           else { /* some constraintes are added to input polyhedron */
    00961               if(emptyQ(polun)){
    00962                       value_clear(h);
    00963                       return ((Enumeration *) 0);
    00964               }
    00965               else {
    00966         printf("\n ##################################################################");
    00967         printf("\n ****** THE RESULT OF ADDING CONSTRAINTS TO THE INPUT POLYHEDRON  ****** \n");
    00968                AffConstraints(polun);
    00969                ee= Domain_Enumerate(polun,C,MAXRAYS,par_name);
    00970                value_clear(h);
    00971                return (ee );
    00972               }
    00973       }
    00974
    00975
    00976         return( NULL );
    00977 }
    00978
    00979