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

Generated on Thu Sep 4 15:28:58 2008 for polylib by doxygen 1.3.5