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, LDX11, 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 $ v2t( ldv2t, * ), work( * ), x11( ldx11, * ),
336 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
344 parameter( one = (1.0d0,0.0d0),
345 $ zero = (0.0d0,0.0d0) )
348 CHARACTER TRANST, SIGNST
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
371 INTRINSIC int, max, min
378 wantu1 = lsame( jobu1,
'Y' )
379 wantu2 = lsame( jobu2,
'Y' )
380 wantv1t = lsame( jobv1t,
'Y' )
381 wantv2t = lsame( jobv2t,
'Y' )
382 colmajor = .NOT. lsame( trans,
'T' )
383 defaultsigns = .NOT. lsame( signs,
'O' )
384 lquery = lwork .EQ. -1
385 lrquery = lrwork .EQ. -1
388 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN 390 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN 392 ELSE IF ( colmajor .AND. ldx11 .LT. max( 1, p ) )
THEN 394 ELSE IF (.NOT. colmajor .AND. ldx11 .LT. max( 1, q ) )
THEN 396 ELSE IF (colmajor .AND. ldx12 .LT. max( 1, p ) )
THEN 398 ELSE IF (.NOT. colmajor .AND. ldx12 .LT. max( 1, m-q ) )
THEN 400 ELSE IF (colmajor .AND. ldx21 .LT. max( 1, m-p ) )
THEN 402 ELSE IF (.NOT. colmajor .AND. ldx21 .LT. max( 1, q ) )
THEN 404 ELSE IF (colmajor .AND. ldx22 .LT. max( 1, m-p ) )
THEN 406 ELSE IF (.NOT. colmajor .AND. ldx22 .LT. max( 1, m-q ) )
THEN 408 ELSE IF( wantu1 .AND. ldu1 .LT. p )
THEN 410 ELSE IF( wantu2 .AND. ldu2 .LT. m-p )
THEN 412 ELSE IF( wantv1t .AND. ldv1t .LT. q )
THEN 414 ELSE IF( wantv2t .AND. ldv2t .LT. m-q )
THEN 420 IF( info .EQ. 0 .AND. min( p, m-p ) .LT. 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 IF( info .EQ. 0 .AND. m-q .LT. 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 IF( info .EQ. 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 IF( lwork .LT. lworkmin
510 $ .AND. .NOT. ( lquery .OR. lrquery ) )
THEN 512 ELSE IF( lrwork .LT. lrworkmin
513 $ .AND. .NOT. ( lquery .OR. lrquery ) )
THEN 516 lorgqrwork = lwork - iorgqr + 1
517 lorglqwork = lwork - iorglq + 1
518 lorbdbwork = lwork - iorbdb + 1
519 lbbcsdwork = lrwork - ibbcsd + 1
525 IF( info .NE. 0 )
THEN 526 CALL xerbla(
'ZUNCSD', -info )
528 ELSE IF( lquery .OR. 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 IF( wantu1 .AND. p .GT. 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 IF( wantu2 .AND. m-p .GT. 0 )
THEN 548 CALL zlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
549 CALL zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
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),
560 CALL 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, ldx12, v2t, ldv2t )
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(itauq2),
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 )
582 CALL zunglq( m-p, m-p, q, u2, ldu2, work(itaup2),
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 )
subroutine zlapmr(FORWRD, M, N, X, LDX, K)
ZLAPMR rearranges rows of a matrix as specified by a permutation vector.
subroutine zunbdb(TRANS, SIGNS, M, P, Q, X11, LDX11, X12, LDX12, X21, LDX21, X22, LDX22, THETA, PHI, TAUP1, TAUP2, TAUQ1, TAUQ2, WORK, LWORK, INFO)
ZUNBDB
subroutine xerbla(SRNAME, INFO)
XERBLA
recursive subroutine zuncsd(JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS, SIGNS, M, P, Q, X11, LDX11, X12, LDX12, X21, LDX21, X22, LDX22, THETA, U1, LDU1, U2, LDU2, V1T, LDV1T, V2T, LDV2T, WORK, LWORK, RWORK, LRWORK, IWORK, INFO)
ZUNCSD
subroutine zbbcsd(JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS, M, P, Q, THETA, PHI, U1, LDU1, U2, LDU2, V1T, LDV1T, V2T, LDV2T, B11D, B11E, B12D, B12E, B21D, B21E, B22D, B22E, RWORK, LRWORK, INFO)
ZBBCSD
subroutine zlacpy(UPLO, M, N, A, LDA, B, LDB)
ZLACPY copies all or part of one two-dimensional array to another.
subroutine zlapmt(FORWRD, M, N, X, LDX, K)
ZLAPMT performs a forward or backward permutation of the columns of a matrix.
subroutine zunglq(M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
ZUNGLQ
subroutine zungqr(M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
ZUNGQR