polylib: Lattice.c Source File

- Main Page
- Classes
- Files

# 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