230     $                       X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
 
  231     $                       LDV1T, WORK, LWORK, IWORK, INFO )
 
  238      CHARACTER          JOBU1, JOBU2, JOBV1T
 
  239      INTEGER            INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
 
  243      DOUBLE PRECISION   THETA(*)
 
  244      DOUBLE PRECISION   U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
 
  245     $                   X11(LDX11,*), X21(LDX21,*)
 
  252      DOUBLE PRECISION   ONE, ZERO
 
  253      PARAMETER          ( ONE = 1.0d0, zero = 0.0d0 )
 
  256      INTEGER            CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
 
  257     $                   IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
 
  258     $                   IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
 
  259     $                   j, lbbcsd, lorbdb, lorglq, lorglqmin,
 
  260     $                   lorglqopt, lorgqr, lorgqrmin, lorgqropt,
 
  261     $                   lworkmin, lworkopt, r
 
  262      LOGICAL            LQUERY, WANTU1, WANTU2, WANTV1T
 
  265      DOUBLE PRECISION   DUM1(1), DUM2(1,1)
 
  278      INTRINSIC          int, max, min
 
  285      wantu1 = lsame( jobu1, 
'Y' )
 
  286      wantu2 = lsame( jobu2, 
'Y' )
 
  287      wantv1t = lsame( jobv1t, 
'Y' )
 
  288      lquery = lwork .EQ. -1
 
  292      ELSE IF( p .LT. 0 .OR. p .GT. m ) 
THEN 
  294      ELSE IF( q .LT. 0 .OR. q .GT. m ) 
THEN 
  296      ELSE IF( ldx11 .LT. max( 1, p ) ) 
THEN 
  298      ELSE IF( ldx21 .LT. max( 1, m-p ) ) 
THEN 
  300      ELSE IF( wantu1 .AND. ldu1 .LT. max( 1, p ) ) 
THEN 
  302      ELSE IF( wantu2 .AND. ldu2 .LT. max( 1, m - p ) ) 
THEN 
  304      ELSE IF( wantv1t .AND. ldv1t .LT. max( 1, q ) ) 
THEN 
  308      r = min( p, m-p, q, m-q )
 
  329      IF( info .EQ. 0 ) 
THEN 
  331         ib11d = iphi + max( 1, r-1 )
 
  332         ib11e = ib11d + max( 1, r )
 
  333         ib12d = ib11e + max( 1, r - 1 )
 
  334         ib12e = ib12d + max( 1, r )
 
  335         ib21d = ib12e + max( 1, r - 1 )
 
  336         ib21e = ib21d + max( 1, r )
 
  337         ib22d = ib21e + max( 1, r - 1 )
 
  338         ib22e = ib22d + max( 1, r )
 
  339         ibbcsd = ib22e + max( 1, r - 1 )
 
  340         itaup1 = iphi + max( 1, r-1 )
 
  341         itaup2 = itaup1 + max( 1, p )
 
  342         itauq1 = itaup2 + max( 1, m-p )
 
  343         iorbdb = itauq1 + max( 1, q )
 
  344         iorgqr = itauq1 + max( 1, q )
 
  345         iorglq = itauq1 + max( 1, q )
 
  351            CALL dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
 
  352     $                    dum1, dum1, dum1, dum1, work,
 
  354            lorbdb = int( work(1) )
 
  355            IF( wantu1 .AND. p .GT. 0 ) 
THEN 
  356               CALL dorgqr( p, p, q, u1, ldu1, dum1, work(1), -1,
 
  358               lorgqrmin = max( lorgqrmin, p )
 
  359               lorgqropt = max( lorgqropt, int( work(1) ) )
 
  361            IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  362               CALL dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1),
 
  364               lorgqrmin = max( lorgqrmin, m-p )
 
  365               lorgqropt = max( lorgqropt, int( work(1) ) )
 
  367            IF( wantv1t .AND. q .GT. 0 ) 
THEN 
  368               CALL dorglq( q-1, q-1, q-1, v1t, ldv1t,
 
  369     $                      dum1, work(1), -1, childinfo )
 
  370               lorglqmin = max( lorglqmin, q-1 )
 
  371               lorglqopt = max( lorglqopt, int( work(1) ) )
 
  373            CALL dbbcsd( jobu1, jobu2, jobv1t, 
'N', 
'N', m, p, q,
 
  375     $                   dum1, u1, ldu1, u2, ldu2, v1t, ldv1t,
 
  376     $                   dum2, 1, dum1, dum1, dum1,
 
  377     $                   dum1, dum1, dum1, dum1,
 
  378     $                   dum1, work(1), -1, childinfo )
 
  379            lbbcsd = int( work(1) )
 
  380         ELSE IF( r .EQ. p ) 
