252 SUBROUTINE zuncsd2by1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
253 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
254 $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
262 CHARACTER JOBU1, JOBU2, JOBV1T
263 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
265 INTEGER LRWORK, LRWORKMIN, LRWORKOPT
268 DOUBLE PRECISION RWORK(*)
269 DOUBLE PRECISION THETA(*)
270 COMPLEX*16 U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
271 $ x11(ldx11,*), x21(ldx21,*)
279 PARAMETER ( ONE = (1.0d0,0.0d0), zero = (0.0d0,0.0d0) )
282 INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
283 $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
284 $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
285 $ j, lbbcsd, lorbdb, lorglq, lorglqmin,
286 $ lorglqopt, lorgqr, lorgqrmin, lorgqropt,
287 $ lworkmin, lworkopt, r
288 LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
291 DOUBLE PRECISION DUM( 1 )
292 COMPLEX*16 CDUM( 1, 1 )
311 wantu1 = lsame( jobu1,
'Y' )
312 wantu2 = lsame( jobu2,
'Y' )
313 wantv1t = lsame( jobv1t
'Y' )
314 lquery = ( lwork.EQ.-1 ) .OR. ( lrwork.EQ.-1 )
318 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
320 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
322 ELSE IF( ldx11 .LT.
max( 1, p ) )
THEN
324 ELSE IF( ldx21 .LT.
max( 1, m-p ) )
THEN
326 ELSE IF( wantu1 .AND. ldu1 .LT.
max( 1, p ) )
THEN
328 ELSE IF( wantu2 .AND. ldu2 .LT.
max( 1, m - p ) )
THEN
330 ELSE IF( wantv1t .AND. ldv1t .LT.
max( 1, q ) )
THEN
334 r =
min( p, m-p, q, m-q )
369 IF( info .EQ. 0 )
THEN
371 ib11d = iphi +
max( 1, r-1 )
372 ib11e = ib11d +
max( 1, r )
373 ib12d = ib11e +
max( 1, r - 1 )
374 ib12e = ib12d +
max( 1, r )
375 ib21d = ib12e +
max( 1, r - 1 )
376 ib21e = ib21d +
max( 1, r )
377 ib22d = ib21e +
max( 1, r - 1 )
378 ib22e = ib22d +
max( 1, r )
379 ibbcsd = ib22e +
max( 1, r - 1 )
381 itaup2 = itaup1 +
max( 1, p )
382 itauq1 = itaup2 +
max( 1, m-p )
383 iorbdb = itauq1 +
max( 1, q )
384 iorgqr = itauq1 +
max( 1, q )
385 iorglq = itauq1 +
max( 1, q )
391 CALL zunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, dum,
392 $ cdum, cdum, cdum, work, -1, childinfo )
393 lorbdb = int( work(1) )
394 IF( wantu1 .AND. p .GT. 0 )
THEN
395 CALL zungqr( p, p, q, u1, ldu1, cdum, work(1), -1,
397 lorgqrmin =
max( lorgqrmin, p )
398 lorgqropt =
max( lorgqropt, int( work(1) ) )
400 IF( wantu2 .AND. m-p .GT. 0 )
THEN
401 CALL zungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
403 lorgqrmin =
max( lorgqrmin, m-p )
404 lorgqropt =
max( lorgqropt, int( work(1) ) )
406 IF( wantv1t .AND. q .GT. 0 )
THEN
407 CALL zunglq( q-1, q-1, q-1, v1t, ldv1t,
408 $ cdum, work(1), -1, childinfo )
409 lorglqmin =
max( lorglqmin, q-1 )
410 lorglqopt =
max( lorglqopt, int( work(1) ) )
412 CALL zbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
413 $ dum, u1, ldu1, u2, ldu2, v1t, ldv1t, cdum, 1,
414 $ dum, dum, dum, dum, dum, dum, dum, dum,
415 $ rwork(1), -1, childinfo )
416 lbbcsd = int( rwork(1) )
417 ELSE IF( r .EQ. p )
THEN
418 CALL zunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, dum,
419 $ cdum, cdum, cdum, work(1), -1, childinfo )
420 lorbdb = int( work(1) )
421 IF( wantu1 .AND. p .GT. 0 )
THEN
422 CALL zungqr( p-1, p-1, p-1, u1(2,2), ldu1, cdum, work(1),
424 lorgqrmin =
max( lorgqrmin, p-1 )
425 lorgqropt =
max( lorgqropt, int( work(1) ) )
427 IF( wantu2 .AND. m-p .GT. 0 )
THEN
428 CALL zungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
430 lorgqrmin =
max( lorgqrmin, m-p )
431 lorgqropt =
max( lorgqropt, int( work(1) ) )
433 IF( wantv1t .AND. q .GT. 0 )
THEN
434 CALL zunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
436 lorglqmin =
max( lorglqmin, q )
437 lorglqopt =
max( lorglqopt, int( work(1) ) )
439 CALL zbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
440 $ dum, v1t, ldv1t, cdum, 1, u1, ldu1, u2, ldu2,
441 $ dum, dum, dum, dum, dum, dum, dum, dum,
442 $ rwork(1), -1, childinfo )
443 lbbcsd = int( rwork(1) )
444 ELSE IF( r .EQ. m-p )
THEN
445 CALL zunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, dum,
447 lorbdb = int( work(1) )
448 IF( wantu1 .AND. p .GT. 0 )
THEN
449 CALL zungqr( p, p, q, u1, ldu1, cdum, work(1), -1,
451 lorgqrmin =
max( lorgqrmin, p )
452 lorgqropt =
max( lorgqropt, int( work(1) ) )
454 IF( wantu2 .AND. m-p .GT. 0 )
THEN
455 CALL zungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2, cdum,
456 $ work(1), -1, childinfo )
457 lorgqrmin =
max( lorgqrmin, m-p-1 )
458 lorgqropt =
max( lorgqropt, int( work(1) ) )
460 IF( wantv1t .AND. q .GT. 0 )
THEN
461 CALL zunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
463 lorglqmin =
max( lorglqmin, q )
464 lorglqopt =
max( lorglqopt, int( work(1) ) )
466 CALL zbbcsd( 'n
', JOBV1T, JOBU2, JOBU1, 't
', M, M-Q, M-P,
467 $ THETA, DUM, CDUM, 1, V1T, LDV1T, U2, LDU2, U1,
468 $ LDU1, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
469 $ RWORK(1), -1, CHILDINFO )
470 LBBCSD = INT( RWORK(1) )
472 CALL ZUNBDB4( M, P, Q, X11, LDX11, X21, LDX21, THETA, DUM,
473 $ CDUM, CDUM, CDUM, CDUM, WORK(1), -1, CHILDINFO
475 LORBDB = M + INT( WORK(1) )
476.AND..GT.
IF( WANTU1 P 0 ) THEN
477 CALL ZUNGQR( P, P, M-Q, U1, LDU1, CDUM, WORK(1), -1,
479 LORGQRMIN = MAX( LORGQRMIN, P )
480 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
482.AND..GT.
IF( WANTU2 M-P 0 ) THEN
483 CALL ZUNGQR( M-P, M-P, M-Q, U2, LDU2, CDUM, WORK(1), -1,
485 LORGQRMIN = MAX( LORGQRMIN, M-P )
486 LORGQROPT = MAX( LORGQROPT, INT( WORK(1) ) )
488.AND..GT.
IF( WANTV1T Q 0 ) THEN
489 CALL ZUNGLQ( Q, Q, Q, V1T, LDV1T, CDUM, WORK(1), -1,
491 LORGLQMIN = MAX( LORGLQMIN, Q )
492 LORGLQOPT = MAX( LORGLQOPT, INT( WORK(1) ) )
494 CALL ZBBCSD( JOBU2, JOBU1, 'n
', JOBV1T, 'n
', M, M-P, M-Q,
495 $ THETA, DUM, U2, LDU2, U1, LDU1, CDUM, 1, V1T,
496 $ LDV1T, DUM, DUM, DUM, DUM, DUM, DUM, DUM, DUM,
497 $ RWORK(1), -1, CHILDINFO )
498 LBBCSD = INT( RWORK(1) )
500 LRWORKMIN = IBBCSD+LBBCSD-1
501 LRWORKOPT = LRWORKMIN
503 LWORKMIN = MAX( IORBDB+LORBDB-1,
504 $ IORGQR+LORGQRMIN-1,
505 $ IORGLQ+LORGLQMIN-1 )
506 LWORKOPT = MAX( IORBDB+LORBDB-1,
507 $ IORGQR+LORGQROPT-1,
508 $ IORGLQ+LORGLQOPT-1 )
510.LT..AND..NOT.
IF( LWORK LWORKMIN LQUERY ) THEN
513.LT..AND..NOT.
IF( LRWORK LRWORKMIN LQUERY ) THEN
517.NE.
IF( INFO 0 ) THEN
520 ELSE IF( LQUERY ) THEN
523 LORGQR = LWORK-IORGQR+1
524 LORGLQ = LWORK-IORGLQ+1
535 CALL ZUNBDB1( M, P, Q, X11, LDX11, X21, LDX21, THETA,
536 $ RWORK(IPHI), WORK(ITAUP1), WORK(ITAUP2),
537 $ WORK(ITAUQ1), WORK(IORBDB), LORBDB, CHILDINFO )
541.AND..GT.
IF( WANTU1 P 0 ) THEN
542 CALL ZLACPY( 'l
', P, Q, X11, LDX11, U1, LDU1 )
543 CALL ZUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
544 $ LORGQR, CHILDINFO )
546.AND..GT.
IF( WANTU2 M-P 0 ) THEN
547 CALL ZLACPY( 'l', m-p, q, x21, ldx21, u2, ldu2 )
548 CALL zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
551 IF( wantv1t .AND. q .GT. 0 )
THEN
557 CALL zlacpy(
'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
559 CALL zunglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
560 $ work(iorglq), lorglq, childinfo )
565 CALL zbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
566 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, cdum,
567 $ 1, rwork(ib11d), rwork(ib11e), rwork(ib12d),
568 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
569 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
570 $ lrwork-ibbcsd+1, childinfo )
575 IF( q .GT. 0 .AND. wantu2 )
THEN
577 iwork(i) = m - p - q + i
582 CALL zlapmt( .false., m-p, m-p, u2, ldu2, iwork )
584 ELSE IF( r .EQ. p )
THEN
590 CALL zunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
591 $ rwork(iphi), work(itaup1), work(itaup2),
592 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
596 IF( wantu1 .AND. p .GT. 0 )
THEN
602 CALL zlacpy(
'L', p-1, p-1, x11(2,1), ldx11, u1(2,2), ldu1 )
603 CALL zungqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
604 $ work(iorgqr), lorgqr, childinfo )
606 IF( wantu2 .AND. m-p .GT. 0 )
THEN
607 CALL zlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
608 CALL zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
609 $ work(iorgqr), lorgqr, childinfo )
611 IF( wantv1t .AND. q .GT. 0 )
THEN
612 CALL zlacpy(
'U', p, q, x11, ldx11, v1t, ldv1t )
613 CALL zunglq( q, q, r, v1t, ldv1t, work(itauq1),
614 $ work(iorglq), lorglq, childinfo )
619 CALL zbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
620 $ rwork(iphi), v1t, ldv1t, cdum, 1, u1, ldu1, u2,
621 $ ldu2, rwork(ib11d), rwork(ib11e), rwork(ib12d),
622 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
623 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd), lbbcsd,
629 IF( q .GT. 0 .AND. wantu2 )
THEN
631 iwork(i) = m - p - q + i
636 CALL zlapmt( .false., m-p, m-p, u2, ldu2, iwork )
638 ELSE IF( r .EQ. m-p )
THEN
644 CALL zunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
645 $ rwork(iphi), work(itaup1), work(itaup2),
646 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
650 IF( wantu1 .AND. p .GT. 0 )
THEN
651 CALL zlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
652 CALL zungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
653 $ lorgqr, childinfo )
655 IF( wantu2 .AND. m-p .GT. 0 )
THEN
661 CALL zlacpy(
'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
663 CALL zungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
664 $ work(itaup2), work(iorgqr), lorgqr, childinfo )
666 IF( wantv1t .AND. q .GT. 0 )
THEN
667 CALL zlacpy(
'U', m-p, q, x21, ldx21, v1t, ldv1t )
668 CALL zunglq( q, q, r, v1t, ldv1t, work(itauq1),
669 $ work(iorglq), lorglq, childinfo )
674 CALL zbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
675 $ theta, rwork(iphi), cdum, 1, v1t, ldv1t, u2, ldu2,
676 $ u1, ldu1, rwork(ib11d), rwork(ib11e),
677 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
678 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
692 CALL zlapmt( .false., p, q, u1, ldu1, iwork )
695 CALL zlapmr( .false., q, q, v1t, ldv1t, iwork )
704 CALL zunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
705 $ rwork(iphi), work(itaup1), work(itaup2),
706 $ work(itauq1), work(iorbdb), work(iorbdb+m),
707 $ lorbdb-m, childinfo )
711 IF( wantu2 .AND. m-p .GT. 0 )
THEN
712 CALL zcopy( m-p, work(iorbdb+p), 1, u2, 1 )
714 IF( wantu1 .AND. p .GT. 0 )
THEN
715 CALL zcopy( p, work(iorbdb), 1, u1, 1 )
719 CALL zlacpy(
'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
721 CALL zungqr( p, p, m-q, u1, ldu1, work(itaup1),
722 $ work(iorgqr), lorgqr, childinfo )
724 IF( wantu2 .AND. m-p .GT. 0 )
THEN
728 CALL zlacpy(
'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
730 CALL zungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
731 $ work(iorgqr), lorgqr, childinfo )
733 IF( wantv1t .AND. q .GT. 0 )
THEN
734 CALL zlacpy(
'U', m-q, q, x21, ldx21, v1t, ldv1t )
735 CALL zlacpy(
'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,
736 $ v1t(m-q+1,m-q+1), ldv1t )
737 CALL zlacpy(
'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
738 $ v1t(p+1,p+1), ldv1t )
739 CALL zunglq( q, q, q, v1t, ldv1t, work(itauq1),
740 $ work(iorglq), lorglq, childinfo )
745 CALL zbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
746 $ theta, rwork(iphi), u2, ldu2, u1, ldu1, cdum, 1,
747 $ v1t, ldv1t, rwork(ib11d), rwork(ib11e),
748 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
749 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
750 $ rwork(ibbcsd), lbbcsd, childinfo )
763 CALL zlapmt( .false., p, p
766 CALL zlapmr( .false., p, q, v1t, ldv1t, iwork )