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 xerbla(srname, info)
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 zlapmr(forwrd, m, n, x, ldx, k)
ZLAPMR rearranges rows of a matrix as specified by a permutation vector.
subroutine zlapmt(forwrd, m, n, x, ldx, k)
ZLAPMT performs a forward or backward permutation of the columns of a matrix.
logical function lsame(ca, cb)
LSAME
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
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 zunglq(m, n, k, a, lda, tau, work, lwork, info)
ZUNGLQ
subroutine zungqr(m, n, k, a, lda, tau, work, lwork, info)
ZUNGQR