polylib: Lattice.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# Lattice.c

Go to the documentation of this file.

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