LAPACK 3.3.1
Linear Algebra PACKage

sgelsy.f

Go to the documentation of this file.
00001       SUBROUTINE SGELSY( M, N, NRHS, A, LDA, B, LDB, JPVT, RCOND, RANK,
00002      $                   WORK, LWORK, INFO )
00003 *
00004 *  -- LAPACK driver routine (version 3.3.1) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *  -- April 2011                                                      --
00008 *
00009 *     .. Scalar Arguments ..
00010       INTEGER            INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
00011       REAL               RCOND
00012 *     ..
00013 *     .. Array Arguments ..
00014       INTEGER            JPVT( * )
00015       REAL               A( LDA, * ), B( LDB, * ), WORK( * )
00016 *     ..
00017 *
00018 *  Purpose
00019 *  =======
00020 *
00021 *  SGELSY computes the minimum-norm solution to a real linear least
00022 *  squares problem:
00023 *      minimize || A * X - B ||
00024 *  using a complete orthogonal factorization of A.  A is an M-by-N
00025 *  matrix which may be rank-deficient.
00026 *
00027 *  Several right hand side vectors b and solution vectors x can be
00028 *  handled in a single call; they are stored as the columns of the
00029 *  M-by-NRHS right hand side matrix B and the N-by-NRHS solution
00030 *  matrix X.
00031 *
00032 *  The routine first computes a QR factorization with column pivoting:
00033 *      A * P = Q * [ R11 R12 ]
00034 *                  [  0  R22 ]
00035 *  with R11 defined as the largest leading submatrix whose estimated
00036 *  condition number is less than 1/RCOND.  The order of R11, RANK,
00037 *  is the effective rank of A.
00038 *
00039 *  Then, R22 is considered to be negligible, and R12 is annihilated
00040 *  by orthogonal transformations from the right, arriving at the
00041 *  complete orthogonal factorization:
00042 *     A * P = Q * [ T11 0 ] * Z
00043 *                 [  0  0 ]
00044 *  The minimum-norm solution is then
00045 *     X = P * Z**T [ inv(T11)*Q1**T*B ]
00046 *                  [        0         ]
00047 *  where Q1 consists of the first RANK columns of Q.
00048 *
00049 *  This routine is basically identical to the original xGELSX except
00050 *  three differences:
00051 *    o The call to the subroutine xGEQPF has been substituted by the
00052 *      the call to the subroutine xGEQP3. This subroutine is a Blas-3
00053 *      version of the QR factorization with column pivoting.
00054 *    o Matrix B (the right hand side) is updated with Blas-3.
00055 *    o The permutation of matrix B (the right hand side) is faster and
00056 *      more simple.
00057 *
00058 *  Arguments
00059 *  =========
00060 *
00061 *  M       (input) INTEGER
00062 *          The number of rows of the matrix A.  M >= 0.
00063 *
00064 *  N       (input) INTEGER
00065 *          The number of columns of the matrix A.  N >= 0.
00066 *
00067 *  NRHS    (input) INTEGER
00068 *          The number of right hand sides, i.e., the number of
00069 *          columns of matrices B and X. NRHS >= 0.
00070 *
00071 *  A       (input/output) REAL array, dimension (LDA,N)
00072 *          On entry, the M-by-N matrix A.
00073 *          On exit, A has been overwritten by details of its
00074 *          complete orthogonal factorization.
00075 *
00076 *  LDA     (input) INTEGER
00077 *          The leading dimension of the array A.  LDA >= max(1,M).
00078 *
00079 *  B       (input/output) REAL array, dimension (LDB,NRHS)
00080 *          On entry, the M-by-NRHS right hand side matrix B.
00081 *          On exit, the N-by-NRHS solution matrix X.
00082 *
00083 *  LDB     (input) INTEGER
00084 *          The leading dimension of the array B. LDB >= max(1,M,N).
00085 *
00086 *  JPVT    (input/output) INTEGER array, dimension (N)
00087 *          On entry, if JPVT(i) .ne. 0, the i-th column of A is permuted
00088 *          to the front of AP, otherwise column i is a free column.
00089 *          On exit, if JPVT(i) = k, then the i-th column of AP
00090 *          was the k-th column of A.
00091 *
00092 *  RCOND   (input) REAL
00093 *          RCOND is used to determine the effective rank of A, which
00094 *          is defined as the order of the largest leading triangular
00095 *          submatrix R11 in the QR factorization with pivoting of A,
00096 *          whose estimated condition number < 1/RCOND.
00097 *
00098 *  RANK    (output) INTEGER
00099 *          The effective rank of A, i.e., the order of the submatrix
00100 *          R11.  This is the same as the order of the submatrix T11
00101 *          in the complete orthogonal factorization of A.
00102 *
00103 *  WORK    (workspace/output) REAL array, dimension (MAX(1,LWORK))
00104 *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
00105 *
00106 *  LWORK   (input) INTEGER
00107 *          The dimension of the array WORK.
00108 *          The unblocked strategy requires that:
00109 *             LWORK >= MAX( MN+3*N+1, 2*MN+NRHS ),
00110 *          where MN = min( M, N ).
00111 *          The block algorithm requires that:
00112 *             LWORK >= MAX( MN+2*N+NB*(N+1), 2*MN+NB*NRHS ),
00113 *          where NB is an upper bound on the blocksize returned
00114 *          by ILAENV for the routines SGEQP3, STZRZF, STZRQF, SORMQR,
00115 *          and SORMRZ.
00116 *
00117 *          If LWORK = -1, then a workspace query is assumed; the routine
00118 *          only calculates the optimal size of the WORK array, returns
00119 *          this value as the first entry of the WORK array, and no error
00120 *          message related to LWORK is issued by XERBLA.
00121 *
00122 *  INFO    (output) INTEGER
00123 *          = 0: successful exit
00124 *          < 0: If INFO = -i, the i-th argument had an illegal value.
00125 *
00126 *  Further Details
00127 *  ===============
00128 *
00129 *  Based on contributions by
00130 *    A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA
00131 *    E. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain
00132 *    G. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain
00133 *
00134 *  =====================================================================
00135 *
00136 *     .. Parameters ..
00137       INTEGER            IMAX, IMIN
00138       PARAMETER          ( IMAX = 1, IMIN = 2 )
00139       REAL               ZERO, ONE
00140       PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0 )
00141 *     ..
00142 *     .. Local Scalars ..
00143       LOGICAL            LQUERY
00144       INTEGER            I, IASCL, IBSCL, ISMAX, ISMIN, J, LWKMIN,
00145      $                   LWKOPT, MN, NB, NB1, NB2, NB3, NB4
00146       REAL               ANRM, BIGNUM, BNRM, C1, C2, S1, S2, SMAX,
00147      $                   SMAXPR, SMIN, SMINPR, SMLNUM, WSIZE
00148 *     ..
00149 *     .. External Functions ..
00150       INTEGER            ILAENV
00151       REAL               SLAMCH, SLANGE
00152       EXTERNAL           ILAENV, SLAMCH, SLANGE
00153 *     ..
00154 *     .. External Subroutines ..
00155       EXTERNAL           SCOPY, SGEQP3, SLABAD, SLAIC1, SLASCL, SLASET,
00156      $                   SORMQR, SORMRZ, STRSM, STZRZF, XERBLA
00157 *     ..
00158 *     .. Intrinsic Functions ..
00159       INTRINSIC          ABS, MAX, MIN
00160 *     ..
00161 *     .. Executable Statements ..
00162 *
00163       MN = MIN( M, N )
00164       ISMIN = MN + 1
00165       ISMAX = 2*MN + 1
00166 *
00167 *     Test the input arguments.
00168 *
00169       INFO = 0
00170       LQUERY = ( LWORK.EQ.-1 )
00171       IF( M.LT.0 ) THEN
00172          INFO = -1
00173       ELSE IF( N.LT.0 ) THEN
00174          INFO = -2
00175       ELSE IF( NRHS.LT.0 ) THEN
00176          INFO = -3
00177       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
00178          INFO = -5
00179       ELSE IF( LDB.LT.MAX( 1, M, N ) ) THEN
00180          INFO = -7
00181       END IF
00182 *
00183 *     Figure out optimal block size
00184 *
00185       IF( INFO.EQ.0 ) THEN
00186          IF( MN.EQ.0 .OR. NRHS.EQ.0 ) THEN
00187             LWKMIN = 1
00188             LWKOPT = 1
00189          ELSE
00190             NB1 = ILAENV( 1, 'SGEQRF', ' ', M, N, -1, -1 )
00191             NB2 = ILAENV( 1, 'SGERQF', ' ', M, N, -1, -1 )
00192             NB3 = ILAENV( 1, 'SORMQR', ' ', M, N, NRHS, -1 )
00193             NB4 = ILAENV( 1, 'SORMRQ', ' ', M, N, NRHS, -1 )
00194             NB = MAX( NB1, NB2, NB3, NB4 )
00195             LWKMIN = MN + MAX( 2*MN, N + 1, MN + NRHS )
00196             LWKOPT = MAX( LWKMIN,
00197      $                    MN + 2*N + NB*( N + 1 ), 2*MN + NB*NRHS )
00198          END IF
00199          WORK( 1 ) = LWKOPT
00200 *
00201          IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN
00202             INFO = -12
00203          END IF
00204       END IF
00205 *
00206       IF( INFO.NE.0 ) THEN
00207          CALL XERBLA( 'SGELSY', -INFO )
00208          RETURN
00209       ELSE IF( LQUERY ) THEN
00210          RETURN
00211       END IF
00212 *
00213 *     Quick return if possible
00214 *
00215       IF( MN.EQ.0 .OR. NRHS.EQ.0 ) THEN
00216          RANK = 0
00217          RETURN
00218       END IF
00219 *
00220 *     Get machine parameters
00221 *
00222       SMLNUM = SLAMCH( 'S' ) / SLAMCH( 'P' )
00223       BIGNUM = ONE / SMLNUM
00224       CALL SLABAD( SMLNUM, BIGNUM )
00225 *
00226 *     Scale A, B if max entries outside range [SMLNUM,BIGNUM]
00227 *
00228       ANRM = SLANGE( 'M', M, N, A, LDA, WORK )
00229       IASCL = 0
00230       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00231 *
00232 *        Scale matrix norm up to SMLNUM
00233 *
00234          CALL SLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
00235          IASCL = 1
00236       ELSE IF( ANRM.GT.BIGNUM ) THEN
00237 *
00238 *        Scale matrix norm down to BIGNUM
00239 *
00240          CALL SLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
00241          IASCL = 2
00242       ELSE IF( ANRM.EQ.ZERO ) THEN
00243 *
00244 *        Matrix all zero. Return zero solution.
00245 *
00246          CALL SLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )
00247          RANK = 0
00248          GO TO 70
00249       END IF
00250 *
00251       BNRM = SLANGE( 'M', M, NRHS, B, LDB, WORK )
00252       IBSCL = 0
00253       IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
00254 *
00255 *        Scale matrix norm up to SMLNUM
00256 *
00257          CALL SLASCL( 'G', 0, 0, BNRM, SMLNUM, M, NRHS, B, LDB, INFO )
00258          IBSCL = 1
00259       ELSE IF( BNRM.GT.BIGNUM ) THEN
00260 *
00261 *        Scale matrix norm down to BIGNUM
00262 *
00263          CALL SLASCL( 'G', 0, 0, BNRM, BIGNUM, M, NRHS, B, LDB, INFO )
00264          IBSCL = 2
00265       END IF
00266 *
00267 *     Compute QR factorization with column pivoting of A:
00268 *        A * P = Q * R
00269 *
00270       CALL SGEQP3( M, N, A, LDA, JPVT, WORK( 1 ), WORK( MN+1 ),
00271      $             LWORK-MN, INFO )
00272       WSIZE = MN + WORK( MN+1 )
00273 *
00274 *     workspace: MN+2*N+NB*(N+1).
00275 *     Details of Householder rotations stored in WORK(1:MN).
00276 *
00277 *     Determine RANK using incremental condition estimation
00278 *
00279       WORK( ISMIN ) = ONE
00280       WORK( ISMAX ) = ONE
00281       SMAX = ABS( A( 1, 1 ) )
00282       SMIN = SMAX
00283       IF( ABS( A( 1, 1 ) ).EQ.ZERO ) THEN
00284          RANK = 0
00285          CALL SLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )
00286          GO TO 70
00287       ELSE
00288          RANK = 1
00289       END IF
00290 *
00291    10 CONTINUE
00292       IF( RANK.LT.MN ) THEN
00293          I = RANK + 1
00294          CALL SLAIC1( IMIN, RANK, WORK( ISMIN ), SMIN, A( 1, I ),
00295      $                A( I, I ), SMINPR, S1, C1 )
00296          CALL SLAIC1( IMAX, RANK, WORK( ISMAX ), SMAX, A( 1, I ),
00297      $                A( I, I ), SMAXPR, S2, C2 )
00298 *
00299          IF( SMAXPR*RCOND.LE.SMINPR ) THEN
00300             DO 20 I = 1, RANK
00301                WORK( ISMIN+I-1 ) = S1*WORK( ISMIN+I-1 )
00302                WORK( ISMAX+I-1 ) = S2*WORK( ISMAX+I-1 )
00303    20       CONTINUE
00304             WORK( ISMIN+RANK ) = C1
00305             WORK( ISMAX+RANK ) = C2
00306             SMIN = SMINPR
00307             SMAX = SMAXPR
00308             RANK = RANK + 1
00309             GO TO 10
00310          END IF
00311       END IF
00312 *
00313 *     workspace: 3*MN.
00314 *
00315 *     Logically partition R = [ R11 R12 ]
00316 *                             [  0  R22 ]
00317 *     where R11 = R(1:RANK,1:RANK)
00318 *
00319 *     [R11,R12] = [ T11, 0 ] * Y
00320 *
00321       IF( RANK.LT.N )
00322      $   CALL STZRZF( RANK, N, A, LDA, WORK( MN+1 ), WORK( 2*MN+1 ),
00323      $                LWORK-2*MN, INFO )
00324 *
00325 *     workspace: 2*MN.
00326 *     Details of Householder rotations stored in WORK(MN+1:2*MN)
00327 *
00328 *     B(1:M,1:NRHS) := Q**T * B(1:M,1:NRHS)
00329 *
00330       CALL SORMQR( 'Left', 'Transpose', M, NRHS, MN, A, LDA, WORK( 1 ),
00331      $             B, LDB, WORK( 2*MN+1 ), LWORK-2*MN, INFO )
00332       WSIZE = MAX( WSIZE, 2*MN+WORK( 2*MN+1 ) )
00333 *
00334 *     workspace: 2*MN+NB*NRHS.
00335 *
00336 *     B(1:RANK,1:NRHS) := inv(T11) * B(1:RANK,1:NRHS)
00337 *
00338       CALL STRSM( 'Left', 'Upper', 'No transpose', 'Non-unit', RANK,
00339      $            NRHS, ONE, A, LDA, B, LDB )
00340 *
00341       DO 40 J = 1, NRHS
00342          DO 30 I = RANK + 1, N
00343             B( I, J ) = ZERO
00344    30    CONTINUE
00345    40 CONTINUE
00346 *
00347 *     B(1:N,1:NRHS) := Y**T * B(1:N,1:NRHS)
00348 *
00349       IF( RANK.LT.N ) THEN
00350          CALL SORMRZ( 'Left', 'Transpose', N, NRHS, RANK, N-RANK, A,
00351      $                LDA, WORK( MN+1 ), B, LDB, WORK( 2*MN+1 ),
00352      $                LWORK-2*MN, INFO )
00353       END IF
00354 *
00355 *     workspace: 2*MN+NRHS.
00356 *
00357 *     B(1:N,1:NRHS) := P * B(1:N,1:NRHS)
00358 *
00359       DO 60 J = 1, NRHS
00360          DO 50 I = 1, N
00361             WORK( JPVT( I ) ) = B( I, J )
00362    50    CONTINUE
00363          CALL SCOPY( N, WORK( 1 ), 1, B( 1, J ), 1 )
00364    60 CONTINUE
00365 *
00366 *     workspace: N.
00367 *
00368 *     Undo scaling
00369 *
00370       IF( IASCL.EQ.1 ) THEN
00371          CALL SLASCL( 'G', 0, 0, ANRM, SMLNUM, N, NRHS, B, LDB, INFO )
00372          CALL SLASCL( 'U', 0, 0, SMLNUM, ANRM, RANK, RANK, A, LDA,
00373      $                INFO )
00374       ELSE IF( IASCL.EQ.2 ) THEN
00375          CALL SLASCL( 'G', 0, 0, ANRM, BIGNUM, N, NRHS, B, LDB, INFO )
00376          CALL SLASCL( 'U', 0, 0, BIGNUM, ANRM, RANK, RANK, A, LDA,
00377      $                INFO )
00378       END IF
00379       IF( IBSCL.EQ.1 ) THEN
00380          CALL SLASCL( 'G', 0, 0, SMLNUM, BNRM, N, NRHS, B, LDB, INFO )
00381       ELSE IF( IBSCL.EQ.2 ) THEN
00382          CALL SLASCL( 'G', 0, 0, BIGNUM, BNRM, N, NRHS, B, LDB, INFO )
00383       END IF
00384 *
00385    70 CONTINUE
00386       WORK( 1 ) = LWKOPT
00387 *
00388       RETURN
00389 *
00390 *     End of SGELSY
00391 *
00392       END
 All Files Functions