polylib: alpha.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# alpha.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 /* polytest.c */
    00019 #include <stdio.h>
    00020 #include <polylib/polylib.h>
    00021
    00022 /* alpha.c
    00023      COPYRIGHT
    00024           Both this software and its documentation are
    00025
    00026               Copyright 1993 by IRISA /Universite de Rennes I - France,
    00027               Copyright 1995,1996 by BYU, Provo, Utah
    00028                          all rights reserved.
    00029
    00030           Permission is granted to copy, use, and distribute
    00031           for any commercial or noncommercial purpose under the terms
    00032           of the GNU General Public license, version 2, June 1991
    00033           (see file : LICENSING).
    00034 */
    00035
    00036 #include <stdio.h>
    00037 #include <stdlib.h>
    00038 #include <string.h>
    00039
    00040 /*---------------------------------------------------------------------*/
    00041 /* int exist_points(pos,P,context)                                     */
    00042 /*    pos : index position of current loop index (0..hdim-1)           */
    00043 /*    P: loop domain                                                   */
    00044 /*    context : context values for fixed indices                       */
    00045 /* recursive procedure, recurs for each imbriquation                   */
    00046 /* returns 1 if there exists any integer points in this polyhedron     */
    00047 /* returns 0 if there are none                                         */
    00048 /*---------------------------------------------------------------------*/
    00049 static int exist_points(int pos,Polyhedron *Pol,Value *context) {
    00050
    00051   Value LB, UB, k,tmp;
    00052
    00053   value_init(LB); value_init(UB);
    00054   value_init(k);  value_init(tmp);
    00055   value_set_si(LB,0);
    00056   value_set_si(UB,0);
    00057
    00058   /* Problem if UB or LB is INFINITY */
    00059   if (lower_upper_bounds(pos,Pol,context,&LB,&UB) !=0) {
    00060     errormsg1("exist_points", "infdom", "infinite domain");
    00061     value_clear(LB);
    00062     value_clear(UB);
    00063     value_clear(k);
    00064     value_clear(tmp);
    00065     return -1;
    00066   }
    00067   value_set_si(context[pos],0);
    00068   if(value_lt(UB,LB)) {
    00069     value_clear(LB);
    00070     value_clear(UB);
    00071     value_clear(k);
    00072     value_clear(tmp);
    00073     return 0;
    00074   }
    00075   if (!Pol->next) {
    00076     value_subtract(tmp,UB,LB);
    00077     value_increment(tmp,tmp);
    00078     value_clear(UB);
    00079     value_clear(LB);
    00080     value_clear(k);
    00081     return (value_pos_p(tmp));
    00082   }
    00083
    00084   for (value_assign(k,LB);value_le(k,UB);value_increment(k,k)) {
    00085
    00086     /* insert k in context */
    00087     value_assign(context[pos],k);
    00088     if (exist_points(pos+1,Pol->next,context) > 0 ) {
    00089       value_clear(LB); value_clear(UB);
    00090       value_clear(k); value_clear(tmp);
    00091       return 1;
    00092     }
    00093   }
    00094   /* Reset context */
    00095   value_set_si(context[pos],0);
    00096   value_clear(UB); value_clear(LB);
    00097   value_clear(k); value_clear(tmp);
    00098   return 0;
    00099 }
    00100
    00101 /*--------------------------------------------------------------*/
    00102 /* Test to see if there are any integral points in a polyhedron */
    00103 /*--------------------------------------------------------------*/
    00104 int Polyhedron_Not_Empty(Polyhedron *P,Polyhedron *C,int MAXRAYS) {
    00105
    00106   int res,i;
    00107   Value *context;
    00108   Polyhedron *L;
    00109
    00110   POL_ENSURE_FACETS(P);
    00111   POL_ENSURE_VERTICES(P);
    00112   POL_ENSURE_FACETS(C);
    00113   POL_ENSURE_VERTICES(C);
    00114
    00115   /* Create a context vector size dim+2 and set it to all zeros */
    00116   context = (Value *) malloc((P->Dimension+2)*sizeof(Value));
    00117
    00118   /* Initialize array 'context' */
    00119   for (i=0;i<(P->Dimension+2);i++)
    00120     value_init(context[i]);
    00121
    00122   Vector_Set(context,0,(P->Dimension+2));
    00123
    00124   /* Set context[P->Dimension+1] = 1  (the constant) */
    00125   value_set_si(context[P->Dimension+1],1);
    00126
    00127   L = Polyhedron_Scan(P,C,MAXRAYS);
    00128   res = exist_points(1,L,context);
    00129   Domain_Free(L);
    00130
    00131   /* Clear array 'context' */
    00132   for (i=0;i<(P->Dimension+2);i++)
    00133     value_clear(context[i]);
    00134   free(context);
    00135   return res;
    00136 }
    00137
    00138 /* PolyhedronLTQ ( P1, P2 ) */
    00139 /* P1 and P2 must be simple polyhedra */
    00140 /* result =  0 --> not comparable */
    00141 /* result = -1 --> P1 < P2        */
    00142 /* result =  1 --> P1 > P2        */
    00143 /* INDEX  = 1 .... Dimension      */
    00144 int PolyhedronLTQ (Polyhedron *Pol1,Polyhedron *Pol2,int INDEX, int PDIM, int NbMaxConstrs) {
    00145
    00146   int res, dim, i, j, k;
    00147   Polyhedron *Q1, *Q2, *Q3, *Q4, *Q;
    00148   Matrix *Mat;
    00149
    00150   if (Pol1->next || Pol2->next) {
    00151     errormsg1("PolyhedronLTQ", "compoly", "Can only compare polyhedra");
    00152     return 0;
    00153   }
    00154   if (Pol1->Dimension != Pol2->Dimension) {
    00155     errormsg1("PolyhedronLTQ","diffdim","Polyhedra are not same dimension");
    00156     return 0;
    00157   }
    00158   dim = Pol1->Dimension+2;
    00159
    00160   POL_ENSURE_FACETS(Pol1);
    00161   POL_ENSURE_VERTICES(Pol1);
    00162   POL_ENSURE_FACETS(Pol2);
    00163   POL_ENSURE_VERTICES(Pol2);
    00164
    00165 #ifdef DEBUG
    00166   fprintf(stdout, "P1\n");
    00167   Polyhedron_Print(stdout,P_VALUE_FMT,Pol1);
    00168   fprintf(stdout, "P2\n");
    00169   Polyhedron_Print(stdout,P_VALUE_FMT,Pol2);
    00170 #endif
    00171
    00172   /* Create the Line to add */
    00173   k = Pol1->Dimension-INDEX+1-PDIM;
    00174   Mat = Matrix_Alloc(k,dim);
    00175   Vector_Set(Mat->p_Init,0,dim*k);
    00176   for(j=0,i=INDEX;j<k;i++,j++)
    00177     value_set_si(Mat->p[j][i],1);
    00178
    00179   Q1 = AddRays(Mat->p[0],k,Pol1,NbMaxConstrs);
    00180   Q2 = AddRays(Mat->p[0],k,Pol2,NbMaxConstrs);
    00181
    00182 #ifdef DEBUG
    00183   fprintf(stdout, "Q1\n");
    00184   Polyhedron_Print(stdout,P_VALUE_FMT,Q1);
    00185   fprintf(stdout, "Q2\n");
    00186   Polyhedron_Print(stdout,P_VALUE_FMT,Q2);
    00187 #endif
    00188
    00189   Matrix_Free(Mat);
    00190   Q  = DomainIntersection(Q1,Q2,NbMaxConstrs);
    00191
    00192 #ifdef DEBUG
    00193   fprintf(stdout, "Q\n");
    00194   Polyhedron_Print(stdout,P_VALUE_FMT,Q);
    00195 #endif
    00196
    00197   Domain_Free(Q1);
    00198   Domain_Free(Q2);
    00199
    00200   if (emptyQ(Q)) res = 0;       /* not comparable */
    00201   else {
    00202     Q1 = DomainIntersection(Pol1,Q,NbMaxConstrs);
    00203     Q2 = DomainIntersection(Pol2,Q,NbMaxConstrs);
    00204
    00205 #ifdef DEBUG
    00206     fprintf(stdout, "Q1\n");
    00207     Polyhedron_Print(stdout,P_VALUE_FMT,Q1);
    00208     fprintf(stdout, "Q2\n");
    00209     Polyhedron_Print(stdout,P_VALUE_FMT,Q2);
    00210 #endif
    00211
    00212     k = Q1->NbConstraints + Q2->NbConstraints;
    00213     Mat = Matrix_Alloc(k, dim);
    00214     Vector_Set(Mat->p_Init,0,k*dim);
    00215
    00216     /* First compute surrounding polyhedron */
    00217     j=0;
    00218     for (i=0; i<Q1->NbConstraints; i++) {
    00219       if ((value_one_p(Q1->Constraint[i][0])) && (value_pos_p(Q1->Constraint[i][INDEX]))) {
    00220
    00221         /* keep Q1's lower bounds */
    00222         for (k=0; k<dim; k++)
    00223           value_assign(Mat->p[j][k],Q1->Constraint[i][k]);
    00224         j++;
    00225       }
    00226     }
    00227     for (i=0; i<Q2->NbConstraints; i++) {
    00228       if ((value_one_p(Q2->Constraint[i][0])) && (value_neg_p(Q2->Constraint[i][INDEX]))) {
    00229
    00230         /* and keep Q2's upper bounds */
    00231         for (k=0; k<dim; k++)
    00232           value_assign(Mat->p[j][k],Q2->Constraint[i][k]);
    00233         j++;
    00234       }
    00235     }
    00236     Q4 = AddConstraints(Mat->p[0], j, Q, NbMaxConstrs);
    00237     Matrix_Free(Mat);
    00238
    00239 #ifdef debug
    00240     fprintf(stderr, "Q4 surrounding polyhedron\n");
    00241     Polyhderon_Print(stderr,P_VALUE_FMT, Q4);
    00242 #endif
    00243
    00244     /* if surrounding polyhedron is empty, D1>D2 */
    00245     if (emptyQ(Q4)) {
    00246       res = 1;
    00247
    00248 #ifdef debug
    00249       fprintf(stderr, "Surrounding polyhedron is empty\n");
    00250 #endif
    00251       goto LTQdone2;
    00252     }
    00253
    00254     /* Test if Q1 < Q2 */
    00255     /* Build a constraint array for >= Q1 and <= Q2 */
    00256     Mat = Matrix_Alloc(2,dim);
    00257     Vector_Set(Mat->p_Init,0,2*dim);
    00258
    00259     /* Choose a contraint from Q1 */
    00260     for (i=0; i<Q1->NbConstraints; i++) {
    00261       if (value_zero_p(Q1->Constraint[i][0])) {
    00262
    00263         /* Equality */
    00264         if (value_zero_p(Q1->Constraint[i][INDEX])) {
    00265
    00266           /* Ignore side constraint (they are in Q) */
    00267           continue;
    00268         }
    00269         else if (value_neg_p(Q1->Constraint[i][INDEX])) {
    00270
    00271           /* copy -constraint to Mat */
    00272           value_set_si(Mat->p[0][0],1);
    00273           for (k=1; k<dim; k++)
    00274             value_oppose(Mat->p[0][k],Q1->Constraint[i][k]);
    00275         }
    00276         else {
    00277
    00278           /* Copy constraint to Mat */
    00279
    00280           value_set_si(Mat->p[0][0],1);
    00281           for (k=1; k<dim; k++)
    00282             value_assign(Mat->p[0][k],Q1->Constraint[i][k]);
    00283         }
    00284       }
    00285       else if(value_neg_p(Q1->Constraint[i][INDEX])) {
    00286
    00287         /* Upper bound -- make a lower bound from it */
    00288         value_set_si(Mat->p[0][0],1);
    00289         for (k=1; k<dim; k++)
    00290           value_oppose(Mat->p[0][k],Q1->Constraint[i][k]);
    00291       }
    00292       else {
    00293
    00294         /* Lower or side bound -- ignore it */
    00295         continue;
    00296       }
    00297
    00298       /* Choose a constraint from Q2 */
    00299       for (j=0; j<Q2->NbConstraints; j++) {
    00300         if (value_zero_p(Q2->Constraint[j][0])) {   /* equality */
    00301           if (value_zero_p(Q2->Constraint[j][INDEX])) {
    00302
    00303             /* Ignore side constraint (they are in Q) */
    00304             continue;
    00305           }
    00306           else if (value_pos_p(Q2->Constraint[j][INDEX])) {
    00307
    00308             /* Copy -constraint to Mat */
    00309             value_set_si(Mat->p[1][0],1);
    00310             for (k=1; k<dim; k++)
    00311               value_oppose(Mat->p[1][k],Q2->Constraint[j][k]);
    00312           }
    00313           else {
    00314
    00315             /* Copy constraint to Mat */
    00316             value_set_si(Mat->p[1][0],1);
    00317             for (k=1; k<dim; k++)
    00318               value_assign(Mat->p[1][k],Q2->Constraint[j][k]);
    00319           };
    00320         }
    00321         else if (value_pos_p(Q2->Constraint[j][INDEX])) {
    00322
    00323           /* Lower bound -- make an upper bound from it */
    00324           value_set_si(Mat->p[1][0],1);
    00325           for(k=1;k<dim;k++)
    00326             value_oppose(Mat->p[1][k],Q2->Constraint[j][k]);
    00327         }
    00328         else {
    00329
    00330           /* Upper or side bound -- ignore it */
    00331           continue;
    00332         };
    00333
    00334 #ifdef DEBUG
    00335         fprintf(stdout, "i=%d j=%d M=\n", i+1, j+1);
    00336         Matrix_Print(stdout,P_VALUE_FMT,Mat);
    00337 #endif
    00338
    00339         /* Add Mat to Q and see if anything is made */
    00340         Q3 = AddConstraints(Mat->p[0],2,Q,NbMaxConstrs);
    00341
    00342 #ifdef DEBUG
    00343         fprintf(stdout, "Q3\n");
    00344         Polyhedron_Print(stdout,P_VALUE_FMT,Q3);
    00345 #endif
    00346
    00347         if (!emptyQ(Q3)) {
    00348           Domain_Free(Q3);
    00349
    00350 #ifdef DEBUG
    00351           fprintf(stdout, "not empty\n");
    00352 #endif
    00353           res = -1;
    00354           goto LTQdone;
    00355         }
    00356 #ifdef DEBUG
    00357         fprintf(stdout,"empty\n");
    00358 #endif
    00359         Domain_Free(Q3);
    00360       } /* end for j */
    00361     } /* end for i */
    00362     res = 1;
    00363 LTQdone:
    00364     Matrix_Free(Mat);
    00365 LTQdone2:
    00366     Domain_Free(Q4);
    00367     Domain_Free(Q1);
    00368     Domain_Free(Q2);
    00369   }
    00370   Domain_Free(Q);
    00371
    00372 #ifdef DEBUG
    00373   fprintf(stdout, "res = %d\n", res);
    00374 #endif
    00375
    00376   return res;
    00377 } /* PolyhedronLTQ */
    00378
    00379 /* GaussSimplify --
    00380    Given Mat1, a matrix of equalities, performs Gaussian elimination.
    00381    Find a minimum basis, Returns the rank.
    00382    Mat1 is context, Mat2 is reduced in context of Mat1
    00383 */
    00384 int GaussSimplify(Matrix *Mat1,Matrix *Mat2) {
    00385
    00386   int NbRows = Mat1->NbRows;
    00387   int NbCols = Mat1->NbColumns;
    00388   int *column_index;
    00389   int i, j, k, n, t, pivot, Rank;
    00390   Value gcd, tmp, *cp;
    00391
    00392   column_index=(int *)malloc(NbCols * sizeof(int));
    00393   if (!column_index) {
    00394     errormsg1("GaussSimplify", "outofmem", "out of memory space\n");
    00395     Pol_status = 1;
    00396     return 0;
    00397   }
    00398
    00399   /* Initialize all the 'Value' variables */
    00400   value_init(gcd); value_init(tmp);
    00401
    00402   Rank=0;
    00403   for (j=0; j<NbCols; j++) {              /* for each column starting at */
    00404     for (i=Rank; i<NbRows; i++)           /* diagonal, look down to find */
    00405       if (value_notzero_p(Mat1->p[i][j])) /* the first non-zero entry    */
    00406         break;
    00407     if (i!=NbRows) {                      /* was one found ? */
    00408       if (i!=Rank)                        /* was it found below the diagonal?*/
    00409         Vector_Exchange(Mat1->p[Rank],Mat1->p[i],NbCols);
    00410
    00411       /* Normalize the pivot row */
    00412       Vector_Gcd(Mat1->p[Rank],NbCols,&gcd);
    00413
    00414       /* If (gcd >= 2) */
    00415       value_set_si(tmp,2);
    00416       if (value_ge(gcd,tmp)) {
    00417         cp = Mat1->p[Rank];
    00418         for (k=0; k<NbCols; k++,cp++)
    00419           value_division(*cp,*cp,gcd);
    00420       }
    00421       if (value_neg_p(Mat1->p[Rank][j])) {
    00422         cp = Mat1->p[Rank];
    00423         for (k=0; k<NbCols; k++,cp++)
    00424           value_oppose(*cp,*cp);
    00425       }
    00426       /* End of normalize */
    00427       pivot=i;
    00428       for (i=0;i<NbRows;i++)    /* Zero out the rest of the column */
    00429         if (i!=Rank) {
    00430           if (value_notzero_p(Mat1->p[i][j])) {
    00431             Value a, a1, a2, a1abs, a2abs;
    00432             value_init(a); value_init(a1); value_init(a2);
    00433             value_init(a1abs); value_init(a2abs);
    00434             value_assign(a1,Mat1->p[i][j]);
    00435             value_absolute(a1abs,a1);
    00436             value_assign(a2,Mat1->p[Rank][j]);
    00437             value_absolute(a2abs,a2);
    00438             value_gcd(a, a1abs, a2abs);
    00439             value_divexact(a1, a1, a);
    00440             value_divexact(a2, a2, a);
    00441             value_oppose(a1,a1);
    00442             Vector_Combine(Mat1->p[i],Mat1->p[Rank],Mat1->p[i],a2,
    00443                            a1,NbCols);
    00444             Vector_Normalize(Mat1->p[i],NbCols);
    00445             value_clear(a); value_clear(a1); value_clear(a2);
    00446             value_clear(a1abs); value_clear(a2abs);
    00447           }
    00448         }
    00449       column_index[Rank]=j;
    00450       Rank++;
    00451     }
    00452   } /* end of Gauss elimination */
    00453
    00454
    00455   if (Mat2) {  /* Mat2 is a transformation matrix  (i,j->f(i,j))....
    00456                   can't scale it because can't scale both sides of -> */
    00457     /* normalizes an affine transformation        */
    00458     /* priority of forms                          */
    00459     /*    1. i' -> i                (identity)    */
    00460     /*    2. i' -> i + constant     (uniform)     */
    00461     /*    3. i' -> constant         (broadcast)   */
    00462     /*    4. i' -> j                (permutation) */
    00463     /*    5. i' -> j + constant     (      )      */
    00464     /*    6. i' -> i + j + constant (non-uniform) */
    00465     for (k=0; k<Rank; k++) {
    00466       j = column_index[k];
    00467       for (i=0; i<(Mat2->NbRows-1);i++) {   /* all but the last row 0...0 1 */
    00468         if ((i!=j) && value_notzero_p(Mat2->p[i][j])) {
    00469
    00470           /* Remove dependency of i' on j */
    00471           Value a, a1, a1abs, a2, a2abs;
    00472           value_init(a); value_init(a1); value_init(a2);
    00473           value_init(a1abs); value_init(a2abs);
    00474           value_assign(a1,Mat2->p[i][j]);
    00475           value_absolute(a1abs,a1);
    00476           value_assign(a2,Mat1->p[k][j]);
    00477           value_absolute(a2abs,a2);
    00478           value_gcd(a, a1abs, a2abs);
    00479           value_divexact(a1, a1, a);
    00480           value_divexact(a2, a2, a);
    00481           value_oppose(a1,a1);
    00482           if (value_one_p(a2)) {
    00483             Vector_Combine(Mat2->p[i],Mat1->p[k],Mat2->p[i],a2,
    00484                            a1,NbCols);
    00485
    00486             /* Vector_Normalize(Mat2->p[i],NbCols); -- can't do T        */
    00487           } /* otherwise, can't do it without mult lhs prod (2i,3j->...) */
    00488           value_clear(a); value_clear(a1); value_clear(a2);
    00489           value_clear(a1abs); value_clear(a2abs);
    00490
    00491         }
    00492         else if ((i==j) && value_zero_p(Mat2->p[i][j])) {
    00493
    00494           /* 'i' does not depend on j */
    00495           for (n=j+1; n < (NbCols-1); n++) {
    00496             if (value_notzero_p(Mat2->p[i][n])) { /* i' depends on some n */
    00497               value_set_si(tmp,1);
    00498               Vector_Combine(Mat2->p[i],Mat1->p[k],Mat2->p[i],tmp,
    00499                              tmp,NbCols);
    00500               break;
    00501             }  /* if 'i' depends on just a constant, then leave it alone.*/
    00502           }
    00503         }
    00504       }
    00505     }
    00506
    00507     /* Check last row of transformation Mat2 */
    00508     for (j=0; j<(NbCols-1); j++)
    00509       if (value_notzero_p(Mat2->p[Mat2->NbRows-1][j])) {
    00510         errormsg1("GaussSimplify", "corrtrans", "Corrupted transformation\n");
    00511         break;
    00512       }
    00513
    00514     if (value_notone_p(Mat2->p[Mat2->NbRows-1][NbCols-1])) {
    00515       errormsg1("GaussSimplify", "corrtrans", "Corrupted transformation\n");
    00516     }
    00517   }
    00518   value_clear(gcd); value_clear(tmp);
    00519   free(column_index);
    00520   return Rank;
    00521 } /* GaussSimplify */
    00522
    00523 /*
    00524  * Topologically sort 'n' polyhdera and return 0 on failure, otherwise return
    00525  * 1 on success. Here 'L' is a an array of pointers to polyhedra, 'n' is the
    00526  * number of polyhedra, 'index' is the level to consider for partial ordering
    00527  * 'pdim' is the parameter space dimension, 'time' is an array of 'n' integers
    00528  * to store logical time values, 'pvect', if not NULL, is an array of 'n'
    00529  * integers that contains a permutation specification after call and MAXRAYS is
    00530  * the workspace size for polyhedra operations.
    00531  */
    00532 int PolyhedronTSort (Polyhedron **L,unsigned int n,unsigned int index,unsigned int pdim,int *time,int *pvect,unsigned int MAXRAYS) {
    00533
    00534   unsigned int const nbcells = ((n*(n-1))>>1);    /* Number of memory cells
    00535                                                      to allocate, see below */
    00536   int *dag;  /* The upper triangular matrix */
    00537   int **p;   /* Array of matrix row addresses */
    00538   unsigned int i, j, k;
    00539   unsigned int t, nb, isroot;
    00540
    00541   if (n<2) return 0;
    00542
    00543   /* we need an upper triangular matrix (example with n=4):
    00544
    00545      . o o o
    00546      . . o o     . are unuseful cells, o are useful cells
    00547      . . . o
    00548      . . . .
    00549
    00550      so we need to allocate (n)(n-1)/2 cells
    00551      - dag will point to this memory.
    00552      - p[i] will point to row i of the matrix
    00553      p[0] = dag - 1 (such that p[0][1] == dag[0])
    00554      p[1] = dag - 1 + (n-1)
    00555      p[2] = dag - 1 + (n-1) + (n-2)
    00556      ...
    00557      p[i] = p[i-1] + (n-1-i)
    00558   */
    00559
    00560   /* malloc n(n-1)/2 for dag and n-1 for p (node n does not have any row) */
    00561   dag = (int *) malloc(nbcells*sizeof(int));
    00562   if (!dag) return 0;
    00563   p = (int **) malloc ((n-1) * sizeof(int *));
    00564   if (!p) {
    00565     free(dag); return 0;
    00566   }
    00567
    00568   /* Initialize 'p' and 'dag' */
    00569   p[0] = dag-1;
    00570   for (i=1; i<n-1; i++)
    00571     p[i] = p[i-1] + (n-1)-i;
    00572   for (i=0; i<nbcells; i++)
    00573     dag[i] = -2;      /* -2 means 'not computed yet' */
    00574   for (i=0; i<n; i++) time[i] = -1;
    00575
    00576   /* Compute the dag using transitivity to reduce the number of */
    00577   /*   PolyhedronLTQ calls.                                     */
    00578   for (i=0; i<n-1; i++) {
    00579     POL_ENSURE_FACETS(L[i]);
    00580     POL_ENSURE_VERTICES(L[i]);
    00581     for (j=i+1; j<n; j++) {
    00582       if (p[i][j] == -2) /* not computed yes */
    00583         p[i][j] = PolyhedronLTQ(L[i], L[j], index, pdim, MAXRAYS);
    00584       if (p[i][j] != 0) {
    00585
    00586         /* if p[i][j] is 1 or -1, look for -p[i][j] on the same row:
    00587            p[i][j] == -p[i][k] ==> p[j][k] = p[i][k] (transitivity)
    00588            note: p[r][c] == -p[c][r], use this to avoid reading or writing
    00589            under the matrix diagonal
    00590         */
    00591
    00592         /* first, k<i so look for p[i][j] == p[k][i] (i.e. -p[i][k]) */
    00593         for (k=0; k<i; k++)
    00594           if (p[k][i] == p[i][j]) p[k][j] = p[k][i];
    00595
    00596         /* then, i<k<j so look for p[i][j] == -p[i][k] */
    00597         for (k=i+1; k<j; k++)
    00598           if (p[i][k] == -p[i][j]) p[k][j] = -p[i][k];
    00599
    00600         /* last, k>j same search but */
    00601         for (k=j+1; k<n; k++)
    00602           if (p[i][k] == -p[i][j]) p[j][k] = p[i][k];
    00603       }
    00604     }
    00605   }
    00606
    00607   /* walk thru the dag to compute the partial order (and optionally
    00608      the permutation)
    00609      Note: this is not the fastest way to do it but it takes
    00610      negligible time compared to a single call of PolyhedronLTQ !
    00611      Each macro-step (while loop) gives the same logical time to all
    00612      found roots and optionally add these nodes in the permutation vector
    00613   */
    00614
    00615   t = 0; /* current logical time, assigned to current roots and
    00616             increased by 1 at the end of each step */
    00617   nb = 0; /* number of processed nodes (have been given a time) */
    00618   while (nb<n) {
    00619     for (i=0; i<n; i++) { /* search for roots */
    00620       /* for any node, if it's not already been given a logical time
    00621          then walk thru the node row; if we find a 1 at some column j,
    00622          it means that node j preceeds the current node, so it is not
    00623          a root */
    00624       if (time[i]<0) {
    00625         isroot = 1; /* assume that it is until it is definitely not */
    00626         /* first search on a column */
    00627         for (j=0; j<i; j++) {
    00628           if (p[j][i]==-1) { /* found a node lower than it */
    00629             isroot = 0; break;
    00630           }
    00631         }
    00632         if /*still*/ (isroot)
    00633           for (j=i+1; j<n; j++) {
    00634             if (p[i][j]==1) { /* greater than this node */
    00635               isroot = 0; break;
    00636             }
    00637           }
    00638         if (isroot) { /* then it definitely is */
    00639           time[i] = t; /* this node gets current logical time */
    00640           if (pvect)
    00641             pvect[nb] = i+1; /* nodes will be numbered from 1 to n */
    00642           nb++; /* one more node processed */
    00643         }
    00644       }
    00645     }
    00646     /* now make roots become neutral, i.e. non comparable with all other nodes */
    00647     for (i=0; i<n; i++) {
    00648       if (time[i]==t) {
    00649         for (j=0; j<i; j++)
    00650           p[j][i] = 0;
    00651         for (j=i+1; j<n; j++)
    00652           p[i][j] = 0;
    00653       }
    00654     }
    00655     t++; /* ready for next set of root nodes */
    00656   }
    00657
    00658   free (p);   /* let's be clean, collect the garbage */
    00659   free (dag);
    00660   return 1;
    00661 } /* PolyhedronTSort */
    00662
    00663
    00664
    00665