THEN 
  381            CALL dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
 
  382     $                    dum1, dum1, dum1, dum1,
 
  383     $                    work(1), -1, childinfo )
 
  384            lorbdb = int( work(1) )
 
  385            IF( wantu1 .AND. p .GT. 0 ) 
THEN 
  386               CALL dorgqr( p-1, p-1, p-1, u1(2,2), ldu1, dum1,
 
  387     $                      work(1), -1, childinfo )
 
  388               lorgqrmin = max( lorgqrmin, p-1 )
 
  389               lorgqropt = max( lorgqropt, int( work(1) ) )
 
  391            IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  392               CALL dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1),
 
  394               lorgqrmin = max( lorgqrmin, m-p )
 
  395               lorgqropt = max( lorgqropt, int( work(1) ) )
 
  397            IF( wantv1t .AND. q .GT. 0 ) 
THEN 
  398               CALL dorglq( q, q, r, v1t, ldv1t, dum1, work(1), -1,
 
  400               lorglqmin = max( lorglqmin, q )
 
  401               lorglqopt = max( lorglqopt, int( work(1) ) )
 
  403            CALL dbbcsd( jobv1t, 
'N', jobu1, jobu2, 
'T', m, q, p,
 
  405     $                   dum1, v1t, ldv1t, dum2, 1, u1, ldu1,
 
  406     $                   u2, ldu2, dum1, dum1, dum1,
 
  407     $                   dum1, dum1, dum1, dum1,
 
  408     $                   dum1, work(1), -1, childinfo )
 
  409            lbbcsd = int( work(1) )
 
  410         ELSE IF( r .EQ. m-p ) 
THEN 
  411            CALL dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
 
  412     $                    dum1, dum1, dum1, dum1,
 
  413     $                    work(1), -1, childinfo )
 
  414            lorbdb = int( work(1) )
 
  415            IF( wantu1 .AND. p .GT. 0 ) 
THEN 
  416               CALL dorgqr( p, p, q, u1, ldu1, dum1, work(1), -1,
 
  418               lorgqrmin = max( lorgqrmin, p )
 
  419               lorgqropt = max( lorgqropt, int( work(1) ) )
 
  421            IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  422               CALL dorgqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
 
  423     $                      dum1, work(1), -1, childinfo )
 
  424               lorgqrmin = max( lorgqrmin, m-p-1 )
 
  425               lorgqropt = max( lorgqropt, int( work(1) ) )
 
  427            IF( wantv1t .AND. q .GT. 0 ) 
THEN 
  428               CALL dorglq( q, q, r, v1t, ldv1t, dum1, work(1), -1,
 
  430               lorglqmin = max( lorglqmin, q )
 
  431               lorglqopt = max( lorglqopt, int( work(1) ) )
 
  433            CALL dbbcsd( 
'N', jobv1t, jobu2, jobu1, 
'T', m, m-q, m-p,
 
  434     $                   theta, dum1, dum2, 1, v1t, ldv1t, u2,
 
  435     $                   ldu2, u1, ldu1, dum1, dum1, dum1,
 
  436     $                   dum1, dum1, dum1, dum1,
 
  437     $                   dum1, work(1), -1, childinfo )
 
  438            lbbcsd = int( work(1) )
 
  440            CALL dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
 
  441     $                    dum1, dum1, dum1, dum1,
 
  442     $                    dum1, work(1), -1, childinfo )
 
  443            lorbdb = m + int( work(1) )
 
  444            IF( wantu1 .AND. p .GT. 0 ) 
THEN 
  445               CALL dorgqr( p, p, m-q, u1, ldu1, dum1, work(1), -1,
 
  447               lorgqrmin = max( lorgqrmin, p )
 
  448               lorgqropt = max( lorgqropt, int( work(1) ) )
 
  450            IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  451               CALL dorgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1),
 
  453               lorgqrmin = max( lorgqrmin, m-p )
 
  454               lorgqropt = max( lorgqropt, int( work(1) ) )
 
  456            IF( wantv1t .AND. q .GT. 0 ) 
