1       SUBROUTINE DGEQLS( M, N, NRHS, A, LDA, TAU, B, LDB, WORK, LWORK,
  2      $                   INFO )
  3 *
  4 *  -- LAPACK routine (version 3.1) --
  5 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
  6 *     November 2006
  7 *
  8 *     .. Scalar Arguments ..
  9       INTEGER            INFO, LDA, LDB, LWORK, M, N, NRHS
 10 *     ..
 11 *     .. Array Arguments ..
 12       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), TAU( * ),
 13      $                   WORK( LWORK )
 14 *     ..
 15 *
 16 *  Purpose
 17 *  =======
 18 *
 19 *  Solve the least squares problem
 20 *      min || A*X - B ||
 21 *  using the QL factorization
 22 *      A = Q*L
 23 *  computed by DGEQLF.
 24 *
 25 *  Arguments
 26 *  =========
 27 *
 28 *  M       (input) INTEGER
 29 *          The number of rows of the matrix A.  M >= 0.
 30 *
 31 *  N       (input) INTEGER
 32 *          The number of columns of the matrix A.  M >= N >= 0.
 33 *
 34 *  NRHS    (input) INTEGER
 35 *          The number of columns of B.  NRHS >= 0.
 36 *
 37 *  A       (input) DOUBLE PRECISION array, dimension (LDA,N)
 38 *          Details of the QL factorization of the original matrix A as
 39 *          returned by DGEQLF.
 40 *
 41 *  LDA     (input) INTEGER
 42 *          The leading dimension of the array A.  LDA >= M.
 43 *
 44 *  TAU     (input) DOUBLE PRECISION array, dimension (N)
 45 *          Details of the orthogonal matrix Q.
 46 *
 47 *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
 48 *          On entry, the m-by-nrhs right hand side matrix B.
 49 *          On exit, the n-by-nrhs solution matrix X, stored in rows
 50 *          m-n+1:m.
 51 *
 52 *  LDB     (input) INTEGER
 53 *          The leading dimension of the array B. LDB >= M.
 54 *
 55 *  WORK    (workspace) DOUBLE PRECISION array, dimension (LWORK)
 56 *
 57 *  LWORK   (input) INTEGER
 58 *          The length of the array WORK.  LWORK must be at least NRHS,
 59 *          and should be at least NRHS*NB, where NB is the block size
 60 *          for this environment.
 61 *
 62 *  INFO    (output) INTEGER
 63 *          = 0: successful exit
 64 *          < 0: if INFO = -i, the i-th argument had an illegal value
 65 *
 66 *  =====================================================================
 67 *
 68 *     .. Parameters ..
 69       DOUBLE PRECISION   ONE
 70       PARAMETER          ( ONE = 1.0D+0 )
 71 *     ..
 72 *     .. External Subroutines ..
 73       EXTERNAL           DORMQL, DTRSM, XERBLA
 74 *     ..
 75 *     .. Intrinsic Functions ..
 76       INTRINSIC          MAX
 77 *     ..
 78 *     .. Executable Statements ..
 79 *
 80 *     Test the input arguments.
 81 *
 82       INFO = 0
 83       IF( M.LT.0 ) THEN
 84          INFO = -1
 85       ELSE IF( N.LT.0 .OR. N.GT.M ) THEN
 86          INFO = -2
 87       ELSE IF( NRHS.LT.0 ) THEN
 88          INFO = -3
 89       ELSE IF( LDA.LT.MAX1, M ) ) THEN
 90          INFO = -5
 91       ELSE IF( LDB.LT.MAX1, M ) ) THEN
 92          INFO = -8
 93       ELSE IF( LWORK.LT.1 .OR. LWORK.LT.NRHS .AND. M.GT.0 .AND. N.GT.0 )
 94      $          THEN
 95          INFO = -10
 96       END IF
 97       IF( INFO.NE.0 ) THEN
 98          CALL XERBLA( 'DGEQLS'-INFO )
 99          RETURN
100       END IF
101 *
102 *     Quick return if possible
103 *
104       IF( N.EQ.0 .OR. NRHS.EQ.0 .OR. M.EQ.0 )
105      $   RETURN
106 *
107 *     B := Q' * B
108 *
109       CALL DORMQL( 'Left''Transpose', M, NRHS, N, A, LDA, TAU, B, LDB,
110      $             WORK, LWORK, INFO )
111 *
112 *     Solve L*X = B(m-n+1:m,:)
113 *
114       CALL DTRSM( 'Left''Lower''No transpose''Non-unit', N, NRHS,
115      $            ONE, A( M-N+11 ), LDA, B( M-N+11 ), LDB )
116 *
117       RETURN
118 *
119 *     End of DGEQLS
120 *
121       END