File:  [local] / rpl / lapack / lapack / dgels.f
Revision 1.17: download - view: text, annotated - select for diffs - revision graph
Tue May 29 07:17:51 2018 UTC (5 years, 11 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_33, rpl-4_1_32, rpl-4_1_31, rpl-4_1_30, rpl-4_1_29, rpl-4_1_28, HEAD
Mise à jour de Lapack.

    1: *> \brief <b> DGELS solves overdetermined or underdetermined systems for GE matrices</b>
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download DGELS + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dgels.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dgels.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgels.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DGELS( TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK,
   22: *                         INFO )
   23: *
   24: *       .. Scalar Arguments ..
   25: *       CHARACTER          TRANS
   26: *       INTEGER            INFO, LDA, LDB, LWORK, M, N, NRHS
   27: *       ..
   28: *       .. Array Arguments ..
   29: *       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), WORK( * )
   30: *       ..
   31: *
   32: *
   33: *> \par Purpose:
   34: *  =============
   35: *>
   36: *> \verbatim
   37: *>
   38: *> DGELS solves overdetermined or underdetermined real linear systems
   39: *> involving an M-by-N matrix A, or its transpose, using a QR or LQ
   40: *> factorization of A.  It is assumed that A has full rank.
   41: *>
   42: *> The following options are provided:
   43: *>
   44: *> 1. If TRANS = 'N' and m >= n:  find the least squares solution of
   45: *>    an overdetermined system, i.e., solve the least squares problem
   46: *>                 minimize || B - A*X ||.
   47: *>
   48: *> 2. If TRANS = 'N' and m < n:  find the minimum norm solution of
   49: *>    an underdetermined system A * X = B.
   50: *>
   51: *> 3. If TRANS = 'T' and m >= n:  find the minimum norm solution of
   52: *>    an underdetermined system A**T * X = B.
   53: *>
   54: *> 4. If TRANS = 'T' and m < n:  find the least squares solution of
   55: *>    an overdetermined system, i.e., solve the least squares problem
   56: *>                 minimize || B - A**T * X ||.
   57: *>
   58: *> Several right hand side vectors b and solution vectors x can be
   59: *> handled in a single call; they are stored as the columns of the
   60: *> M-by-NRHS right hand side matrix B and the N-by-NRHS solution
   61: *> matrix X.
   62: *> \endverbatim
   63: *
   64: *  Arguments:
   65: *  ==========
   66: *
   67: *> \param[in] TRANS
   68: *> \verbatim
   69: *>          TRANS is CHARACTER*1
   70: *>          = 'N': the linear system involves A;
   71: *>          = 'T': the linear system involves A**T.
   72: *> \endverbatim
   73: *>
   74: *> \param[in] M
   75: *> \verbatim
   76: *>          M is INTEGER
   77: *>          The number of rows of the matrix A.  M >= 0.
   78: *> \endverbatim
   79: *>
   80: *> \param[in] N
   81: *> \verbatim
   82: *>          N is INTEGER
   83: *>          The number of columns of the matrix A.  N >= 0.
   84: *> \endverbatim
   85: *>
   86: *> \param[in] NRHS
   87: *> \verbatim
   88: *>          NRHS is INTEGER
   89: *>          The number of right hand sides, i.e., the number of
   90: *>          columns of the matrices B and X. NRHS >=0.
   91: *> \endverbatim
   92: *>
   93: *> \param[in,out] A
   94: *> \verbatim
   95: *>          A is DOUBLE PRECISION array, dimension (LDA,N)
   96: *>          On entry, the M-by-N matrix A.
   97: *>          On exit,
   98: *>            if M >= N, A is overwritten by details of its QR
   99: *>                       factorization as returned by DGEQRF;
  100: *>            if M <  N, A is overwritten by details of its LQ
  101: *>                       factorization as returned by DGELQF.
  102: *> \endverbatim
  103: *>
  104: *> \param[in] LDA
  105: *> \verbatim
  106: *>          LDA is INTEGER
  107: *>          The leading dimension of the array A.  LDA >= max(1,M).
  108: *> \endverbatim
  109: *>
  110: *> \param[in,out] B
  111: *> \verbatim
  112: *>          B is DOUBLE PRECISION array, dimension (LDB,NRHS)
  113: *>          On entry, the matrix B of right hand side vectors, stored
  114: *>          columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS
  115: *>          if TRANS = 'T'.
  116: *>          On exit, if INFO = 0, B is overwritten by the solution
  117: *>          vectors, stored columnwise:
  118: *>          if TRANS = 'N' and m >= n, rows 1 to n of B contain the least
  119: *>          squares solution vectors; the residual sum of squares for the
  120: *>          solution in each column is given by the sum of squares of
  121: *>          elements N+1 to M in that column;
  122: *>          if TRANS = 'N' and m < n, rows 1 to N of B contain the
  123: *>          minimum norm solution vectors;
  124: *>          if TRANS = 'T' and m >= n, rows 1 to M of B contain the
  125: *>          minimum norm solution vectors;
  126: *>          if TRANS = 'T' and m < n, rows 1 to M of B contain the
  127: *>          least squares solution vectors; the residual sum of squares
  128: *>          for the solution in each column is given by the sum of
  129: *>          squares of elements M+1 to N in that column.
  130: *> \endverbatim
  131: *>
  132: *> \param[in] LDB
  133: *> \verbatim
  134: *>          LDB is INTEGER
  135: *>          The leading dimension of the array B. LDB >= MAX(1,M,N).
  136: *> \endverbatim
  137: *>
  138: *> \param[out] WORK
  139: *> \verbatim
  140: *>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
  141: *>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
  142: *> \endverbatim
  143: *>
  144: *> \param[in] LWORK
  145: *> \verbatim
  146: *>          LWORK is INTEGER
  147: *>          The dimension of the array WORK.
  148: *>          LWORK >= max( 1, MN + max( MN, NRHS ) ).
  149: *>          For optimal performance,
  150: *>          LWORK >= max( 1, MN + max( MN, NRHS )*NB ).
  151: *>          where MN = min(M,N) and NB is the optimum block size.
  152: *>
  153: *>          If LWORK = -1, then a workspace query is assumed; the routine
  154: *>          only calculates the optimal size of the WORK array, returns
  155: *>          this value as the first entry of the WORK array, and no error
  156: *>          message related to LWORK is issued by XERBLA.
  157: *> \endverbatim
  158: *>
  159: *> \param[out] INFO
  160: *> \verbatim
  161: *>          INFO is INTEGER
  162: *>          = 0:  successful exit
  163: *>          < 0:  if INFO = -i, the i-th argument had an illegal value
  164: *>          > 0:  if INFO =  i, the i-th diagonal element of the
  165: *>                triangular factor of A is zero, so that A does not have
  166: *>                full rank; the least squares solution could not be
  167: *>                computed.
  168: *> \endverbatim
  169: *
  170: *  Authors:
  171: *  ========
  172: *
  173: *> \author Univ. of Tennessee
  174: *> \author Univ. of California Berkeley
  175: *> \author Univ. of Colorado Denver
  176: *> \author NAG Ltd.
  177: *
  178: *> \date December 2016
  179: *
  180: *> \ingroup doubleGEsolve
  181: *
  182: *  =====================================================================
  183:       SUBROUTINE DGELS( TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK,
  184:      $                  INFO )
  185: *
  186: *  -- LAPACK driver routine (version 3.7.0) --
  187: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  188: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  189: *     December 2016
  190: *
  191: *     .. Scalar Arguments ..
  192:       CHARACTER          TRANS
  193:       INTEGER            INFO, LDA, LDB, LWORK, M, N, NRHS
  194: *     ..
  195: *     .. Array Arguments ..
  196:       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), WORK( * )
  197: *     ..
  198: *
  199: *  =====================================================================
  200: *
  201: *     .. Parameters ..
  202:       DOUBLE PRECISION   ZERO, ONE
  203:       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
  204: *     ..
  205: *     .. Local Scalars ..
  206:       LOGICAL            LQUERY, TPSD
  207:       INTEGER            BROW, I, IASCL, IBSCL, J, MN, NB, SCLLEN, WSIZE
  208:       DOUBLE PRECISION   ANRM, BIGNUM, BNRM, SMLNUM
  209: *     ..
  210: *     .. Local Arrays ..
  211:       DOUBLE PRECISION   RWORK( 1 )
  212: *     ..
  213: *     .. External Functions ..
  214:       LOGICAL            LSAME
  215:       INTEGER            ILAENV
  216:       DOUBLE PRECISION   DLAMCH, DLANGE
  217:       EXTERNAL           LSAME, ILAENV, DLABAD, DLAMCH, DLANGE
  218: *     ..
  219: *     .. External Subroutines ..
  220:       EXTERNAL           DGELQF, DGEQRF, DLASCL, DLASET, DORMLQ, DORMQR,
  221:      $                   DTRTRS, XERBLA
  222: *     ..
  223: *     .. Intrinsic Functions ..
  224:       INTRINSIC          DBLE, MAX, MIN
  225: *     ..
  226: *     .. Executable Statements ..
  227: *
  228: *     Test the input arguments.
  229: *
  230:       INFO = 0
  231:       MN = MIN( M, N )
  232:       LQUERY = ( LWORK.EQ.-1 )
  233:       IF( .NOT.( LSAME( TRANS, 'N' ) .OR. LSAME( TRANS, 'T' ) ) ) THEN
  234:          INFO = -1
  235:       ELSE IF( M.LT.0 ) THEN
  236:          INFO = -2
  237:       ELSE IF( N.LT.0 ) THEN
  238:          INFO = -3
  239:       ELSE IF( NRHS.LT.0 ) THEN
  240:          INFO = -4
  241:       ELSE IF( LDA.LT.MAX( 1, M ) ) THEN
  242:          INFO = -6
  243:       ELSE IF( LDB.LT.MAX( 1, M, N ) ) THEN
  244:          INFO = -8
  245:       ELSE IF( LWORK.LT.MAX( 1, MN+MAX( MN, NRHS ) ) .AND. .NOT.LQUERY )
  246:      $          THEN
  247:          INFO = -10
  248:       END IF
  249: *
  250: *     Figure out optimal block size
  251: *
  252:       IF( INFO.EQ.0 .OR. INFO.EQ.-10 ) THEN
  253: *
  254:          TPSD = .TRUE.
  255:          IF( LSAME( TRANS, 'N' ) )
  256:      $      TPSD = .FALSE.
  257: *
  258:          IF( M.GE.N ) THEN
  259:             NB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 )
  260:             IF( TPSD ) THEN
  261:                NB = MAX( NB, ILAENV( 1, 'DORMQR', 'LN', M, NRHS, N,
  262:      $              -1 ) )
  263:             ELSE
  264:                NB = MAX( NB, ILAENV( 1, 'DORMQR', 'LT', M, NRHS, N,
  265:      $              -1 ) )
  266:             END IF
  267:          ELSE
  268:             NB = ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 )
  269:             IF( TPSD ) THEN
  270:                NB = MAX( NB, ILAENV( 1, 'DORMLQ', 'LT', N, NRHS, M,
  271:      $              -1 ) )
  272:             ELSE
  273:                NB = MAX( NB, ILAENV( 1, 'DORMLQ', 'LN', N, NRHS, M,
  274:      $              -1 ) )
  275:             END IF
  276:          END IF
  277: *
  278:          WSIZE = MAX( 1, MN+MAX( MN, NRHS )*NB )
  279:          WORK( 1 ) = DBLE( WSIZE )
  280: *
  281:       END IF
  282: *
  283:       IF( INFO.NE.0 ) THEN
  284:          CALL XERBLA( 'DGELS ', -INFO )
  285:          RETURN
  286:       ELSE IF( LQUERY ) THEN
  287:          RETURN
  288:       END IF
  289: *
  290: *     Quick return if possible
  291: *
  292:       IF( MIN( M, N, NRHS ).EQ.0 ) THEN
  293:          CALL DLASET( 'Full', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )
  294:          RETURN
  295:       END IF
  296: *
  297: *     Get machine parameters
  298: *
  299:       SMLNUM = DLAMCH( 'S' ) / DLAMCH( 'P' )
  300:       BIGNUM = ONE / SMLNUM
  301:       CALL DLABAD( SMLNUM, BIGNUM )
  302: *
  303: *     Scale A, B if max element outside range [SMLNUM,BIGNUM]
  304: *
  305:       ANRM = DLANGE( 'M', M, N, A, LDA, RWORK )
  306:       IASCL = 0
  307:       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
  308: *
  309: *        Scale matrix norm up to SMLNUM
  310: *
  311:          CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO )
  312:          IASCL = 1
  313:       ELSE IF( ANRM.GT.BIGNUM ) THEN
  314: *
  315: *        Scale matrix norm down to BIGNUM
  316: *
  317:          CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO )
  318:          IASCL = 2
  319:       ELSE IF( ANRM.EQ.ZERO ) THEN
  320: *
  321: *        Matrix all zero. Return zero solution.
  322: *
  323:          CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB )
  324:          GO TO 50
  325:       END IF
  326: *
  327:       BROW = M
  328:       IF( TPSD )
  329:      $   BROW = N
  330:       BNRM = DLANGE( 'M', BROW, NRHS, B, LDB, RWORK )
  331:       IBSCL = 0
  332:       IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
  333: *
  334: *        Scale matrix norm up to SMLNUM
  335: *
  336:          CALL DLASCL( 'G', 0, 0, BNRM, SMLNUM, BROW, NRHS, B, LDB,
  337:      $                INFO )
  338:          IBSCL = 1
  339:       ELSE IF( BNRM.GT.BIGNUM ) THEN
  340: *
  341: *        Scale matrix norm down to BIGNUM
  342: *
  343:          CALL DLASCL( 'G', 0, 0, BNRM, BIGNUM, BROW, NRHS, B, LDB,
  344:      $                INFO )
  345:          IBSCL = 2
  346:       END IF
  347: *
  348:       IF( M.GE.N ) THEN
  349: *
  350: *        compute QR factorization of A
  351: *
  352:          CALL DGEQRF( M, N, A, LDA, WORK( 1 ), WORK( MN+1 ), LWORK-MN,
  353:      $                INFO )
  354: *
  355: *        workspace at least N, optimally N*NB
  356: *
  357:          IF( .NOT.TPSD ) THEN
  358: *
  359: *           Least-Squares Problem min || A * X - B ||
  360: *
  361: *           B(1:M,1:NRHS) := Q**T * B(1:M,1:NRHS)
  362: *
  363:             CALL DORMQR( 'Left', 'Transpose', M, NRHS, N, A, LDA,
  364:      $                   WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,
  365:      $                   INFO )
  366: *
  367: *           workspace at least NRHS, optimally NRHS*NB
  368: *
  369: *           B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS)
  370: *
  371:             CALL DTRTRS( 'Upper', 'No transpose', 'Non-unit', N, NRHS,
  372:      $                   A, LDA, B, LDB, INFO )
  373: *
  374:             IF( INFO.GT.0 ) THEN
  375:                RETURN
  376:             END IF
  377: *
  378:             SCLLEN = N
  379: *
  380:          ELSE
  381: *
  382: *           Underdetermined system of equations A**T * X = B
  383: *
  384: *           B(1:N,1:NRHS) := inv(R**T) * B(1:N,1:NRHS)
  385: *
  386:             CALL DTRTRS( 'Upper', 'Transpose', 'Non-unit', N, NRHS,
  387:      $                   A, LDA, B, LDB, INFO )
  388: *
  389:             IF( INFO.GT.0 ) THEN
  390:                RETURN
  391:             END IF
  392: *
  393: *           B(N+1:M,1:NRHS) = ZERO
  394: *
  395:             DO 20 J = 1, NRHS
  396:                DO 10 I = N + 1, M
  397:                   B( I, J ) = ZERO
  398:    10          CONTINUE
  399:    20       CONTINUE
  400: *
  401: *           B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS)
  402: *
  403:             CALL DORMQR( 'Left', 'No transpose', M, NRHS, N, A, LDA,
  404:      $                   WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,
  405:      $                   INFO )
  406: *
  407: *           workspace at least NRHS, optimally NRHS*NB
  408: *
  409:             SCLLEN = M
  410: *
  411:          END IF
  412: *
  413:       ELSE
  414: *
  415: *        Compute LQ factorization of A
  416: *
  417:          CALL DGELQF( M, N, A, LDA, WORK( 1 ), WORK( MN+1 ), LWORK-MN,
  418:      $                INFO )
  419: *
  420: *        workspace at least M, optimally M*NB.
  421: *
  422:          IF( .NOT.TPSD ) THEN
  423: *
  424: *           underdetermined system of equations A * X = B
  425: *
  426: *           B(1:M,1:NRHS) := inv(L) * B(1:M,1:NRHS)
  427: *
  428:             CALL DTRTRS( 'Lower', 'No transpose', 'Non-unit', M, NRHS,
  429:      $                   A, LDA, B, LDB, INFO )
  430: *
  431:             IF( INFO.GT.0 ) THEN
  432:                RETURN
  433:             END IF
  434: *
  435: *           B(M+1:N,1:NRHS) = 0
  436: *
  437:             DO 40 J = 1, NRHS
  438:                DO 30 I = M + 1, N
  439:                   B( I, J ) = ZERO
  440:    30          CONTINUE
  441:    40       CONTINUE
  442: *
  443: *           B(1:N,1:NRHS) := Q(1:N,:)**T * B(1:M,1:NRHS)
  444: *
  445:             CALL DORMLQ( 'Left', 'Transpose', N, NRHS, M, A, LDA,
  446:      $                   WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,
  447:      $                   INFO )
  448: *
  449: *           workspace at least NRHS, optimally NRHS*NB
  450: *
  451:             SCLLEN = N
  452: *
  453:          ELSE
  454: *
  455: *           overdetermined system min || A**T * X - B ||
  456: *
  457: *           B(1:N,1:NRHS) := Q * B(1:N,1:NRHS)
  458: *
  459:             CALL DORMLQ( 'Left', 'No transpose', N, NRHS, M, A, LDA,
  460:      $                   WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN,
  461:      $                   INFO )
  462: *
  463: *           workspace at least NRHS, optimally NRHS*NB
  464: *
  465: *           B(1:M,1:NRHS) := inv(L**T) * B(1:M,1:NRHS)
  466: *
  467:             CALL DTRTRS( 'Lower', 'Transpose', 'Non-unit', M, NRHS,
  468:      $                   A, LDA, B, LDB, INFO )
  469: *
  470:             IF( INFO.GT.0 ) THEN
  471:                RETURN
  472:             END IF
  473: *
  474:             SCLLEN = M
  475: *
  476:          END IF
  477: *
  478:       END IF
  479: *
  480: *     Undo scaling
  481: *
  482:       IF( IASCL.EQ.1 ) THEN
  483:          CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, SCLLEN, NRHS, B, LDB,
  484:      $                INFO )
  485:       ELSE IF( IASCL.EQ.2 ) THEN
  486:          CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, SCLLEN, NRHS, B, LDB,
  487:      $                INFO )
  488:       END IF
  489:       IF( IBSCL.EQ.1 ) THEN
  490:          CALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB,
  491:      $                INFO )
  492:       ELSE IF( IBSCL.EQ.2 ) THEN
  493:          CALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB,
  494:      $                INFO )
  495:       END IF
  496: *
  497:    50 CONTINUE
  498:       WORK( 1 ) = DBLE( WSIZE )
  499: *
  500:       RETURN
  501: *
  502: *     End of DGELS
  503: *
  504:       END

CVSweb interface <joel.bertrand@systella.fr>