Annotation of rpl/lapack/lapack/dorcsd2by1.f, revision 1.1

1.1     ! bertrand    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>