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

Lattice.c

Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <polylib/polylib.h>
00003 
00004 
00005 typedef struct {
00006   int count;
00007   int *fac;
00008 } factor;
00009 
00010 static factor allfactors (int num);
00011 
00012 /* 
00013  * Print the contents of a list of Lattices 'Head'  
00014  */
00015 void PrintLatticeUnion(FILE *fp, char *format, LatticeUnion *Head) {
00016   
00017   LatticeUnion *temp;
00018 
00019   for(temp = Head; temp != NULL; temp = temp->next)
00020     Matrix_Print(fp,format,(Matrix *)temp->M);
00021   return;
00022 } /* PrintLatticeUnion */
00023 
00024 /* 
00025  * Free the memory allocated to a list of lattices 'Head' 
00026  */
00027 void LatticeUnion_Free(LatticeUnion *Head) {
00028 
00029   LatticeUnion  *temp;
00030 
00031   while (Head != NULL) {
00032     temp = Head;
00033     Head = temp->next;
00034     Matrix_Free(temp->M);
00035     free(temp);
00036   }
00037   return;
00038 } /* LatticeUnion_Free */
00039 
00040 /* 
00041  * Allocate a heads for a list of Lattices
00042  */
00043 LatticeUnion *LatticeUnion_Alloc(void) {
00044 
00045   LatticeUnion  *temp;
00046 
00047   temp = (LatticeUnion *)malloc(sizeof(LatticeUnion));
00048   temp->M=NULL;
00049   temp->next=NULL;
00050   return temp;
00051 } /* LatticeUnion_Alloc */
00052 
00053 /*
00054  * Given two Lattices 'A' and 'B', return True if they have the same affine 
00055  * part (the last column) otherwise return 'False'. 
00056  */
00057 Bool sameAffinepart (Lattice *A, Lattice *B) {
00058   
00059   int i;
00060 
00061 #ifdef DOMDEBUG
00062   FILE *fp;
00063   fp = fopen("_debug","a");
00064   fprintf(fp,"\nEntered SAMEAFFINEPART \n"); 
00065   fclose(fp);
00066 #endif
00067   
00068   for (i = 0; i < A->NbRows; i ++)
00069     if (value_ne(A->p[i][A->NbColumns-1],B->p[i][B->NbColumns-1]))
00070       return False;
00071   return True;
00072 } /* sameAffinepart */ 
00073 
00074 /*
00075  * Return an empty lattice of dimension 'dimension-1'. An empty lattice is 
00076  * represented as [[0 0 ... 0] .... [0 ... 0][0 0.....0 1]]. 
00077  */ 
00078 Lattice *EmptyLattice(int dimension) {
00079 
00080   Lattice *result;
00081   int i,j;
00082   
00083 #ifdef DOMDEBUG
00084   FILE *fp;
00085   fp = fopen ("_debug", "a");
00086   fprintf (fp, "\nEntered NULLATTICE \n"); 
00087   fclose (fp);
00088 #endif
00089   
00090   result = (Lattice *) Matrix_Alloc(dimension, dimension);
00091   for (i = 0; i < dimension; i ++)
00092     for (j = 0; j < dimension; j ++)
00093       value_set_si(result->p[i][j],0);
00094   value_set_si(result->p[i-1][i-1],1);
00095   return result;
00096 } /* EmptyLattice */ 
00097 
00098 /*
00099  * Return True if Lattice 'A' is empty, otherwise return False. 
00100  */
00101 Bool isEmptyLattice (Lattice *A) {
00102   
00103   int i,j;  
00104   
00105 #ifdef DOMDEBUG
00106   FILE *fp;
00107   fp = fopen("_debug", "a");
00108   fprintf(fp,"\nEntered ISNULLATTICE \n"); 
00109   fclose(fp);
00110 #endif
00111   
00112   for (i = 0; i < A->NbRows-1; i ++)
00113     for (j = 0; j < A->NbColumns-1; j ++)
00114       if(value_notzero_p(A->p[i][j])) {
00115         return False;
00116       }
00117   if (value_one_p(A->p[i][A->NbColumns-1])) {
00118     return True ;
00119   }
00120   return False ;
00121 } /* isEmptyLaattice */ 
00122 
00123 /*
00124  * Given a Lattice 'A', check whether it is linear or not, i.e. whether the 
00125  * affine part is NULL or not. If affine part is empty, it returns True other-
00126  * wise it returns False.
00127  */
00128 Bool isLinear(Lattice  *A) {
00129   
00130   int i;
00131 
00132 #ifdef DOMDEBUG
00133   FILE *fp;
00134   fp = fopen ("_debug", "a");
00135   fprintf (fp, "\nEntered ISLINEAR \n"); 
00136   fclose (fp);
00137 #endif
00138 
00139   for (i = 0; i < A->NbRows-1; i ++)
00140     if (value_notzero_p(A->p[i][A->NbColumns-1])) {
00141       return False;
00142     }
00143   return True;
00144 } /* isLinear */ 
00145           
00146 /* 
00147  * Return the affine Hermite normal form of the affine lattice 'A'. The unique 
00148  * affine Hermite form if a lattice is stored in 'H' and the unimodular matrix 
00149  * corresponding to 'A = H*U' is stored in the matrix 'U'. 
00150  * Algorithm : 
00151  *            1) Check if the Lattice is Linear or not.
00152  *            2) If it is not Linear, then Homogenise the Lattice.
00153  *            3) Call Hermite.
00154  *            4) If the Lattice was Homogenised, the HNF H must be 
00155  *               Dehomogenised and also corresponding changes must
00156  *               be made to the Unimodular Matrix U.
00157  *            5) Return.
00158  */ 
00159 void AffineHermite (Lattice *A, Lattice **H, Matrix **U) {
00160  
00161   Lattice *temp;
00162   Bool flag = True;
00163   
00164 #ifdef DOMDEBUG
00165   FILE *fp;
00166   fp = fopen ("_debug", "a");
00167   fprintf (fp, "\nEntered AFFINEHERMITE \n"); 
00168   fclose (fp);
00169 #endif
00170 
00171   if (isLinear(A) == False)
00172     temp = Homogenise(A,True); 
00173   else {
00174     flag = False ;
00175     temp = (Lattice *)Matrix_Copy(A);
00176   }  
00177   Hermite((Matrix *)temp,(Matrix **) H, U);
00178   if (flag == True) {
00179     Matrix_Free ((Matrix *) temp);
00180     temp = Homogenise(H[0],False);
00181     Matrix_Free((Matrix *) H[0]);
00182     H[0] = (Lattice *)Matrix_Copy(temp);
00183     Matrix_Free((Matrix *) temp);
00184     temp = Homogenise(U[0],False);
00185     Matrix_Free ((Matrix *) U[0]);
00186     U[0] = (Matrix *)Matrix_Copy(temp);
00187   }  
00188   Matrix_Free((Matrix *) temp);
00189   return;
00190 } /* AffineHermite */
00191 
00192 /*
00193  * Given a Polylib matrix 'A' that rerepresents an affine function, return the
00194  * affine Smith normal form 'Delta' of 'A' and unimodular matrices 'U' and 'V'
00195  * such that 'A = U*Delta*V'. 
00196  * Algorithm:
00197  *           (1) Homogenise the Lattice.
00198  *           (2) Call Smith
00199  *           (3) The Smith Normal Form Delta must be Dehomogenised and also 
00200  *               corresponding changes must be made to the Unimodular Matrices 
00201  *               U and V.
00202  *           4) Bring Delta into AffineSmith Form.
00203  */
00204 void AffineSmith(Lattice *A, Lattice **U, Lattice **V, Lattice **Diag) {
00205  
00206   Lattice *temp;
00207   Lattice *Uinv;
00208   int i,j;
00209   Value sum, tmp, quo, rem;
00210   
00211 #ifdef DOMDEBUG
00212   FILE *fp;
00213   fp = fopen("_debug", "a");
00214   fprintf(fp,"\nEntered AFFINESMITH \n"); 
00215   fclose(fp);
00216 #endif
00217   
00218   value_init(sum); value_init(tmp);
00219   value_init(quo); value_init(rem);
00220   temp = Homogenise(A,True);  
00221   Smith((Matrix *)temp, (Matrix **)U, (Matrix **)V, (Matrix **)Diag);
00222   Matrix_Free((Matrix *)temp);
00223   
00224   temp = Homogenise (*U, False);
00225   Matrix_Free ((Matrix *) *U);
00226   *U = (Lattice *)Matrix_Copy ((Matrix *)temp);
00227   Matrix_Free ((Matrix *)temp);
00228   
00229   temp = Homogenise (*V, False);
00230   Matrix_Free ((Matrix *)*V);
00231   *V = (Lattice *) Matrix_Copy ((Matrix *)temp);
00232   Matrix_Free ((Matrix *)temp);
00233   
00234   temp = Homogenise (*Diag, False);
00235   Matrix_Free ((Matrix *)*Diag);
00236   *Diag = (Lattice *)Matrix_Copy ((Matrix *)temp);
00237   Matrix_Free ((Matrix *)temp);
00238   
00239   temp = (Lattice *) Matrix_Copy ((Matrix *) *U);
00240   Uinv = (Lattice *) Matrix_Alloc (U[0]->NbRows, U[0]->NbColumns);
00241   Matrix_Inverse( (Matrix *) temp, (Matrix *)  Uinv);
00242   Matrix_Free ((Matrix *) temp);
00243   
00244   for (i = 0; i < U[0]->NbRows-1; i ++) {
00245     value_set_si(sum,0);
00246     for(j = 0; j < U[0]->NbColumns-1; j ++) {
00247       value_multiply(tmp,Uinv->p[i][j],U[0]->p[j][U[0]->NbColumns-1]);
00248       value_addto(sum,sum,tmp);
00249     }
00250     value_assign(Diag[0]->p[i][j],sum);
00251   }
00252   Matrix_Free((Matrix *) Uinv);  
00253   for(i = 0; i < U[0]->NbRows-1; i ++) 
00254     value_set_si(U[0]->p[i][U[0]->NbColumns-1],0);
00255   for(i = 0; i < Diag[0]->NbRows-1; i ++) {
00256     value_division(quo,Diag[0]->p[i][Diag[0]->NbColumns-1],Diag[0]->p[i][i]);
00257     value_modulus(rem,Diag[0]->p[i][Diag[0]->NbColumns-1],Diag[0]->p[i][i]);
00258     
00259     fprintf(stdout," pourcent "); 
00260     value_print(stdout,VALUE_FMT,rem);
00261     fprintf(stdout," quotient ");
00262     value_print(stdout,VALUE_FMT,quo);
00263     fprintf(stdout," \n");
00264     
00265     /* Apparently the % operator is strange when sign are different */
00266     if(value_neg_p(rem)) {
00267       value_addto(rem,rem,Diag[0]->p[i][i]);
00268       value_decrement(quo,quo);
00269     };
00270     fprintf(stdout,"apres  pourcent "); 
00271     value_print(stdout,VALUE_FMT,rem);
00272     fprintf(stdout," quotient ");
00273     value_print(stdout,VALUE_FMT,quo);
00274     fprintf(stdout," \n");
00275     value_assign( Diag[0]->p[i][Diag[0]->NbColumns-1],rem);
00276     value_assign(V[0]->p[i][V[0]->NbColumns-1],quo);
00277   }  
00278   value_clear(sum); value_clear(tmp);
00279   value_clear(quo); value_clear(rem);
00280   return;
00281 } /* AffineSmith */
00282 
00283 /*
00284  * Given a lattice 'A' and a boolean variable 'Forward', homogenise the lattice
00285  * if 'Forward' is True, otherwise if 'Forward' is False, dehomogenise the 
00286  * lattice 'A'. 
00287  * Algorithm: 
00288  *            (1) If Forward == True
00289  *                Put the last row first. 
00290  *                Put the last columns first. 
00291  *            (2) Else 
00292  *                Put the first row last. 
00293  *                Put the first column last.
00294  *            (3) Return the result. 
00295  */
00296 Lattice *Homogenise(Lattice *A, Bool Forward) {
00297   
00298   Lattice *result;
00299 
00300 #ifdef DOMDEBUG
00301   FILE *fp;
00302   fp = fopen("_debug","a");
00303   fprintf(fp,"\nEntered HOMOGENISE \n"); 
00304   fclose(fp);
00305 #endif
00306     
00307   result = (Lattice *)Matrix_Copy(A);  
00308   if (Forward == True ) { 
00309     PutColumnFirst((Matrix *)result, A->NbColumns-1);
00310     PutRowFirst((Matrix *)result, result->NbRows-1);
00311   }
00312   else  { 
00313     PutColumnLast((Matrix *)result,0);
00314     PutRowLast((Matrix *)result,0);
00315   }   
00316   return result;
00317 } /* Homogenise */ 
00318 
00319 /*
00320  * Given two lattices 'A' and 'B', verify if lattice 'A' is included in 'B' or
00321  * not. If 'A' is included in 'B' the 'A' intersection 'B', will be 'A'. So, 
00322  * compute 'A' intersection 'B' and check if it is the same as 'A'. 
00323  */
00324 Bool LatticeIncludes(Lattice *A, Lattice *B) {
00325   
00326   Lattice *temp, *UA, *HA;
00327   Bool flag = False;
00328 
00329 #ifdef DOMDEBUG
00330   FILE *fp;
00331   fp = fopen("_debug", "a");
00332   fprintf(fp,"\nEntered LATTICE INCLUDES \n"); 
00333   fclose(fp);
00334 #endif
00335   
00336   AffineHermite(A,&HA,&UA);  
00337   temp = LatticeIntersection(B,HA); 
00338   if (sameLattice(temp, HA) == True)
00339     flag = True;
00340   
00341   Matrix_Free((Matrix *)temp);
00342   Matrix_Free((Matrix *)UA);
00343   Matrix_Free((Matrix *)HA);
00344   return flag; 
00345 } /* LatticeIncludes */
00346 
00347 /*
00348  * Given two lattices 'A' and 'B', verify if 'A' and 'B' are the same lattice.
00349  * Algorithm: 
00350  *           The Affine Hermite form of two full dimensional matrices are 
00351  * unique. So, take the Affine Hermite form of both 'A' and 'B' and compare the
00352  * matrices. If they are equal, the function returns True, else it returns 
00353  * False. 
00354  */
00355 Bool sameLattice(Lattice *A, Lattice *B) {
00356   
00357   Lattice *HA, *HB, *UA, *UB;
00358   int i,j;
00359   Bool result = True;
00360   
00361 #ifdef DOMDEBUG
00362   FILE *fp;
00363   fp = fopen("_debug", "a");
00364   fprintf(fp,"\nEntered SAME LATTICE \n"); 
00365   fclose(fp);
00366 #endif
00367   
00368   AffineHermite(A, &HA, &UA);
00369   AffineHermite(B, &HB, &UB);
00370     
00371   for (i = 0 ; i < A->NbRows; i ++)
00372     for (j =  0; j < A->NbColumns; j ++)
00373       if (value_ne(HA->p[i][j],HB->p[i][j])) {  
00374         result = False; 
00375         break; 
00376       }  
00377   
00378   Matrix_Free ((Matrix *) HA); 
00379   Matrix_Free ((Matrix *) HB); 
00380   Matrix_Free ((Matrix *) UA); 
00381   Matrix_Free ((Matrix *) UB); 
00382   
00383   return result;
00384 } /* sameLattice */ 
00385 
00386 /*
00387  * Given a matrix 'A' and an integer 'dimension', do the following: 
00388  * If dimension < A->dimension), output a (dimension * dimension) submatrix of 
00389  * A. Otherwise the output matrix is [A 0][0 ID]. The order if the identity 
00390  * matrix is (dimension - A->dimension). The input matrix is not necessarily 
00391  * a Polylib matrix but the output is a polylib matrix. 
00392  */
00393 Lattice *ChangeLatticeDimension(Lattice *A, int dimension) {
00394   
00395   int i, j;
00396   Lattice *Result ;
00397   
00398   Result = Matrix_Alloc(dimension, dimension);
00399   if(dimension <= A->NbRows) {
00400     for (i = 0; i < dimension; i ++)
00401       for (j = 0; j < dimension; j ++)
00402         value_assign(Result->p[i][j],A->p[i][j]);
00403     return Result;
00404   }  
00405   for (i = 0; i < A->NbRows; i ++)
00406     for (j = 0; j < A->NbRows; j ++)
00407       value_assign(Result->p[i][j],A->p[i][j]);
00408   
00409   for (i = A->NbRows; i < dimension; i ++)
00410     for (j = 0; j < dimension; j ++) {
00411         value_set_si(Result->p[i][j],0);
00412         value_set_si(Result->p[j][i],0);
00413     }  
00414   for (i = A->NbRows; i < dimension; i ++)
00415      value_set_si(Result->p[i][i],1);   
00416   return Result;
00417 } /* ChangeLatticeDimension */
00418 
00419 /* 
00420  * Given an affine lattice 'A', return a matrix of the linear part of the 
00421  * lattice.  
00422  */
00423 Lattice *ExtractLinearPart(Lattice *A) {
00424 
00425   Lattice *Result;
00426   int i, j; 
00427   Result = (Lattice *) Matrix_Alloc(A->NbRows-1, A->NbColumns-1);
00428   for (i = 0; i < A->NbRows-1; i ++)
00429     for (j = 0; j < A->NbColumns-1; j ++)
00430       value_assign(Result->p[i][j],A->p[i][j]);  
00431   return Result;
00432 } /* ExtractLinearPart */
00433 
00434 static Matrix *MakeDioEqforInter(Matrix *A, Matrix *B);
00435 
00436 /*
00437  * Given two lattices 'A' and 'B', return the intersection of the two lattcies.
00438  * The dimension of 'A' and 'B' should be the same. 
00439  * Algorithm:
00440  *           (1) Verify if the lattcies 'A' and 'B' have the same affine part. 
00441  *               If they have same affine part, then only their Linear parts 
00442  *               need to be intersected. If they don't have the same affine
00443  *               part then the affine part has to be taken into consideration. 
00444  *               For this, homogenise the lattices to get their Hermite Forms
00445  *               and then find their intersection.
00446  *
00447  *           (2) Step(2) involves, solving the Diophantine Equations in order 
00448  *               to extract the intersection of the Lattices. The Diophantine
00449  *               equations are formed taking into consideration whether the 
00450  *               affine part has to be included or not. 
00451  *
00452  *           (3) Solve the Diophantine equations. 
00453  *
00454  *           (4) Extract the necessary information from the result. 
00455  * 
00456  *           (5) If the lattices have different affine parts and they were 
00457  *               homogenised, the result is dehomogenised. 
00458  */ 
00459 Lattice *LatticeIntersection(Lattice *X, Lattice *Y) {
00460   
00461   int i, j, exist;
00462   Lattice *result = NULL, *U = NULL ;
00463   Lattice *A = NULL, *B = NULL, *H = NULL;
00464   Matrix *fordio;
00465   Vector *X1 = NULL;
00466   
00467 #ifdef DOMDEBUG
00468   FILE *fp;
00469   fp = fopen("_debug", "a");
00470   fprintf(fp,"\nEntered LATTICEINTERSECTION \n"); 
00471   fclose(fp);
00472 #endif
00473 
00474   if (X->NbRows != X->NbColumns) {
00475     fprintf(stderr, "\nIn LatticeIntersection : The Input Matrix X is a not a well defined Lattice\n");
00476     return EmptyLattice(X->NbRows);
00477   }
00478   
00479   if (Y->NbRows != Y->NbColumns) {
00480     fprintf (stderr, "\nIn LatticeIntersection : The Input Matrix Y is a not a well defined Lattice\n");
00481     return EmptyLattice(X->NbRows);
00482   }
00483   
00484   if (Y->NbRows != X->NbRows) {
00485     fprintf (stderr, "\nIn LatticeIntersection : The Input Lattices X and Y are of incompatible dimensions\n");
00486     return EmptyLattice(X->NbRows);
00487   }
00488   
00489   if (isinHnf(X))
00490     A = (Lattice *) Matrix_Copy(X);
00491   else {
00492     AffineHermite(X, &H, &U);
00493     A = (Lattice *)Matrix_Copy (H);
00494     Matrix_Free((Matrix *) H);
00495     Matrix_Free((Matrix *) U);
00496   }
00497   
00498   if (isinHnf(Y))
00499     B = (Lattice *)Matrix_Copy(Y);
00500   else {
00501     AffineHermite(Y, &H, &U);
00502     B = (Lattice *)Matrix_Copy (H);
00503     Matrix_Free((Matrix *) H);
00504     Matrix_Free((Matrix *) U);
00505   }
00506   
00507   if ((isEmptyLattice(A)) || (isEmptyLattice (B))) {
00508     result = EmptyLattice(X->NbRows);
00509     Matrix_Free ((Matrix *) A); 
00510     Matrix_Free ((Matrix *) B);
00511     return result;   
00512   }
00513   fordio = MakeDioEqforInter (A, B);
00514   Matrix_Free (A);
00515   Matrix_Free (B);
00516   exist = SolveDiophantine(fordio,(Matrix **) &U, &X1);
00517   if (exist < 0) { /* Intersection is NULL */    
00518     result = (EmptyLattice(X->NbRows)); 
00519     return result;
00520   }
00521   
00522   result = (Lattice *)Matrix_Alloc(X->NbRows, X->NbColumns);
00523   for (i = 0; i < result->NbRows-1; i ++)
00524     for (j = 0; j < result->NbColumns-1; j ++)
00525       value_assign(result->p[i][j],U->p[i][j]);
00526   
00527   for (i = 0; i < result->NbRows-1; i ++)
00528     value_assign(result->p[i][result->NbColumns-1],X1->p[i]); 
00529   for (i = 0; i < result->NbColumns-1; i ++)
00530     value_set_si(result->p[result->NbRows-1][i],0);
00531   value_set_si(result->p[result->NbRows-1][result->NbColumns-1],1);
00532   
00533   Matrix_Free((Matrix *) U);
00534   Vector_Free(X1);
00535   Matrix_Free(fordio);
00536   
00537   AffineHermite(result,&H,&U);  
00538   Matrix_Free((Matrix *)result);
00539   result = (Lattice *)Matrix_Copy(H); 
00540   
00541   Matrix_Free((Matrix *) H);
00542   Matrix_Free((Matrix *) U);
00543   
00544   /* Check whether the Lattice is NULL or not */
00545   
00546   if (isEmptyLattice (result)) {
00547     Matrix_Free ((Matrix *)result);
00548     return (EmptyLattice (X->NbRows));
00549   }  
00550   return result;
00551 } /* LatticeIntersection */
00552 
00553 static Matrix * MakeDioEqforInter (Lattice *A, Lattice *B) {
00554   
00555   Matrix *Dio ;
00556   int i,j;
00557   
00558 #ifdef DOMDEBUG
00559   FILE *fp;
00560   fp = fopen("_debug", "a");
00561   fprintf(fp,"\nEntered MAKEDIOEQFORINTER \n"); 
00562   fclose(fp);
00563 #endif
00564   
00565  Dio = Matrix_Alloc(2*(A->NbRows-1) + 1, 3 * (A->NbColumns-1)+1);
00566  
00567  for (i = 0; i < Dio->NbRows; i ++)
00568    for (j = 0; j < Dio->NbColumns; j ++)
00569      value_set_si(Dio->p[i][j],0);
00570  
00571  for (i = 0; i < A->NbRows-1; i++) {
00572    value_set_si(Dio->p[i][i],1);
00573    value_set_si(Dio->p[i+A->NbRows-1][i],1);  
00574  } 
00575  for (i = 0; i < A->NbRows-1 ; i ++)
00576    for (j = 0; j < A->NbRows-1; j ++) {
00577      value_oppose(Dio->p[i][j+A->NbRows-1],A->p[i][j]);
00578      value_oppose(Dio->p[i+(A->NbRows-1)][j+2*(A->NbRows-1)],B->p[i][j]);
00579    }
00580  
00581  /* Adding the affine part */
00582  
00583  for (i = 0; i < A->NbColumns-1; i++) {
00584    value_oppose(Dio->p[i][Dio->NbColumns-1],A->p[i][A->NbColumns-1]);
00585    value_oppose(Dio->p[i+A->NbRows-1][Dio->NbColumns-1],B->p[i][A->NbColumns-1]) ;
00586  } 
00587  value_set_si(Dio->p[Dio->NbRows-1][Dio->NbColumns-1],1); 
00588  return Dio;
00589 } /* MakeDioEqforInter */
00590 
00591 static void AddLattice(LatticeUnion *,Matrix *,  Matrix *, int , int);
00592 LatticeUnion *SplitLattice(Matrix *, Matrix *, Matrix *);
00593 
00594 
00595 
00596 /*
00597  * The function is transforming a lattice X in a union of lattices based on a starting lattice Y.
00598  * Note1: If the intersection of X and Y lattices is empty the result is identic with the first argument (X) because no operation can be made.
00599  *Note2: The function is availabe only for simple Lattices and not for a union of Lattices.
00600 
00601  *       Step 1:  Find Intersection = LatticeIntersection (A, B).
00602  *       Step 2:  Extract the Linear Parts of the Lattices A and Intersection.
00603  *                (while dealing with Basis we only deal with the Linear Parts)
00604  *       Step 3:  Let M1 = Basis of A and M2 = Basis of B.
00605  *                Let B1 and B2 be the Basis of A and B respectively, 
00606  *                corresponding to the above Theorem.
00607  *                Then we Have B1 = M1 * U1 {a unimodular Matrix }
00608  *                and B2 = M2 * U2. M1 and M2 we know, they are the linear 
00609  *                parts we obtained in Step 2. Our Task is now to find U1 and
00610  *                U2. 
00611  *                We know that B1  * Delta = B2.
00612  *                i.e. M1 * U1 * Delta = M2 * U2
00613  *                or U1*Delta*U2Inverse = M1Inverse * M2.
00614  *                and Delta is the Diagonal Matrix which satisifies the 
00615  *                above properties (in the Theorem).
00616  *                So Delta is nothing but the Smith Normal Form of 
00617  *                M1Inverse * M2.
00618  *                So, first we have to find M1Inverse.
00619  *             
00620  *                This Step, involves finding the Inverse of the Matrix M1.
00621  *                We find the Inverse using the Polylib function 
00622  *                Matrix_Inverse. There is a catch here, the result of this
00623  *                function is an integral matrix, not necessarily the exact
00624  *                Inverse (since M1 need not be Unimodular), but a multiple
00625  *                of the actual inverse. The number by which we have to divide
00626  *                the matrix, is not obtained here as the input matrix is not
00627  *                a Polylib matrix { We input only the Linear part }. Later I
00628  *                give a way for finding that number.
00629  *
00630  *                M1Inverse = Matrix_Inverse ( M1 );
00631  *      
00632  *      Step 4 :  MtProduct = Matrix_Product (M1Inverse, M2);
00633  *      Step 5 :  SmithNormalFrom (MtProduct, Delta, U, V);
00634  *                U1 = U and U2Inverse = V.
00635  *      Step 6 :  Find U2 = Matrix_Inverse  (U2inverse). Here there is no prob
00636  *                as U1 and its inverse are unimodular.
00637  *      
00638  *      Step 7 :  Compute B1 = M1 * U1;
00639  *      Step 8 :  Compute B2 = M2 * U2;
00640  *      Step 9 :  Earlier when we computed M1Inverse, we knew that it was not
00641  *                the exact inverse but a multiple of it. Now we find the 
00642  *                number, such that ( M1Inverse / number ) would give us the 
00643  *                exact inverse of M1.
00644  *                We know that B1 * Delta = B2.
00645  *                Let k = B2[0][0] / B1[0][0].
00646  *                Let number = Delta[0][0]/k;
00647  *                This 'number' is the number we want.
00648  *                We Divide the matrix Delta by this number, to get the actual
00649  *                Delta such that B1 * Delta = B2.
00650  *     Step 10 :  Call Split Lattice (B1, B2, Delta ).
00651  *                This function returns the Union of Lattices in such a way 
00652  *                that B2 is at the Head of this List.
00653  *
00654  *If the intersection between X and Y is empty then the result is NULL.
00655  */
00656 
00657 
00658 LatticeUnion *Lattice2LatticeUnion(Lattice *X,Lattice *Y)
00659 {
00660   Lattice *B1 = NULL, *B2 = NULL, *newB1 = NULL, *newB2 = NULL, *Intersection=NULL;
00661   Matrix *U = NULL,*M1 = NULL, *M2 = NULL, *M1Inverse = NULL,*MtProduct = NULL;
00662   Matrix *Vinv, *V , *temp, *DiagMatrix ;
00663 
00664   LatticeUnion *Head = NULL, *tempHead = NULL;
00665   int i;
00666   Value k;
00667   
00668 
00669   Intersection = LatticeIntersection(X,Y);
00670   if (isEmptyLattice(Intersection) == True) {
00671     fprintf(stderr,"\nIn Lattice2LatticeUnion : The Input Lattices X and Y does not have any common part\n");
00672     return NULL;
00673   }  
00674 
00675   value_init(k);
00676   M1 = (Matrix *)ExtractLinearPart(X);
00677   M2 = (Matrix *)ExtractLinearPart(Intersection);
00678 
00679   M1Inverse = Matrix_Alloc(M1->NbRows,M1->NbColumns);
00680   temp = Matrix_Copy(M1);
00681   Matrix_Inverse(temp,M1Inverse);
00682   Matrix_Free(temp);
00683 
00684   MtProduct = Matrix_Alloc(M1->NbRows, M1->NbColumns);
00685   Matrix_Product(M1Inverse,M2,MtProduct) ;  
00686   Smith(MtProduct, &U, &Vinv, &DiagMatrix);  
00687   V = Matrix_Alloc(Vinv->NbRows,Vinv->NbColumns);
00688   Matrix_Inverse(Vinv, V);
00689   Matrix_Free(Vinv);  
00690   B1 = Matrix_Alloc(M1->NbRows, U->NbColumns);
00691   B2 = Matrix_Alloc(M2->NbRows, V->NbColumns);  
00692   Matrix_Product(M1, U, B1);
00693   Matrix_Product(M2, V, B2);
00694   Matrix_Free(M1);
00695   Matrix_Free(M2);  
00696   value_division(k,B2->p[0][0],B1->p[0][0]);
00697   value_division(k,DiagMatrix->p[0][0],k);  
00698   for (i = 0; i < DiagMatrix->NbRows; i++)
00699     value_division(DiagMatrix->p[i][i],DiagMatrix->p[i][i],k);
00700   newB1 = ChangeLatticeDimension(B1, B1->NbRows + 1); 
00701   Matrix_Free(B1);
00702   newB2 = ChangeLatticeDimension(B2, B2->NbRows +1);
00703   Matrix_Free(B2);  
00704   for(i = 0; i < newB1->NbRows - 1;i ++)
00705     value_assign(newB2->p[i][newB1->NbRows-1],Intersection->p[i][X->NbRows-1]);
00706   Head = SplitLattice(newB1,newB2,DiagMatrix); 
00707   Matrix_Free(newB1);
00708   Matrix_Free(DiagMatrix); 
00709   value_clear(k);
00710   return Head;
00711 }
00712 
00713 
00714 
00715 /**
00716 
00717 ***        Method : 
00718 ***               
00719 **/
00720 /* 
00721  * Return the Union of lattices that constitute the difference the lattices 
00722  * 'A' and 'B'. The dimensions of 'A' and 'B' should be the same. 
00723  * Note :
00724  *        Inorder to Find the Difference of Lattices, we make use of
00725  *        the following facts.
00726  *               
00727  * Theorem : Given Two Lattices L1 and L2, (L2 subset of L1) there exists a
00728  *           Basis B = {b1, b2,..bn} of L1 and integers {a1, a2...,an} such 
00729  *           that a1 divides a2, a2 divides a3 and so on and {a1b1, a2b2 ,...,
00730  *           .., anbn} is a Basis of L2. So given this theorem we can express 
00731  *           the Lattice L1 in terms of Union of Lattices Involving L2, such 
00732  *           that Lattice L1 = B1 = Union of (B2 + i1b1 + i2b2 + .. inbn) such
00733  *           that 0 <= i1 < a1; 0 <= i2 < a2; .......   0 <= in < an. We also
00734  *           know that A/B = A/(A Intersection B) and that (A Intersection B) 
00735  *           is a subset of A. So, Making use of these two facts, we find the 
00736  *           A/B. We Split The Lattice A in terms of Lattice (A Int B). From 
00737  *           this Union of Lattices Delete the Lattice (A Int B).
00738  *
00739  * Algorithm : 
00740  *
00741  *       Step 1:  Find Intersection = LatticeIntersection (A, B).
00742  *       Step 2:  Extract the Linear Parts of the Lattices A and Intersection.
00743  *                (while dealing with Basis we only deal with the Linear Parts)
00744  *       Step 3:  Let M1 = Basis of A and M2 = Basis of B.
00745  *                Let B1 and B2 be the Basis of A and B respectively, 
00746  *                corresponding to the above Theorem.
00747  *                Then we Have B1 = M1 * U1 {a unimodular Matrix }
00748  *                and B2 = M2 * U2. M1 and M2 we know, they are the linear 
00749  *                parts we obtained in Step 2. Our Task is now to find U1 and
00750  *                U2. 
00751  *                We know that B1  * Delta = B2.
00752  *                i.e. M1 * U1 * Delta = M2 * U2
00753  *                or U1*Delta*U2Inverse = M1Inverse * M2.
00754  *                and Delta is the Diagonal Matrix which satisifies the 
00755  *                above properties (in the Theorem).
00756  *                So Delta is nothing but the Smith Normal Form of 
00757  *                M1Inverse * M2.
00758  *                So, first we have to find M1Inverse.
00759  *             
00760  *                This Step, involves finding the Inverse of the Matrix M1.
00761  *                We find the Inverse using the Polylib function 
00762  *                Matrix_Inverse. There is a catch here, the result of this
00763  *                function is an integral matrix, not necessarily the exact
00764  *                Inverse (since M1 need not be Unimodular), but a multiple
00765  *                of the actual inverse. The number by which we have to divide
00766  *                the matrix, is not obtained here as the input matrix is not
00767  *                a Polylib matrix { We input only the Linear part }. Later I
00768  *                give a way for finding that number.
00769  *
00770  *                M1Inverse = Matrix_Inverse ( M1 );
00771  *      
00772  *      Step 4 :  MtProduct = Matrix_Product (M1Inverse, M2);
00773  *      Step 5 :  SmithNormalFrom (MtProduct, Delta, U, V);
00774  *                U1 = U and U2Inverse = V.
00775  *      Step 6 :  Find U2 = Matrix_Inverse  (U2inverse). Here there is no prob
00776  *                as U1 and its inverse are unimodular.
00777  *      
00778  *      Step 7 :  Compute B1 = M1 * U1;
00779  *      Step 8 :  Compute B2 = M2 * U2;
00780  *      Step 9 :  Earlier when we computed M1Inverse, we knew that it was not
00781  *                the exact inverse but a multiple of it. Now we find the 
00782  *                number, such that ( M1Inverse / number ) would give us the 
00783  *                exact inverse of M1.
00784  *                We know that B1 * Delta = B2.
00785  *                Let k = B2[0][0] / B1[0][0].
00786  *                Let number = Delta[0][0]/k;
00787  *                This 'number' is the number we want.
00788  *                We Divide the matrix Delta by this number, to get the actual
00789  *                Delta such that B1 * Delta = B2.
00790  *     Step 10 :  Call Split Lattice (B1, B2, Delta ).
00791  *                This function returns the Union of Lattices in such a way 
00792  *                that B2 is at the Head of this List.
00793  *     Step 11 :  To Remove B2 From the list of the Union of Lattices.
00794  *                Head = Head->next;
00795  *     Step 12 :  Free the Memory that is now not needed and return Head.
00796  *
00797  */
00798 LatticeUnion *LatticeDifference(Lattice  *A,Lattice *B) {
00799  
00800   Lattice *Intersection = NULL;
00801   LatticeUnion *Head = NULL, *tempHead = NULL;
00802   Matrix *H , *U1 , *X, *Y ;
00803 
00804 #ifdef DOMDEBUG
00805   FILE *fp;
00806   fp = fopen("_debug", "a");
00807   fprintf(fp,"\nEntered LATTICEDIFFERENCE \n"); 
00808   fclose(fp);
00809 #endif
00810 
00811   if (A->NbRows != A->NbColumns) { 
00812     fprintf(stderr,"\nIn LatticeDifference : The Input Matrix A is not a proper Lattice \n");
00813     return NULL;
00814   }
00815   
00816   if (B->NbRows != B->NbColumns) { 
00817     fprintf(stderr,"\nIn LatticeDifference : The Input Matrix B is not a proper Lattice \n");
00818     return NULL;
00819   }
00820   
00821   if (A->NbRows != B->NbRows) {
00822     fprintf(stderr,"\nIn Lattice Difference : The Input Lattices A and B have ");
00823     fprintf(stderr,"incompatible dimensions \n");
00824     return NULL;
00825   }
00826 
00827 if (isinHnf (A) != True) {
00828     AffineHermite(A,&H,&U1);
00829     X = Matrix_Copy(H);    
00830     Matrix_Free(U1);
00831     Matrix_Free(H);
00832   }
00833   else
00834     X = Matrix_Copy(A);
00835   
00836   if (isinHnf(B) != True) {
00837     AffineHermite(B,&H,&U1);
00838     Y = Matrix_Copy(H);   
00839     Matrix_Free(H);
00840     Matrix_Free(U1);
00841   }
00842   else
00843     Y = Matrix_Copy(B);  
00844   if (isEmptyLattice(X)) {
00845     return NULL;  
00846   } 
00847 
00848   Head=Lattice2LatticeUnion(X,Y);
00849 
00850 /* If the spliting operation can't be done the result is X. */
00851 
00852   if (Head == NULL) {
00853     Head = (LatticeUnion *)malloc(sizeof(LatticeUnion));
00854     Head->M = Matrix_Copy(X);
00855     Head->next = NULL;
00856     Matrix_Free(X);
00857     Matrix_Free(Y);
00858     return Head;
00859   } 
00860 
00861   tempHead = Head;
00862   Head = Head->next;  
00863   Matrix_Free (tempHead->M);
00864   tempHead->next = NULL; 
00865   free(tempHead);  
00866 
00867   if ((Head != NULL))
00868     Head = LatticeSimplify (Head);
00869   Matrix_Free (X);
00870   Matrix_Free (Y); 
00871 
00872   return Head;
00873 } /* LatticeDifference */
00874 
00875 
00876 /*
00877  * Given a Lattice 'B1' and a Lattice 'B2' and a Diagonal Matrix 'C' such that
00878  * 'B2' is a subset of 'B1' and C[0][0] divides C[1][1], C[1][1] divides C[2]
00879  * [2] and so on, output the list of matrices whose union is B1. The function
00880  * expresses the Lattice B1 in terms of B2 Unions of B1 = Union of {B2 + i0b0 +
00881  * i1b1 + .... + inbn} where 0 <= i0 < C[0][0]; 0 <= i1 < C[1][1] and so on and
00882  * {b0 ... bn} are the columns of Lattice B1. The list is so formed that the 
00883  * Lattice B2 is the Head of the list. 
00884  */     
00885 LatticeUnion *SplitLattice(Lattice *B1, Lattice *B2, Matrix *C) {
00886   
00887   int i;
00888   
00889   LatticeUnion *Head = NULL;  
00890   Head = (LatticeUnion *)malloc(sizeof(LatticeUnion));
00891   Head->M = (Lattice *)B2;
00892   Head->next = NULL;  
00893   for (i = 0; i < C->NbRows ; i++)
00894     AddLattice(Head,B1,B2,VALUE_TO_INT(C->p[i][i]),i);  
00895   return Head;
00896 } /* SplitLattice */
00897 
00898 /*
00899  * Given lattices 'B1' and 'B2', an integer 'NumofTimes', a column number 
00900  * 'Colnumber' and a pointer to a list of lattices, the function does the 
00901  * following :-
00902  * For every lattice in the list, it adds a set of lattices such that the 
00903  * affine part of the new lattices is greater than the original lattice by 0 to
00904  * NumofTimes-1 * {the (ColumnNumber)-th column of B1}. 
00905  * Note : 
00906  * Three pointers are defined to point at various points of the list. They are:
00907  * Head   -> It always points to the head of the list. 
00908  * tail   -> It always points to the last element in the list. 
00909  * marker -> It points to the element, which is the last element of the Input 
00910  *           list.
00911  */ 
00912 static void AddLattice (LatticeUnion *Head, Matrix  *B1,  Matrix *B2, int NumofTimes, int Colnumber) {
00913   
00914   LatticeUnion *temp, *tail, *marker;
00915   int i,j;
00916   Value tmp;
00917   
00918   value_init(tmp);
00919   tail =  Head;  
00920   while (tail->next != NULL)
00921     tail = tail->next;  
00922   marker = tail;
00923   
00924   for(temp = Head; temp != NULL; temp=temp->next) {
00925     for (i = 1; i < NumofTimes; i++) { 
00926       Lattice *tempMatrix, *H, *U;
00927       
00928       tempMatrix = (Lattice *)Matrix_Copy(temp->M);       
00929       for (j = 0; j < B2->NbRows; j++) {
00930         value_set_si(tmp,i);
00931         value_multiply(tmp,tmp,B1->p[j][Colnumber]);
00932         value_addto(tempMatrix->p[j][B2->NbColumns-1],tempMatrix->p[j][B2->NbColumns-1],tmp);   
00933       }
00934       tail->next = (LatticeUnion *)malloc(sizeof(LatticeUnion)); 
00935       AffineHermite(tempMatrix,&H,&U);
00936       Matrix_Free((Matrix *)tempMatrix);
00937       Matrix_Free(U);
00938       tail->next->M = H;
00939       tail->next->next=NULL;
00940       tail = tail->next;
00941     }
00942     if (temp == marker)
00943       break;
00944   }  
00945   value_clear(tmp);
00946   return;
00947 } /* AddLattice */
00948 
00949 /* 
00950  * Given a polyhedron 'A', store the Hermite basis 'B' and return the true 
00951  * dimension of the polyhedron 'A'. 
00952  * Algorithm : 
00953  *
00954  *             1) First we find all the vertices of the Polyhedron A.
00955  *                Now suppose the vertices are [v1, v2...vn], then 
00956  *                a particular set of vectors governing the space of A are 
00957  *                given by [v1-v2, v1-v3, ... v1-vn] (let us say V).
00958  *                So we initially calculate these vectors.
00959  *             2) Then there are the rays and lines which contribute to the
00960  *                space in which A is going to lie.
00961  *                So we append to the rays and lines. So now we get a matrix
00962  *                {These are the rows} [ V ] [l1] [l2]...[lk] 
00963  *                where l1 to lk are either rays or lines of the Polyhedron A.
00964  *             3) The above matrix is the set of vectors which determine
00965  *                the space in which A is going to lie.
00966  *                Using this matrix we find a Basis which is such that
00967  *                the first 'm' columns of it determine the space of A. 
00968  *             4) But we also have to ensure that in the last 'n-m' 
00969  *                coordinates the Polyhedron is '0', this is done by
00970  *                taking the image by B(inv) of A and finding the remaining
00971  *                equalities, and composing it with the matrix B, so as
00972  *                to get a new matrix which is the actual Hermite Basis of
00973  *                the Polyhedron.
00974  */
00975 int FindHermiteBasisofDomain(Polyhedron *A, Matrix **B) {
00976   
00977   int i, j;
00978   Matrix *temp,*temp1, *tempinv, *Newmat ;
00979   Matrix *vert, *rays, *result;
00980   Polyhedron *Image;
00981   int rank, equcount ;
00982   int noofvertices = 0, noofrays = 0;
00983   int vercount , raycount;
00984   Value lcm, fact;
00985   
00986 #ifdef DOMDEBUG
00987   FILE *fp;
00988   fp = fopen("_debug", "a");
00989   fprintf(fp,"\nEntered FINDHERMITEBASISOFDOMAIN \n"); 
00990   fclose(fp);
00991 #endif
00992   
00993   /* Checking is empty */  
00994   if (emptyQ(A)) {
00995       B[0] = Identity(A->Dimension+1);
00996       return(-1);
00997    }
00998 
00999   value_init(lcm); value_init(fact);
01000   value_set_si(lcm,1);
01001 
01002   /* Finding the Vertices */  
01003   for (i = 0; i < A->NbRays; i++)
01004     if ((value_notzero_p(A->Ray[i][0])) && value_notzero_p(A->Ray[i][A->Dimension+1]))
01005       noofvertices++;
01006     else 
01007       noofrays ++;
01008   
01009   vert = Matrix_Alloc(noofvertices,A->Dimension+1);
01010   rays = Matrix_Alloc(noofrays,A->Dimension);
01011   vercount = 0;
01012   raycount = 0;
01013   
01014   for(i = 0; i < A->NbRays; i++) {
01015     if ((value_notzero_p(A->Ray[i][0])) && value_notzero_p(A->Ray[i][A->Dimension+1])) {
01016       for(j = 1; j < A->Dimension+2; j++) 
01017         value_assign(vert->p[vercount][j-1],A->Ray[i][j]);
01018       value_assign(lcm,*Lcm(lcm,A->Ray[i][j-1]));
01019       vercount++;
01020     }
01021     else {
01022       for (j = 1; j < A->Dimension+1; j++)
01023         value_assign(rays->p[raycount][j-1],A->Ray[i][j]);
01024       raycount++;       
01025     }
01026   }
01027   
01028   /* Multiplying the rows by the lcm */
01029   for(i = 0; i < vert->NbRows; i ++) {    
01030     value_division(fact,lcm,vert->p[i][vert->NbColumns-1]);
01031     for (j = 0; j < vert->NbColumns-1; j++)
01032       value_multiply(vert->p[i][j],vert->p[i][j],fact);
01033   }
01034   
01035   /* Drop the Last Columns */
01036   temp = RemoveColumn(vert,vert->NbColumns-1);
01037   Matrix_Free(vert);
01038   
01039   /* Getting the Vectors */
01040   vert = Matrix_Alloc(temp->NbRows-1, temp->NbColumns);
01041   for (i = 1; i < temp->NbRows; i++)
01042     for (j = 0; j < temp->NbColumns ; j++)
01043       value_substract(vert->p[i-1][j],temp->p[0][j],temp->p[i][j]);
01044   
01045   /* Add the Rays and Lines */
01046   /* Combined Matrix */  
01047   result = Matrix_Alloc(vert->NbRows+rays->NbRows, vert->NbColumns);
01048   for (i = 0; i < vert->NbRows; i++)
01049     for (j = 0 ;j < result->NbColumns ; j++)
01050       value_assign(result->p[i][j],vert->p[i][j]);
01051   
01052   for (; i<result->NbRows; i++)
01053     for (j = 0; j < result->NbColumns; j++)
01054       value_assign(result->p[i][j],rays->p[i-vert->NbRows][j]);
01055 
01056 //  printf("\nIn FHB:-\n");
01057 //  Matrix_Print(stdout,P_VALUE_FMT, result);
01058 
01059   rank = findHermiteBasis(result, &temp);
01060   temp1 = ChangeLatticeDimension(temp,temp->NbRows+1);
01061 
01062   //  printf("\nThe rank of the Domain is %d\n", rank);
01063   //  Matrix_Print(stdout,P_VALUE_FMT,temp1);
01064   Matrix_Free(temp);
01065   
01066   /* Adding the Affine Part to take care of the Equalities */  
01067   temp = Matrix_Copy(temp1);
01068   tempinv = Matrix_Alloc(temp->NbRows,temp->NbColumns);
01069   Matrix_Inverse(temp,tempinv); 
01070   Matrix_Free(temp);
01071   Image = DomainImage(A,tempinv,MAXNOOFRAYS);  
01072   Newmat = Matrix_Alloc(temp1->NbRows,temp1->NbColumns);
01073   for(i = 0; i < rank ; i++)
01074     for(j = 0; j < Newmat->NbColumns ; j++) 
01075       value_set_si(Newmat->p[i][j],0);  
01076   for(i = 0; i < rank; i++)
01077     value_set_si(Newmat->p[i][i],1);  
01078   equcount = 0;  
01079   for (i = 0; i < Image->NbConstraints; i ++)
01080     if (value_zero_p(Image->Constraint[i][0])) {
01081       for (j = 1; j<Image->Dimension+2; j ++)
01082         value_assign(Newmat->p[rank+equcount][j-1],Image->Constraint[i][j]);
01083       ++equcount ;
01084     } 
01085   for (i = 0; i < Newmat->NbColumns-1; i++)
01086     value_set_si(Newmat->p[Newmat->NbRows-1][i],0);
01087   value_set_si(Newmat->p[Newmat->NbRows-1][Newmat->NbColumns-1],1);
01088   temp = Matrix_Alloc(Newmat->NbRows, Newmat->NbColumns);
01089   Matrix_Inverse(Newmat,temp);
01090   B[0] = Matrix_Alloc(temp1->NbRows,temp->NbColumns);
01091 
01092 //  Matrix_Print (stdout,P_VALUE_FMT,temp);
01093   
01094   Matrix_Product(temp1,temp,B[0]);  
01095   value_clear(lcm);
01096   value_clear(fact);
01097   return rank;
01098 } /* FindHermiteBasisofDomain */ 
01099 
01100 /*
01101  * Return the image of a lattice 'A' by the invertible, affine, rational 
01102  * function 'M'. 
01103  */
01104 Lattice *LatticeImage(Lattice *A, Matrix *M) {
01105  
01106   Lattice *Img, *temp, *Minv;
01107 
01108 #ifdef DOMDEBUG
01109   FILE *fp;
01110   fp = fopen("_debug", "a");
01111   fprintf(fp, "\nEntered LATTICEIMAGE \n"); 
01112   fclose(fp);
01113 #endif
01114 
01115   if ((A->NbRows != M->NbRows) || (M->NbRows != M->NbColumns))
01116     return (EmptyLattice (A->NbRows));
01117   
01118   if (value_one_p(M->p[M->NbRows-1][M->NbColumns-1])) {
01119     Img = Matrix_Alloc ( M->NbRows, A->NbColumns );
01120     Matrix_Product (M,A,Img);
01121     return Img;
01122   } 
01123   temp = Matrix_Copy(M);
01124   Minv = Matrix_Alloc(temp->NbColumns, temp->NbRows);
01125   Matrix_Inverse(temp, Minv);
01126   Matrix_Free(temp);
01127   
01128   Img = LatticePreimage(A, Minv);
01129   Matrix_Free (Minv);
01130   return Img;
01131 } /* LatticeImage */
01132 
01133 /* 
01134  * Return the preimage of a lattice 'L' by an affine, rational function 'G'.
01135  * Algorithm: 
01136  *           (1) Prepare Diophantine equation :
01137  *               [Gl -Ll][x y] = [Ga -La]{"l-linear, a-affine"}
01138  *           (2) Solve the Diophantine equations.
01139  *           (3) If there is solution to the Diophantine eq., extract the 
01140  *               general solution and the particular solution of x and that 
01141  *               forms the preimage of 'L' by 'G'. 
01142  */
01143 Lattice *LatticePreimage(Lattice *L, Matrix *G) {
01144  
01145   Matrix *Dio, *U ;
01146   Lattice *Result;
01147   Vector *X;
01148   int i,j;
01149   int rank;
01150   Value divisor, tmp;
01151   
01152 #ifdef DOMDEBUG
01153   FILE *fp;
01154   fp = fopen("_debug", "a");
01155   fprintf(fp,"\nEntered LATTICEPREIMAGE \n"); 
01156   fclose(fp);
01157 #endif
01158   
01159   /* Check for the validity of the function */  
01160   if (G->NbRows != L->NbRows) {
01161     fprintf (stderr, "\nIn LatticePreimage: Incompatible types of Lattice and the function\n");
01162     return (EmptyLattice(G->NbColumns));
01163   }
01164   
01165   value_init(divisor); value_init(tmp);
01166   
01167   /* Making Diophantine Equations [g -L] */
01168   value_assign(divisor,G->p[G->NbRows-1][G->NbColumns-1]);
01169   Dio = Matrix_Alloc(G->NbRows, G->NbColumns+L->NbColumns-1);
01170   for (i = 0; i < G->NbRows-1; i++)
01171     for (j = 0; j < G->NbColumns-1; j++)
01172       value_assign(Dio->p[i][j],G->p[i][j]);
01173   
01174   for (i = 0;i < G->NbRows-1; i++)
01175     for (j = 0; j < L->NbColumns-1; j++) {
01176       value_multiply(tmp,divisor,L->p[i][j]);
01177       value_oppose(Dio->p[i][j+G->NbColumns-1],tmp);
01178     }
01179   
01180   for (i = 0; i < Dio->NbRows-1; i++) {
01181     value_multiply(tmp,divisor,L->p[i][L->NbColumns-1]);
01182     value_substract(tmp,G->p[i][G->NbColumns-1],tmp);
01183     value_assign(Dio->p[i][Dio->NbColumns-1],tmp);
01184   }
01185   for (i = 0; i < Dio->NbColumns-1; i++)
01186     value_set_si(Dio->p[Dio->NbRows-1][i],0);
01187   
01188   value_set_si(Dio->p[Dio->NbRows-1][Dio->NbColumns-1],1); 
01189   rank = SolveDiophantine(Dio, &U, &X);
01190   
01191   if (rank == -1)
01192     Result = EmptyLattice(G->NbColumns);
01193   else {
01194     Result = Matrix_Alloc (G->NbColumns, G->NbColumns);
01195     for (i = 0; i < Result->NbRows-1; i++)
01196       for (j = 0; j < Result->NbColumns-1; j++)
01197         value_assign(Result->p[i][j],U->p[i][j]);
01198     
01199     for (i = 0; i < Result->NbRows-1; i ++)
01200       value_assign(Result->p[i][Result->NbColumns-1],X->p[i]);  
01201     Matrix_Free (U);
01202     Vector_Free (X);   
01203     for (i = 0; i < Result->NbColumns-1; i ++)
01204       value_set_si(Result->p[Result->NbRows-1][i],0);
01205     value_set_si(Result->p[i][i],1);
01206   } 
01207   Matrix_Free(Dio);
01208   value_clear(divisor);
01209   value_clear(tmp);
01210   return Result;
01211 } /* LatticePreimage */
01212  
01213 /*
01214  * Return True if the matrix 'm' is a valid lattice, otherwise return False. 
01215  * Note: A valid lattice has the last row as [0 0 0 ... 1]. 
01216  */ 
01217 Bool IsLattice(Matrix *m) {
01218   
01219   int i;
01220   
01221 #ifdef DOMDEBUG
01222   FILE *fp;
01223   fp = fopen ("_debug", "a");
01224   fprintf (fp, "\nEntered ISLATTICE \n"); 
01225   fclose (fp);
01226 #endif
01227   
01228   /* Is it necessary to check if the lattice
01229      is fulldimensional or not here only? */
01230   
01231   if (m->NbRows != m->NbColumns)
01232     return False;
01233   
01234   for (i = 0; i < m->NbColumns-1; i++)
01235     if (value_notzero_p(m->p[m->NbRows-1][i])) 
01236       return False ;
01237   if (value_notone_p(m->p[i][i])) 
01238     return False;
01239   return True ;
01240 } /* IsLattice */ 
01241  
01242 /*
01243  *  Check whether the matrix 'm' is full row-rank or not. 
01244  */ 
01245 Bool isfulldim(Matrix *m) {
01246   
01247   Matrix *h, *u ;
01248   int i ;
01249   
01250   /* 
01251      res = Hermite (m, &h, &u);
01252      if (res != m->NbRows)
01253      return False ;
01254   */
01255   
01256   Hermite(m, &h, &u);
01257   for (i = 0; i < h->NbRows; i ++)
01258     if (value_zero_p(h->p[i][i])) {
01259       Matrix_Free (h);
01260       Matrix_Free (u);
01261       return False;
01262     }
01263   Matrix_Free (h);
01264   Matrix_Free (u);
01265   return True;
01266 } /* isfulldim */
01267      
01268 /* 
01269  * This function takes as input a lattice list in which the lattices have the 
01270  * same linear part, and almost the same affinepart, i.e. if A and B are two 
01271  * of the lattices in the above lattice list and [a1, .. , an] and [b1 .. bn]
01272  * are the affineparts of A and B respectively, then for 0 < i < n ai = bi and
01273  * 'an' may not be equal to 'bn'. These are not the affine parts in the n-th
01274  * dimension, but the lattices have been tranformed such that the value of the 
01275  * elment in the dimension on which we are simplifying is in the last row and
01276  * also the lattices are in a sorted order. 
01277  *              This function also takes as input the dimension along which we
01278  * are simplifying and takes the diagonal element of the lattice along that
01279  * dimension and tries to find out the factors of that element and sees if the
01280  * list of lattices can be simplified using these factors. The output of this 
01281  * function is the list of lattices in the simplified form and a flag to indic-
01282  * ate whether any form of simplification was actually done or not.  
01283  */
01284 static Bool Simplify(LatticeUnion **InputList, LatticeUnion **ResultList, int dim) {
01285   
01286   int i;
01287   LatticeUnion *prev, *temp;
01288   factor allfac;
01289   Bool retval = False;
01290   int width;
01291   Value cnt, aux, k, fac, num, tmp, foobar;
01292   
01293   if ((*InputList == NULL) || (InputList[0]->next == NULL))
01294     return False ;
01295 
01296   value_init(aux); value_init(cnt); 
01297   value_init(k); value_init(fac);
01298   value_init(num); value_init(tmp);
01299   value_init(foobar);
01300 
01301   width = InputList[0]->M->NbRows-1; 
01302   allfac = allfactors(VALUE_TO_INT(InputList[0]->M->p[dim][dim]));
01303   value_set_si(cnt,0);
01304   for (temp = InputList[0]; temp != NULL; temp = temp->next)
01305     value_increment(cnt,cnt);  
01306   for(i = 0; i < allfac.count; i++) {
01307     value_set_si(foobar,allfac.fac[i]);
01308     value_division(aux,InputList[0]->M->p[dim][dim],foobar);
01309     if(value_ge(cnt,aux))
01310       break;
01311   }
01312   if (i == allfac.count) {
01313     value_clear(cnt); value_clear(aux);   
01314     value_clear(k); value_clear(fac);
01315     value_clear(num); value_clear(tmp);
01316     value_clear(foobar);
01317     return False; 
01318   }
01319   for (; i < allfac.count; i++) {    
01320     Bool Present = False;
01321     value_set_si(k,0);
01322     
01323     if (*InputList == NULL) {
01324       value_clear(cnt); value_clear(aux);
01325       value_clear(k); value_clear(fac);
01326       value_clear(num); value_clear(tmp);
01327       value_clear(foobar);
01328       return retval;
01329     }
01330     value_set_si(foobar,allfac.fac[i]);
01331     value_division(num,InputList[0]->M->p[dim][dim],foobar);
01332     while (value_lt(k,foobar)) {          
01333       Present = False;
01334       value_assign(fac,k); 
01335       for (temp = *InputList; temp != NULL; temp = temp->next) {
01336         if (value_eq(temp->M->p[temp->M->NbRows-1][temp->M->NbColumns-1],fac)) {
01337           value_set_si(foobar,allfac.fac[i]);
01338           value_addto(fac,fac,foobar);
01339           if (value_ge(fac,(*InputList)->M->p[dim][dim])) {
01340             Present = True;
01341             break;
01342           }
01343         }       
01344         if (value_gt(temp->M->p[temp->M->NbRows-1][temp->M->NbColumns-1],fac))
01345           break;
01346       }      
01347       if (Present == True) {    
01348         retval = True;
01349         if (*ResultList == NULL)
01350           *ResultList = temp = (LatticeUnion *)malloc(sizeof(LatticeUnion));
01351         else {
01352           for (temp = *ResultList; temp->next != NULL; temp = temp->next);
01353           temp->next = (LatticeUnion *) malloc (sizeof (LatticeUnion));
01354           temp = temp->next;
01355         }
01356         temp->M = Matrix_Copy(InputList[0]->M); 
01357         temp->next = NULL;
01358         value_set_si(foobar,allfac.fac[i]);
01359         value_assign(temp->M->p[dim][dim],foobar);
01360         value_assign(temp->M->p[dim][width],k);
01361         value_set_si(temp->M->p[width][width],1);
01362         
01363         /* Deleting the Lattices from the curlist */
01364         value_assign(tmp,k);
01365         prev = NULL;
01366         temp = InputList[0];
01367         while (temp != NULL) {
01368           if (value_eq(temp->M->p[width][width],tmp)) {
01369             if (temp == InputList[0]) {
01370               prev = temp;
01371               temp = InputList [0] = temp->next;
01372               Matrix_Free(prev->M);
01373               free(prev);         
01374             }
01375             else {
01376               prev->next = temp->next;
01377               Matrix_Free(temp->M);
01378               free(temp);
01379               temp = prev->next;
01380             }
01381             value_set_si(foobar,allfac.fac[i]);
01382             value_addto(tmp,tmp,foobar); 
01383           }
01384           else {
01385             prev = temp;
01386             temp = temp->next;
01387           }
01388         }   
01389       } 
01390       value_increment(k,k);
01391     }    
01392   }
01393   value_clear(cnt); value_clear(aux);
01394   value_clear(k); value_clear(fac);
01395   value_clear(num); value_clear(tmp);
01396   value_clear(foobar);
01397   return retval;          
01398 } /* Simplify */     
01399  
01400 /*
01401  * This function is used in the qsort function in sorting the lattices. Given 
01402  * two lattices 'A' and 'B', both in HNF, where A = [ [a11 0], [a21, a22, 0] .
01403  * .... [an1, .., ann] ] and B = [ [b11 0], [b21, b22, 0] ..[bn1, .., bnn] ],
01404  * then A < B, if there exists a pair <i,j> such that [aij < bij] and for every
01405  * other pair <i1, j1>, 0<=i1<i, 0<=j1<j [ai1j1 = bi1j1]. 
01406  */
01407 static int LinearPartCompare(const void *A, const void *B) {
01408  
01409   Lattice **L1, **L2;
01410   int i, j;
01411   
01412   L1 = (Lattice **) A; 
01413   L2 = (Lattice **) B;
01414   
01415   for (i = 0;  i < L1[0]->NbRows-1; i++)
01416     for (j = 0; j <= i ; j++) {
01417       if (value_gt(L1[0]->p[i][j],L2[0]->p[i][j]))
01418         return 1;      
01419       if (value_lt(L1[0]->p[i][j],L2[0]->p[i][j]))
01420         return -1;
01421     }   
01422   return 0;
01423 } /* LinearPartCompare */
01424   
01425 /*
01426  * This function takes as input a List of Lattices and sorts them on the basis
01427  * of their Linear parts. It sorts in place, as a result of which the input 
01428  * list is modified to the sorted order.
01429  */ 
01430 static void LinearPartSort (LatticeUnion *Head) {
01431 
01432   int  cnt;
01433   Lattice **Latlist;
01434   LatticeUnion *temp ;
01435   
01436   cnt = 0;
01437   for (temp = Head; temp != NULL; temp = temp->next)
01438     cnt ++;
01439  
01440   Latlist = (Lattice **) malloc ( sizeof (Lattice *) * cnt);
01441   
01442   cnt = 0; 
01443   for (temp = Head; temp != NULL; temp = temp->next)
01444     Latlist[cnt++] = temp->M; 
01445   
01446   qsort(Latlist, cnt, sizeof(Lattice *), LinearPartCompare);
01447   
01448   cnt = 0;  
01449   for (temp = Head; temp != NULL; temp = temp->next)
01450     temp->M = Latlist[cnt++];
01451   
01452  free (Latlist);
01453  return;
01454 } /* LinearPartSort */
01455 
01456 /*
01457  * This function is used in 'AfiinePartSort' in sorting the lattices with the
01458  * same linear part. GIven two lattices 'A' and 'B' with affineparts [a1 .. an]
01459  * and [b1 ... bn], then A < B if for some 0 < i <= n, ai < bi and for 0 < i1 <
01460  * i, ai1 = bi1. 
01461  */ 
01462 static int AffinePartCompare(const void *A, const void *B) {
01463   
01464   int i;
01465   Lattice **L1, **L2; 
01466 
01467   L1 = (Lattice **)A;
01468   L2 = (Lattice **)B;
01469   
01470   for (i = 0; i < L1[0]->NbRows; i++) {
01471     if (value_gt(L1[0]->p[i][L1[0]->NbColumns-1],L2[0]->p[i][L1[0]->NbColumns-1]))
01472       return 1;  
01473     
01474     if (value_lt(L1[0]->p[i][L1[0]->NbColumns-1],L2[0]->p[i][L1[0]->NbColumns-1]))
01475       return -1;  
01476   }  
01477   return 0 ;
01478 } /* AffinePartCompare */
01479 
01480 /* 
01481  * This function takes a list of lattices with the same linear part and sorts
01482  * them on the basis of their affine part. The sorting is done in place.
01483  */
01484 static void AffinePartSort (LatticeUnion *List) {
01485   
01486   int cnt;
01487   Lattice **LatList;
01488   LatticeUnion *tmp;
01489   
01490   cnt = 0;
01491   for (tmp = List; tmp != NULL; tmp = tmp->next)
01492     cnt ++;  
01493   
01494   LatList = (Lattice **) malloc (sizeof(Lattice *) * cnt);
01495   
01496   cnt = 0;
01497   for (tmp = List; tmp != NULL; tmp = tmp->next)
01498     LatList[cnt++] = tmp->M;
01499   
01500   qsort(LatList,cnt, sizeof (Lattice *), AffinePartCompare);
01501   
01502   cnt = 0;
01503   for (tmp = List; tmp != NULL; tmp = tmp->next) 
01504     tmp->M = LatList[cnt++];
01505   return;
01506 } /* AffinePartSort */
01507 
01508 static Bool AlmostSameAffinePart(LatticeUnion *A, LatticeUnion *B) {
01509   
01510   int i;
01511   
01512   if ((A == NULL) || (B == NULL))
01513     return False;
01514 
01515   for (i = 0; i < A->M->NbRows-1; i ++)
01516     if (value_ne(A->M->p[i][A->M->NbColumns-1],B->M->p[i][A->M->NbColumns-1]))
01517       return False;   
01518   return True;
01519 } /* AlmostSameAffinePart */
01520 
01521 /* 
01522  * This function takes a list of lattices having the same linear part and tries
01523  * to simplify these lattices. This may not be the only way of simplifying the
01524  * lattices. The function returns a list of partially simplified lattices and 
01525  * also a flag to tell whether any simplification was performed at all. 
01526  */
01527 static Bool AffinePartSimplify(LatticeUnion *curlist, LatticeUnion **newlist) {
01528   
01529   int i;
01530   Value aux;
01531   LatticeUnion *temp, *curr, *next;
01532   LatticeUnion *nextlist;
01533   Bool change = False, chng;
01534   
01535   if (curlist == NULL) 
01536     return False;
01537   
01538   if (curlist->next == NULL) {
01539     curlist->next = newlist[0];
01540     newlist[0] = curlist;
01541     return False ;
01542   }
01543   
01544   value_init(aux);
01545   for (i = 0; i < curlist->M->NbRows - 1; i ++) {
01546     
01547     /* Interchanging the elements of the Affine part for easy computation
01548        of the sort (using qsort) */
01549     
01550     for (temp = curlist; temp != NULL; temp = temp->next) {      
01551       value_assign(aux,temp->M->p[temp->M->NbRows-1][temp->M->NbColumns-1]);
01552       value_assign(temp->M->p[temp->M->NbRows-1][temp->M->NbColumns-1],temp->M->p[i][temp->M->NbColumns-1]);
01553       value_assign(temp->M->p[i][temp->M->NbColumns-1],aux);
01554     }     
01555     AffinePartSort(curlist);
01556     nextlist = NULL;
01557     curr = curlist;
01558     while (curr != NULL) {
01559       next = curr->next;
01560       if (!AlmostSameAffinePart(curr, next)) {
01561         curr->next = NULL;
01562         chng = Simplify(&curlist, newlist, i);
01563         if (nextlist == NULL)
01564           nextlist = curlist;
01565         else {
01566           LatticeUnion *tmp;
01567           for (tmp = nextlist; tmp->next; tmp=tmp->next);
01568           tmp->next = curlist;
01569         }
01570         change = change | chng ;
01571         curlist = next;
01572       }
01573       curr = next;
01574     }  
01575     curlist = nextlist;
01576     
01577     /* Interchanging the elements of the Affine part for easy computation
01578        of the sort (using qsort) */
01579     
01580     for(temp = curlist; temp != NULL; temp = temp->next) {
01581       value_assign(aux,temp->M->p[temp->M->NbRows-1][temp->M->NbColumns-1]);
01582       value_assign(temp->M->p[temp->M->NbRows-1][temp->M->NbColumns-1],temp->M->p[i][temp->M->NbColumns-1]);
01583       value_assign(temp->M->p[i][temp->M->NbColumns-1],aux);
01584     }     
01585     if (curlist == NULL)
01586       break;
01587   }
01588   if ( *newlist == NULL)
01589     *newlist = nextlist;
01590   else {
01591     for (curr = *newlist; curr->next != NULL; curr = curr->next);
01592     curr->next = nextlist;
01593   }  
01594   value_clear(aux);
01595   return change;
01596 } /* AffinePartSimplify */
01597      
01598 static Bool SameLinearPart(LatticeUnion *A, LatticeUnion *B) {
01599   
01600   int i, j;  
01601   if ((A == NULL) || (B ==NULL))
01602     return False;
01603   for (i = 0; i < A->M->NbRows-1; i++)
01604     for (j = 0; j <= i; j++)
01605       if (value_ne(A->M->p[i][j],B->M->p[i][j]))
01606         return False;
01607   
01608   return True;
01609 } /* SameLinearPart */
01610 
01611 /* 
01612  * Given a union of lattices, return a simplified list of lattices. 
01613  */ 
01614 LatticeUnion *LatticeSimplify(LatticeUnion *latlist) {
01615   
01616   LatticeUnion  *curlist, *nextlist;
01617   LatticeUnion *curr, *next;
01618   Bool change = True, chng;
01619   
01620   curlist = latlist;
01621   while (change == True) {
01622     change = False;
01623     LinearPartSort(curlist);
01624     curr = curlist;
01625     nextlist = NULL;
01626     while(curr != NULL) {
01627       next = curr->next;
01628       if (!SameLinearPart(curr, next)) {
01629         curr->next = NULL; 
01630         chng = AffinePartSimplify(curlist, &nextlist);
01631         change = change | chng ;
01632         curlist = next; 
01633       }
01634       curr = next; 
01635     }
01636     curlist = nextlist; 
01637   }
01638   return curlist;
01639 } /* LatticeSimplify */
01640 
01641 int intcompare (const void *a, const void *b) {
01642 
01643   int *i, *j;
01644   
01645   i = (int *) a;
01646   j = (int *) b;
01647   if (*i > *j)
01648     return 1;
01649   if (*i < *j)
01650     return -1;
01651   return 0;
01652 } /* intcompare */
01653 
01654 static int polylib_sqrt(int i);
01655 static factor allfactors (int num) {
01656  
01657   int i,j, tmp;
01658   int noofelmts = 1;
01659   int *list, *newlist;
01660   int count;
01661   factor result;
01662   
01663   list = (int *)malloc(sizeof (int));
01664   list[0] = 1;
01665   
01666   tmp = num;
01667   for (i = 2; i <= polylib_sqrt(tmp); i++) {
01668     if ((tmp % i) == 0) {
01669       if (noofelmts == 0) {
01670         list = (int *) malloc (sizeof (int));
01671         list[0] = i;
01672         noofelmts = 1;
01673       }
01674       else {
01675         newlist = (int *) malloc (sizeof (int) * 2 * noofelmts + 1);
01676         for (j = 0; j < noofelmts; j++)
01677           newlist[j] = list[j] ;
01678         newlist[j] = i;
01679         for (j = 0; j < noofelmts; j++)
01680           newlist[j+noofelmts+1] = i * list[j];
01681         free (list);
01682         list = newlist;
01683         noofelmts= 2*noofelmts+1;
01684       }
01685       tmp = tmp / i;
01686       i = 1;
01687     } 
01688   }
01689   
01690   if ((tmp != 0) && (tmp != num)) {
01691     newlist = (int *) malloc (sizeof (int) * 2 * noofelmts + 1);
01692     for (j = 0; j < noofelmts; j ++)
01693       newlist[j] = list[j] ;
01694     newlist[j] = tmp;
01695     for (j = 0; j < noofelmts; j ++)
01696       newlist[j+noofelmts+1] = tmp * list[j];
01697     free (list);
01698     list = newlist;
01699     noofelmts= 2*noofelmts+1;
01700   }  
01701   qsort (list, noofelmts, sizeof(int), intcompare);
01702   count = 1;
01703   for (i = 1; i < noofelmts; i ++)
01704     if (list[i] != list[i-1])
01705       list[count++] = list[i]; 
01706   if (list[count-1] == num)
01707     count --;
01708   
01709   result.fac = (int *) malloc (sizeof (int) * count);
01710   result.count = count;
01711   for (i = 0; i < count; i ++)
01712     result.fac[i] = list[i];
01713   free (list); 
01714   return result;
01715 } /* allfactors */
01716 
01717 static int polylib_sqrt (int i) {
01718   
01719   int j;
01720   j = 0;
01721   i = i > 0 ? i : -i;
01722   
01723   while (1) {
01724     if ((j * j) > i)
01725       break;
01726     else
01727       j ++;
01728   }
01729   return (j-1);
01730 } /* polylib_sqrt */
01731 
01732 
01733 
01734 
01735 
01736 
01737 

Generated on Mon Sep 12 14:48:29 2005 for polylib by doxygen 1.3.5