polylib: ext_ehrhart.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# ext_ehrhart.c

Go to the documentation of this file.

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