
          F01 -- Matrix Factorization                   Introduction -- F01
                                    Chapter F01
                               Matrix Factorization

          1. Scope of the Chapter

          This chapter provides facilities for matrix factorizations and
          associated transformations.

          2. Background to the Problems

          An n by n matrix may be factorized as

                                            T
                                      A=PLUQ ,

          where L and U are respectively lower and uper triangular
          matrices, and P and Q are permutation matrices. This is called an
          LU factorization. For general dense matrices it is usual to
          choose Q=I and to then choose P to ensure that the factorization
          is numerically stable. For sparse matrices, judicious choice of P
          and Q ensures numerical stability as well as maintaining as much
          sparsity as possible in the factors L and U. The LU factorization
          is normally used in connection with the solution of the linear
          equations


                                        Ax=b,

          whose solution, x, may then be obtained by solving in succession
          the simpler equations

                                    T
                                Ly=P b,  Uz=y,  x=Qz

          the first by forward substitution and the second by backward
          substitution. Routines to perform this solution are to be found
          in Chapter F04.

                                                                      T
          When A is symmetric positive-definite then we can choose U=L  and
          Q=P, to give the Cholesky factorization. This factorization is
          numerically stable without permutations, but in the sparse case
          the permutations can again be used to try to maintain sparsity.
          The Cholesky factorization is sometimes expressed as

                                           T T
                                     A=PLDL P ,

          where D is a diagonal matrix with positive diagonal elements and
          L is unit lower triangular.

          The LU factorization can also be performed on rectangular
          matrices, but in this case it is more usual to perform a QR
          factorization. When A is an m by n (m>=n) matrix this is given by


                                          (R)
                                       A=Q(0),

          where R is an n by n upper triangular matrix and Q is an
          orthogonal (unitary in the complex case) matrix.

          3. Recommendations on Choice and Use of Routines

          Routine F07ADF performs the LU factorization of a real m by n
          dense matrix.

          The LU factorization of a sparse matrix is performed by routine
          F01BRF. Following the use of F01BRF, matrices with the same
          sparsity pattern may be factorized by routine F01BSF.

          The Cholesky factorization of a real symmetric positive-definite
          dense matrix is performed by routine F07FDF.

          Routine F01MCF performs the Cholesky factorization of a real
          symmetric positive-definite variable band (skyline) matrix, and a
          general sparse symmetric positive-definite matrix may be
          factorized using routine F01MAF.

          The QR factorization of an m by n (m>=n) matrix is performed by
          routine F01QCF in the real case, and F01RCF in the complex case.
          Following the use of F01QCF, operations with Q may be performed
          using routine F01QDF and some, or all, of the columns of Q may be
          formed using routine F01QEF. Routines F01RDF and F01REF perform
          the same tasks following the use of F01RCF.


          F01 -- Matrix Factorizations                      Contents -- F01
          Chapter F01

          Matrix Factorizations

          F01BRF  LU factorization of real sparse matrix

          F01BSF  LU factorization of real sparse matrix with known
                  sparsity pattern

                    T
          F01MAF  LL  factorization of real sparse symmetric positive-
                  definite matrix

                     T
          F01MCF  LDL  factorization of real symmetric positive-definite
                  variable-bandwidth matrix

          F01QCF  QR factorization of real m by n matrix (m>=n)

                                                                      T
          F01QDF  Operations with orthogonal matrices, compute QB or Q B
                  after factorization by F01QCF

          F01QEF  Operations with orthogonal matrices, form columns of Q
                  after factorization by F01QCF

          F01RCF  QR factorization of complex m by n matrix (m>=n)

                                                                   H
          F01RDF  Operations with unitary matrices, compute QB or Q B after
                  factorization by F01RCF

          F01REF  Operations with unitary matrices, form columns of Q after
                  factorization by F01RCF

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01BRF
                  F01BRF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01BRF factorizes a real sparse matrix. The routine either forms
          the LU factorization of a permutation of the entire matrix, or,
          optionally, first permutes the matrix to block lower triangular
          form and then only factorizes the diagonal blocks.

          2. Specification

                 SUBROUTINE F01BRF (N, NZ, A, LICN, IRN, LIRN, ICN, PIVOT,
                1                   IKEEP, IW, W, LBLOCK, GROW, ABORT,
                2                   IDISP, IFAIL)
                 INTEGER          N, NZ, LICN, IRN(LIRN), LIRN, ICN(LICN),
                1                 IKEEP(5*N), IW(8*N), IDISP(10), IFAIL
                 DOUBLE PRECISION A(LICN), PIVOT, W(N)
                 LOGICAL          LBLOCK, GROW, ABORT(4)

          3. Description

          Given a real sparse matrix A, this routine may be used to obtain
          the LU factorization of a permutation of A,

                                       PAQ=LU

          where P and Q are permutation matrices, L is unit lower
          triangular and U is upper triangular. The routine uses a sparse
          variant of Gaussian elimination, and the pivotal strategy is
          designed to compromise between maintaining sparsity and
          controlling loss of accuracy through round-off.

          Optionally the routine first permutes the matrix into block lower
          triangular form and then only factorizes the diagonal blocks. For
          some matrices this gives a considerable saving in storage and
          execution time.

          Extensive data checks are made; duplicated non-zeros can be
          accumulated.

          The factorization is intended to be used by F04AXF to solve
                                                      T
          sparse systems of linear equations Ax=b or A x=b. If several
          matrices of the same sparsity pattern are to be factorized,
          F01BSF should be used for the second and subsequent matrices.

          The method is fully described by Duff [1].

          4. References

          [1]   Duff I S (1977) MA28 -- a set of Fortran subroutines for
                sparse unsymmetric linear equations. A.E.R.E. Report R.8730.
                HMSO.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N > 0.

           2:  NZ -- INTEGER                                          Input
               On entry: the number of non-zero elements in the matrix A.
               Constraint: NZ > 0.

           3:  A(LICN) -- DOUBLE PRECISION array               Input/Output
               On entry: A(i), for i = 1,2,...,NZ must contain the non-
               zero elements of the sparse matrix A. They can be in any
               order since the routine will reorder them. On exit: the non-
               zero elements in the LU factorization. The array must not be
               changed by the user between a call of this routine and a
               call of F04AXF.

           4:  LICN -- INTEGER                                        Input
               On entry:
               the dimension of the arrays A and ICN as declared in the
               (sub)program from which F01BRF is called.
               Since the factorization is returned in A and ICN, LICN
               should be large enough to accommodate this and should
               ordinarily be 2 to 4 times as large as NZ. Constraint: LICN
               >= NZ.

           5:  IRN(LIRN) -- INTEGER array                      Input/Output
               On entry: IRN(i), for i = 1,2,...,NZ must contain the row
               index of the non-zero element stored in A(i). On exit: the
               array is overwritten and is not needed for subsequent calls
               of F01BSF or F04AXF.

           6:  LIRN -- INTEGER                                        Input
               On entry:
               the dimension of the array IRN as declared in the
               (sub)program from which F01BRF is called.
               It need not be as large as LICN; normally it will not need
               to be very much greater than NZ. Constraint: LIRN >= NZ.

           7:  ICN(LICN) -- INTEGER array                      Input/Output
               On entry: ICN(i), for i = 1,2,...,NZ must contain the
               column index of the non-zero element stored in A(i). On
               exit: the column indices of the non-zero elements in the
               factorization. The array must not be changed by the user
               between a call of this routine and subsequent calls of
               F01BSF or F04AXF.

           8:  PIVOT -- DOUBLE PRECISION                              Input
               On entry: PIVOT should have a value in the range 0.0 <=
               PIVOT <= 0.9999 and is used to control the choice of pivots.
               If PIVOT < 0.0, the value 0.0 is assumed, and if PIVOT > 0.
               9999, the value 0.9999 is assumed. When searching a row for
               a pivot, any element is excluded which is less than PIVOT
               times the largest of those elements in the row available as
               pivots. Thus decreasing PIVOT biases the algorithm to
               maintaining sparsity at the expense of stability. Suggested
               value: PIVOT = 0.1 has been found to work well on test
               examples.

           9:  IKEEP(5*N) -- INTEGER array                           Output
               On exit: indexing information about the factorization. The
               array must not be changed by the user between a call of this
               routine and calls of F01BSF or F04AXF.

          10:  IW(8*N) -- INTEGER array                           Workspace

          11:  W(N) -- DOUBLE PRECISION array                        Output
               On exit: if GROW = .TRUE., W(1) contains an estimate (an
               upper bound) of the increase in size of elements encountered
               during the factorization (see GROW); the rest of the array
               is used as workspace.

               If GROW = .FALSE., the array is not used.

          12:  LBLOCK -- LOGICAL                                      Input
               On entry: if LBLOCK = .TRUE., the matrix is pre-ordered
               into block lower triangular form before the LU factorization
               is performed; otherwise the entire matrix is factorized.
               Suggested value: LBLOCK = .TRUE. unless the matrix is known
               to be irreducible.

          13:  GROW -- LOGICAL                                        Input
               On entry: if GROW = .TRUE., then on exit W(1) contains an
               estimate (an upper bound) of the increase in size of
               elements encountered during the factorization. If the matrix
               is well-scaled (see Section 8.2), then a high value for W(1)
               indicates that the LU factorization may be inaccurate and
               the user should be wary of the results and perhaps increase
               the parameter PIVOT for subsequent runs (see Section 7).
               Suggested value: GROW = .TRUE..

          14:  ABORT(4) -- LOGICAL array                              Input
               On entry:
                    if ABORT(1) = .TRUE., the routine will exit
                    immediately on detecting a structural singularity (one
                    that depends on the pattern of non-zeros) and return

                    IFAIL = 1; otherwise it will complete the
                    factorization (see Section 8.3).

                    If ABORT(2) = .TRUE., the routine will exit
                    immediately on detecting a numerical singularity (one
                    that depends on the numerical values) and return IFAIL
                    = 2; otherwise it will complete the factorization (see
                    Section 8.3).

                    If ABORT(3) = .TRUE., the routine will exit
                    immediately (with IFAIL = 5) when the arrays A and ICN
                    are filled up by the previously factorized, active and
                    unfactorized parts of the matrix; otherwise it
                    continues so that better guidance on necessary array
                    sizes can be given in IDISP(6) and IDISP(7), and will
                    exit with IFAIL in the range 4 to 6. Note that there
                    is always an immediate error exit if the array IRN is
                    too small.

                    If ABORT(4) = .TRUE., the routine exits immediately
                    (with IFAIL = 13) if it finds duplicate elements in
                    the input matrix. If ABORT(4) = .FALSE., the routine
                    proceeds using a value equal to the sum of the
                    duplicate elements. In either case details of each
                    duplicate element are output on the current advisory
                    message unit (see X04ABF), unless suppressed by the
                    value of IFAIL on entry.
                Suggested values:
                    ABORT(1) = .TRUE.

                    ABORT(2) = .TRUE.

                    ABORT(3) = .FALSE.

                    ABORT(4) = .TRUE..

          15:  IDISP(10) -- INTEGER array                            Output
               On exit: IDISP is used to communicate information about the
               factorization to the user and also between a call of F01BRF
               and subsequent calls to F01BSF or F04AXF.
                    IDISP(1) and IDISP(2), indicate the position in arrays
                    A and ICN of the first and last elements in the LU
                    factorization of the diagonal blocks. (IDISP(2) gives
                    the number of non-zeros in the factorization.)

                    IDISP(3) and IDISP(4), monitor the adequacy of 'elbow
                    room' in the arrays IRN and A/ICN respectively, by
                    giving the number of times that the data in these
                    arrays has been compressed during the factorization to
                    release more storage. If either IDISP(3) or IDISP(4)
                    is quite large (say greater than 10), it will probably
                    pay the user to increase the size of the corresponding
                    array(s) for subsequent runs. If either is very low or
                    zero, then the user can perhaps save storage by
                    reducing the size of the corresponding array(s).

                    IDISP(5), gives an upper bound on the rank of the
                    matrix.

                    IDISP(6) and IDISP(7), give the minimum size of arrays
                    IRN and A/ICN respectively which would enable a
                    successful run on an identical matrix (but some '
                    elbow-room' should be allowed - see Section 8).

                    IDISP(8) to (10), are only used if LBLOCK = .TRUE..

                    IDISP(8), gives the structural rank of the matrix.

                    IDISP(9), gives the number of diagonal blocks.

                    IDISP(10), gives the size of the largest diagonal
                    block.

                    IDISP(1) and IDISP(2), must not be changed by the user
                    between a call of F01BRF and subsequent calls to
                    F01BSF or F04AXF.

          16:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL=-2
               Successful factorization of a numerically singular matrix
               (which may also be structurally singular) (see Section 8.3).

          IFAIL=-1
               Successful factorization of a structurally singular matrix
               (see Section 8.3).

          IFAIL= 1
               The matrix is structurally singular and the factorization
               has been abandoned (ABORT(1) was .TRUE. on entry).

          IFAIL= 2
               The matrix is numerically singular and the factorization has
               been abandoned (ABORT(2) was .TRUE. on entry).

          IFAIL= 3
               LIRN is too small: there is not enough space in the array
               IRN to continue the factorization. The user is recommended
               to try again with LIRN (and the length of IRN) equal to at
               least IDISP(6) + N/2.

          IFAIL= 4
               LICN is much too small: there is much too little space in
               the arrays A and ICN to continue the factorization.

          IFAIL= 5
               LICN is too small: there is not enough space in the arrays A
               and ICN to store the factorization. If ABORT(3) was .FALSE.
               on entry, the factorization has been completed but some of
               the LU factors have been discarded to create space, IDISP(7)
               then gives the minimum value of LICN (i.e., the minimum
               length of A and ICN) required for a successful factorization
               of the same matrix.

          IFAIL= 6
               LICN and LIRN are both too small: effectively this is a
               combination of IFAIL = 3 and IFAIL = 5 (with ABORT(3) = .
               FALSE.).

          IFAIL= 7
               LICN is too small: there is not enough space in the arrays A
               and ICN for the permutation to block triangular form.

          IFAIL= 8
               On entry N <= 0.

          IFAIL= 9
               On entry NZ <= 0.

          IFAIL= 10
               On entry LICN < NZ.

          IFAIL= 11
               On entry LIRN < NZ.

          IFAIL= 12
               On entry an element of the input matrix has a row or column
               index (i.e., an element of IRN or ICN) outside the range 1
               to N.

          IFAIL= 13
               Duplicate elements have been found in the input matrix and
               the factorization has been abandoned (ABORT(4) = .TRUE. on
               entry).

          7. Accuracy

          The factorization obtained is exact for a perturbed matrix whose
          (i,j)th element differs from a   by less than 3(epsilon)(rho)m
                                        ij                              ij
          where (epsilon) is the machine precision, (rho) is the growth
          value returned in W(1) if GROW = .TRUE., and m   the number of
                                                        ij
          Gaussian elimination operations applied to element (i,j). The
          value of m   is not greater than n and is usually much less.
                    ij
          Small (rho) values therefore guarantee accurate results, but
          unfortunately large (rho) values may give a very pessimistic
          indication of accuracy.

          8. Further Comments

          8.1. Timing

          The time required may be estimated very roughly from the number
          (tau) of non-zeros in the factorized form (output as IDISP(2))
          and for this routine and its associates is

                             2
               F01BRF: 5(tau) /n units

                            2
               F01BSF: (tau) /n units

               F04AXF: 2(tau) units

          where our unit is the time for the inner loop of a full matrix
                                                                  1 3
          code (e.g. solving a full set of equations takes about  -n
                                                                  3
          units). Note that the faster F01BSF time makes it well worthwhile
          to use this for a sequence of problems with the same pattern.

          It should be appreciated that (tau) varies widely from problem to
          problem. For network problems it may be little greater than NZ,
          the number of non-zeros in A; for discretisation of 2-dimensional
          and 3-dimensional partial differential equations it may be about
                       1 5/3
          3nlog n and  -n   , respectively.
               2       2

          The time taken to find the block lower triangular form (LBLOCK =
          it is not found (LBLOCK = .FALSE.). If the matrix is irreducible
          (IDISP(9) = 1 after a call with LBLOCK = .TRUE.) then this time
          is wasted. Otherwise, particularly if the largest block is small
          (IDISP(10)<<n), the consequent savings are likely to be greater.

          The time taken to estimate growth (GROW = .TRUE.) is typically
          under 2% of the overall time.

          The overall time may be substantially increased if there is
          inadequate 'elbow-room' in the arrays A, IRN and ICN. When the
          sizes of the arrays are minimal (IDISP(6) and IDISP(7)) it can
          execute as much as three times slower. Values of IDISP(3) and
          IDISP(4) greater than about 10 indicate that it may be worthwhile
          to increase array sizes.

          8.2. Scaling

          The use of a relative pivot tolerance PIVOT essentially
          presupposes that the matrix is well-scaled, i.e., that the matrix
          elements are broadly comparable in size. Practical problems are
          often naturally well-scaled but particular care is needed for
          problems containing mixed types of variables (for example
          millimetres and neutron fluxes).

          8.3. Singular and Rectangular Systems

          It is envisaged that this routine will almost always be called
          for square non-singular matrices and that singularity indicates
          an error condition. However, even if the matrix is singular it is
          possible to complete the factorization. It is even possible for
          F04AXF to solve a set of equations whose matrix is singular
          provided the set is consistent.

          Two forms of singularity are possible. If the matrix would be
          singular for any values of the non-zeros (e.g. if it has a whole
          row of zeros), then we say it is structurally singular, and
          continue only if ABORT(1) = .FALSE.. If the matrix is non-
          singular by virtue of the particular values of the non-zeros,
          then we say that it is numerically singular and continue only if
          ABORT(2) = .FALSE..

          Rectangular matrices may be treated by setting N to the larger of
          the number of rows and numbers of columns and setting ABORT(1) =

          Note: the soft failure option should be used (last digit of IFAIL
          = 1) if the user wishes to factorize singular matrices with ABORT
          (1) or ABORT(2) set to .FALSE..

          8.4. Duplicated Non-zeros

          The matrix A may consist of a sum of contributions from different
          sub-systems (for example finite elements). In such cases the user
          may rely on this routine to perform assembly, since duplicated
          elements are summed.

          9. Example

          To factorize the real sparse matrix:

                                 ( 5  0  0  0 0  0)
                                 ( 0  2 -1  2 0  0)
                                 ( 0  0  3  0 0  0)
                                 (-2  0  0  1 1  0).
                                 (-1  0  0 -1 2 -3)
                                 (-1 -1  0  0 0  6)

          This example program simply prints out some information about the
          factorization as returned by F01BRF in W(1) and IDISP. Normally
          the call of F01BRF would be followed by a call of F04AXF (see
          Example for F04AXF).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01BSF
                  F01BSF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01BSF factorizes a real sparse matrix using the pivotal sequence
          previously obtained by F01BRF when a matrix of the same sparsity
          pattern was factorized.

          2. Specification

                 SUBROUTINE F01BSF (N, NZ, A, LICN, IVECT, JVECT, ICN,
                1                   IKEEP, IW, W, GROW, ETA, RPMIN, ABORT,
                2                   IDISP, IFAIL)
                 INTEGER          N, NZ, LICN, IVECT(NZ), JVECT(NZ), ICN
                1                 (LICN), IKEEP(5*N), IW(8*N), IDISP(2),
                2                 IFAIL
                 DOUBLE PRECISION A(LICN), W(N), ETA, RPMIN
                 LOGICAL          GROW, ABORT

          3. Description

          This routine accepts as input a real sparse matrix of the same
          sparsity pattern as a matrix previously factorized by a call of
          F01BRF. It first applies to the matrix the same permutations as
          were used by F01BRF, both for permutation to block triangular
          form and for pivoting, and then performs Gaussian elimination to
          obtain the LU factorization of the diagonal blocks.

          Extensive data checks are made; duplicated non-zeros can be
          accumulated.

          The factorization is intended to be used by F04AXF to solve
                                                      T
          sparse systems of linear equations Ax=b or A x=b.

          F01BSF is much faster than F01BRF and in some applications it is
          expected that there will be many calls of F01BSF for each call of
          F01BRF.

          The method is fully described in Duff [1].

          4. References

          [1]   Duff I S (1977) MA28 -- a set of Fortran subroutines for
                sparse unsymmetric linear equations. A.E.R.E. Report R.8730.
                HMSO.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N > 0.

           2:  NZ -- INTEGER                                          Input
               On entry: the number of non-zeros in the matrix A.
               Constraint: NZ > 0.

           3:  A(LICN) -- DOUBLE PRECISION array               Input/Output
               On entry: A(i), for i = 1,2,...,NZ must contain the non-
               zero elements of the sparse matrix A. They can be in any
               order since the routine will reorder them. On exit: the non-
               zero elements in the factorization. The array must not be
               changed by the user between a call of this routine and a
               call of F04AXF.

           4:  LICN -- INTEGER                                        Input
               On entry:
               the dimension of the arrays A and ICN as declared in the
               (sub)program from which F01BSF is called.
               It should have the same value as it had for F01BRF.
               Constraint: LICN >= NZ.

           5:  IVECT(NZ) -- INTEGER array                             Input

           6:  JVECT(NZ) -- INTEGER array                             Input
               On entry: IVECT(i) and JVECT(i), for i = 1,2,...,NZ must
               contain the row index and the column index respectively of
               the non-zero element stored in A(i).

           7:  ICN(LICN) -- INTEGER array                             Input
               On entry: the same information as output by F01BRF. It must
               not be changed by the user between a call of this routine
               and a call of F04AXF.

           8:  IKEEP(5*N) -- INTEGER array                            Input
               On entry: the same indexing information about the
               factorization as output from F01BRF. It must not be changed
               between a call of this routine and a call of F04AXF.

           9:  IW(8*N) -- INTEGER array                           Workspace

          10:  W(N) -- DOUBLE PRECISION array                        Output
               On exit: if GROW = .TRUE., W(1) contains an estimate (an
               upper bound) of the increase in size of elements encountered
               during the factorization (see GROW); the rest of the array
               is used as workspace.

               If GROW = .FALSE., the array is not used.

          11:  GROW -- LOGICAL                                        Input
               On entry: if GROW = .TRUE., then on exit W(1) contains an
               estimate (an upper bound) of the increase in size of
               elements encountered during the factorization. If the matrix
               is well-scaled (see Section 8.2), then a high value for W(1)
               indicates that the LU factorization may be inaccurate and
               the user should be wary of the results and perhaps increase
               the parameter PIVOT for subsequent runs (see Section 7).

          12:  ETA -- DOUBLE PRECISION                                Input
               On entry: the relative pivot threshold below which an error
               diagnostic is provoked and IFAIL is set to 7. If ETA is
               greater than 1.0, then no check on pivot size is made.
                                        -4
               Suggested value: ETA = 10  .

          13:  RPMIN -- DOUBLE PRECISION                             Output
               On exit: if ETA is less than 1.0, then RPMIN gives the
               smallest ratio of the pivot to the largest element in the
               row of the corresponding upper triangular factor thus
               monitoring the stability of the factorization. If RPMIN is
               very small it may be advisable to perform a new
               factorization using F01BRF.

          14:  ABORT -- LOGICAL                                       Input
               On entry: if ABORT = .TRUE., the routine exits immediately
               (with IFAIL = 8) if it finds duplicate elements in the input
               matrix. If ABORT = .FALSE., the routine proceeds using a
               value equal to the sum of the duplicate elements. In either
               case details of each duplicate element are output on the
               current advisory message unit (see X04ABF), unless
               suppressed by the value of IFAIL on entry. Suggested value:
               ABORT = .TRUE..

          15:  IDISP(2) -- INTEGER array                              Input
               On entry: IDISP(1) and IDISP(2) must be unchanged since the
               previous call of F01BRF.

          16:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL= 1
               On entry N <= 0.

          IFAIL= 2
               On entry NZ <= 0.

          IFAIL= 3
               On entry LICN < NZ.

          IFAIL= 4
               On entry an element of the input matrix has a row or column
               index (i.e., an element of IVECT or JVECT) outside the range
               1 to N.

          IFAIL= 5
               The input matrix is incompatible with the matrix factorized
               by the previous call of F01BRF (see Section 8).

          IFAIL= 6
               The input matrix is numerically singular.

          IFAIL= 7
               A very small pivot has been detected (see Section 5, ETA).
               The factorization has been completed but is potentially
               unstable.

          IFAIL= 8
               Duplicate elements have been found in the input matrix and
               the factorization has been abandoned (ABORT = .TRUE. on
               entry).

          7. Accuracy

          The factorization obtained is exact for a perturbed matrix whose
          (i,j)th element differs from a   by less than 3(epsilon)(rho)m
                                        ij                              ij
          where (epsilon) is the machine precision, (rho) is the growth
          value returned in W(1) if GROW = .TRUE., and m   the number of
                                                        ij
          Gaussian elimination operations applied to element (i,j).

          If (rho) = W(1) is very large or RPMIN is very small, then a
          fresh call of F01BRF is recommended.

          8. Further Comments

          If the user has a sequence of problems with the same sparsity
          pattern then this routine is recommended after F01BRF has been
          called for one such problem. It is typically 4 to 7 times faster
          but is potentially unstable since the previous pivotal sequence
          is used. Further details on timing are given in document F01BRF.

          If growth estimation is performed (GROW = .TRUE.), then the time
          increases by between 5% and 10%. Pivot size monitoring (ETA <= 1.
          0) involves a similar overhead.

          We normally expect this routine to be entered with a matrix
          having the same pattern of non-zeros as was earlier presented to
          F01BRF. However there is no record of this pattern, but rather a
          record of the pattern including all fill-ins. Therefore we permit
          additional non-zeros in positions corresponding to fill-ins.

          If singular matrices are being treated then it is also required
          that the present matrix be sufficiently like the previous one for
          the same permutations to be suitable for factorization with the
          same set of zero pivots.

          9. Example

          To factorize the real sparse matrices

                                 ( 5  0  0  0 0  0)
                                 ( 0  2 -1  2 0  0)
                                 ( 0  0  3  0 0  0)
                                 (-2  0  0  1 1  0)
                                 (-1  0  0 -1 2 -3)
                                 (-1 -1  0  0 0  6)

          and

                                (10  0  0  0  0  0)
                                ( 0 12 -3 -1  0  0)
                                ( 0  0 15  0  0  0)
                                (-2  0  0 10 -1  0).
                                (-1  0  0 -5  1 -1)
                                (-1 -2  0  0  0  6)

          This example program simply prints the values of W(1) and RPMIN
          returned by F01BSF. Normally the calls of F01BRF and F01BSF would
          be followed by calls of F04AXF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01MAF
                  F01MAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01MAF computes an incomplete Cholesky factorization of a real
          sparse symmetric positive-definite matrix A.

          2. Specification

                 SUBROUTINE F01MAF (N, NZ, A, LICN, IRN, LIRN, ICN, DROPTL,
                1                   DENSW, WKEEP, IKEEP, IWORK, ABORT,
                2                   INFORM, IFAIL)
                 INTEGER          N, NZ, LICN, IRN(LIRN), LIRN, ICN(LICN),
                1                 IKEEP(2*N), IWORK(6*N), INFORM(4), IFAIL
                 DOUBLE PRECISION A(LICN), DROPTL, DENSW, WKEEP(3*N)
                 LOGICAL          ABORT(3)

          3. Description

          F01MAF computes an incomplete Cholesky factorization

                                      T T
                                C=PLDL P ,   WAW=C+E

          for the sparse symmetric positive-definite matrix A, where P is a
          permutation matrix, L is a unit lower triangular matrix, D is a
          diagonal matrix with positive diagonal elements, E is an error
          matrix representing elements dropped during the factorization and
          diagonal elements that have been modified to ensure that C is
          positive-definite, and W is a diagonal matrix, chosen to make the
          diagonal elements of WAW unity.

           -1  -1
          W  CW   is a pre-conditioning matrix for A, and the factorization
          of C is intended to be used by F04MAF to solve systems of linear
          equations Ax=b.

          The permutation matrix P is chosen to reduce the amount of fill-
          in that occurs in L and the user-supplied parameter DROPTL can
          also be used to control the amount of fill-in that occurs.

          Full details on the factorization can be found in Munksgaard [1].

          F01MAF is based on the Harwell Library routine MA31A.

          4. References

          [1]   Munksgaard N (1980) Solving Sparse Symmetric Sets of Linear
                Equations by Pre-conditioned Conjugate Gradients. ACM Trans.
                Math. Softw. 6 206--219.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 1.

           2:  NZ -- INTEGER                                          Input
               On entry: the number of non-zero elements in the upper
               triangular part of the matrix A, including the number of
               elements on the leading diagonal. Constraint: NZ >= N.

           3:  A(LICN) -- DOUBLE PRECISION array               Input/Output
               On entry: the first NZ elements of the array A must contain
               the non-zero elements of the upper triangular part of the
               sparse positive-definite symmetric matrix A, including the
               elements on the leading diagonal. On exit: the first (NZ-N)
               elements of A contain the elements above the diagonal of the
               matrix WAW, where W is a diagonal matrix whose ith diagonal
                              -1/2
               element is w =a    . These elements are returned in order by
                           i  ii
               rows and the value returned in ICN(k) gives the column index
               of the element returned in A(k). The value w  is returned in
                                                           i
               the ith element of the array WKEEP. The remaining LROW-NZ+N
               elements of A, where LROW is the value returned in INFORM(1),
               return details of the factorization for use by F04MAF.

           4:  LICN -- INTEGER                                        Input
               On entry:
               the dimension of the array A as declared in the (sub)program
               from which F01MAF is called.
               If fill-in is expected during the factorization, then a
               larger value of LICN will allow fewer elements to be dropped
               during the factorization, thus giving a more accurate
               factorization, which in turn will almost certainly mean that
               fewer iterations will be required by F04MAF. Constraint:
               LICN>=2*NZ.

           5:  IRN(LIRN) -- INTEGER array                      Input/Output
               On entry: IRN(k), for k = 1,2,...,NZ must contain the row
               index of the non-zero element of the matrix A supplied in A
               (k). On exit: the first LCOL elements of IRN, where LCOL is
               the value returned in INFORM(2), return details of the
               factorization for use by F04MAF.

           6:  LIRN -- INTEGER                                        Input
               On entry:
               the dimension of the array IRN as declared in the
               (sub)program from which F01MAF is called.
               LIRN must be at least NZ, but, as with LICN, if fill-in is
               expected then a larger value of LIRN will allow a more
               accurate factorization. For this purpose LIRN should exceed
               NZ by the same amount that LICN exceeds 2*NZ. Constraint:
               LIRN >= NZ.

           7:  ICN(LICN) -- INTEGER array                      Input/Output
               On entry: ICN(k), for k = 1,2,...,NZ must contain the column
               index of the non-zero element of the matrix A supplied in A
               (k). Thus a  =A(k), where i = IRN(k) and j = ICN(k). On
                          ij
               exit: the first (NZ-N) elements of ICN give the column
               indices of the first (NZ-N) elements returned in A. The
               remaining LROW - NZ + N elements of ICN return details of
               the factorization for use by F04MAF.

           8:  DROPTL -- DOUBLE PRECISION                      Input/Output
               On entry: a value in the range [-1.0,1.0] to be used as a
               tolerance in deciding whether or not to drop elements during
                                                                     (k+1)
               the factorization. At the kth pivot step the element a
                                                                     ij
               is dropped if it would cause fill-in and if
                                                   

                               (k+1)              / (k) (k)
                             |a     |<|DROPTL|*  / a   a   .
                               ij              \/   ii  jj
               If DROPTL is supplied as negative, then it is not altered
               during the factorization and so is unchanged on exit, but if
               DROPTL is supplied as positive then it may be altered by the
               routine with the aim of obtaining an accurate factorization
               in the space available. If DROPTL is supplied as -1.0, then
               no fill-in will occur during the factorization; and if
               DROPTL is supplied as 0.0 then a complete factorization is
               performed. On exit: may be overwritten with the value used
               by the routine in order to obtain an accurate factorization
               in the space available, if DROPTL > 0.0 on entry.

           9:  DENSW -- DOUBLE PRECISION                       Input/Output
               On entry: a value in the range [0.0,1.0] to be used in
               deciding whether or not to regard the active part of the
               matrix at the kth pivot step as being full. If the ratio of
               non-zero elements to the total number of elements is greater
               than or equal to DENSW, then the active part is regarded as
               full. If DENSW < 1.0, then the storage used is likely to
               increase compared to the case where DENSW = 0, but the
               execution time is likely to decrease. Suggested value: DENSW
               = 0.8. On exit: if on entry DENSW is not in the range
               [0.0,1.0], then it is set to 0.8. Otherwise it is unchanged.

          10:  WKEEP(3*N) -- DOUBLE PRECISION array                  Output
               On exit: information which must be passed unchanged to
               F04MAF. The first N elements contain the values w , for
                                                                i
               i=1,2,...,n, and the next N elements contain the diagonal
               elements of D.

          11:  IKEEP(2*N) -- INTEGER array                           Output
               On exit: information which must be passed unchanged to
               F04MAF.

          12:  IWORK(6*N) -- INTEGER array                        Workspace

          13:  ABORT(3) -- LOGICAL array                              Input
               On entry:
                    if ABORT(1) = .TRUE., the routine will exit
                    immediately on detecting duplicate elements and return
                    IFAIL = 5. Otherwise when ABORT(1) = .FALSE., the
                    calculations will continue using the sum of the
                    duplicate entries. In either case details of the
                    duplicate elements are output on the current advisory
                    message unit (see X04ABF), unless suppressed by the
                    value of IFAIL on entry.

                    If ABORT(2) = .TRUE., the routine will exit
                    immediately on detecting a zero or negative pivot
                    element and return IFAIL = 6. Otherwise when ABORT(2)
                    = .FALSE., the zero or negative pivot element will be
                    modified to ensure positive-definiteness and a message
                    will be printed on the current advisory message unit,
                    unless suppressed by the value of IFAIL on entry.

                    If ABORT(3) = .TRUE., the routine will exit
                    immediately if the arrays A and ICN have been filled
                    up and return IFAIL = 7. Otherwise when ABORT(3) = .
                    FALSE., the data in the arrays is compressed to
                    release more storage and a message will be printed on
                    the current advisory message unit, unless suppressed
                    by the value of IFAIL on entry. If DROPTL is positive
                    on entry, it may be modified in order to allow a
                    factorization to be completed in the available space.
               Suggested values:
                    ABORT(1) = .TRUE.,

                    ABORT(2) = .TRUE.,

                    ABORT(3) = .TRUE..

          14:  INFORM(4) -- INTEGER array                            Output
               On exit:
                    INFORM(1) returns the number of elements of A and ICN
                    that have been used by the routine. Thus at least the
                    first INFORM(1) elements of A and of ICN must be
                    supplied to F04MAF.

                    Similarly, INFORM(2) returns the number of elements of
                    IRN that have been used by the routine and so at least
                    the first INFORM(2) elements must be supplied to
                    F04MAF.

                    INFORM(3) returns the number of entries supplied in A
                    that corresponded to diagonal and duplicate elements.
                    If no duplicate entries were found, then INFORM(3)
                    will return the value of N.

                    INFORM(4) returns the value k of the pivot step from
                    which the active matrix was regarded as full.
               INFORM must be passed unchanged to F04MAF.

          15:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL= 1
               On entry N < 1,

               or       NZ < N,

               or       LIRN < NZ,

               or       LICN<2*NZ.

          IFAIL= 2
               One of the conditions 0 < IRN(k) <= ICN(k) <= N is not
               satisfied so that A(k) is not in the upper triangle of the
               matrix. No further computation is attempted.

          IFAIL= 3
               One of the diagonal elements of the matrix A is zero or
               negative so that A is not positive-definite. No further
               computation is attempted.

          IFAIL= 4
               The available space has been used and no further
               compressions are possible. The user should either increase
               DROPTL, or allocate more space to A, IRN and ICN.

               For all the remaining values of IFAIL the computations will
               continue in the case of soft failure, so that more than one
               advisory message may be printed.

          IFAIL= 5
               Duplicate elements have been detected and ABORT(1) = .TRUE..

          IFAIL= 6
               A zero or negative pivot element has been detected during
               the factorization and ABORT(2) = .TRUE..

               This should not happen if A is an M-matrix (see Munksgaard
               [1]), but may occur for other types of positive-definite
               matrix.

          IFAIL= 7
               The available space has been used and ABORT(3) = .TRUE..

          7. Accuracy

          The accuracy of the factorization will be determined by the size
          of the elements that are dropped and the size of the
          modifications made to the diagonal elements. If these sizes are
          small then the computed factors will correspond to a matrix close
          to A and the number of iterations required by F04MAF will be
          small. The more incomplete the factorization, the higher the
          number of iterations required by F04MAF.

          8. Further Comments

          The time taken by the routine will depend upon the sparsity
          pattern of the matrix and the number of fill-ins that occur
          during the factorization. At the very least the time taken can be
          expected to be roughly proportional to n(tau), where (tau) is the
          number of non-zeros.
          The routine is intended for use with positive-definite matrices,
          but the user is warned that it will not necessarily detect non-
          positive-definiteness. Indeed the routine may return a
          factorization that can satisfactorily be used by F04MAF even when
          A is not positive-definite, but this should not be relied upon as
          F04MAF may not converge.

          9. Example

          The example program illustrates the use of F01MAF in conjunction
          with F04MAF to solve the 16 linear equations Ax=b, where

                          (1 z     z                      )
                          (z 1 z     z                    )
                          (  z 1 z     z                  )
                          (    z 1 0     z                )
                          (z     0 1 z     z              )
                          (  z     z 1 z     z            )
                          (    z     z 1 z     z          )
                          (      z     z 1 0     z        )
                        A=(        z     0 1 z     z      ).
                          (          z     z 1 z     z    )
                          (            z     z 1 z     z  )
                          (              z     z 1 0     z)
                          (                z     0 1 z    )
                          (                  z     z 1 z  )
                          (                    z     z 1 z)
                          (                      z     z 1)

           T ( 1  1  1  1  1      1  1      1  1  1  1  1)
          b =( -  -  -  -  - 0 0  -  - 0 0  -  -  -  -  -),
             ( 2  4  4  2  4      4  4      4  2  4  4  2)

                    1
          where z=- -.
                    4

          The n by n matrix A arises in the solution of Laplace's equation
          in a unit square, using a 5-point formula with a 6 by 6
          discretisation, with unity on the boundaries.

          The drop tolerance, DROPTL, is taken as 0.1, and the density
          factor, DENSW, is taken as 0.8. The value IFAIL = 111 is used so
          that advisory and error messages will be printed, but soft
          failure would occur if IFAIL were returned as non-zero.

          A relative accuracy of about 0.0001 is requested in the solution
          from F04MAF, with a maximum of 50 iterations.

          The example program for F02FJF illustrates the use of F01MAF and
          F04MAF in solving an eigenvalue problem.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01MCF
                  F01MCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01MCF computes the Cholesky factorization of a real symmetric
          positive-definite variable-bandwidth matrix.

          2. Specification

                 SUBROUTINE F01MCF (N, A, LAL, NROW, AL, D, IFAIL)
                 INTEGER          N, LAL, NROW(N), IFAIL
                 DOUBLE PRECISION A(LAL), AL(LAL), D(N)

          3. Description

          This routine determines the unit lower triangular matrix L and
                                                                   T
          the diagonal matrix D in the Cholesky factorization A=LDL  of a
          symmetric positive-definite variable-bandwidth matrix A of order
          n. (Such a matrix is sometimes called a 'sky-line' matrix.)

          The matrix A is represented by the elements lying within the
          envelope of its lower triangular part, that is, between the first
          non-zero of each row and the diagonal (see Section 9 for an
          example). The width NROW(i) of the ith row is the number of
          elements between the first non-zero element and the element on
          the diagonal, inclusive. Although, of course, any matrix
          possesses an envelope as defined, this routine is primarily
          intended for the factorization of symmetric positive-definite
          matrices with an average bandwidth which is small compared with n
          (also see Section 8).

          The method is based on the property that during Cholesky
          factorization there is no fill-in outside the envelope.

          The determination of L and D is normally the first of two steps
          in the solution of the system of equations Ax=b. The remaining
                                        T
          step, viz. the solution of LDL x=b may be carried out using
          F04MCF.

          4. References

          [1]   Jennings A (1966) A Compact Storage Scheme for the Solution
                of Symmetric Linear Simultaneous Equations. Comput. J. 9
                281--285.

          [2]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 1.

           2:  A(LAL) -- DOUBLE PRECISION array                       Input
               On entry: the elements within the envelope of the lower
               triangle of the positive-definite symmetric matrix A, taken
               in row by row order. The following code assigns the matrix
               elements within the envelope to the correct elements of the
               array:

                     K = 0
                     DO 20 I = 1, N
                     DO 10 J = I-NROW(I)+1, I
                     K = K + 1
                     A(K) = matrix (I,J)
                     10    CONTINUE
                     20 CONTINUE

               See also Section 8.

           3:  LAL -- INTEGER                                         Input
               On entry: the smaller of the dimensions of the arrays A and
               AL as declared in the calling (sub)program from which F01MCF
               is called. Constraint: LAL >= NROW(1) + NROW(2) +... + NROW(
               n).

           4:  NROW(N) -- INTEGER array                               Input
               On entry: NROW(i) must contain the width of row i of the
               matrix A, i.e., the number of elements between the first
               (leftmost) non-zero element and the element on the diagonal,
               inclusive. Constraint: 1 <= NROW(i) <= i, for i=1,2,...,n.

           5:  AL(LAL) -- DOUBLE PRECISION array                     Output
               On exit: the elements within the envelope of the lower
               triangular matrix L, taken in row by row order. The envelope
               of L is identical to that of the lower triangle of A. The
               unit diagonal elements of L are stored explicitly. See also
               Section 8.

           6:  D(N) -- DOUBLE PRECISION array                        Output
               On exit: the diagonal elements of the the diagonal matrix D
               . Note that the determinant of A is equal to the product of
               these diagonal elements. If the value of the determinant is
               required it should not be determined by forming the product
               explicitly, because of the possibility of overflow or
               underflow. The logarithm of the determinant may safely be
               formed from the sum of the logarithms of the diagonal
               elements.

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry N < 1,

               or       for some i, NROW(i) < 1 or NROW(i) > i,

               or       LAL < NROW(1) + NROW(2) +... + NROW(N).

          IFAIL= 2
               A is not positive-definite, or this property has been
               destroyed by rounding errors. The factorization has not been
               completed.

          IFAIL= 3
               A is not positive-definite, or this property has been
               destroyed by rounding errors. The factorization has been
               completed but may be very inaccurate (see Section 7).

          7. Accuracy

          If IFAIL = 0 on exit, then the computed L and D satisfy the
                      T
          relation LDL =A+F, where

                                        2
                              ||F|| <=km (epsilon)max a
                                   2                 i ii

          and

                                       2
                             ||F|| <=km (epsilon)||A|| ,
                                  2                   2

          where k is a constant of order unity, m is the largest value of
          NROW(i), and (epsilon) is the machine precision. See Wilkinson
          and Reinsch [2], pp 25--27, 54--55. If IFAIL = 3 on exit, then
          the factorization has been completed although the matrix was not
          positive-definite. However the factorization may be very
          inaccurate and should be used only with great caution. For
          instance, if it is used to solve a set of equations Ax=b using
          F04MCF, the residual vector b-Ax should be checked.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          the sum of squares of the values of NROW(i).

          The distribution of row widths may be very non-uniform without
          undue loss of efficiency. Moreover, the routine has been designed
          to be as competitive as possible in speed with routines designed
          for full or uniformly banded matrices, when applied to such
          matrices.

          Unless otherwise stated in the Users' Note for your
          implementation, the routine may be called with the same actual
          array supplied for parameters A and AL, in which case L
          overwrites the lower triangle of A. However this is not standard
          Fortran 77 and may not work in all implementations.

          9. Example

          To obtain the Cholesky factorization of the symmetric matrix,
          whose lower triangle is:

                                 (1               )
                                 (2  5            )
                                 (0  3 13         )
                                 (0  0  0 16      ).
                                 (5 14 18  8 55   )
                                 (0  0  0 24 17 77)

          For this matrix, the elements of NROW must be set to 1, 2, 2, 1,
          5, 3, and the elements within the envelope must be supplied in
          row order as:

          1, 2, 5, 3, 13, 16, 5, 14, 18, 8, 55, 24, 17, 77.


          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01QCF
                  F01QCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01QCF finds the QR factorization of the real m by n matrix A,
          where m>=n.

          2. Specification

                 SUBROUTINE F01QCF (M, N, A, LDA, ZETA, IFAIL)
                 INTEGER          M, N, LDA, IFAIL
                 DOUBLE PRECISION A(LDA,*), ZETA(*)

          3. Description

          The m by n matrix A is factorized as

                    (R)
                 A=Q(0)       when m>n,

                 A=QR         when m=n,

          where Q is an m by m orthogonal matrix and R is an n by n upper
          triangular matrix. The factorization is obtained by Householder's
          method. The kth transformation matrix, Q , which is used to
                                                  k
          introduce zeros into the kth column of A is given in the form

                                         (I 0 )
                                      Q =(0 T )
                                       k (   k)

          where

                                             T
                                     T =I-u u ,
                                      k    k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (zeta)  is a scalar and z  is an (m-k) element vector. (zeta)
                k                  k                                   k
          and z  are chosen to annihilate the elements below the triangular
               k
          part of A.

          The vector u  is returned in the kth element of the array ZETA
                      k
          and in the kth column of A, such that (zeta)  is in ZETA(k) and
                                                      k
          the elements of z  are in A(k+1,k),...,A(m,k). The elements of R
                           k
          are returned in the upper triangular part of A.

          Q is given by

                                                 T
                                  Q=(Q Q   ...Q ) .
                                      n n-1    1

          Good background descriptions to the QR factorization are given in
          Dongarra et al [1] and Golub and Van Loan [2], but note that this
          routine is not based upon LINPACK routine DQRDC.

          4. References

          [1]   Dongarra J J, Moler C B, Bunch J R and Stewart G W (1979)
                LINPACK Users' Guide. SIAM, Philadelphia.

          [2]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          [3]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           2:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A.

               When N = 0 then an immediate return is effected.
               Constraint: N >= 0.

           3:  A(LDA,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array A must be at least
               max(1,n).
               On entry: the leading m by n part of the array A must
               contain the matrix to be factorized. On exit: the n by n
               upper triangular part of A will contain the upper triangular
               matrix R and the m by n strictly lower triangular part of A
               will contain details of the factorization as described in
               Section 3.

           4:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01QCF is called.
               Constraint: LDA >= max(1,M).

           5:  ZETA(*) -- DOUBLE PRECISION array                     Output
               Note: the dimension of the array ZETA must be at least max
               (1,n) On exit: ZETA(k) contains the scalar (zeta)  for the k
                                                                k
               th transformation. If T =I then ZETA(k)=0.0, otherwise ZETA(
                                      k
               k) contains (zeta)  as described in Section 3 and (zeta)  is
                                 k                                     k

               always in the range (1.0, \/2.0).

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry M < N,

               or       N < 0,

               or       LDA < M.

          7. Accuracy

          The computed factors Q and R satisfy the relation

                                       (R)
                                      Q(0)=A+E,

          where

                             |||E|||<=c(epsilon)|||A|||,

          and (epsilon) is the machine precision (see X02AJF(*)), c is a
          modest function of m and n and |||.||| denotes the spectral (two)
          norm.

          8. Further Comments

          The approximate number of floating-point operations is given by
            2
          2n (3m-n)/3.

          Following the use of this routine the operations

                                                 T
                                 B:=QB  and  B:=Q B,

          where B is an m by k matrix, can be performed by calls to F01QDF.
          The operation B:=QB can be obtained by the call:


                IFAIL = 0
                CALL F01QDF('No transpose', 'Separate', M, N, A, LDA, ZETA,
               *            K, B, LDB, WORK, IFAIL)

                  T
          and B:=Q B can be obtained by the call:


                IFAIL = 0
                CALL F01QDF('Transpose', 'Separate', M, N, A, LDA, ZETA,
               *            K, B, LDB, WORK, IFAIL)

          In both cases WORK must be a k element array that is used as
          workspace. If B is a one-dimensional array (single column) then
          the parameter LDB can be replaced by M. See F01QDF for further
          details.

          The first k columns of the orthogonal matrix Q can either be
          obtained by setting B to the first k columns of the unit matrix
          and using the first of the above two calls, or by calling F01QEF,
          which overwrites the k columns of Q on the first k columns of the
          array A. Q is obtained by the call:


               CALL F01QEF('Separate', M, N, K, A, LDA, ZETA, WORK, IFAIL)

          As above WORK must be a k element array. If k is larger than N,
          then A must have been declared to have at least k columns.

          Operations involving the matrix R can readily be performed by the
          Level 2 BLAS routines DTRSV and DTRMV (see Chapter F06), but note
          that no test for near singularity of R is incorporated in DTRSV.
          If R is singular, or nearly singular then F02WUF(*) can be used
          to determine the singular value decomposition of R.

          9. Example

          To obtain the QR factorization of the 5 by 3 matrix

                                   (2.0  2.5  2.5)
                                   (2.0  2.5  2.5)
                                 A=(1.6 -0.4  2.8).
                                   (2.0 -0.5  0.5)
                                   (1.2 -0.3 -2.9)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01QDF
                  F01QDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01QDF performs one of the transformations

                                               T
                                  B:=QB or B:=Q B,

          where B is an m by ncolb real matrix and Q is an m by m
          orthogonal matrix, given as the product of Householder
          transformation matrices.

          This routine is intended for use following F01QCF or F01QFF(*).

          2. Specification

                 SUBROUTINE F01QDF (TRANS, WHERET, M, N, A, LDA, ZETA,
                1                   NCOLB, B, LDB, WORK, IFAIL)
                 INTEGER          M, N, LDA, NCOLB, LDB, IFAIL
                 DOUBLE PRECISION A(LDA,*), ZETA(*), B(LDB,*), WORK(*)
                 CHARACTER*1      TRANS, WHERET

          3. Description

          Q is assumed to be given by

                                                 T
                                  Q=(Q Q   ...Q ) ,
                                      n n-1    1

          Q  being given in the form
           k

                                         (I 0 )
                                      Q =(0 T )
                                       k (   k)

          where

                                             T
                                     T =I-u u ,
                                      k    k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (zeta)  is a scalar and z  is an (m-k) element vector. z  must be
                k                  k                              k
          supplied in the kth column of A in elements A(k+1,k),...,A(m,k)
          and (zeta)  must be supplied either in A(k,k) or in ZETA(k),
                    k
          depending upon the parameter WHERET.

          To obtain Q explicitly B may be set to I and pre-multiplied by Q.
                                                 T
          This is more efficient than obtaining Q .

          4. References

          [1]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          [2]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  TRANS -- CHARACTER*1                                   Input
               On entry: the operation to be performed as follows:
               TRANS = 'N' (No transpose)
                     Perform the operation B:=QB.

               TRANS = 'T' or 'C' (Transpose)
                                               T
                     Perform the operation B:=Q B.
                Constraint: TRANS must be one of 'N', 'T' or 'C'.

           2:  WHERET -- CHARACTER*1                                  Input
               On entry: indicates where the elements of (zeta) are to be
               found as follows:
               WHERET = 'I' (In A)
                     The elements of (zeta) are in A.

               WHERET = 'S' (Separate)
                     The elements of (zeta) are separate from A, in ZETA.
               Constraint: WHERET must be one of 'I' or 'S'.

           3:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           4:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A.

               When N = 0 then an immediate return is effected.
               Constraint: N >= 0.

           5:  A(LDA,*) -- DOUBLE PRECISION array                     Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the leading m by n strictly lower triangular part
               of the array A must contain details of the matrix Q. In
               addition, when WHERET = 'I', then the diagonal elements of A
               must contain the elements of (zeta) as described under the
               argument ZETA below.

               When WHERET = 'S', the diagonal elements of the array A are
               referenced, since they are used temporarily to store the
               (zeta) , but they contain their original values on return.
                     k

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01QDF is called.
               Constraint: LDA >= max(1,M).

           7:  ZETA(*) -- DOUBLE PRECISION array                      Input
               Note: when WHERET = 'S', the dimension of the array ZETA
               must be greater than or equal to max(1,N). On entry: if
               WHERET = 'S', the array ZETA must contain the elements of
               (zeta). If ZETA(k) = 0.0 then T  is assumed to be I
                                              k
               otherwise ZETA(k) is assumed to contain (zeta) .
                                                             k

               When WHERET = 'I', ZETA is not referenced.

           8:  NCOLB -- INTEGER                                       Input
               On entry: ncolb, number of columns of B.

               When NCOLB = 0 then an immediate return is effected.
               Constraint: NCOLB >= 0.

           9:  B(LDB,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array B must be at least
               max(1,NCOLB).
               On entry: the leading m by ncolb part of the array B must
               contain the matrix to be transformed. On exit: B is
               overwritten by the transformed matrix.

          10:  LDB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F01QDF is called.
               Constraint: LDB >= max(1,M).

          11:  WORK(*) -- DOUBLE PRECISION array                  Workspace
               Note: the dimension of the array WORK must be at least
               max(1,NCOLB).

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry TRANS /= 'N', 'T' or 'C',

               or       WHERET /= 'I' or 'S',

               or       M < N,

               or       N < 0,

               or       LDA < M,

               or       NCOLB < 0,

               or       LDB < M.

          7. Accuracy

                                                T
          Letting C denote the computed matrix Q B, C satisfies the
          relation

                                       QC=B+E,

          where

                               ||E||<=c(epsilon)||B||,

          and (epsilon) the machine precision (see X02AJF(*)), c is a
          modest function of m and |||.||| denotes the spectral (two) norm.
          An equivalent result holds for the computed matrix QB. See also
          Section 7 of F01QCF.

          8. Further Comments

          The approximate number of floating-point operations is given by
          2n(2m-n)ncolb.

          9. Example

                                T
          To obtain the matrix Q B for the matrix B given by

                                     ( 1.1  0.00)
                                     ( 0.9  0.00)
                                   B=( 0.6  1.32)
                                     ( 0.0  1.10)
                                     (-0.8 -0.26)

          following the QR factorization of the 5 by 3 matrix A given by

                                   (2.0  2.5  2.5)
                                   (2.0  2.5  2.5)
                                 A=(1.6 -0.4  2.8).
                                   (2.0 -0.5  0.5)
                                   (1.2 -0.3 -2.9)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01QEF
                  F01QEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01QEF returns the first ncolq columns of the real m by m
          orthogonal matrix Q, where Q is given as the product of
          Householder transformation matrices.

          This routine is intended for use following F01QCF or F01QFF(*).

          2. Specification

                 SUBROUTINE F01QEF (WHERET, M, N, NCOLQ, A, LDA, ZETA,
                1                   WORK, IFAIL)
                 INTEGER          M, N, NCOLQ, LDA, IFAIL
                 DOUBLE PRECISION A(LDA,*), ZETA(*), WORK(*)
                 CHARACTER*1      WHERET

          3. Description

          Q is assumed to be given by

                                                 T
                                  Q=(Q Q   ...Q ) ,
                                      n n-1    1

          Q  being given in the form
           k

                                         (I 0 )
                                      Q =(0 T )
                                       k (   k)

          where

                                             T
                                     T =I-u u ,
                                      k    k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (zeta)  is a scalar and z  is an (m-k) element vector. z  must be
                k                  k                              k
          supplied in the kth column of A in elements A(k+1,k),...,A(m,k)
          and (zeta)  must be supplied either in A(k,k) or in ZETA(k),
                    k
          depending upon the parameter WHERET.

          4. References

          [1]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          [2]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  WHERET -- CHARACTER*1                                  Input
               On entry: indicates where the elements of (zeta) are to be
               found as follows:
               WHERET = 'I' (In A)
                     The elements of (zeta) are in A.

               WHERET = 'S' (Separate)
                     The elements of (zeta) are separate from A, in ZETA.
               Constraint: WHERET must be one of 'I' or 'S'.

           2:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: N >=
               0.

           4:  NCOLQ -- INTEGER                                       Input
               On entry: ncolq, the required number of columns of Q.
               Constraint: 0 <= NCOLQ <= M.

               When NCOLQ = 0 then an immediate return is effected.

           5:  A(LDA,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N,NCOLQ).
               On entry: the leading m by n strictly lower triangular part
               of the array A must contain details of the matrix Q. In
               addition, when WHERET = 'I', then the diagonal elements of A
               must contain the elements of (zeta) as described under the
               argument ZETA below. On exit: the first NCOLQ columns of the
               array A are overwritten by the first NCOLQ columns of the m
               by m orthogonal matrix Q. When N = 0 then the first NCOLQ
               columns of A are overwritten by the first NCOLQ columns of
               the identity matrix.

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01QEF is called.
               Constraint: LDA >= max(1,M).

           7:  ZETA(*) -- DOUBLE PRECISION array                      Input
               Note: the dimension of the array ZETA must be at least
               max(1,N).
               On entry: with WHERET = 'S', the array ZETA must contain the
               elements of (zeta). If ZETA(k) = 0.0 then T  is assumed to
                                                          k
               be I, otherwise ZETA(k) is assumed to contain (zeta) .
                                                                   k

               When WHERET = 'I', the array ZETA is not referenced.

           8:  WORK(*) -- DOUBLE PRECISION array                  Workspace
               Note: the dimension of the array WORK must be at least
               max(1,NCOLQ).

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry WHERET /= 'I' or 'S',

               or       M < N,

               or       N < 0,

               or       NCOLQ < 0 or NCOLQ > M,

               or       LDA < M.

          7. Accuracy

          The computed matrix Q satisfies the relation

                                       Q=P+E,

          where P is an exactly orthogonal matrix and

                                 ||E||<=c(epsilon)

          (epsilon) is the machine precision (see X02AJF(*)), c is a modest
          function of m and |||.||| denotes the spectral (two) norm. See
          also Section 7 of F01QCF.

          8. Further Comments

          The approximate number of floating-point operations required is
          given by

               2
               -n{(3m-n)(2ncolq-n)-n(ncolq-n)},    ncolq>n,
               3

               2     2
               -ncolq (3m-ncolq),                  ncolq<=n.
               3

          9. Example

          To obtain the 5 by 5 orthogonal matrix Q following the QR
          factorization of the 5 by 3 matrix A given by

                                   (2.0  2.5  2.5)
                                   (2.0  2.5  2.5)
                                 A=(1.6 -0.4  2.8).
                                   (2.0 -0.5  0.5)
                                   (1.2 -0.3 -2.9)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01RCF
                  F01RCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01RCF finds the QR factorization of the complex m by n matrix A,
          where m>=n.

          2. Specification

                 SUBROUTINE   F01RCF (M, N, A, LDA, THETA, IFAIL)
                 INTEGER              M, N, LDA, IFAIL
                 COMPLEX(KIND(1.0D0)) A(LDA,*), THETA(*)

          3. Description

          The m by n matrix A is factorized as

                    (R)
                 A=Q(0)       when m>n,

                 A=QR         when m=n,

          where Q is an m by m unitary matrix and R is an n by n upper
          triangular matrix with real diagonal elements.

          The factorization is obtained by Householder's method. The kth
          transformation matrix, Q , which is used to introduce zeros into
                                  k
          the kth column of A is given in the form

                                        (I 0 )
                                     Q =(0 T ),
                                      k (   k)

          where

                                                 H
                                 T =I-(gamma) u u ,
                                  k          k k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (gamma)  is a scalar for which Re (gamma) =1.0, (zeta)  is a real
                 k                                 k            k
          scalar and z  is an (m-k) element vector. (gamma) , (zeta)  and
                      k                                    k        k
          z  are chosen to annihilate the elements below the triangular
           k
          part of A and to make the diagonal elements real.

          The scalar (gamma)  and the vector u  are returned in the kth
                            k                 k
          element of the array THETA and in the kth column of A, such that
          (theta) , given by
                 k

                           (theta) =((zeta) ,Im(gamma) ),
                                  k        k          k

          is in THETA(k) and the elements of z  are in a     ,...,a   . The
                                              k         k+1,k      m,k
          elements of R are returned in the upper triangular part of A.

          Q is given by

                                                 H
                                  Q=(Q Q   ...Q ) .
                                      n n-1    1

          A good background description to the QR factorization is given in
          Dongarra et al [1], but note that this routine is not based upon
          LINPACK routine ZQRDC.

          4. References

          [1]   Dongarra J J, Moler C B, Bunch J R and Stewart G W (1979)
                LINPACK Users' Guide. SIAM, Philadelphia.

          [2]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           2:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: N >=
               0.

               When N = 0 then an immediate return is effected.

           3:  A(LDA,*) -- COMPLEX(KIND(1.0D0)) array          Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the leading m by n part of the array A must
               contain the matrix to be factorized. On exit: the n by n
               upper triangular part of A will contain the upper triangular
               matrix R, with the imaginary parts of the diagonal elements
               set to zero, and the m by n strictly lower triangular part
               of A will contain details of the factorization as described
               above.

           4:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01RCF is called.
               Constraint: LDA >= max(1,M).

           5:  THETA(*) -- COMPLEX(KIND(1.0D)) array                 Output
               Note: the dimension of the array THETA must be at least
               max(1,N).
               On exit: the scalar (theta)  for the kth transformation. If
                                          k
               T =I then THETA(k) = 0.0; if
                k
                                ((alpha) 0)
                             T =(      0 I)   Re(alpha)<0.0,
                              k
               then THETA(k)=(alpha); otherwise THETA(k) contains THETA(k)
               as described in Section 3 and Re(THETA(k)) is always in the
                             

               range (1.0, \/2.0).

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry M < N,

               or       N < 0,

               or       LDA < M.

          7. Accuracy
          The computed factors Q and R satisfy the relation

                                       (R)
                                      Q(0)=A+E,

          where

                             ||E||<=c(epsilon)||A||,

          (epsilon) being the machine precision, c is a modest function of
          m and n and ||.|| denotes the spectral (two) norm.

          8. Further Comments

          The approximate number of real floating-point operations is given
               2
          by 8n (3m-n)/3.

          Following the use of this routine the operations

                                                 H
                                 B:=QB  and  B:=Q B,

          where B is an m by k matrix, can be performed by calls to F01RDF.
          The operation B:=QB can be obtained by the call:


                IFAIL = 0
                CALL F01RDF(`No conjugate', 'Separate', M, N, A, LDA, THETA,
               *            K, B, LDB, WORK, IFAIL)

                  H
          and B:=Q B can be obtained by the call:


                IFAIL = 0
                CALL F01RDF(`Conjugate', 'Separate', M, N, A, LDA, THETA,
               *            K, B, LDB, WORK, IFAIL)

          In both cases WORK must be a k element array that is used as
          workspace. If B is a one-dimensional array (single column) then
          the parameter LDB can be replaced by M. See F01RDF for further
          details.

          The first k columns of the unitary matrix Q can either be
          obtained by setting B to the first k columns of the unit matrix
          and using the first of the above two calls, or by calling F01REF,
          which overwrites the k columns of Q on the first k columns of the
          array A. Q is obtained by the call:


                CALL F01REF(`Separate', M, N, K, A, LDA, THETA, WORK, IFAIL)

          As above, WORK must be a k element array. If k is larger than n,
          then A must have been declared to have at least k columns.

          Operations involving the matrix R can readily be performed by the
          Level 2 BLAS routines ZTRSV and ZTRMV (see Chapter F06), but note
          that no test for near singularity of R is incorporated in ZTRSV.
          If R is singular, or nearly singular, then F02XUF(*) can be used
          to determine the singular value decomposition of R.

          9. Example

          To obtain the QR factorization of the 5 by 3 matrix

                             (  0.5i -0.5+1.5i -1.0+1.0i)
                             (0.4+0.3i 0.9+1.3i 0.2+1.4i)
                           A=(  0.4 -0.4+0.4i    1.8    ).
                             (0.3-0.4i 0.1+0.7i    0.0  )
                             ( -0.3i 0.3+0.3i   2.4i    )

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01RDF
                  F01RDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01RDF performs one of the transformations

                                               H
                                  B:=QB or B:=Q B,

          where B is an m by ncolb complex matrix and Q is an m by m
          unitary matrix, given as the product of Householder
          transformation matrices.

          This routine is intended for use following F01RCF or F01RFF(*).

          2. Specification

                 SUBROUTINE F01RDF (TRANS, WHERET, M, N, A, LDA, THETA,
                1                   NCOLB, B, LDB, WORK, IFAIL)
                 INTEGER              M, N, LDA, NCOLB, LDB, IFAIL
                 COMPLEX(KIND(1.0D0)) A(LDA,*), THETA(*), B(LDB,*), WORK(*)
                 CHARACTER*1          TRANS, WHERET

          3. Description

          The unitary matrix Q is assumed to be given by

                                                 H
                                  Q=(Q Q   ...Q ) ,
                                      n n-1    1

          Q  being given in the form
           k

                                        (I 0 )
                                     Q =(0 T ),
                                      k (   k)

          where

                                                 H
                                 T =I-(gamma) u u ,
                                  k          k k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (gamma)  is a scalar for which Re (gamma) =1.0, (zeta)  is a real
                 k                                 k            k
          scalar and z  is an (m-k) element vector.
                      k

          z  must be supplied in the kth column of A in elements
           k
          a     ,...,a    and (theta) , given by
           k+1,k      m,k            k

                           (theta) =((zeta) ,Im (gamma) ),
                                  k        k           k

          must be supplied either in a    or in THETA(k), depending upon
                                      k,k
          the parameter WHERET.

          To obtain Q explicitly B may be set to I and pre-multiplied by Q.
                                                 H
          This is more efficient than obtaining Q . Alternatively, F01REF
          may be used to obtain Q overwritten on A.

          4. References

          [1]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  TRANS -- CHARACTER*1                                   Input
               On entry: the operation to be performed as follows:
               TRANS = 'N' (No transpose)
                     Perform the operation B:=QB.

               TRANS = 'C' (Conjugate transpose)
                                               H
                     Perform the operation B:=Q B.
               Constraint: TRANS must be one of 'N' or 'C'.

           2:  WHERET -- CHARACTER*1                                  Input
               On entry: the elements of (theta) are to be found as
               follows:
               WHERET = 'I' (In A)
                     The elements of (theta) are in A.

               WHERET = 'S' (Separate)
                     The elements of (theta) are separate from A, in THETA.
               Constraint: WHERET must be one of 'I' or 'S'.

           3:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           4:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: N >=
               0.

               When N = 0 then an immediate return is effected.

           5:  A(LDA,*) -- COMPLEX(KIND(1.0D)) array                  Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the leading m by n strictly lower triangular part
               of the array A must contain details of the matrix Q. In
               addition, when WHERET = 'I', then the diagonal elements of A
               must contain the elements of (theta) as described under the
               argument THETA below.

               When WHERET = 'S', then the diagonal elements of the array A
               are referenced, since they are used temporarily to store the
               (zeta) , but they contain their original values on return.
                     k

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01RDF is called.
               Constraint: LDA >= max(1,M).

           7:  THETA(*) -- COMPLEX(KIND(1.0D)) array                  Input
               Note: the dimension of the array THETA must be at least
               max(1,N).
               On entry: with WHERET = 'S', the array THETA must contain
               the elements of (theta). If THETA(k)=0.0 then T  is assumed
                                                              k
               to be I; if THETA(k)=(alpha), with Re(alpha)<0.0, then T  is
                                                                       k
               assumed to be of the form
                                        ((alpha) 0)
                                     T =(0       I);
                                      k
               otherwise THETA(k) is assumed to contain (theta)  given by
                                                               k
               (theta) =((zeta) ,Im(gamma) ).
                      k        k          k

               When WHERET = 'I', the array THETA is not referenced, and
               may be dimensioned of length 1.

           8:  NCOLB -- INTEGER                                       Input
               On entry: ncolb, the number of columns of B. Constraint:
               NCOLB >= 0.
               When NCOLB = 0 then an immediate return is effected.

           9:  B(LDB,*) -- COMPLEX(KIND(1.0D)) array           Input/Output
               Note: the second dimension of the array B must be at least
               max(1,NCOLB).
               On entry: the leading m by ncolb part of the array B must
               contain the matrix to be transformed. On exit: B is
               overwritten by the transformed matrix.

          10:  LDB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F01RDF is called.
               Constraint: LDB >= max(1,M).

          11:  WORK(*) -- COMPLEX(KIND(1.0D)) array               Workspace
               Note: the dimension of the array WORK must be at least
               max(1,NCOLB).

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry TRANS /= 'N' or 'C',

               or       WHERET /= 'I' or 'S',

               or       M < N,

               or       N < 0,

               or       LDA < M,

               or       NCOLB < 0,

               or       LDB < M.

          7. Accuracy

          Letting C denote the computed matrix Q B, C satisfies the
          relation

                                       QC=B+E,

          where

                             ||E||<=c(epsilon)||B||,

          (epsilon) being the machine precision, c is a modest function of
          m and |||.||| denotes the spectral (two) norm. An equivalent
          result holds for the computed matrix QB. See also Section 7 of
          F01RCF.

          8. Further Comments

          The approximate number of real floating-point operations is given
          by 8n(2m-n)ncolb.

          9. Example

                                H
          To obtain the matrix Q B for the matrix B given by

                               (-0.55+1.05i  0.45+1.05i)
                               ( 0.49+0.93i  1.09+0.13i)
                             B=( 0.56-0.16i  0.64+0.16i)
                               ( 0.39+0.23i -0.39-0.23i)
                               ( 1.13+0.83i -1.13+0.77i)

          following the QR factorization of the 5 by 3 matrix A given by

                             (  0.5i   -0.5+1.5i -1.0+1.0i)
                             (0.4+0.3i  0.9+1.3i  0.2+1.4i)
                           A=(  0.4    -0.4+0.4i  1.8     ).
                             (0.3-0.4i  0.1+0.7i  0.0     )
                             ( -0.3i    0.3+0.3i      2.4i)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

          F01 -- Matrix Factorizations                               F01REF
                  F01REF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01REF returns the first ncolq columns of the complex m by m
          unitary matrix Q, where Q is given as the product of Householder
          transformation matrices.

          This routine is intended for use following F01RCF.

          2. Specification

                 SUBROUTINE F01REF (WHERET, M, N, NCOLQ, A, LDA, THETA,
                1                   WORK, IFAIL)
                 INTEGER              M, N, NCOLQ, LDA, IFAIL
                 COMPLEX(KIND(1.0D0)) A(LDA,*), THETA(*), WORK(*)
                 CHARACTER*1          WHERET

          3. Description

          The unitary matrix Q is assumed to be given by

                                                 H
                                  Q=(Q Q   ...Q ) ,
                                      n n-1    1

          Q  being given in the form
           k

                                        (I 0 )
                                     Q =(0 T ),
                                      k (   k)

          where

                                                 H
                                 T =I-(gamma) u u ,
                                  k          k k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (gamma)  is a scalar for which Re (gamma) =1.0, (zeta)  is a real
                 k                                 k            k

          scalar and z  is an (m-k) element vector.
                      k

          z  must be supplied in the kth column of A in elements
           k
          a     ,...,a    and (theta) , given by
           k+1,k      m,k            k

                           (theta) =((zeta) ,Im (gamma) ),
                                  k        k           k

          must be supplied either in a    or in THETA(k) depending upon the
                                      k,k
          parameter WHERET.

          4. References

          [1]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  WHERET -- CHARACTER*1                                  Input
               On entry: the elements of (theta) are to be found as
               follows:
               WHERET = 'I' (In A)
                     The elements of (theta) are in A.

               WHERET = 'S' (Separate)
                     The elements of (theta) are separate from A, in THETA.
               Constraint: WHERET must be one of 'I' or 'S'.

           2:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: N >=
               0.

           4:  NCOLQ -- INTEGER                                       Input
               On entry: ncolq, the required number of columns of Q.
               Constraint: 0 <= NCOLQ <= M.

               When NCOLQ = 0 then an immediate return is effected.

           5:  A(LDA,*) -- COMPLEX(KIND(1.0D)) array           Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N,NCOLQ).
               On entry: the leading m by n strictly lower triangular part
               of the array A must contain details of the matrix Q. In
               addition, when WHERET = 'I', then the diagonal elements of A
               must contain the elements of (theta) as described under the
               argument THETA below. On exit: the first NCOLQ columns of
               the array A are overwritten by the first NCOLQ columns of
               the m by m unitary matrix Q. When N = 0 then the first NCOLQ
               columns of A are overwritten by the first NCOLQ columns of
               the unit matrix.

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01REF is called.
               Constraint: LDA >= max(1,M).

           7:  THETA(*) -- COMPLEX(KIND(1.0D)) array                  Input
               Note: the dimension of the array THETA must be at least
               max(1,N).
               On entry: if WHERET = 'S', the array THETA must contain the
               elements of (theta). If THETA(k)=0.0 then T  is assumed to
                                                          k
               be I; if THETA(k)=(alpha), with Re(alpha)<0.0, then T  is
                                                                    k
               assumed to be of the form
                                        ((alpha) 0)
                                     T =(   0    I);
                                      k
               otherwise THETA(k) is assumed to contain (theta)  given by
                                                               k
               (theta) =((zeta) ,Im(gamma) ).
                      k        k          k

               When WHERET = 'I', the array THETA is not referenced.

           8:  WORK(*) -- COMPLEX(KIND(1.0D)) array               Workspace
               Note: the dimension of the array WORK must be at least
               max(1,NCOLQ).

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry WHERET /= 'I' or 'S',

               or       M < N,

               or       N < 0,

               or       NCOLQ < 0 or NCOLQ > M,

               or       LDA < M.

          7. Accuracy

          The computed matrix Q satisfies the relation

                                       Q=P+E,

          where P is an exactly unitary matrix and

                                ||E||<=c(epsilon),

          (epsilon) being the machine precision, c is a modest function of
          m and |||.||| denotes the spectral (two) norm. See also Section 7
          of F01RCF.

          8. Further Comments

          The approximate number of real floating-point operations required
          is given by

               8
               -n{(3m-n)(2ncolq-n)-n(ncolq-n)},  ncolq>n
               3

               8     2
               -ncolq (3m-ncolq),                ncolq<=n
               3

          9. Example

          To obtain the 5 by 5 unitary matrix Q following the QR
          factorization of the 5 by 3 matrix A given by

                             (    0.5i -0.5+1.5i -1.0+1.4i)
                             (0.4+0.3i  0.9+1.3i  0.2+1.4i)
                           A=(0.4      -0.4+0.4i  1.8     ).
                             (0.3-0.4i  0.1+0.7i  0.0     )
                             (   -0.3i  0.3+0.3i      2.4i)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

