File:  [local] / rpl / lapack / lapack / dorcsd2by1.f
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Mon Jan 27 09:28:24 2014 UTC (10 years, 3 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_23, rpl-4_1_22, rpl-4_1_21, rpl-4_1_20, rpl-4_1_19, rpl-4_1_18, rpl-4_1_17, HEAD
Cohérence.

    1: *> \brief \b DORCSD2BY1
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at 
    6: *            http://www.netlib.org/lapack/explore-html/ 
    7: *
    8: *> \htmlonly
    9: *> Download DORCSD2BY1 + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dorcsd2by1.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dorcsd2by1.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorcsd2by1.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DORCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
   22: *                              X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
   23: *                              LDV1T, WORK, LWORK, IWORK, INFO )
   24:    25: *       .. Scalar Arguments ..
   26: *       CHARACTER          JOBU1, JOBU2, JOBV1T
   27: *       INTEGER            INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
   28: *      $                   M, P, Q
   29: *       ..
   30: *       .. Array Arguments ..
   31: *       DOUBLE PRECISION   THETA(*)
   32: *       DOUBLE PRECISION   U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
   33: *      $                   X11(LDX11,*), X21(LDX21,*)
   34: *       INTEGER            IWORK(*)
   35: *       ..
   36: *    
   37:    38: *> \par Purpose:
   39: *> =============
   40: *>
   41: *>\verbatim
   42: *> Purpose:
   43: *> ========
   44: *>
   45: *> DORCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with
   46: *> orthonormal columns that has been partitioned into a 2-by-1 block
   47: *> structure:
   48: *>
   49: *>                                [  I  0  0 ]
   50: *>                                [  0  C  0 ]
   51: *>          [ X11 ]   [ U1 |    ] [  0  0  0 ]
   52: *>      X = [-----] = [---------] [----------] V1**T .
   53: *>          [ X21 ]   [    | U2 ] [  0  0  0 ]
   54: *>                                [  0  S  0 ]
   55: *>                                [  0  0  I ]
   56: *> 
   57: *> X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P,
   58: *> (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are
   59: *> R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in
   60: *> which R = MIN(P,M-P,Q,M-Q).
   61: *>
   62: *>\endverbatim
   63: *
   64: *  Arguments:
   65: *  ==========
   66: *
   67: *> \param[in] JOBU1
   68: *> \verbatim
   69: *>          JOBU1 is CHARACTER
   70: *>           = 'Y':      U1 is computed;
   71: *>           otherwise:  U1 is not computed.
   72: *> \endverbatim
   73: *>
   74: *> \param[in] JOBU2
   75: *> \verbatim
   76: *>          JOBU2 is CHARACTER
   77: *>           = 'Y':      U2 is computed;
   78: *>           otherwise:  U2 is not computed.
   79: *> \endverbatim
   80: *>
   81: *> \param[in] JOBV1T
   82: *> \verbatim
   83: *>          JOBV1T is CHARACTER
   84: *>           = 'Y':      V1T is computed;
   85: *>           otherwise:  V1T is not computed.
   86: *> \endverbatim
   87: *>
   88: *> \param[in] M
   89: *> \verbatim
   90: *>          M is INTEGER
   91: *>           The number of rows and columns in X.
   92: *> \endverbatim
   93: *>
   94: *> \param[in] P
   95: *> \verbatim
   96: *>          P is INTEGER
   97: *>           The number of rows in X11 and X12. 0 <= P <= M.
   98: *> \endverbatim
   99: *>
  100: *> \param[in] Q
  101: *> \verbatim
  102: *>          Q is INTEGER
  103: *>           The number of columns in X11 and X21. 0 <= Q <= M.
  104: *> \endverbatim
  105: *>
  106: *> \param[in,out] X11
  107: *> \verbatim
  108: *>          X11 is DOUBLE PRECISION array, dimension (LDX11,Q)
  109: *>           On entry, part of the orthogonal matrix whose CSD is
  110: *>           desired.
  111: *> \endverbatim
  112: *>
  113: *> \param[in] LDX11
  114: *> \verbatim
  115: *>          LDX11 is INTEGER
  116: *>           The leading dimension of X11. LDX11 >= MAX(1,P).
  117: *> \endverbatim
  118: *>
  119: *> \param[in,out] X21
  120: *> \verbatim
  121: *>          X21 is DOUBLE PRECISION array, dimension (LDX21,Q)
  122: *>           On entry, part of the orthogonal matrix whose CSD is
  123: *>           desired.
  124: *> \endverbatim
  125: *>
  126: *> \param[in] LDX21
  127: *> \verbatim
  128: *>          LDX21 is INTEGER
  129: *>           The leading dimension of X21. LDX21 >= MAX(1,M-P).
  130: *> \endverbatim
  131: *>
  132: *> \param[out] THETA
  133: *> \verbatim
  134: *>          THETA is DOUBLE PRECISION array, dimension (R), in which R =
  135: *>           MIN(P,M-P,Q,M-Q).
  136: *>           C = DIAG( COS(THETA(1)), ... , COS(THETA(R)) ) and
  137: *>           S = DIAG( SIN(THETA(1)), ... , SIN(THETA(R)) ).
  138: *> \endverbatim
  139: *>
  140: *> \param[out] U1
  141: *> \verbatim
  142: *>          U1 is DOUBLE PRECISION array, dimension (P)
  143: *>           If JOBU1 = 'Y', U1 contains the P-by-P orthogonal matrix U1.
  144: *> \endverbatim
  145: *>
  146: *> \param[in] LDU1
  147: *> \verbatim
  148: *>          LDU1 is INTEGER
  149: *>           The leading dimension of U1. If JOBU1 = 'Y', LDU1 >=
  150: *>           MAX(1,P).
  151: *> \endverbatim
  152: *>
  153: *> \param[out] U2
  154: *> \verbatim
  155: *>          U2 is DOUBLE PRECISION array, dimension (M-P)
  156: *>           If JOBU2 = 'Y', U2 contains the (M-P)-by-(M-P) orthogonal
  157: *>           matrix U2.
  158: *> \endverbatim
  159: *>
  160: *> \param[in] LDU2
  161: *> \verbatim
  162: *>          LDU2 is INTEGER
  163: *>           The leading dimension of U2. If JOBU2 = 'Y', LDU2 >=
  164: *>           MAX(1,M-P).
  165: *> \endverbatim
  166: *>
  167: *> \param[out] V1T
  168: *> \verbatim
  169: *>          V1T is DOUBLE PRECISION array, dimension (Q)
  170: *>           If JOBV1T = 'Y', V1T contains the Q-by-Q matrix orthogonal
  171: *>           matrix V1**T.
  172: *> \endverbatim
  173: *>
  174: *> \param[in] LDV1T
  175: *> \verbatim
  176: *>          LDV1T is INTEGER
  177: *>           The leading dimension of V1T. If JOBV1T = 'Y', LDV1T >=
  178: *>           MAX(1,Q).
  179: *> \endverbatim
  180: *>
  181: *> \param[out] WORK
  182: *> \verbatim
  183: *>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
  184: *>           On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
  185: *>           If INFO > 0 on exit, WORK(2:R) contains the values PHI(1),
  186: *>           ..., PHI(R-1) that, together with THETA(1), ..., THETA(R),
  187: *>           define the matrix in intermediate bidiagonal-block form
  188: *>           remaining after nonconvergence. INFO specifies the number
  189: *>           of nonzero PHI's.
  190: *> \endverbatim
  191: *>
  192: *> \param[in] LWORK
  193: *> \verbatim
  194: *>          LWORK is INTEGER
  195: *>           The dimension of the array WORK.
  196: *> \endverbatim
  197: *>
  198: *>           If LWORK = -1, then a workspace query is assumed; the routine
  199: *>           only calculates the optimal size of the WORK array, returns
  200: *>           this value as the first entry of the work array, and no error
  201: *>           message related to LWORK is issued by XERBLA.
  202: *> \param[out] IWORK
  203: *> \verbatim
  204: *>          IWORK is INTEGER array, dimension (M-MIN(P,M-P,Q,M-Q))
  205: *> \endverbatim
  206: *>
  207: *> \param[out] INFO
  208: *> \verbatim
  209: *>          INFO is INTEGER
  210: *>           = 0:  successful exit.
  211: *>           < 0:  if INFO = -i, the i-th argument had an illegal value.
  212: *>           > 0:  DBBCSD did not converge. See the description of WORK
  213: *>                above for details.
  214: *> \endverbatim
  215: *
  216: *  Authors:
  217: *  ========
  218: *
  219: *> \author Univ. of Tennessee 
  220: *> \author Univ. of California Berkeley 
  221: *> \author Univ. of Colorado Denver 
  222: *> \author NAG Ltd. 
  223: *
  224: *> \date July 2012
  225: *
  226: *> \ingroup doubleOTHERcomputational
  227: *
  228: *> \par References:
  229: *  ================
  230: *>
  231: *>  [1] Brian D. Sutton. Computing the complete CS decomposition. Numer.
  232: *>      Algorithms, 50(1):33-65, 2009.
  233: *> \endverbatim
  234: *>
  235: *  =====================================================================
  236:       SUBROUTINE DORCSD2BY1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
  237:      $                       X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
  238:      $                       LDV1T, WORK, LWORK, IWORK, INFO )
  239: *
  240: *  -- LAPACK computational routine (3.5.0) --
  241: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  242: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  243: *     July 2012
  244: *
  245: *     .. Scalar Arguments ..
  246:       CHARACTER          JOBU1, JOBU2, JOBV1T
  247:       INTEGER            INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
  248:      $                   M, P, Q
  249: *     ..
  250: *     .. Array Arguments ..
  251:       DOUBLE PRECISION   THETA(*)
  252:       DOUBLE PRECISION   U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
  253:      $                   X11(LDX11,*), X21(LDX21,*)
  254:       INTEGER            IWORK(*)
  255: *     ..
  256: *  
  257: *  =====================================================================
  258: *
  259: *     .. Parameters ..
  260:       DOUBLE PRECISION   ONE, ZERO
  261:       PARAMETER          ( ONE = 1.0D0, ZERO = 0.0D0 )
  262: *     ..
  263: *     .. Local Scalars ..
  264:       INTEGER            CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
  265:      $                   IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
  266:      $                   IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
  267:      $                   J, LBBCSD, LORBDB, LORGLQ, LORGLQMIN,
  268:      $                   LORGLQOPT, LORGQR, LORGQRMIN, LORGQROPT,
  269:      $                   LWORKMIN, LWORKOPT, R
  270:       LOGICAL            LQUERY, WANTU1, WANTU2, WANTV1T
  271: *     ..
  272: *     .. External Subroutines ..
  273:       EXTERNAL           DBBCSD, DCOPY, DLACPY, DLAPMR, DLAPMT, DORBDB1,
  274:      $                   DORBDB2, DORBDB3, DORBDB4, DORGLQ, DORGQR,
  275:      $                   XERBLA
  276: *     ..
  277: *     .. External Functions ..
  278:       LOGICAL            LSAME
  279:       EXTERNAL           LSAME
  280: *     ..
  281: *     .. Intrinsic Function ..
  282:       INTRINSIC          INT, MAX, MIN
  283: *     ..
  284: *     .. Executable Statements ..
  285: *
  286: *     Test input arguments
  287: *
  288:       INFO = 0
  289:       WANTU1 = LSAME( JOBU1, 'Y' )
  290:       WANTU2 = LSAME( JOBU2, 'Y' )
  291:       WANTV1T = LSAME( JOBV1T, 'Y' )
  292:       LQUERY = LWORK .EQ. -1
  293: *
  294:       IF( M .LT. 0 ) THEN
  295:          INFO = -4
  296:       ELSE IF( P .LT. 0 .OR. P .GT. M ) THEN
  297:          INFO = -5
  298:       ELSE IF( Q .LT. 0 .OR. Q .GT. M ) THEN
  299:          INFO = -6
  300:       ELSE IF( LDX11 .LT. MAX( 1, P ) ) THEN
  301:          INFO = -8
  302:       ELSE IF( LDX21 .LT. MAX( 1, M-P ) ) THEN
  303:          INFO = -10
  304:       ELSE IF( WANTU1 .AND. LDU1 .LT. P ) THEN
  305:          INFO = -13
  306:       ELSE IF( WANTU2 .AND. LDU2 .LT. M - P ) THEN
  307:          INFO = -15
  308:       ELSE IF( WANTV1T .AND. LDV1T .LT. Q ) THEN
  309:          INFO = -17
  310:       END IF
  311: *
  312:       R = MIN( P, M-P, Q, M-Q )
  313: *
  314: *     Compute workspace
  315: *
  316: *       WORK layout:
  317: *     |-------------------------------------------------------|
  318: *     | LWORKOPT (1)                                          |
  319: *     |-------------------------------------------------------|
  320: *     | PHI (MAX(1,R-1))                                      |
  321: *     |-------------------------------------------------------|
  322: *     | TAUP1 (MAX(1,P))                        | B11D (R)    |
  323: *     | TAUP2 (MAX(1,M-P))                      | B11E (R-1)  |
  324: *     | TAUQ1 (MAX(1,Q))                        | B12D (R)    |
  325: *     |-----------------------------------------| B12E (R-1)  |
  326: *     | DORBDB WORK | DORGQR WORK | DORGLQ WORK | B21D (R)    |
  327: *     |             |             |             | B21E (R-1)  |
  328: *     |             |             |             | B22D (R)    |
  329: *     |             |             |             | B22E (R-1)  |
  330: *     |             |             |             | DBBCSD WORK |
  331: *     |-------------------------------------------------------|
  332: *
  333:       IF( INFO .EQ. 0 ) THEN
  334:          IPHI = 2
  335:          IB11D = IPHI + MAX( 1, R-1 )
  336:          IB11E = IB11D + MAX( 1, R )
  337:          IB12D = IB11E + MAX( 1, R - 1 )
  338:          IB12E = IB12D + MAX( 1, R )
  339:          IB21D = IB12E + MAX( 1, R - 1 )
  340:          IB21E = IB21D + MAX( 1, R )
  341:          IB22D = IB21E + MAX( 1, R - 1 )
  342:          IB22E = IB22D + MAX( 1, R )
  343:          IBBCSD = IB22E + MAX( 1, R - 1 )
  344:          ITAUP1 = IPHI + MAX( 1, R-1 )
  345:          ITAUP2 = ITAUP1 + MAX( 1, P )
  346:          ITAUQ1 = ITAUP2 + MAX( 1, M-P )
  347:          IORBDB = ITAUQ1 + MAX( 1, Q )
  348:          IORGQR = ITAUQ1 + MAX( 1, Q )
  349:          IORGLQ = ITAUQ1 + MAX( 1, Q )
  350:          IF( R .EQ. Q ) THEN
  351:             CALL DORBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  352:      $                    0, 0, WORK, -1, CHILDINFO )
  353:             LORBDB = INT( WORK(1) )
  354:             IF( P .GE. M-P ) THEN
  355:                CALL DORGQR( P, P, Q, U1, LDU1, 0, WORK(1), -1,
  356:      $                      CHILDINFO )
  357:                LORGQRMIN = MAX( 1, P )
  358:                LORGQROPT = INT( WORK(1) )
  359:             ELSE
  360:                CALL DORGQR( M-P, M-P, Q, U2, LDU2, 0, WORK(1), -1,
  361:      $                      CHILDINFO )
  362:                LORGQRMIN = MAX( 1, M-P )
  363:                LORGQROPT = INT( WORK(1) )
  364:             END IF
  365:             CALL DORGLQ( MAX(0,Q-1), MAX(0,Q-1), MAX(0,Q-1), V1T, LDV1T,
  366:      $                   0, WORK(1), -1, CHILDINFO )
  367:             LORGLQMIN = MAX( 1, Q-1 )
  368:             LORGLQOPT = INT( WORK(1) )
  369:             CALL DBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
  370:      $                   0, U1, LDU1, U2, LDU2, V1T, LDV1T, 0, 1, 0, 0,
  371:      $                   0, 0, 0, 0, 0, 0, WORK(1), -1, CHILDINFO )
  372:             LBBCSD = INT( WORK(1) )
  373:          ELSE IF( R .EQ. P ) THEN
  374:             CALL DORBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  375:      $                    0, 0, WORK(1), -1, CHILDINFO )
  376:             LORBDB = INT( WORK(1) )
  377:             IF( P-1 .GE. M-P ) THEN
  378:                CALL DORGQR( P-1, P-1, P-1, U1(2,2), LDU1, 0, WORK(1),
  379:      $                      -1, CHILDINFO )
  380:                LORGQRMIN = MAX( 1, P-1 )
  381:                LORGQROPT = INT( WORK(1) )
  382:             ELSE
  383:                CALL DORGQR( M-P, M-P, Q, U2, LDU2, 0, WORK(1), -1,
  384:      $                      CHILDINFO )
  385:                LORGQRMIN = MAX( 1, M-P )
  386:                LORGQROPT = INT( WORK(1) )
  387:             END IF
  388:             CALL DORGLQ( Q, Q, R, V1T, LDV1T, 0, WORK(1), -1,
  389:      $                   CHILDINFO )
  390:             LORGLQMIN = MAX( 1, Q )
  391:             LORGLQOPT = INT( WORK(1) )
  392:             CALL DBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
  393:      $                   0, V1T, LDV1T, 0, 1, U1, LDU1, U2, LDU2, 0, 0,
  394:      $                   0, 0, 0, 0, 0, 0, WORK(1), -1, CHILDINFO )
  395:             LBBCSD = INT( WORK(1) )
  396:          ELSE IF( R .EQ. M-P ) THEN
  397:             CALL DORBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  398:      $                    0, 0, WORK(1), -1, CHILDINFO )
  399:             LORBDB = INT( WORK(1) )
  400:             IF( P .GE. M-P-1 ) THEN
  401:                CALL DORGQR( P, P, Q, U1, LDU1, 0, WORK(1), -1,
  402:      $                      CHILDINFO )
  403:                LORGQRMIN = MAX( 1, P )
  404:                LORGQROPT = INT( WORK(1) )
  405:             ELSE
  406:                CALL DORGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2, 0,
  407:      $                      WORK(1), -1, CHILDINFO )
  408:                LORGQRMIN = MAX( 1, M-P-1 )
  409:                LORGQROPT = INT( WORK(1) )
  410:             END IF
  411:             CALL DORGLQ( Q, Q, R, V1T, LDV1T, 0, WORK(1), -1,
  412:      $                   CHILDINFO )
  413:             LORGLQMIN = MAX( 1, Q )
  414:             LORGLQOPT = INT( WORK(1) )
  415:             CALL DBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
  416:      $                   THETA, 0, 0, 1, V1T, LDV1T, U2, LDU2, U1, LDU1,
  417:      $                   0, 0, 0, 0, 0, 0, 0, 0, WORK(1), -1,
  418:      $                   CHILDINFO )
  419:             LBBCSD = INT( WORK(1) )
  420:          ELSE
  421:             CALL DORBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA, 0, 0,
  422:      $                    0, 0, 0, WORK(1), -1, CHILDINFO )
  423:             LORBDB = M + INT( WORK(1) )
  424:             IF( P .GE. M-P ) THEN
  425:                CALL DORGQR( P, P, M-Q, U1, LDU1, 0, WORK(1), -1,
  426:      $                      CHILDINFO )
  427:                LORGQRMIN = MAX( 1, P )
  428:                LORGQROPT = INT( WORK(1) )
  429:             ELSE
  430:                CALL DORGQR( M-P, M-P, M-Q, U2, LDU2, 0, WORK(1), -1,
  431:      $                      CHILDINFO )
  432:                LORGQRMIN = MAX( 1, M-P )
  433:                LORGQROPT = INT( WORK(1) )
  434:             END IF
  435:             CALL DORGLQ( Q, Q, Q, V1T, LDV1T, 0, WORK(1), -1,
  436:      $                   CHILDINFO )
  437:             LORGLQMIN = MAX( 1, Q )
  438:             LORGLQOPT = INT( WORK(1) )
  439:             CALL DBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
  440:      $                   THETA, 0, U2, LDU2, U1, LDU1, 0, 1, V1T, LDV1T,
  441:      $                   0, 0, 0, 0, 0, 0, 0, 0, WORK(1), -1,
  442:      $                   CHILDINFO )
  443:             LBBCSD = INT( WORK(1) )
  444:          END IF
  445:          LWORKMIN = MAX( IORBDB+LORBDB-1,
  446:      $                   IORGQR+LORGQRMIN-1,
  447:      $                   IORGLQ+LORGLQMIN-1,
  448:      $                   IBBCSD+LBBCSD-1 )
  449:          LWORKOPT = MAX( IORBDB+LORBDB-1,
  450:      $                   IORGQR+LORGQROPT-1,
  451:      $                   IORGLQ+LORGLQOPT-1,
  452:      $                   IBBCSD+LBBCSD-1 )
  453:          WORK(1) = LWORKOPT
  454:          IF( LWORK .LT. LWORKMIN .AND. .NOT.LQUERY ) THEN
  455:             INFO = -19
  456:          END IF
  457:       END IF
  458:       IF( INFO .NE. 0 ) THEN
  459:          CALL XERBLA( 'DORCSD2BY1', -INFO )
  460:          RETURN
  461:       ELSE IF( LQUERY ) THEN
  462:          RETURN
  463:       END IF
  464:       LORGQR = LWORK-IORGQR+1
  465:       LORGLQ = LWORK-IORGLQ+1
  466: *
  467: *     Handle four cases separately: R = Q, R = P, R = M-P, and R = M-Q,
  468: *     in which R = MIN(P,M-P,Q,M-Q)
  469: *
  470:       IF( R .EQ. Q ) THEN
  471: *
  472: *        Case 1: R = Q
  473: *
  474: *        Simultaneously bidiagonalize X11 and X21
  475: *
  476:          CALL DORBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  477:      $                 WORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  478:      $                 WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  479: *
  480: *        Accumulate Householder reflectors
  481: *
  482:          IF( WANTU1 .AND. P .GT. 0 ) THEN
  483:             CALL DLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  484:             CALL DORGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  485:      $                   LORGQR, CHILDINFO )
  486:          END IF
  487:          IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  488:             CALL DLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  489:             CALL DORGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  490:      $                   WORK(IORGQR), LORGQR, CHILDINFO )
  491:          END IF
  492:          IF( WANTV1T .AND. Q .GT. 0 ) THEN
  493:             V1T(1,1) = ONE
  494:             DO J = 2, Q
  495:                V1T(1,J) = ZERO
  496:                V1T(J,1) = ZERO
  497:             END DO
  498:             CALL DLACPY( 'U', Q-1, Q-1, X21(1,2), LDX21, V1T(2,2),
  499:      $                   LDV1T )
  500:             CALL DORGLQ( Q-1, Q-1, Q-1, V1T(2,2), LDV1T, WORK(ITAUQ1),
  501:      $                   WORK(IORGLQ), LORGLQ, CHILDINFO )
  502:          END IF
  503: *   
  504: *        Simultaneously diagonalize X11 and X21.
  505: *   
  506:          CALL DBBCSD( JOBU1, JOBU2, JOBV1T, 'N', 'N', M, P, Q, THETA,
  507:      $                WORK(IPHI), U1, LDU1, U2, LDU2, V1T, LDV1T, 0, 1,
  508:      $                WORK(IB11D), WORK(IB11E), WORK(IB12D),
  509:      $                WORK(IB12E), WORK(IB21D), WORK(IB21E),
  510:      $                WORK(IB22D), WORK(IB22E), WORK(IBBCSD), LBBCSD,
  511:      $                CHILDINFO )
  512: *   
  513: *        Permute rows and columns to place zero submatrices in
  514: *        preferred positions
  515: *
  516:          IF( Q .GT. 0 .AND. WANTU2 ) THEN
  517:             DO I = 1, Q
  518:                IWORK(I) = M - P - Q + I
  519:             END DO
  520:             DO I = Q + 1, M - P
  521:                IWORK(I) = I - Q
  522:             END DO
  523:             CALL DLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  524:          END IF
  525:       ELSE IF( R .EQ. P ) THEN
  526: *
  527: *        Case 2: R = P
  528: *
  529: *        Simultaneously bidiagonalize X11 and X21
  530: *
  531:          CALL DORBDB2( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  532:      $                 WORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  533:      $                 WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  534: *
  535: *        Accumulate Householder reflectors
  536: *
  537:          IF( WANTU1 .AND. P .GT. 0 ) THEN
  538:             U1(1,1) = ONE
  539:             DO J = 2, P
  540:                U1(1,J) = ZERO
  541:                U1(J,1) = ZERO
  542:             END DO
  543:             CALL DLACPY( 'L', P-1, P-1, X11(2,1), LDX11, U1(2,2), LDU1 )
  544:             CALL DORGQR( P-1, P-1, P-1, U1(2,2), LDU1, WORK(ITAUP1),
  545:      $                   WORK(IORGQR), LORGQR, CHILDINFO )
  546:          END IF
  547:          IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  548:             CALL DLACPY( 'L', M-P, Q, X21, LDX21, U2, LDU2 )
  549:             CALL DORGQR( M-P, M-P, Q, U2, LDU2, WORK(ITAUP2),
  550:      $                   WORK(IORGQR), LORGQR, CHILDINFO )
  551:          END IF
  552:          IF( WANTV1T .AND. Q .GT. 0 ) THEN
  553:             CALL DLACPY( 'U', P, Q, X11, LDX11, V1T, LDV1T )
  554:             CALL DORGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
  555:      $                   WORK(IORGLQ), LORGLQ, CHILDINFO )
  556:          END IF
  557: *   
  558: *        Simultaneously diagonalize X11 and X21.
  559: *   
  560:          CALL DBBCSD( JOBV1T, 'N', JOBU1, JOBU2, 'T', M, Q, P, THETA,
  561:      $                WORK(IPHI), V1T, LDV1T, 0, 1, U1, LDU1, U2, LDU2,
  562:      $                WORK(IB11D), WORK(IB11E), WORK(IB12D),
  563:      $                WORK(IB12E), WORK(IB21D), WORK(IB21E),
  564:      $                WORK(IB22D), WORK(IB22E), WORK(IBBCSD), LBBCSD,
  565:      $                CHILDINFO )
  566: *   
  567: *        Permute rows and columns to place identity submatrices in
  568: *        preferred positions
  569: *
  570:          IF( Q .GT. 0 .AND. WANTU2 ) THEN
  571:             DO I = 1, Q
  572:                IWORK(I) = M - P - Q + I
  573:             END DO
  574:             DO I = Q + 1, M - P
  575:                IWORK(I) = I - Q
  576:             END DO
  577:             CALL DLAPMT( .FALSE., M-P, M-P, U2, LDU2, IWORK )
  578:          END IF
  579:       ELSE IF( R .EQ. M-P ) THEN
  580: *
  581: *        Case 3: R = M-P
  582: *
  583: *        Simultaneously bidiagonalize X11 and X21
  584: *
  585:          CALL DORBDB3( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  586:      $                 WORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  587:      $                 WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
  588: *
  589: *        Accumulate Householder reflectors
  590: *
  591:          IF( WANTU1 .AND. P .GT. 0 ) THEN
  592:             CALL DLACPY( 'L', P, Q, X11, LDX11, U1, LDU1 )
  593:             CALL DORGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
  594:      $                   LORGQR, CHILDINFO )
  595:          END IF
  596:          IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  597:             U2(1,1) = ONE
  598:             DO J = 2, M-P
  599:                U2(1,J) = ZERO
  600:                U2(J,1) = ZERO
  601:             END DO
  602:             CALL DLACPY( 'L', M-P-1, M-P-1, X21(2,1), LDX21, U2(2,2),
  603:      $                   LDU2 )
  604:             CALL DORGQR( M-P-1, M-P-1, M-P-1, U2(2,2), LDU2,
  605:      $                   WORK(ITAUP2), WORK(IORGQR), LORGQR, CHILDINFO )
  606:          END IF
  607:          IF( WANTV1T .AND. Q .GT. 0 ) THEN
  608:             CALL DLACPY( 'U', M-P, Q, X21, LDX21, V1T, LDV1T )
  609:             CALL DORGLQ( Q, Q, R, V1T, LDV1T, WORK(ITAUQ1),
  610:      $                   WORK(IORGLQ), LORGLQ, CHILDINFO )
  611:          END IF
  612: *   
  613: *        Simultaneously diagonalize X11 and X21.
  614: *   
  615:          CALL DBBCSD( 'N', JOBV1T, JOBU2, JOBU1, 'T', M, M-Q, M-P,
  616:      $                THETA, WORK(IPHI), 0, 1, V1T, LDV1T, U2, LDU2, U1,
  617:      $                LDU1, WORK(IB11D), WORK(IB11E), WORK(IB12D),
  618:      $                WORK(IB12E), WORK(IB21D), WORK(IB21E),
  619:      $                WORK(IB22D), WORK(IB22E), WORK(IBBCSD), LBBCSD,
  620:      $                CHILDINFO )
  621: *   
  622: *        Permute rows and columns to place identity submatrices in
  623: *        preferred positions
  624: *
  625:          IF( Q .GT. R ) THEN
  626:             DO I = 1, R
  627:                IWORK(I) = Q - R + I
  628:             END DO
  629:             DO I = R + 1, Q
  630:                IWORK(I) = I - R
  631:             END DO
  632:             IF( WANTU1 ) THEN
  633:                CALL DLAPMT( .FALSE., P, Q, U1, LDU1, IWORK )
  634:             END IF
  635:             IF( WANTV1T ) THEN
  636:                CALL DLAPMR( .FALSE., Q, Q, V1T, LDV1T, IWORK )
  637:             END IF
  638:          END IF
  639:       ELSE
  640: *
  641: *        Case 4: R = M-Q
  642: *
  643: *        Simultaneously bidiagonalize X11 and X21
  644: *
  645:          CALL DORBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA,
  646:      $                 WORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
  647:      $                 WORK(ITAUQ1), WORK(IORBDB), WORK(IORBDB+M),
  648:      $                 LORBDB-M, CHILDINFO )
  649: *
  650: *        Accumulate Householder reflectors
  651: *
  652:          IF( WANTU1 .AND. P .GT. 0 ) THEN
  653:             CALL DCOPY( P, WORK(IORBDB), 1, U1, 1 )
  654:             DO J = 2, P
  655:                U1(1,J) = ZERO
  656:             END DO
  657:             CALL DLACPY( 'L', P-1, M-Q-1, X11(2,1), LDX11, U1(2,2),
  658:      $                   LDU1 )
  659:             CALL DORGQR( P, P, M-Q, U1, LDU1, WORK(ITAUP1),
  660:      $                   WORK(IORGQR), LORGQR, CHILDINFO )
  661:          END IF
  662:          IF( WANTU2 .AND. M-P .GT. 0 ) THEN
  663:             CALL DCOPY( M-P, WORK(IORBDB+P), 1, U2, 1 )
  664:             DO J = 2, M-P
  665:                U2(1,J) = ZERO
  666:             END DO
  667:             CALL DLACPY( 'L', M-P-1, M-Q-1, X21(2,1), LDX21, U2(2,2),
  668:      $                   LDU2 )
  669:             CALL DORGQR( M-P, M-P, M-Q, U2, LDU2, WORK(ITAUP2),
  670:      $                   WORK(IORGQR), LORGQR, CHILDINFO )
  671:          END IF
  672:          IF( WANTV1T .AND. Q .GT. 0 ) THEN
  673:             CALL DLACPY( 'U', M-Q, Q, X21, LDX21, V1T, LDV1T )
  674:             CALL DLACPY( 'U', P-(M-Q), Q-(M-Q), X11(M-Q+1,M-Q+1), LDX11,
  675:      $                   V1T(M-Q+1,M-Q+1), LDV1T )
  676:             CALL DLACPY( 'U', -P+Q, Q-P, X21(M-Q+1,P+1), LDX21,
  677:      $                   V1T(P+1,P+1), LDV1T )
  678:             CALL DORGLQ( Q, Q, Q, V1T, LDV1T, WORK(ITAUQ1),
  679:      $                   WORK(IORGLQ), LORGLQ, CHILDINFO )
  680:          END IF
  681: *   
  682: *        Simultaneously diagonalize X11 and X21.
  683: *   
  684:          CALL DBBCSD( JOBU2, JOBU1, 'N', JOBV1T, 'N', M, M-P, M-Q,
  685:      $                THETA, WORK(IPHI), U2, LDU2, U1, LDU1, 0, 1, V1T,
  686:      $                LDV1T, WORK(IB11D), WORK(IB11E), WORK(IB12D),
  687:      $                WORK(IB12E), WORK(IB21D), WORK(IB21E),
  688:      $                WORK(IB22D), WORK(IB22E), WORK(IBBCSD), LBBCSD,
  689:      $                CHILDINFO )
  690: *   
  691: *        Permute rows and columns to place identity submatrices in
  692: *        preferred positions
  693: *
  694:          IF( P .GT. R ) THEN
  695:             DO I = 1, R
  696:                IWORK(I) = P - R + I
  697:             END DO
  698:             DO I = R + 1, P
  699:                IWORK(I) = I - R
  700:             END DO
  701:             IF( WANTU1 ) THEN
  702:                CALL DLAPMT( .FALSE., P, P, U1, LDU1, IWORK )
  703:             END IF
  704:             IF( WANTV1T ) THEN
  705:                CALL DLAPMR( .FALSE., P, Q, V1T, LDV1T, IWORK )
  706:             END IF
  707:          END IF
  708:       END IF
  709: *
  710:       RETURN
  711: *
  712: *     End of DORCSD2BY1
  713: *
  714:       END
  715: 

CVSweb interface <joel.bertrand@systella.fr>