314 RECURSIVE SUBROUTINE cuncsd( 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
334 COMPLEX U1( ldu1, * ), U2( ldu2, * ), V1T( ldv1t, * ),
335 $ v2t( ldv2t, * ), work( * ), x11( ldx11, * ),
336 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
344 parameter( one = (1.0e0,0.0e0),
345 $ zero = (0.0e0,0.0e0) )
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 cuncsd( 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 cuncsd( 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 cbbcsd( 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 cungqr( 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 cunglq( 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 cunbdb( 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(
'CUNCSD', -info )
528 ELSE IF( lquery .OR. lrquery )
THEN 534 CALL cunbdb( 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 clacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
544 CALL cungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
547 IF( wantu2 .AND. m-p .GT. 0 )
THEN 548 CALL clacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
549 CALL cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
550 $ work(iorgqr), lorgqrwork, info )
552 IF( wantv1t .AND. q .GT. 0 )
THEN 553 CALL clacpy(
'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
560 CALL cunglq( 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 clacpy(
'U', p, m-q, x12, ldx12, v2t, ldv2t )
565 IF( m-p .GT. q )
THEN 566 CALL clacpy(
'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
567 $ v2t(p+1,p+1), ldv2t )
570 CALL cunglq( 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 clacpy(
'U', q, p, x11, ldx11, u1, ldu1 )
577 CALL cunglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),
580 IF( wantu2 .AND. m-p .GT. 0 )
THEN 581 CALL clacpy(
'U', q, m-p, x21, ldx21, u2, ldu2 )
582 CALL cunglq( m-p, m-p, q, u2, ldu2, work(itaup2),
583 $ work(iorglq), lorglqwork, info )
585 IF( wantv1t .AND. q .GT. 0 )
THEN 586 CALL clacpy(
'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
593 CALL cungqr( 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 clacpy(
'L', m-q, p, x12, ldx12, v2t, ldv2t )
600 IF ( m .GT. p+q )
THEN 601 CALL clacpy(
'L', m-p-q, m-p-q, x22(p1,q1), ldx22,
602 $ v2t(p+1,p+1), ldv2t )
604 CALL cungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
605 $ work(iorgqr), lorgqrwork, info )
611 CALL cbbcsd( 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 clapmt( .false., m-p, m-p, u2, ldu2, iwork )
633 CALL clapmr( .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 clapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
646 CALL clapmr( .false., m-q, m-q, v2t, ldv2t, iwork )
subroutine clacpy(UPLO, M, N, A, LDA, B, LDB)
CLACPY copies all or part of one two-dimensional array to another.
subroutine cunglq(M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
CUNGLQ
subroutine cunbdb(TRANS, SIGNS, M, P, Q, X11, LDX11, X12, LDX12, X21, LDX21, X22, LDX22, THETA, PHI, TAUP1, TAUP2, TAUQ1, TAUQ2, WORK, LWORK, INFO)
CUNBDB
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine clapmr(FORWRD, M, N, X, LDX, K)
CLAPMR rearranges rows of a matrix as specified by a permutation vector.
recursive subroutine cuncsd(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)
CUNCSD
subroutine cungqr(M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
CUNGQR
subroutine clapmt(FORWRD, M, N, X, LDX, K)
CLAPMT performs a forward or backward permutation of the columns of a matrix.
subroutine cbbcsd(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)
CBBCSD