src/glplux.c
changeset 2 4c8956a7bdf4
equal deleted inserted replaced
-1:000000000000 0:71db7b341309
       
     1 /* glplux.c */
       
     2 
       
     3 /***********************************************************************
       
     4 *  This code is part of GLPK (GNU Linear Programming Kit).
       
     5 *
       
     6 *  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
       
     7 *  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
       
     8 *  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
       
     9 *  E-mail: <mao@gnu.org>.
       
    10 *
       
    11 *  GLPK is free software: you can redistribute it and/or modify it
       
    12 *  under the terms of the GNU General Public License as published by
       
    13 *  the Free Software Foundation, either version 3 of the License, or
       
    14 *  (at your option) any later version.
       
    15 *
       
    16 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
       
    17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
       
    18 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
       
    19 *  License for more details.
       
    20 *
       
    21 *  You should have received a copy of the GNU General Public License
       
    22 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
       
    23 ***********************************************************************/
       
    24 
       
    25 #include "glplux.h"
       
    26 #define xfault xerror
       
    27 #define dmp_create_poolx(size) dmp_create_pool()
       
    28 
       
    29 /*----------------------------------------------------------------------
       
    30 // lux_create - create LU-factorization.
       
    31 //
       
    32 // SYNOPSIS
       
    33 //
       
    34 // #include "glplux.h"
       
    35 // LUX *lux_create(int n);
       
    36 //
       
    37 // DESCRIPTION
       
    38 //
       
    39 // The routine lux_create creates LU-factorization data structure for
       
    40 // a matrix of the order n. Initially the factorization corresponds to
       
    41 // the unity matrix (F = V = P = Q = I, so A = I).
       
    42 //
       
    43 // RETURNS
       
    44 //
       
    45 // The routine returns a pointer to the created LU-factorization data
       
    46 // structure, which represents the unity matrix of the order n. */
       
    47 
       
    48 LUX *lux_create(int n)
       
    49 {     LUX *lux;
       
    50       int k;
       
    51       if (n < 1)
       
    52          xfault("lux_create: n = %d; invalid parameter\n", n);
       
    53       lux = xmalloc(sizeof(LUX));
       
    54       lux->n = n;
       
    55       lux->pool = dmp_create_poolx(sizeof(LUXELM));
       
    56       lux->F_row = xcalloc(1+n, sizeof(LUXELM *));
       
    57       lux->F_col = xcalloc(1+n, sizeof(LUXELM *));
       
    58       lux->V_piv = xcalloc(1+n, sizeof(mpq_t));
       
    59       lux->V_row = xcalloc(1+n, sizeof(LUXELM *));
       
    60       lux->V_col = xcalloc(1+n, sizeof(LUXELM *));
       
    61       lux->P_row = xcalloc(1+n, sizeof(int));
       
    62       lux->P_col = xcalloc(1+n, sizeof(int));
       
    63       lux->Q_row = xcalloc(1+n, sizeof(int));
       
    64       lux->Q_col = xcalloc(1+n, sizeof(int));
       
    65       for (k = 1; k <= n; k++)
       
    66       {  lux->F_row[k] = lux->F_col[k] = NULL;
       
    67          mpq_init(lux->V_piv[k]);
       
    68          mpq_set_si(lux->V_piv[k], 1, 1);
       
    69          lux->V_row[k] = lux->V_col[k] = NULL;
       
    70          lux->P_row[k] = lux->P_col[k] = k;
       
    71          lux->Q_row[k] = lux->Q_col[k] = k;
       
    72       }
       
    73       lux->rank = n;
       
    74       return lux;
       
    75 }
       
    76 
       
    77 /*----------------------------------------------------------------------
       
    78 // initialize - initialize LU-factorization data structures.
       
    79 //
       
    80 // This routine initializes data structures for subsequent computing
       
    81 // the LU-factorization of a given matrix A, which is specified by the
       
    82 // formal routine col. On exit V = A and F = P = Q = I, where I is the
       
    83 // unity matrix. */
       
    84 
       
    85 static void initialize(LUX *lux, int (*col)(void *info, int j,
       
    86       int ind[], mpq_t val[]), void *info, LUXWKA *wka)
       
    87 {     int n = lux->n;
       
    88       DMP *pool = lux->pool;
       
    89       LUXELM **F_row = lux->F_row;
       
    90       LUXELM **F_col = lux->F_col;
       
    91       mpq_t *V_piv = lux->V_piv;
       
    92       LUXELM **V_row = lux->V_row;
       
    93       LUXELM **V_col = lux->V_col;
       
    94       int *P_row = lux->P_row;
       
    95       int *P_col = lux->P_col;
       
    96       int *Q_row = lux->Q_row;
       
    97       int *Q_col = lux->Q_col;
       
    98       int *R_len = wka->R_len;
       
    99       int *R_head = wka->R_head;
       
   100       int *R_prev = wka->R_prev;
       
   101       int *R_next = wka->R_next;
       
   102       int *C_len = wka->C_len;
       
   103       int *C_head = wka->C_head;
       
   104       int *C_prev = wka->C_prev;
       
   105       int *C_next = wka->C_next;
       
   106       LUXELM *fij, *vij;
       
   107       int i, j, k, len, *ind;
       
   108       mpq_t *val;
       
   109       /* F := I */
       
   110       for (i = 1; i <= n; i++)
       
   111       {  while (F_row[i] != NULL)
       
   112          {  fij = F_row[i], F_row[i] = fij->r_next;
       
   113             mpq_clear(fij->val);
       
   114             dmp_free_atom(pool, fij, sizeof(LUXELM));
       
   115          }
       
   116       }
       
   117       for (j = 1; j <= n; j++) F_col[j] = NULL;
       
   118       /* V := 0 */
       
   119       for (k = 1; k <= n; k++) mpq_set_si(V_piv[k], 0, 1);
       
   120       for (i = 1; i <= n; i++)
       
   121       {  while (V_row[i] != NULL)
       
   122          {  vij = V_row[i], V_row[i] = vij->r_next;
       
   123             mpq_clear(vij->val);
       
   124             dmp_free_atom(pool, vij, sizeof(LUXELM));
       
   125          }
       
   126       }
       
   127       for (j = 1; j <= n; j++) V_col[j] = NULL;
       
   128       /* V := A */
       
   129       ind = xcalloc(1+n, sizeof(int));
       
   130       val = xcalloc(1+n, sizeof(mpq_t));
       
   131       for (k = 1; k <= n; k++) mpq_init(val[k]);
       
   132       for (j = 1; j <= n; j++)
       
   133       {  /* obtain j-th column of matrix A */
       
   134          len = col(info, j, ind, val);
       
   135          if (!(0 <= len && len <= n))
       
   136             xfault("lux_decomp: j = %d: len = %d; invalid column length"
       
   137                "\n", j, len);
       
   138          /* copy elements of j-th column to matrix V */
       
   139          for (k = 1; k <= len; k++)
       
   140          {  /* get row index of a[i,j] */
       
   141             i = ind[k];
       
   142             if (!(1 <= i && i <= n))
       
   143                xfault("lux_decomp: j = %d: i = %d; row index out of ran"
       
   144                   "ge\n", j, i);
       
   145             /* check for duplicate indices */
       
   146             if (V_row[i] != NULL && V_row[i]->j == j)
       
   147                xfault("lux_decomp: j = %d: i = %d; duplicate row indice"
       
   148                   "s not allowed\n", j, i);
       
   149             /* check for zero value */
       
   150             if (mpq_sgn(val[k]) == 0)
       
   151                xfault("lux_decomp: j = %d: i = %d; zero elements not al"
       
   152                   "lowed\n", j, i);
       
   153             /* add new element v[i,j] = a[i,j] to V */
       
   154             vij = dmp_get_atom(pool, sizeof(LUXELM));
       
   155             vij->i = i, vij->j = j;
       
   156             mpq_init(vij->val);
       
   157             mpq_set(vij->val, val[k]);
       
   158             vij->r_prev = NULL;
       
   159             vij->r_next = V_row[i];
       
   160             vij->c_prev = NULL;
       
   161             vij->c_next = V_col[j];
       
   162             if (vij->r_next != NULL) vij->r_next->r_prev = vij;
       
   163             if (vij->c_next != NULL) vij->c_next->c_prev = vij;
       
   164             V_row[i] = V_col[j] = vij;
       
   165          }
       
   166       }
       
   167       xfree(ind);
       
   168       for (k = 1; k <= n; k++) mpq_clear(val[k]);
       
   169       xfree(val);
       
   170       /* P := Q := I */
       
   171       for (k = 1; k <= n; k++)
       
   172          P_row[k] = P_col[k] = Q_row[k] = Q_col[k] = k;
       
   173       /* the rank of A and V is not determined yet */
       
   174       lux->rank = -1;
       
   175       /* initially the entire matrix V is active */
       
   176       /* determine its row lengths */
       
   177       for (i = 1; i <= n; i++)
       
   178       {  len = 0;
       
   179          for (vij = V_row[i]; vij != NULL; vij = vij->r_next) len++;
       
   180          R_len[i] = len;
       
   181       }
       
   182       /* build linked lists of active rows */
       
   183       for (len = 0; len <= n; len++) R_head[len] = 0;
       
   184       for (i = 1; i <= n; i++)
       
   185       {  len = R_len[i];
       
   186          R_prev[i] = 0;
       
   187          R_next[i] = R_head[len];
       
   188          if (R_next[i] != 0) R_prev[R_next[i]] = i;
       
   189          R_head[len] = i;
       
   190       }
       
   191       /* determine its column lengths */
       
   192       for (j = 1; j <= n; j++)
       
   193       {  len = 0;
       
   194          for (vij = V_col[j]; vij != NULL; vij = vij->c_next) len++;
       
   195          C_len[j] = len;
       
   196       }
       
   197       /* build linked lists of active columns */
       
   198       for (len = 0; len <= n; len++) C_head[len] = 0;
       
   199       for (j = 1; j <= n; j++)
       
   200       {  len = C_len[j];
       
   201          C_prev[j] = 0;
       
   202          C_next[j] = C_head[len];
       
   203          if (C_next[j] != 0) C_prev[C_next[j]] = j;
       
   204          C_head[len] = j;
       
   205       }
       
   206       return;
       
   207 }
       
   208 
       
   209 /*----------------------------------------------------------------------
       
   210 // find_pivot - choose a pivot element.
       
   211 //
       
   212 // This routine chooses a pivot element v[p,q] in the active submatrix
       
   213 // of matrix U = P*V*Q.
       
   214 //
       
   215 // It is assumed that on entry the matrix U has the following partially
       
   216 // triangularized form:
       
   217 //
       
   218 //       1       k         n
       
   219 //    1  x x x x x x x x x x
       
   220 //       . x x x x x x x x x
       
   221 //       . . x x x x x x x x
       
   222 //       . . . x x x x x x x
       
   223 //    k  . . . . * * * * * *
       
   224 //       . . . . * * * * * *
       
   225 //       . . . . * * * * * *
       
   226 //       . . . . * * * * * *
       
   227 //       . . . . * * * * * *
       
   228 //    n  . . . . * * * * * *
       
   229 //
       
   230 // where rows and columns k, k+1, ..., n belong to the active submatrix
       
   231 // (elements of the active submatrix are marked by '*').
       
   232 //
       
   233 // Since the matrix U = P*V*Q is not stored, the routine works with the
       
   234 // matrix V. It is assumed that the row-wise representation corresponds
       
   235 // to the matrix V, but the column-wise representation corresponds to
       
   236 // the active submatrix of the matrix V, i.e. elements of the matrix V,
       
   237 // which does not belong to the active submatrix, are missing from the
       
   238 // column linked lists. It is also assumed that each active row of the
       
   239 // matrix V is in the set R[len], where len is number of non-zeros in
       
   240 // the row, and each active column of the matrix V is in the set C[len],
       
   241 // where len is number of non-zeros in the column (in the latter case
       
   242 // only elements of the active submatrix are counted; such elements are
       
   243 // marked by '*' on the figure above).
       
   244 //
       
   245 // Due to exact arithmetic any non-zero element of the active submatrix
       
   246 // can be chosen as a pivot. However, to keep sparsity of the matrix V
       
   247 // the routine uses Markowitz strategy, trying to choose such element
       
   248 // v[p,q], which has smallest Markowitz cost (nr[p]-1) * (nc[q]-1),
       
   249 // where nr[p] and nc[q] are the number of non-zero elements, resp., in
       
   250 // p-th row and in q-th column of the active submatrix.
       
   251 //
       
   252 // In order to reduce the search, i.e. not to walk through all elements
       
   253 // of the active submatrix, the routine exploits a technique proposed by
       
   254 // I.Duff. This technique is based on using the sets R[len] and C[len]
       
   255 // of active rows and columns.
       
   256 //
       
   257 // On exit the routine returns a pointer to a pivot v[p,q] chosen, or
       
   258 // NULL, if the active submatrix is empty. */
       
   259 
       
   260 static LUXELM *find_pivot(LUX *lux, LUXWKA *wka)
       
   261 {     int n = lux->n;
       
   262       LUXELM **V_row = lux->V_row;
       
   263       LUXELM **V_col = lux->V_col;
       
   264       int *R_len = wka->R_len;
       
   265       int *R_head = wka->R_head;
       
   266       int *R_next = wka->R_next;
       
   267       int *C_len = wka->C_len;
       
   268       int *C_head = wka->C_head;
       
   269       int *C_next = wka->C_next;
       
   270       LUXELM *piv, *some, *vij;
       
   271       int i, j, len, min_len, ncand, piv_lim = 5;
       
   272       double best, cost;
       
   273       /* nothing is chosen so far */
       
   274       piv = NULL, best = DBL_MAX, ncand = 0;
       
   275       /* if in the active submatrix there is a column that has the only
       
   276          non-zero (column singleton), choose it as a pivot */
       
   277       j = C_head[1];
       
   278       if (j != 0)
       
   279       {  xassert(C_len[j] == 1);
       
   280          piv = V_col[j];
       
   281          xassert(piv != NULL && piv->c_next == NULL);
       
   282          goto done;
       
   283       }
       
   284       /* if in the active submatrix there is a row that has the only
       
   285          non-zero (row singleton), choose it as a pivot */
       
   286       i = R_head[1];
       
   287       if (i != 0)
       
   288       {  xassert(R_len[i] == 1);
       
   289          piv = V_row[i];
       
   290          xassert(piv != NULL && piv->r_next == NULL);
       
   291          goto done;
       
   292       }
       
   293       /* there are no singletons in the active submatrix; walk through
       
   294          other non-empty rows and columns */
       
   295       for (len = 2; len <= n; len++)
       
   296       {  /* consider active columns having len non-zeros */
       
   297          for (j = C_head[len]; j != 0; j = C_next[j])
       
   298          {  /* j-th column has len non-zeros */
       
   299             /* find an element in the row of minimal length */
       
   300             some = NULL, min_len = INT_MAX;
       
   301             for (vij = V_col[j]; vij != NULL; vij = vij->c_next)
       
   302             {  if (min_len > R_len[vij->i])
       
   303                   some = vij, min_len = R_len[vij->i];
       
   304                /* if Markowitz cost of this element is not greater than
       
   305                   (len-1)**2, it can be chosen right now; this heuristic
       
   306                   reduces the search and works well in many cases */
       
   307                if (min_len <= len)
       
   308                {  piv = some;
       
   309                   goto done;
       
   310                }
       
   311             }
       
   312             /* j-th column has been scanned */
       
   313             /* the minimal element found is a next pivot candidate */
       
   314             xassert(some != NULL);
       
   315             ncand++;
       
   316             /* compute its Markowitz cost */
       
   317             cost = (double)(min_len - 1) * (double)(len - 1);
       
   318             /* choose between the current candidate and this element */
       
   319             if (cost < best) piv = some, best = cost;
       
   320             /* if piv_lim candidates have been considered, there is a
       
   321                doubt that a much better candidate exists; therefore it
       
   322                is the time to terminate the search */
       
   323             if (ncand == piv_lim) goto done;
       
   324          }
       
   325          /* now consider active rows having len non-zeros */
       
   326          for (i = R_head[len]; i != 0; i = R_next[i])
       
   327          {  /* i-th row has len non-zeros */
       
   328             /* find an element in the column of minimal length */
       
   329             some = NULL, min_len = INT_MAX;
       
   330             for (vij = V_row[i]; vij != NULL; vij = vij->r_next)
       
   331             {  if (min_len > C_len[vij->j])
       
   332                   some = vij, min_len = C_len[vij->j];
       
   333                /* if Markowitz cost of this element is not greater than
       
   334                   (len-1)**2, it can be chosen right now; this heuristic
       
   335                   reduces the search and works well in many cases */
       
   336                if (min_len <= len)
       
   337                {  piv = some;
       
   338                   goto done;
       
   339                }
       
   340             }
       
   341             /* i-th row has been scanned */
       
   342             /* the minimal element found is a next pivot candidate */
       
   343             xassert(some != NULL);
       
   344             ncand++;
       
   345             /* compute its Markowitz cost */
       
   346             cost = (double)(len - 1) * (double)(min_len - 1);
       
   347             /* choose between the current candidate and this element */
       
   348             if (cost < best) piv = some, best = cost;
       
   349             /* if piv_lim candidates have been considered, there is a
       
   350                doubt that a much better candidate exists; therefore it
       
   351                is the time to terminate the search */
       
   352             if (ncand == piv_lim) goto done;
       
   353          }
       
   354       }
       
   355 done: /* bring the pivot v[p,q] to the factorizing routine */
       
   356       return piv;
       
   357 }
       
   358 
       
   359 /*----------------------------------------------------------------------
       
   360 // eliminate - perform gaussian elimination.
       
   361 //
       
   362 // This routine performs elementary gaussian transformations in order
       
   363 // to eliminate subdiagonal elements in the k-th column of the matrix
       
   364 // U = P*V*Q using the pivot element u[k,k], where k is the number of
       
   365 // the current elimination step.
       
   366 //
       
   367 // The parameter piv specifies the pivot element v[p,q] = u[k,k].
       
   368 //
       
   369 // Each time when the routine applies the elementary transformation to
       
   370 // a non-pivot row of the matrix V, it stores the corresponding element
       
   371 // to the matrix F in order to keep the main equality A = F*V.
       
   372 //
       
   373 // The routine assumes that on entry the matrices L = P*F*inv(P) and
       
   374 // U = P*V*Q are the following:
       
   375 //
       
   376 //       1       k                  1       k         n
       
   377 //    1  1 . . . . . . . . .     1  x x x x x x x x x x
       
   378 //       x 1 . . . . . . . .        . x x x x x x x x x
       
   379 //       x x 1 . . . . . . .        . . x x x x x x x x
       
   380 //       x x x 1 . . . . . .        . . . x x x x x x x
       
   381 //    k  x x x x 1 . . . . .     k  . . . . * * * * * *
       
   382 //       x x x x _ 1 . . . .        . . . . # * * * * *
       
   383 //       x x x x _ . 1 . . .        . . . . # * * * * *
       
   384 //       x x x x _ . . 1 . .        . . . . # * * * * *
       
   385 //       x x x x _ . . . 1 .        . . . . # * * * * *
       
   386 //    n  x x x x _ . . . . 1     n  . . . . # * * * * *
       
   387 //
       
   388 //            matrix L                   matrix U
       
   389 //
       
   390 // where rows and columns of the matrix U with numbers k, k+1, ..., n
       
   391 // form the active submatrix (eliminated elements are marked by '#' and
       
   392 // other elements of the active submatrix are marked by '*'). Note that
       
   393 // each eliminated non-zero element u[i,k] of the matrix U gives the
       
   394 // corresponding element l[i,k] of the matrix L (marked by '_').
       
   395 //
       
   396 // Actually all operations are performed on the matrix V. Should note
       
   397 // that the row-wise representation corresponds to the matrix V, but the
       
   398 // column-wise representation corresponds to the active submatrix of the
       
   399 // matrix V, i.e. elements of the matrix V, which doesn't belong to the
       
   400 // active submatrix, are missing from the column linked lists.
       
   401 //
       
   402 // Let u[k,k] = v[p,q] be the pivot. In order to eliminate subdiagonal
       
   403 // elements u[i',k] = v[i,q], i' = k+1, k+2, ..., n, the routine applies
       
   404 // the following elementary gaussian transformations:
       
   405 //
       
   406 //    (i-th row of V) := (i-th row of V) - f[i,p] * (p-th row of V),
       
   407 //
       
   408 // where f[i,p] = v[i,q] / v[p,q] is a gaussian multiplier.
       
   409 //
       
   410 // Additionally, in order to keep the main equality A = F*V, each time
       
   411 // when the routine applies the transformation to i-th row of the matrix
       
   412 // V, it also adds f[i,p] as a new element to the matrix F.
       
   413 //
       
   414 // IMPORTANT: On entry the working arrays flag and work should contain
       
   415 // zeros. This status is provided by the routine on exit. */
       
   416 
       
   417 static void eliminate(LUX *lux, LUXWKA *wka, LUXELM *piv, int flag[],
       
   418       mpq_t work[])
       
   419 {     DMP *pool = lux->pool;
       
   420       LUXELM **F_row = lux->F_row;
       
   421       LUXELM **F_col = lux->F_col;
       
   422       mpq_t *V_piv = lux->V_piv;
       
   423       LUXELM **V_row = lux->V_row;
       
   424       LUXELM **V_col = lux->V_col;
       
   425       int *R_len = wka->R_len;
       
   426       int *R_head = wka->R_head;
       
   427       int *R_prev = wka->R_prev;
       
   428       int *R_next = wka->R_next;
       
   429       int *C_len = wka->C_len;
       
   430       int *C_head = wka->C_head;
       
   431       int *C_prev = wka->C_prev;
       
   432       int *C_next = wka->C_next;
       
   433       LUXELM *fip, *vij, *vpj, *viq, *next;
       
   434       mpq_t temp;
       
   435       int i, j, p, q;
       
   436       mpq_init(temp);
       
   437       /* determine row and column indices of the pivot v[p,q] */
       
   438       xassert(piv != NULL);
       
   439       p = piv->i, q = piv->j;
       
   440       /* remove p-th (pivot) row from the active set; it will never
       
   441          return there */
       
   442       if (R_prev[p] == 0)
       
   443          R_head[R_len[p]] = R_next[p];
       
   444       else
       
   445          R_next[R_prev[p]] = R_next[p];
       
   446       if (R_next[p] == 0)
       
   447          ;
       
   448       else
       
   449          R_prev[R_next[p]] = R_prev[p];
       
   450       /* remove q-th (pivot) column from the active set; it will never
       
   451          return there */
       
   452       if (C_prev[q] == 0)
       
   453          C_head[C_len[q]] = C_next[q];
       
   454       else
       
   455          C_next[C_prev[q]] = C_next[q];
       
   456       if (C_next[q] == 0)
       
   457          ;
       
   458       else
       
   459          C_prev[C_next[q]] = C_prev[q];
       
   460       /* store the pivot value in a separate array */
       
   461       mpq_set(V_piv[p], piv->val);
       
   462       /* remove the pivot from p-th row */
       
   463       if (piv->r_prev == NULL)
       
   464          V_row[p] = piv->r_next;
       
   465       else
       
   466          piv->r_prev->r_next = piv->r_next;
       
   467       if (piv->r_next == NULL)
       
   468          ;
       
   469       else
       
   470          piv->r_next->r_prev = piv->r_prev;
       
   471       R_len[p]--;
       
   472       /* remove the pivot from q-th column */
       
   473       if (piv->c_prev == NULL)
       
   474          V_col[q] = piv->c_next;
       
   475       else
       
   476          piv->c_prev->c_next = piv->c_next;
       
   477       if (piv->c_next == NULL)
       
   478          ;
       
   479       else
       
   480          piv->c_next->c_prev = piv->c_prev;
       
   481       C_len[q]--;
       
   482       /* free the space occupied by the pivot */
       
   483       mpq_clear(piv->val);
       
   484       dmp_free_atom(pool, piv, sizeof(LUXELM));
       
   485       /* walk through p-th (pivot) row, which already does not contain
       
   486          the pivot v[p,q], and do the following... */
       
   487       for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next)
       
   488       {  /* get column index of v[p,j] */
       
   489          j = vpj->j;
       
   490          /* store v[p,j] in the working array */
       
   491          flag[j] = 1;
       
   492          mpq_set(work[j], vpj->val);
       
   493          /* remove j-th column from the active set; it will return there
       
   494             later with a new length */
       
   495          if (C_prev[j] == 0)
       
   496             C_head[C_len[j]] = C_next[j];
       
   497          else
       
   498             C_next[C_prev[j]] = C_next[j];
       
   499          if (C_next[j] == 0)
       
   500             ;
       
   501          else
       
   502             C_prev[C_next[j]] = C_prev[j];
       
   503          /* v[p,j] leaves the active submatrix, so remove it from j-th
       
   504             column; however, v[p,j] is kept in p-th row */
       
   505          if (vpj->c_prev == NULL)
       
   506             V_col[j] = vpj->c_next;
       
   507          else
       
   508             vpj->c_prev->c_next = vpj->c_next;
       
   509          if (vpj->c_next == NULL)
       
   510             ;
       
   511          else
       
   512             vpj->c_next->c_prev = vpj->c_prev;
       
   513          C_len[j]--;
       
   514       }
       
   515       /* now walk through q-th (pivot) column, which already does not
       
   516          contain the pivot v[p,q], and perform gaussian elimination */
       
   517       while (V_col[q] != NULL)
       
   518       {  /* element v[i,q] has to be eliminated */
       
   519          viq = V_col[q];
       
   520          /* get row index of v[i,q] */
       
   521          i = viq->i;
       
   522          /* remove i-th row from the active set; later it will return
       
   523             there with a new length */
       
   524          if (R_prev[i] == 0)
       
   525             R_head[R_len[i]] = R_next[i];
       
   526          else
       
   527             R_next[R_prev[i]] = R_next[i];
       
   528          if (R_next[i] == 0)
       
   529             ;
       
   530          else
       
   531             R_prev[R_next[i]] = R_prev[i];
       
   532          /* compute gaussian multiplier f[i,p] = v[i,q] / v[p,q] and
       
   533             store it in the matrix F */
       
   534          fip = dmp_get_atom(pool, sizeof(LUXELM));
       
   535          fip->i = i, fip->j = p;
       
   536          mpq_init(fip->val);
       
   537          mpq_div(fip->val, viq->val, V_piv[p]);
       
   538          fip->r_prev = NULL;
       
   539          fip->r_next = F_row[i];
       
   540          fip->c_prev = NULL;
       
   541          fip->c_next = F_col[p];
       
   542          if (fip->r_next != NULL) fip->r_next->r_prev = fip;
       
   543          if (fip->c_next != NULL) fip->c_next->c_prev = fip;
       
   544          F_row[i] = F_col[p] = fip;
       
   545          /* v[i,q] has to be eliminated, so remove it from i-th row */
       
   546          if (viq->r_prev == NULL)
       
   547             V_row[i] = viq->r_next;
       
   548          else
       
   549             viq->r_prev->r_next = viq->r_next;
       
   550          if (viq->r_next == NULL)
       
   551             ;
       
   552          else
       
   553             viq->r_next->r_prev = viq->r_prev;
       
   554          R_len[i]--;
       
   555          /* and also from q-th column */
       
   556          V_col[q] = viq->c_next;
       
   557          C_len[q]--;
       
   558          /* free the space occupied by v[i,q] */
       
   559          mpq_clear(viq->val);
       
   560          dmp_free_atom(pool, viq, sizeof(LUXELM));
       
   561          /* perform gaussian transformation:
       
   562             (i-th row) := (i-th row) - f[i,p] * (p-th row)
       
   563             note that now p-th row, which is in the working array,
       
   564             does not contain the pivot v[p,q], and i-th row does not
       
   565             contain the element v[i,q] to be eliminated */
       
   566          /* walk through i-th row and transform existing non-zero
       
   567             elements */
       
   568          for (vij = V_row[i]; vij != NULL; vij = next)
       
   569          {  next = vij->r_next;
       
   570             /* get column index of v[i,j] */
       
   571             j = vij->j;
       
   572             /* v[i,j] := v[i,j] - f[i,p] * v[p,j] */
       
   573             if (flag[j])
       
   574             {  /* v[p,j] != 0 */
       
   575                flag[j] = 0;
       
   576                mpq_mul(temp, fip->val, work[j]);
       
   577                mpq_sub(vij->val, vij->val, temp);
       
   578                if (mpq_sgn(vij->val) == 0)
       
   579                {  /* new v[i,j] is zero, so remove it from the active
       
   580                      submatrix */
       
   581                   /* remove v[i,j] from i-th row */
       
   582                   if (vij->r_prev == NULL)
       
   583                      V_row[i] = vij->r_next;
       
   584                   else
       
   585                      vij->r_prev->r_next = vij->r_next;
       
   586                   if (vij->r_next == NULL)
       
   587                      ;
       
   588                   else
       
   589                      vij->r_next->r_prev = vij->r_prev;
       
   590                   R_len[i]--;
       
   591                   /* remove v[i,j] from j-th column */
       
   592                   if (vij->c_prev == NULL)
       
   593                      V_col[j] = vij->c_next;
       
   594                   else
       
   595                      vij->c_prev->c_next = vij->c_next;
       
   596                   if (vij->c_next == NULL)
       
   597                      ;
       
   598                   else
       
   599                      vij->c_next->c_prev = vij->c_prev;
       
   600                   C_len[j]--;
       
   601                   /* free the space occupied by v[i,j] */
       
   602                   mpq_clear(vij->val);
       
   603                   dmp_free_atom(pool, vij, sizeof(LUXELM));
       
   604                }
       
   605             }
       
   606          }
       
   607          /* now flag is the pattern of the set v[p,*] \ v[i,*] */
       
   608          /* walk through p-th (pivot) row and create new elements in
       
   609             i-th row, which appear due to fill-in */
       
   610          for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next)
       
   611          {  j = vpj->j;
       
   612             if (flag[j])
       
   613             {  /* create new non-zero v[i,j] = 0 - f[i,p] * v[p,j] and
       
   614                   add it to i-th row and j-th column */
       
   615                vij = dmp_get_atom(pool, sizeof(LUXELM));
       
   616                vij->i = i, vij->j = j;
       
   617                mpq_init(vij->val);
       
   618                mpq_mul(vij->val, fip->val, work[j]);
       
   619                mpq_neg(vij->val, vij->val);
       
   620                vij->r_prev = NULL;
       
   621                vij->r_next = V_row[i];
       
   622                vij->c_prev = NULL;
       
   623                vij->c_next = V_col[j];
       
   624                if (vij->r_next != NULL) vij->r_next->r_prev = vij;
       
   625                if (vij->c_next != NULL) vij->c_next->c_prev = vij;
       
   626                V_row[i] = V_col[j] = vij;
       
   627                R_len[i]++, C_len[j]++;
       
   628             }
       
   629             else
       
   630             {  /* there is no fill-in, because v[i,j] already exists in
       
   631                   i-th row; restore the flag, which was reset before */
       
   632                flag[j] = 1;
       
   633             }
       
   634          }
       
   635          /* now i-th row has been completely transformed and can return
       
   636             to the active set with a new length */
       
   637          R_prev[i] = 0;
       
   638          R_next[i] = R_head[R_len[i]];
       
   639          if (R_next[i] != 0) R_prev[R_next[i]] = i;
       
   640          R_head[R_len[i]] = i;
       
   641       }
       
   642       /* at this point q-th (pivot) column must be empty */
       
   643       xassert(C_len[q] == 0);
       
   644       /* walk through p-th (pivot) row again and do the following... */
       
   645       for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next)
       
   646       {  /* get column index of v[p,j] */
       
   647          j = vpj->j;
       
   648          /* erase v[p,j] from the working array */
       
   649          flag[j] = 0;
       
   650          mpq_set_si(work[j], 0, 1);
       
   651          /* now j-th column has been completely transformed, so it can
       
   652             return to the active list with a new length */
       
   653          C_prev[j] = 0;
       
   654          C_next[j] = C_head[C_len[j]];
       
   655          if (C_next[j] != 0) C_prev[C_next[j]] = j;
       
   656          C_head[C_len[j]] = j;
       
   657       }
       
   658       mpq_clear(temp);
       
   659       /* return to the factorizing routine */
       
   660       return;
       
   661 }
       
   662 
       
   663 /*----------------------------------------------------------------------
       
   664 // lux_decomp - compute LU-factorization.
       
   665 //
       
   666 // SYNOPSIS
       
   667 //
       
   668 // #include "glplux.h"
       
   669 // int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[],
       
   670 //    mpq_t val[]), void *info);
       
   671 //
       
   672 // DESCRIPTION
       
   673 //
       
   674 // The routine lux_decomp computes LU-factorization of a given square
       
   675 // matrix A.
       
   676 //
       
   677 // The parameter lux specifies LU-factorization data structure built by
       
   678 // means of the routine lux_create.
       
   679 //
       
   680 // The formal routine col specifies the original matrix A. In order to
       
   681 // obtain j-th column of the matrix A the routine lux_decomp calls the
       
   682 // routine col with the parameter j (1 <= j <= n, where n is the order
       
   683 // of A). In response the routine col should store row indices and
       
   684 // numerical values of non-zero elements of j-th column of A to the
       
   685 // locations ind[1], ..., ind[len] and val[1], ..., val[len], resp.,
       
   686 // where len is the number of non-zeros in j-th column, which should be
       
   687 // returned on exit. Neiter zero nor duplicate elements are allowed.
       
   688 //
       
   689 // The parameter info is a transit pointer passed to the formal routine
       
   690 // col; it can be used for various purposes.
       
   691 //
       
   692 // RETURNS
       
   693 //
       
   694 // The routine lux_decomp returns the singularity flag. Zero flag means
       
   695 // that the original matrix A is non-singular while non-zero flag means
       
   696 // that A is (exactly!) singular.
       
   697 //
       
   698 // Note that LU-factorization is valid in both cases, however, in case
       
   699 // of singularity some rows of the matrix V (including pivot elements)
       
   700 // will be empty.
       
   701 //
       
   702 // REPAIRING SINGULAR MATRIX
       
   703 //
       
   704 // If the routine lux_decomp returns non-zero flag, it provides all
       
   705 // necessary information that can be used for "repairing" the matrix A,
       
   706 // where "repairing" means replacing linearly dependent columns of the
       
   707 // matrix A by appropriate columns of the unity matrix. This feature is
       
   708 // needed when the routine lux_decomp is used for reinverting the basis
       
   709 // matrix within the simplex method procedure.
       
   710 //
       
   711 // On exit linearly dependent columns of the matrix U have the numbers
       
   712 // rank+1, rank+2, ..., n, where rank is the exact rank of the matrix A
       
   713 // stored by the routine to the member lux->rank. The correspondence
       
   714 // between columns of A and U is the same as between columns of V and U.
       
   715 // Thus, linearly dependent columns of the matrix A have the numbers
       
   716 // Q_col[rank+1], Q_col[rank+2], ..., Q_col[n], where Q_col is an array
       
   717 // representing the permutation matrix Q in column-like format. It is
       
   718 // understood that each j-th linearly dependent column of the matrix U
       
   719 // should be replaced by the unity vector, where all elements are zero
       
   720 // except the unity diagonal element u[j,j]. On the other hand j-th row
       
   721 // of the matrix U corresponds to the row of the matrix V (and therefore
       
   722 // of the matrix A) with the number P_row[j], where P_row is an array
       
   723 // representing the permutation matrix P in row-like format. Thus, each
       
   724 // j-th linearly dependent column of the matrix U should be replaced by
       
   725 // a column of the unity matrix with the number P_row[j].
       
   726 //
       
   727 // The code that repairs the matrix A may look like follows:
       
   728 //
       
   729 //    for (j = rank+1; j <= n; j++)
       
   730 //    {  replace column Q_col[j] of the matrix A by column P_row[j] of
       
   731 //       the unity matrix;
       
   732 //    }
       
   733 //
       
   734 // where rank, P_row, and Q_col are members of the structure LUX. */
       
   735 
       
   736 int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[],
       
   737       mpq_t val[]), void *info)
       
   738 {     int n = lux->n;
       
   739       LUXELM **V_row = lux->V_row;
       
   740       LUXELM **V_col = lux->V_col;
       
   741       int *P_row = lux->P_row;
       
   742       int *P_col = lux->P_col;
       
   743       int *Q_row = lux->Q_row;
       
   744       int *Q_col = lux->Q_col;
       
   745       LUXELM *piv, *vij;
       
   746       LUXWKA *wka;
       
   747       int i, j, k, p, q, t, *flag;
       
   748       mpq_t *work;
       
   749       /* allocate working area */
       
   750       wka = xmalloc(sizeof(LUXWKA));
       
   751       wka->R_len = xcalloc(1+n, sizeof(int));
       
   752       wka->R_head = xcalloc(1+n, sizeof(int));
       
   753       wka->R_prev = xcalloc(1+n, sizeof(int));
       
   754       wka->R_next = xcalloc(1+n, sizeof(int));
       
   755       wka->C_len = xcalloc(1+n, sizeof(int));
       
   756       wka->C_head = xcalloc(1+n, sizeof(int));
       
   757       wka->C_prev = xcalloc(1+n, sizeof(int));
       
   758       wka->C_next = xcalloc(1+n, sizeof(int));
       
   759       /* initialize LU-factorization data structures */
       
   760       initialize(lux, col, info, wka);
       
   761       /* allocate working arrays */
       
   762       flag = xcalloc(1+n, sizeof(int));
       
   763       work = xcalloc(1+n, sizeof(mpq_t));
       
   764       for (k = 1; k <= n; k++)
       
   765       {  flag[k] = 0;
       
   766          mpq_init(work[k]);
       
   767       }
       
   768       /* main elimination loop */
       
   769       for (k = 1; k <= n; k++)
       
   770       {  /* choose a pivot element v[p,q] */
       
   771          piv = find_pivot(lux, wka);
       
   772          if (piv == NULL)
       
   773          {  /* no pivot can be chosen, because the active submatrix is
       
   774                empty */
       
   775             break;
       
   776          }
       
   777          /* determine row and column indices of the pivot element */
       
   778          p = piv->i, q = piv->j;
       
   779          /* let v[p,q] correspond to u[i',j']; permute k-th and i'-th
       
   780             rows and k-th and j'-th columns of the matrix U = P*V*Q to
       
   781             move the element u[i',j'] to the position u[k,k] */
       
   782          i = P_col[p], j = Q_row[q];
       
   783          xassert(k <= i && i <= n && k <= j && j <= n);
       
   784          /* permute k-th and i-th rows of the matrix U */
       
   785          t = P_row[k];
       
   786          P_row[i] = t, P_col[t] = i;
       
   787          P_row[k] = p, P_col[p] = k;
       
   788          /* permute k-th and j-th columns of the matrix U */
       
   789          t = Q_col[k];
       
   790          Q_col[j] = t, Q_row[t] = j;
       
   791          Q_col[k] = q, Q_row[q] = k;
       
   792          /* eliminate subdiagonal elements of k-th column of the matrix
       
   793             U = P*V*Q using the pivot element u[k,k] = v[p,q] */
       
   794          eliminate(lux, wka, piv, flag, work);
       
   795       }
       
   796       /* determine the rank of A (and V) */
       
   797       lux->rank = k - 1;
       
   798       /* free working arrays */
       
   799       xfree(flag);
       
   800       for (k = 1; k <= n; k++) mpq_clear(work[k]);
       
   801       xfree(work);
       
   802       /* build column lists of the matrix V using its row lists */
       
   803       for (j = 1; j <= n; j++)
       
   804          xassert(V_col[j] == NULL);
       
   805       for (i = 1; i <= n; i++)
       
   806       {  for (vij = V_row[i]; vij != NULL; vij = vij->r_next)
       
   807          {  j = vij->j;
       
   808             vij->c_prev = NULL;
       
   809             vij->c_next = V_col[j];
       
   810             if (vij->c_next != NULL) vij->c_next->c_prev = vij;
       
   811             V_col[j] = vij;
       
   812          }
       
   813       }
       
   814       /* free working area */
       
   815       xfree(wka->R_len);
       
   816       xfree(wka->R_head);
       
   817       xfree(wka->R_prev);
       
   818       xfree(wka->R_next);
       
   819       xfree(wka->C_len);
       
   820       xfree(wka->C_head);
       
   821       xfree(wka->C_prev);
       
   822       xfree(wka->C_next);
       
   823       xfree(wka);
       
   824       /* return to the calling program */
       
   825       return (lux->rank < n);
       
   826 }
       
   827 
       
   828 /*----------------------------------------------------------------------
       
   829 // lux_f_solve - solve system F*x = b or F'*x = b.
       
   830 //
       
   831 // SYNOPSIS
       
   832 //
       
   833 // #include "glplux.h"
       
   834 // void lux_f_solve(LUX *lux, int tr, mpq_t x[]);
       
   835 //
       
   836 // DESCRIPTION
       
   837 //
       
   838 // The routine lux_f_solve solves either the system F*x = b (if the
       
   839 // flag tr is zero) or the system F'*x = b (if the flag tr is non-zero),
       
   840 // where the matrix F is a component of LU-factorization specified by
       
   841 // the parameter lux, F' is a matrix transposed to F.
       
   842 //
       
   843 // On entry the array x should contain elements of the right-hand side
       
   844 // vector b in locations x[1], ..., x[n], where n is the order of the
       
   845 // matrix F. On exit this array will contain elements of the solution
       
   846 // vector x in the same locations. */
       
   847 
       
   848 void lux_f_solve(LUX *lux, int tr, mpq_t x[])
       
   849 {     int n = lux->n;
       
   850       LUXELM **F_row = lux->F_row;
       
   851       LUXELM **F_col = lux->F_col;
       
   852       int *P_row = lux->P_row;
       
   853       LUXELM *fik, *fkj;
       
   854       int i, j, k;
       
   855       mpq_t temp;
       
   856       mpq_init(temp);
       
   857       if (!tr)
       
   858       {  /* solve the system F*x = b */
       
   859          for (j = 1; j <= n; j++)
       
   860          {  k = P_row[j];
       
   861             if (mpq_sgn(x[k]) != 0)
       
   862             {  for (fik = F_col[k]; fik != NULL; fik = fik->c_next)
       
   863                {  mpq_mul(temp, fik->val, x[k]);
       
   864                   mpq_sub(x[fik->i], x[fik->i], temp);
       
   865                }
       
   866             }
       
   867          }
       
   868       }
       
   869       else
       
   870       {  /* solve the system F'*x = b */
       
   871          for (i = n; i >= 1; i--)
       
   872          {  k = P_row[i];
       
   873             if (mpq_sgn(x[k]) != 0)
       
   874             {  for (fkj = F_row[k]; fkj != NULL; fkj = fkj->r_next)
       
   875                {  mpq_mul(temp, fkj->val, x[k]);
       
   876                   mpq_sub(x[fkj->j], x[fkj->j], temp);
       
   877                }
       
   878             }
       
   879          }
       
   880       }
       
   881       mpq_clear(temp);
       
   882       return;
       
   883 }
       
   884 
       
   885 /*----------------------------------------------------------------------
       
   886 // lux_v_solve - solve system V*x = b or V'*x = b.
       
   887 //
       
   888 // SYNOPSIS
       
   889 //
       
   890 // #include "glplux.h"
       
   891 // void lux_v_solve(LUX *lux, int tr, double x[]);
       
   892 //
       
   893 // DESCRIPTION
       
   894 //
       
   895 // The routine lux_v_solve solves either the system V*x = b (if the
       
   896 // flag tr is zero) or the system V'*x = b (if the flag tr is non-zero),
       
   897 // where the matrix V is a component of LU-factorization specified by
       
   898 // the parameter lux, V' is a matrix transposed to V.
       
   899 //
       
   900 // On entry the array x should contain elements of the right-hand side
       
   901 // vector b in locations x[1], ..., x[n], where n is the order of the
       
   902 // matrix V. On exit this array will contain elements of the solution
       
   903 // vector x in the same locations. */
       
   904 
       
   905 void lux_v_solve(LUX *lux, int tr, mpq_t x[])
       
   906 {     int n = lux->n;
       
   907       mpq_t *V_piv = lux->V_piv;
       
   908       LUXELM **V_row = lux->V_row;
       
   909       LUXELM **V_col = lux->V_col;
       
   910       int *P_row = lux->P_row;
       
   911       int *Q_col = lux->Q_col;
       
   912       LUXELM *vij;
       
   913       int i, j, k;
       
   914       mpq_t *b, temp;
       
   915       b = xcalloc(1+n, sizeof(mpq_t));
       
   916       for (k = 1; k <= n; k++)
       
   917          mpq_init(b[k]), mpq_set(b[k], x[k]), mpq_set_si(x[k], 0, 1);
       
   918       mpq_init(temp);
       
   919       if (!tr)
       
   920       {  /* solve the system V*x = b */
       
   921          for (k = n; k >= 1; k--)
       
   922          {  i = P_row[k], j = Q_col[k];
       
   923             if (mpq_sgn(b[i]) != 0)
       
   924             {  mpq_set(x[j], b[i]);
       
   925                mpq_div(x[j], x[j], V_piv[i]);
       
   926                for (vij = V_col[j]; vij != NULL; vij = vij->c_next)
       
   927                {  mpq_mul(temp, vij->val, x[j]);
       
   928                   mpq_sub(b[vij->i], b[vij->i], temp);
       
   929                }
       
   930             }
       
   931          }
       
   932       }
       
   933       else
       
   934       {  /* solve the system V'*x = b */
       
   935          for (k = 1; k <= n; k++)
       
   936          {  i = P_row[k], j = Q_col[k];
       
   937             if (mpq_sgn(b[j]) != 0)
       
   938             {  mpq_set(x[i], b[j]);
       
   939                mpq_div(x[i], x[i], V_piv[i]);
       
   940                for (vij = V_row[i]; vij != NULL; vij = vij->r_next)
       
   941                {  mpq_mul(temp, vij->val, x[i]);
       
   942                   mpq_sub(b[vij->j], b[vij->j], temp);
       
   943                }
       
   944             }
       
   945          }
       
   946       }
       
   947       for (k = 1; k <= n; k++) mpq_clear(b[k]);
       
   948       mpq_clear(temp);
       
   949       xfree(b);
       
   950       return;
       
   951 }
       
   952 
       
   953 /*----------------------------------------------------------------------
       
   954 // lux_solve - solve system A*x = b or A'*x = b.
       
   955 //
       
   956 // SYNOPSIS
       
   957 //
       
   958 // #include "glplux.h"
       
   959 // void lux_solve(LUX *lux, int tr, mpq_t x[]);
       
   960 //
       
   961 // DESCRIPTION
       
   962 //
       
   963 // The routine lux_solve solves either the system A*x = b (if the flag
       
   964 // tr is zero) or the system A'*x = b (if the flag tr is non-zero),
       
   965 // where the parameter lux specifies LU-factorization of the matrix A,
       
   966 // A' is a matrix transposed to A.
       
   967 //
       
   968 // On entry the array x should contain elements of the right-hand side
       
   969 // vector b in locations x[1], ..., x[n], where n is the order of the
       
   970 // matrix A. On exit this array will contain elements of the solution
       
   971 // vector x in the same locations. */
       
   972 
       
   973 void lux_solve(LUX *lux, int tr, mpq_t x[])
       
   974 {     if (lux->rank < lux->n)
       
   975          xfault("lux_solve: LU-factorization has incomplete rank\n");
       
   976       if (!tr)
       
   977       {  /* A = F*V, therefore inv(A) = inv(V)*inv(F) */
       
   978          lux_f_solve(lux, 0, x);
       
   979          lux_v_solve(lux, 0, x);
       
   980       }
       
   981       else
       
   982       {  /* A' = V'*F', therefore inv(A') = inv(F')*inv(V') */
       
   983          lux_v_solve(lux, 1, x);
       
   984          lux_f_solve(lux, 1, x);
       
   985       }
       
   986       return;
       
   987 }
       
   988 
       
   989 /*----------------------------------------------------------------------
       
   990 // lux_delete - delete LU-factorization.
       
   991 //
       
   992 // SYNOPSIS
       
   993 //
       
   994 // #include "glplux.h"
       
   995 // void lux_delete(LUX *lux);
       
   996 //
       
   997 // DESCRIPTION
       
   998 //
       
   999 // The routine lux_delete deletes LU-factorization data structure,
       
  1000 // which the parameter lux points to, freeing all the memory allocated
       
  1001 // to this object. */
       
  1002 
       
  1003 void lux_delete(LUX *lux)
       
  1004 {     int n = lux->n;
       
  1005       LUXELM *fij, *vij;
       
  1006       int i;
       
  1007       for (i = 1; i <= n; i++)
       
  1008       {  for (fij = lux->F_row[i]; fij != NULL; fij = fij->r_next)
       
  1009             mpq_clear(fij->val);
       
  1010          mpq_clear(lux->V_piv[i]);
       
  1011          for (vij = lux->V_row[i]; vij != NULL; vij = vij->r_next)
       
  1012             mpq_clear(vij->val);
       
  1013       }
       
  1014       dmp_delete_pool(lux->pool);
       
  1015       xfree(lux->F_row);
       
  1016       xfree(lux->F_col);
       
  1017       xfree(lux->V_piv);
       
  1018       xfree(lux->V_row);
       
  1019       xfree(lux->V_col);
       
  1020       xfree(lux->P_row);
       
  1021       xfree(lux->P_col);
       
  1022       xfree(lux->Q_row);
       
  1023       xfree(lux->Q_col);
       
  1024       xfree(lux);
       
  1025       return;
       
  1026 }
       
  1027 
       
  1028 /* eof */