THEN 
  457               CALL dorglq( q, q, q, v1t, ldv1t, dum1, work(1), -1,
 
  459               lorglqmin = max( lorglqmin, q )
 
  460               lorglqopt = max( lorglqopt, int( work(1) ) )
 
  462            CALL dbbcsd( jobu2, jobu1, 
'N', jobv1t, 
'N', m, m-p, m-q,
 
  463     $                   theta, dum1, u2, ldu2, u1, ldu1, dum2,
 
  464     $                   1, v1t, ldv1t, dum1, dum1, dum1,
 
  465     $                   dum1, dum1, dum1, dum1,
 
  466     $                   dum1, work(1), -1, childinfo )
 
  467            lbbcsd = int( work(1) )
 
  469         lworkmin = max( iorbdb+lorbdb-1,
 
  470     $                   iorgqr+lorgqrmin-1,
 
  471     $                   iorglq+lorglqmin-1,
 
  473         lworkopt = max( iorbdb+lorbdb-1,
 
  474     $                   iorgqr+lorgqropt-1,
 
  475     $                   iorglq+lorglqopt-1,
 
  478         IF( lwork .LT. lworkmin .AND. .NOT.lquery ) 
THEN 
  482      IF( info .NE. 0 ) 
THEN 
  483         CALL xerbla( 
'DORCSD2BY1', -info )
 
  485      ELSE IF( lquery ) 
THEN 
  488      lorgqr = lwork-iorgqr+1
 
  489      lorglq = lwork-iorglq+1
 
  500         CALL dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
 
  501     $                 work(iphi), work(itaup1), work(itaup2),
 
  502     $                 work(itauq1), work(iorbdb), lorbdb, childinfo )
 
  506         IF( wantu1 .AND. p .GT. 0 ) 
THEN 
  507            CALL dlacpy( 
'L', p, q, x11, ldx11, u1, ldu1 )
 
  508            CALL dorgqr( p, p, q, u1, ldu1, work(itaup1),
 
  510     $                   lorgqr, childinfo )
 
  512         IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  513            CALL dlacpy( 
'L', m-p, q, x21, ldx21, u2, ldu2 )
 
  514            CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
 
  515     $                   work(iorgqr), lorgqr, childinfo )
 
  517         IF( wantv1t .AND. q .GT. 0 ) 
THEN 
  523            CALL dlacpy( 
'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
 
  525            CALL dorglq( q-1, q-1, q-1, v1t(2,2), ldv1t,
 
  527     $                   work(iorglq), lorglq, childinfo )
 
  532         CALL dbbcsd( jobu1, jobu2, jobv1t, 
'N', 
'N', m, p, q, theta,
 
  533     $                work(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t,
 
  534     $                dum2, 1, work(ib11d), work(ib11e),
 
  535     $                work(ib12d), work(ib12e), work(ib21d),
 
  536     $                work(ib21e), work(ib22d), work(ib22e),
 
  537     $                work(ibbcsd), lbbcsd, childinfo )
 
  542         IF( q .GT. 0 .AND. wantu2 ) 
THEN 
  544               iwork(i) = m - p - q + i
 
  549            CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
 
  551      ELSE IF( r .EQ. p ) 
THEN 
  557         CALL dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
 
  558     $                 work(iphi), work(itaup1), work(itaup2),
 
  559     $                 work(itauq1), work(iorbdb), lorbdb, childinfo )
 
  563         IF( wantu1 .AND. p .GT. 0 ) 
THEN 
  569            CALL dlacpy( 
'L', p-1, p-1, x11(2,1), ldx11, u1(2,2),
 
  571            CALL dorgqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
 
  572     $                   work(iorgqr), lorgqr, childinfo )
 
  574         IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  575            CALL dlacpy( 
'L', m-p, q, x21, ldx21, u2, ldu2 )
 
  576            CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
 
  577     $                   work(iorgqr), lorgqr, childinfo )
 
  579         IF( wantv1t .AND. q .GT. 0 ) 
THEN 
  580            CALL dlacpy( 
'U', p, q, x11, ldx11, v1t, ldv1t )
 
  581            CALL dorglq( q, q, r, v1t, ldv1t, work(itauq1),
 
  582     $                   work(iorglq), lorglq, childinfo )
 
  587         CALL dbbcsd( jobv1t, 
'N', jobu1, jobu2, 
'T', m, q, p, theta,
 
  588     $                work(iphi), v1t, ldv1t, dum1, 1, u1, ldu1, u2,
 
  589     $                ldu2, work(ib11d), work(ib11e), work(ib12d),
 
  590     $                work(ib12e), work(ib21d), work(ib21e),
 
  591     $                work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,
 
  597         IF( q .GT. 0 .AND. wantu2 ) 
THEN 
  599               iwork(i) = m - p - q + i
 
  604            CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
 
  606      ELSE IF( r .EQ. m-p ) 
THEN 
  612         CALL dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
 
  613     $                 work(iphi), work(itaup1), work(itaup2),
 
  614     $                 work(itauq1), work(iorbdb), lorbdb, childinfo )
 
  618         IF( wantu1 .AND. p .GT. 0 ) 
THEN 
  619            CALL dlacpy( 
'L', p, q, x11, ldx11, u1, ldu1 )
 
  620            CALL dorgqr( p, p, q, u1, ldu1, work(itaup1),
 
  622     $                   lorgqr, childinfo )
 
  624         IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  630            CALL dlacpy( 
'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
 
  632            CALL dorgqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
 
  633     $                   work(itaup2), work(iorgqr), lorgqr, childinfo )
 
  635         IF( wantv1t .AND. q .GT. 0 ) 
THEN 
  636            CALL dlacpy( 
'U', m-p, q, x21, ldx21, v1t, ldv1t )
 
  637            CALL dorglq( q, q, r, v1t, ldv1t, work(itauq1),
 
  638     $                   work(iorglq), lorglq, childinfo )
 
  643         CALL dbbcsd( 
'N', jobv1t, jobu2, jobu1, 
'T', m, m-q, m-p,
 
  644     $                theta, work(iphi), dum1, 1, v1t, ldv1t, u2,
 
  645     $                ldu2, u1, ldu1, work(ib11d), work(ib11e),
 
  646     $                work(ib12d), work(ib12e), work(ib21d),
 
  647     $                work(ib21e), work(ib22d), work(ib22e),
 
  648     $                work(ibbcsd), lbbcsd, childinfo )
 
  661               CALL dlapmt( .false., p, q, u1, ldu1, iwork )
 
  664               CALL dlapmr( .false., q, q, v1t, ldv1t, iwork )
 
  673         CALL dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
 
  674     $                 work(iphi), work(itaup1), work(itaup2),
 
  675     $                 work(itauq1), work(iorbdb), work(iorbdb+m),
 
  676     $                 lorbdb-m, childinfo )
 
  680         IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  681            CALL dcopy( m-p, work(iorbdb+p), 1, u2, 1 )
 
  683         IF( wantu1 .AND. p .GT. 0 ) 
