314 RECURSIVE SUBROUTINE zuncsd( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS,
315 $ SIGNS, M, P, Q, X11, LDX11, X12,
316 $ LDX12, X21, LDX21, X22, LDX22, THETA,
317 $ U1, LDU1, U2, LDU2, V1T, LDV1T, V2T,
318 $ LDV2T, WORK, LWORK, RWORK, LRWORK,
326 CHARACTER jobu1, jobu2, jobv1t, jobv2t, signs, trans
327 INTEGER info, ldu1, ldu2, ldv1t, ldv2t, , ldx12,
328 $ ldx21, ldx22, lrwork, lwork, m, p, q
332 DOUBLE PRECISION theta( * )
333 DOUBLE PRECISION rwork( * )
334 COMPLEX*16 u1( ldu1, * ), u2( ldu2, * ), v1t( ldv1t, * ),
335 $ ( , * ), work( * ), x11( ldx11, * ),
336 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
344 PARAMETER ( one = (1.0d0,0.0d0),
345 $ zero = (0.0d0,0.0d0) )
349 INTEGER childinfo, i, ib11d, ib11e, ib12d, ib12e,
350 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
351 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
352 $ itauq2, j, lbbcsdwork, lbbcsdworkmin,
353 $ lbbcsdworkopt, lorbdbwork, lorbdbworkmin,
354 $ lorbdbworkopt, lorglqwork, lorglqworkmin,
355 $ lorglqworkopt, lorgqrwork, lorgqrworkmin,
356 $ lorgqrworkopt, lworkmin, lworkopt, p1, q1
357 LOGICAL colmajor, defaultsigns, lquery, wantu1, wantu2,
359 INTEGER lrworkmin, lrworkopt
378 wantu1 =
lsame( jobu1, 'y
' )
379 WANTU2 = LSAME( JOBU2, 'y
' )
380 WANTV1T = LSAME( JOBV1T, 'y
' )
381 WANTV2T = LSAME( JOBV2T, 'y
' )
382.NOT.
COLMAJOR = LSAME( TRANS, 't
' )
383.NOT.
DEFAULTSIGNS = LSAME( SIGNS, 'o
' )
384.EQ.
LQUERY = LWORK -1
385.EQ.
LRQUERY = LRWORK -1
388.LT..OR..GT.
ELSE IF( P 0 P M ) THEN
390.LT..OR..GT.
ELSE IF( Q 0 Q M ) THEN
392.AND..LT.
ELSE IF ( COLMAJOR LDX11 MAX( 1, P ) ) THEN
394.NOT..AND..LT.
ELSE IF ( COLMAJOR LDX11 MAX( 1, Q ) ) THEN
396.AND..LT.
ELSE IF (COLMAJOR LDX12 MAX( 1, P ) ) THEN
398.NOT..AND..LT.
ELSE IF ( COLMAJOR LDX12 MAX( 1, M-Q ) ) THEN
400.AND..LT.
ELSE IF (COLMAJOR LDX21 MAX( 1, M-P ) ) THEN
402.NOT..AND..LT.
ELSE IF ( COLMAJOR LDX21 MAX( 1, Q ) ) THEN
404.AND..LT.
ELSE IF (COLMAJOR LDX22 MAX( 1, M-P ) ) THEN
406.NOT..AND..LT.
ELSE IF ( COLMAJOR LDX22 MAX( 1, M-Q ) ) THEN
408.AND..LT.
ELSE IF( WANTU1 LDU1 P ) THEN
410.AND..LT.
ELSE IF( WANTU2 LDU2 M-P ) THEN
412.AND..LT.
ELSE IF( WANTV1T LDV1T Q ) THEN
414.AND..LT.
ELSE IF( WANTV2T LDV2T M-Q ) THEN
420.EQ..AND..LT.
IF( INFO 0 MIN( P, M-P ) MIN( Q, M-Q ) ) THEN
426 IF( DEFAULTSIGNS ) THEN
431 CALL ZUNCSD( JOBV1T, JOBV2T, JOBU1, JOBU2, TRANST, SIGNST, M,
432 $ Q, P, X11, LDX11, X21, LDX21, X12, LDX12, X22,
433 $ LDX22, THETA, V1T, LDV1T, V2T, LDV2T, U1, LDU1,
434 $ U2, LDU2, WORK, LWORK, RWORK, LRWORK, IWORK,
442.EQ..AND..LT.
IF( INFO 0 M-Q Q ) THEN
443 IF( DEFAULTSIGNS ) THEN
448 CALL ZUNCSD( JOBU2, JOBU1, JOBV2T, JOBV1T, TRANS, SIGNST, M,
449 $ M-P, M-Q, X22, LDX22, X21, LDX21, X12, LDX12, X11,
450 $ LDX11, THETA, U2, LDU2, U1, LDU1, V2T, LDV2T, V1T,
451 $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK, INFO )
457.EQ.
IF( INFO 0 ) THEN
462 IB11D = IPHI + MAX( 1, Q - 1 )
463 IB11E = IB11D + MAX( 1, Q )
464 IB12D = IB11E + MAX( 1, Q - 1 )
465 IB12E = IB12D + MAX( 1, Q )
466 IB21D = IB12E + MAX( 1, Q - 1 )
467 IB21E = IB21D + MAX( 1, Q )
468 IB22D = IB21E + MAX( 1, Q - 1 )
469 IB22E = IB22D + MAX( 1, Q )
470 IBBCSD = IB22E + MAX( 1, Q - 1 )
471 CALL ZBBCSD( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS, M, P, Q,
472 $ THETA, THETA, U1, LDU1, U2, LDU2, V1T, LDV1T,
473 $ V2T, LDV2T, THETA, THETA, THETA, THETA, THETA,
474 $ THETA, THETA, THETA, RWORK, -1, CHILDINFO )
475 LBBCSDWORKOPT = INT( RWORK(1) )
476 LBBCSDWORKMIN = LBBCSDWORKOPT
477 LRWORKOPT = IBBCSD + LBBCSDWORKOPT - 1
478 LRWORKMIN = IBBCSD + LBBCSDWORKMIN - 1
484 ITAUP2 = ITAUP1 + MAX( 1, P )
485 ITAUQ1 = ITAUP2 + MAX( 1, M - P )
486 ITAUQ2 = ITAUQ1 + MAX( 1, Q )
487 IORGQR = ITAUQ2 + MAX( 1, M - Q )
488 CALL ZUNGQR( M-Q, M-Q, M-Q, U1, MAX(1,M-Q), U1, WORK, -1,
490 LORGQRWORKOPT = INT( WORK(1) )
491 LORGQRWORKMIN = MAX( 1, M - Q )
492 IORGLQ = ITAUQ2 + MAX( 1, M - Q )
493 CALL ZUNGLQ( M-Q, M-Q, M-Q, U1, MAX(1,M-Q), U1, WORK, -1,
495 LORGLQWORKOPT = INT( WORK(1) )
496 LORGLQWORKMIN = MAX( 1, M - Q )
497 IORBDB = ITAUQ2 + MAX( 1, M - Q )
498 CALL ZUNBDB( TRANS, SIGNS, M, P, Q, X11, LDX11, X12, LDX12,
499 $ X21, LDX21, X22, LDX22, THETA, THETA, U1, U2,
500 $ V1T, V2T, WORK, -1, CHILDINFO )
501 LORBDBWORKOPT = INT( WORK(1) )
502 LORBDBWORKMIN = LORBDBWORKOPT
503 LWORKOPT = MAX( IORGQR + LORGQRWORKOPT, IORGLQ + LORGLQWORKOPT,
504 $ IORBDB + LORBDBWORKOPT ) - 1
505 LWORKMIN = MAX( IORGQR + LORGQRWORKMIN, IORGLQ + LORGLQWORKMIN,
506 $ IORBDB + LORBDBWORKMIN ) - 1
507 WORK(1) = MAX(LWORKOPT,LWORKMIN)
509.LT.
IF( LWORK LWORKMIN
510.AND..NOT..OR.
$ ( LQUERY LRQUERY ) ) THEN
512.LT.
ELSE IF( LRWORK LRWORKMIN
513.AND..NOT..OR.
$ ( LQUERY LRQUERY ) ) THEN
516 LORGQRWORK = LWORK - IORGQR + 1
517 LORGLQWORK = LWORK - IORGLQ + 1
518 LORBDBWORK = LWORK - IORBDB + 1
519 LBBCSDWORK = LRWORK - IBBCSD + 1
525.NE.
IF( INFO 0 ) THEN
526 CALL XERBLA( 'zuncsd', -INFO )
528.OR.
ELSE IF( LQUERY LRQUERY ) THEN
534 CALL ZUNBDB( TRANS, SIGNS, M, P, Q, X11, LDX11, X12, LDX12, X21,
535 $ LDX21, X22, LDX22, THETA, RWORK(IPHI), WORK(ITAUP1),
536 $ WORK(ITAUP2), WORK(ITAUQ1), WORK(ITAUQ2),
537 $ WORK(IORBDB), LORBDBWORK, CHILDINFO )
542.AND..GT.
IF( WANTU1 P 0 ) THEN
543 CALL ZLACPY( 'l
', P, Q, X11, LDX11, U1, LDU1 )
544 CALL ZUNGQR( P, P, Q, U1, LDU1, WORK(ITAUP1), WORK(IORGQR),
547.AND..GT.
IF( WANTU2 M-P 0 ) THEN
548 CALL ZLACPY( 'l', m-p, q, x21, ldx21, u2, ldu2 )
550 $ work(iorgqr), lorgqrwork, info )
552 IF( wantv1t .AND. q .GT. 0 )
THEN
553 CALL zlacpy(
'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
560CALL zunglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
561 $ work(iorglq), lorglqwork, info )
563 IF( wantv2t .AND. m-q .GT. 0 )
THEN
564 CALL zlacpy(
'U', p, m-q, x12
566 CALL zlacpy(
'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
567 $ v2t(p+1,p+1), ldv2t )
570 CALL zunglq( m-q, m-q, m-q, v2t, ldv2t, work
571 $ work(iorglq), lorglqwork, info )
575 IF( wantu1 .AND. p .GT. 0 )
THEN
576 CALL zlacpy(
'U', q, p, x11, ldx11, u1, ldu1 )
577 CALL zunglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),
580 IF( wantu2 .AND. m-p .GT. 0 )
THEN
581 CALL zlacpy(
'U', q, m-p, x21, ldx21, u2, ldu2 )
583 $ work(iorglq), lorglqwork, info )
585 IF( wantv1t .AND. q .GT. 0 )
THEN
586 CALL zlacpy(
'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
593 CALL zungqr( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
594 $ work(iorgqr), lorgqrwork, info )
596 IF( wantv2t .AND. m-q .GT. 0 )
THEN
599 CALL zlacpy(
'L', m-q, p, x12, ldx12, v2t, ldv2t )
600 IF( m .GT. p+q )
THEN
601 CALL zlacpy(
'L', m-p-q, m-p-q, x22(p1,q1), ldx22,
602 $ v2t(p+1,p+1), ldv2t )
604 CALL zungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
605 $ work(iorgqr), lorgqrwork, info )
611 CALL zbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,
612 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
613 $ ldv2t, rwork(ib11d), rwork(ib11e), rwork(ib12d),
614 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
615 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
623 IF( q .GT. 0 .AND. wantu2 )
THEN
625 iwork(i) = m - p - q + i
631 CALL zlapmt( .false., m-p, m-p, u2, ldu2, iwork )
633 CALL zlapmr( .false., m-p, m-p, u2, ldu2, iwork )
636 IF( m .GT. 0 .AND. wantv2t )
THEN
638 iwork(i) = m - p - q + i
643 IF( .NOT. colmajor )
THEN
644 CALL zlapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
646 CALL zlapmr( .false., m-q, m-q, v2t, ldv2t, iwork )