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
372 INTRINSIC int, max, min
379 wantu1 =
lsame( jobu1,
'Y' )
380 wantu2 =
lsame( jobu2,
'Y' )
381 wantv1t =
lsame( jobv1t,
'Y' )
382 wantv2t =
lsame( jobv2t,
'Y' )
383 colmajor = .NOT.
lsame( trans,
'T' )
384 defaultsigns = .NOT.
lsame( signs,
'O' )
385 lquery = lwork .EQ. -1
386 lrquery = lrwork .EQ. -1
389 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
391 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
393 ELSE IF ( colmajor .AND. ldx11 .LT. max( 1, p ) )
THEN
395 ELSE IF (.NOT. colmajor .AND. ldx11 .LT. max( 1, q ) )
THEN
397 ELSE IF (colmajor .AND. ldx12 .LT. max( 1, p ) )
THEN
399 ELSE IF (.NOT. colmajor .AND. ldx12 .LT. max( 1, m-q ) )
THEN
401 ELSE IF (colmajor .AND. ldx21 .LT. max( 1, m-p ) )
THEN
403 ELSE IF (.NOT. colmajor .AND. ldx21 .LT. max( 1, q ) )
THEN
405 ELSE IF (colmajor .AND. ldx22 .LT. max( 1, m-p ) )
THEN
407 ELSE IF (.NOT. colmajor .AND. ldx22 .LT. max( 1, m-q ) )
THEN
409 ELSE IF( wantu1 .AND. ldu1 .LT. p )
THEN
411 ELSE IF( wantu2 .AND. ldu2 .LT. m-p )
THEN
413 ELSE IF( wantv1t .AND. ldv1t .LT. q )
THEN
415 ELSE IF( wantv2t .AND. ldv2t .LT. m-q )
THEN
421 IF( info .EQ. 0 .AND. min( p, m-p ) .LT. min( q, m-q ) )
THEN
427 IF( defaultsigns )
THEN
432 CALL cuncsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,
433 $ q, p, x11, ldx11, x21, ldx21, x12, ldx12, x22,
434 $ ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,
435 $ u2, ldu2, work, lwork, rwork, lrwork, iwork,
443 IF( info .EQ. 0 .AND. m-q .LT. q )
THEN
444 IF( defaultsigns )
THEN
449 CALL cuncsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,
450 $ m-p, m-q, x22, ldx22, x21, ldx21, x12, ldx12, x11,
451 $ ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, v1t,
452 $ ldv1t, work, lwork, rwork, lrwork, iwork, info )
458 IF( info .EQ. 0 )
THEN
463 ib11d = iphi + max( 1, q - 1 )
464 ib11e = ib11d + max( 1, q )
465 ib12d = ib11e + max( 1, q - 1 )
466 ib12e = ib12d + max( 1, q )
467 ib21d = ib12e + max( 1, q - 1 )
468 ib21e = ib21d + max( 1, q )
469 ib22d = ib21e + max( 1, q - 1 )
470 ib22e = ib22d + max( 1, q )
471 ibbcsd = ib22e + max( 1, q - 1 )
472 CALL cbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,
473 $ theta, theta, u1, ldu1, u2, ldu2, v1t, ldv1t,
474 $ v2t, ldv2t, theta, theta, theta, theta, theta,
475 $ theta, theta, theta, rwork, -1, childinfo )
476 lbbcsdworkopt = int( rwork(1) )
477 lbbcsdworkmin = lbbcsdworkopt
478 lrworkopt = ibbcsd + lbbcsdworkopt - 1
479 lrworkmin = ibbcsd + lbbcsdworkmin - 1
485 itaup2 = itaup1 + max( 1, p )
486 itauq1 = itaup2 + max( 1, m - p )
487 itauq2 = itauq1 + max( 1, q )
488 iorgqr = itauq2 + max( 1, m - q )
489 CALL cungqr( m-q, m-q, m-q, u1, max(1,m-q), u1, work, -1,
491 lorgqrworkopt = int( work(1) )
492 lorgqrworkmin = max( 1, m - q )
493 iorglq = itauq2 + max( 1, m - q )
494 CALL cunglq( m-q, m-q, m-q, u1, max(1,m-q), u1, work, -1,
496 lorglqworkopt = int( work(1) )
497 lorglqworkmin = max( 1, m - q )
498 iorbdb = itauq2 + max( 1, m - q )
499 CALL cunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
500 $ x21, ldx21, x22, ldx22, theta, theta, u1, u2,
501 $ v1t, v2t, work, -1, childinfo )
502 lorbdbworkopt = int( work(1) )
503 lorbdbworkmin = lorbdbworkopt
504 lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,
505 $ iorbdb + lorbdbworkopt ) - 1
506 lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,
507 $ iorbdb + lorbdbworkmin ) - 1
508 lworkopt = max(lworkopt,lworkmin)
511 IF( lwork .LT. lworkmin
512 $ .AND. .NOT. ( lquery .OR. lrquery ) )
THEN
514 ELSE IF( lrwork .LT. lrworkmin
515 $ .AND. .NOT. ( lquery .OR. lrquery ) )
THEN
518 lorgqrwork = lwork - iorgqr + 1
519 lorglqwork = lwork - iorglq + 1
520 lorbdbwork = lwork - iorbdb + 1
521 lbbcsdwork = lrwork - ibbcsd + 1
527 IF( info .NE. 0 )
THEN
528 CALL xerbla(
'CUNCSD', -info )
530 ELSE IF( lquery .OR. lrquery )
THEN
536 CALL cunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,
537 $ ldx21, x22, ldx22, theta, rwork(iphi), work(itaup1),
538 $ work(itaup2), work(itauq1), work(itauq2),
539 $ work(iorbdb), lorbdbwork, childinfo )
544 IF( wantu1 .AND. p .GT. 0 )
THEN
545 CALL clacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
546 CALL cungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
549 IF( wantu2 .AND. m-p .GT. 0 )
THEN
550 CALL clacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
551 CALL cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
552 $ work(iorgqr), lorgqrwork, info )
554 IF( wantv1t .AND. q .GT. 0 )
THEN
555 CALL clacpy(
'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
562 CALL cunglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
563 $ work(iorglq), lorglqwork, info )
565 IF( wantv2t .AND. m-q .GT. 0 )
THEN
566 CALL clacpy(
'U', p, m-q, x12, ldx12, v2t, ldv2t )
567 IF( m-p .GT. q )
THEN
568 CALL clacpy(
'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
569 $ v2t(p+1,p+1), ldv2t )
572 CALL cunglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
573 $ work(iorglq), lorglqwork, info )
577 IF( wantu1 .AND. p .GT. 0 )
THEN
578 CALL clacpy(
'U', q, p, x11, ldx11, u1, ldu1 )
579 CALL cunglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),
582 IF( wantu2 .AND. m-p .GT. 0 )
THEN
583 CALL clacpy(
'U', q, m-p, x21, ldx21, u2, ldu2 )
584 CALL cunglq( m-p, m-p, q, u2, ldu2, work(itaup2),
585 $ work(iorglq), lorglqwork, info )
587 IF( wantv1t .AND. q .GT. 0 )
THEN
588 CALL clacpy(
'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
595 CALL cungqr( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
596 $ work(iorgqr), lorgqrwork, info )
598 IF( wantv2t .AND. m-q .GT. 0 )
THEN
601 CALL clacpy(
'L', m-q, p, x12, ldx12, v2t, ldv2t )
602 IF ( m .GT. p+q )
THEN
603 CALL clacpy(
'L', m-p-q, m-p-q, x22(p1,q1), ldx22,
604 $ v2t(p+1,p+1), ldv2t )
606 CALL cungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
607 $ work(iorgqr), lorgqrwork, info )
613 CALL cbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,
614 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
615 $ ldv2t, rwork(ib11d), rwork(ib11e), rwork(ib12d),
616 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
617 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
625 IF( q .GT. 0 .AND. wantu2 )
THEN
627 iwork(i) = m - p - q + i
633 CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
635 CALL clapmr( .false., m-p, m-p, u2, ldu2, iwork )
638 IF( m .GT. 0 .AND. wantv2t )
THEN
640 iwork(i) = m - p - q + i
645 IF( .NOT. colmajor )
THEN
646 CALL clapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
648 CALL clapmr( .false., m-q, m-q, v2t, ldv2t, iwork )
subroutine xerbla(srname, info)
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
subroutine clacpy(uplo, m, n, a, lda, b, ldb)
CLACPY copies all or part of one two-dimensional array to another.
subroutine clapmr(forwrd, m, n, x, ldx, k)
CLAPMR rearranges rows of a matrix as specified by a permutation vector.
subroutine clapmt(forwrd, m, n, x, ldx, k)
CLAPMT performs a forward or backward permutation of the columns of a matrix.
logical function lsame(ca, cb)
LSAME
real function sroundup_lwork(lwork)
SROUNDUP_LWORK
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
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 cunglq(m, n, k, a, lda, tau, work, lwork, info)
CUNGLQ
subroutine cungqr(m, n, k, a, lda, tau, work, lwork, info)
CUNGQR