THEN 
  684            CALL dcopy( p, work(iorbdb), 1, u1, 1 )
 
  688            CALL dlacpy( 
'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
 
  690            CALL dorgqr( p, p, m-q, u1, ldu1, work(itaup1),
 
  691     $                   work(iorgqr), lorgqr, childinfo )
 
  693         IF( wantu2 .AND. m-p .GT. 0 ) 
THEN 
  697            CALL dlacpy( 
'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
 
  699            CALL dorgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
 
  700     $                   work(iorgqr), lorgqr, childinfo )
 
  702         IF( wantv1t .AND. q .GT. 0 ) 
THEN 
  703            CALL dlacpy( 
'U', m-q, q, x21, ldx21, v1t, ldv1t )
 
  704            CALL dlacpy( 
'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1),
 
  706     $                   v1t(m-q+1,m-q+1), ldv1t )
 
  707            CALL dlacpy( 
'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
 
  708     $                   v1t(p+1,p+1), ldv1t )
 
  709            CALL dorglq( q, q, q, v1t, ldv1t, work(itauq1),
 
  710     $                   work(iorglq), lorglq, childinfo )
 
  715         CALL dbbcsd( jobu2, jobu1, 
'N', jobv1t, 
'N', m, m-p, m-q,
 
  716     $                theta, work(iphi), u2, ldu2, u1, ldu1, dum1,
 
  717     $                1, v1t, ldv1t, work(ib11d), work(ib11e),
 
  718     $                work(ib12d), work(ib12e), work(ib21d),
 
  719     $                work(ib21e), work(ib22d), work(ib22e),
 
  720     $                work(ibbcsd), lbbcsd, childinfo )
 
  733               CALL dlapmt( .false., p, p, u1, ldu1, iwork )
 
  736               CALL dlapmr( .false., p, q, v1t, ldv1t, iwork )