253 SUBROUTINE cuncsd2by1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
254 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
255 $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
263 CHARACTER JOBU1, JOBU2, JOBV1T
264 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
266 INTEGER LRWORK, LRWORKMIN, LRWORKOPT
271 COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
272 $ x11(ldx11,*), x21(ldx21,*)
280 PARAMETER ( ONE = (1.0e0,0.0e0), zero = (0.0e0,0.0e0) )
283 INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
284 $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
285 $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
286 $ j, lbbcsd, lorbdb, lorglq, lorglqmin,
287 $ lorglqopt, lorgqr, lorgqrmin, lorgqropt,
288 $ lworkmin, lworkopt, r
289 LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
303 EXTERNAL LSAME, SROUNDUP_LWORK
306 INTRINSIC int, max, min
313 wantu1 = lsame( jobu1,
'Y' )
314 wantu2 = lsame( jobu2,
'Y' )
315 wantv1t = lsame( jobv1t,
'Y' )
316 lquery = ( lwork.EQ.-1 ) .OR. ( lrwork.EQ.-1 )
320 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
322 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
324 ELSE IF( ldx11 .LT. max( 1, p ) )
THEN
326 ELSE IF( ldx21 .LT. max( 1, m-p ) )
THEN
328 ELSE IF( wantu1 .AND. ldu1 .LT. max( 1, p ) )
THEN
330 ELSE IF( wantu2 .AND. ldu2 .LT. max( 1, m - p ) )
THEN
332 ELSE IF( wantv1t .AND. ldv1t .LT. max( 1, q ) )
THEN
336 r = min( p, m-p, q, m-q )
371 IF( info .EQ. 0 )
THEN
373 ib11d = iphi + max( 1, r-1 )
374 ib11e = ib11d + max( 1, r )
375 ib12d = ib11e + max( 1, r - 1 )
376 ib12e = ib12d + max( 1, r )
377 ib21d = ib12e + max( 1, r - 1 )
378 ib21e = ib21d + max( 1, r )
379 ib22d = ib21e + max( 1, r - 1 )
380 ib22e = ib22d + max( 1, r )
381 ibbcsd = ib22e + max( 1, r - 1 )
383 itaup2 = itaup1 + max( 1, p )
384 itauq1 = itaup2 + max( 1, m-p )
385 iorbdb = itauq1 + max( 1, q )
386 iorgqr = itauq1 + max( 1, q )
387 iorglq = itauq1 + max( 1, q )
393 CALL cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
394 $ dum, cdum, cdum, cdum, work, -1,
396 lorbdb = int( work(1) )
397 IF( wantu1 .AND. p .GT. 0 )
THEN
398 CALL cungqr( p, p, q, u1, ldu1, cdum, work(1), -1,
400 lorgqrmin = max( lorgqrmin, p )
401 lorgqropt = max( lorgqropt, int( work(1) ) )
403 IF( wantu2 .AND. m-p .GT. 0 )
THEN
404 CALL cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
406 lorgqrmin = max( lorgqrmin, m-p )
407 lorgqropt = max( lorgqropt, int( work(1) ) )
409 IF( wantv1t .AND. q .GT. 0 )
THEN
410 CALL cunglq( q-1, q-1, q-1, v1t, ldv1t,
411 $ cdum, work(1), -1, childinfo )
412 lorglqmin = max( lorglqmin, q-1 )
413 lorglqopt = max( lorglqopt, int( work(1) ) )
415 CALL cbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
416 $ dum(1), u1, ldu1, u2, ldu2, v1t, ldv1t, cdum,
417 $ 1, dum, dum, dum, dum, dum, dum, dum, dum,
418 $ rwork(1), -1, childinfo )
419 lbbcsd = int( rwork(1) )
420 ELSE IF( r .EQ. p )
THEN
421 CALL cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, dum,
422 $ cdum, cdum, cdum, work(1), -1, childinfo )
423 lorbdb = int( work(1) )
424 IF( wantu1 .AND. p .GT. 0 )
THEN
425 CALL cungqr( p-1, p-1, p-1, u1(2,2), ldu1, cdum, work(1),
427 lorgqrmin = max( lorgqrmin, p-1 )
428 lorgqropt = max( lorgqropt, int( work(1) ) )
430 IF( wantu2 .AND. m-p .GT. 0 )
THEN
431 CALL cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
433 lorgqrmin = max( lorgqrmin, m-p )
434 lorgqropt = max( lorgqropt, int( work(1) ) )
436 IF( wantv1t .AND. q .GT. 0 )
THEN
437 CALL cunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
439 lorglqmin = max( lorglqmin, q )
440 lorglqopt = max( lorglqopt, int( work(1) ) )
442 CALL cbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
443 $ dum, v1t, ldv1t, cdum, 1, u1, ldu1, u2, ldu2,
444 $ dum, dum, dum, dum, dum, dum, dum, dum,
445 $ rwork(1), -1, childinfo )
446 lbbcsd = int( rwork(1) )
447 ELSE IF( r .EQ. m-p )
THEN
448 CALL cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, dum,
449 $ cdum, cdum, cdum, work(1), -1, childinfo )
450 lorbdb = int( work(1) )
451 IF( wantu1 .AND. p .GT. 0 )
THEN
452 CALL cungqr( p, p, q, u1, ldu1, cdum, work(1), -1,
454 lorgqrmin = max( lorgqrmin, p )
455 lorgqropt = max( lorgqropt, int( work(1) ) )
457 IF( wantu2 .AND. m-p .GT. 0 )
THEN
458 CALL cungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2, cdum,
459 $ work(1), -1, childinfo )
460 lorgqrmin = max( lorgqrmin, m-p-1 )
461 lorgqropt = max( lorgqropt, int( work(1) ) )
463 IF( wantv1t .AND. q .GT. 0 )
THEN
464 CALL cunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
466 lorglqmin = max( lorglqmin, q )
467 lorglqopt = max( lorglqopt, int( work(1) ) )
469 CALL cbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
470 $ theta, dum, cdum, 1, v1t, ldv1t, u2, ldu2, u1,
471 $ ldu1, dum, dum, dum, dum, dum, dum, dum, dum,
472 $ rwork(1), -1, childinfo )
473 lbbcsd = int( rwork(1) )
475 CALL cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, dum,
476 $ cdum, cdum, cdum, cdum, work(1), -1, childinfo
478 lorbdb = m + int( work(1) )
479 IF( wantu1 .AND. p .GT. 0 )
THEN
480 CALL cungqr( p, p, m-q, u1, ldu1, cdum, work(1), -1,
482 lorgqrmin = max( lorgqrmin, p )
483 lorgqropt = max( lorgqropt, int( work(1) ) )
485 IF( wantu2 .AND. m-p .GT. 0 )
THEN
486 CALL cungqr( m-p, m-p, m-q, u2, ldu2, cdum, work(1), -1,
488 lorgqrmin = max( lorgqrmin, m-p )
489 lorgqropt = max( lorgqropt, int( work(1) ) )
491 IF( wantv1t .AND. q .GT. 0 )
THEN
492 CALL cunglq( q, q, q, v1t, ldv1t, cdum, work(1), -1,
494 lorglqmin = max( lorglqmin, q )
495 lorglqopt = max( lorglqopt, int( work(1) ) )
497 CALL cbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
498 $ theta, dum, u2, ldu2, u1, ldu1, cdum, 1, v1t,
499 $ ldv1t, dum, dum, dum, dum, dum, dum, dum, dum,
500 $ rwork(1), -1, childinfo )
501 lbbcsd = int( rwork(1) )
503 lrworkmin = ibbcsd+lbbcsd-1
504 lrworkopt = lrworkmin
506 lworkmin = max( iorbdb+lorbdb-1,
507 $ iorgqr+lorgqrmin-1,
508 $ iorglq+lorglqmin-1 )
509 lworkopt = max( iorbdb+lorbdb-1,
510 $ iorgqr+lorgqropt-1,
511 $ iorglq+lorglqopt-1 )
512 work(1) = sroundup_lwork(lworkopt)
513 IF( lwork .LT. lworkmin .AND. .NOT.lquery )
THEN
516 IF( lrwork .LT. lrworkmin .AND. .NOT.lquery )
THEN
520 IF( info .NE. 0 )
THEN
521 CALL xerbla(
'CUNCSD2BY1', -info )
523 ELSE IF( lquery )
THEN
526 lorgqr = lwork-iorgqr+1
527 lorglq = lwork-iorglq+1
538 CALL cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
539 $ rwork(iphi), work(itaup1), work(itaup2),
540 $ work(itauq1), work(iorbdb), lorbdb, 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),
547 $ lorgqr, childinfo )
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), lorgqr, childinfo )
554 IF( wantv1t .AND. q .GT. 0 )
THEN
560 CALL clacpy(
'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
562 CALL cunglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
563 $ work(iorglq), lorglq, childinfo )
568 CALL cbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
569 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, cdum,
570 $ 1, rwork(ib11d), rwork(ib11e), rwork(ib12d),
571 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
572 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
573 $ lrwork-ibbcsd+1, childinfo )
578 IF( q .GT. 0 .AND. wantu2 )
THEN
580 iwork(i) = m - p - q + i
585 CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
587 ELSE IF( r .EQ. p )
THEN
593 CALL cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
594 $ rwork(iphi), work(itaup1), work(itaup2),
595 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
599 IF( wantu1 .AND. p .GT. 0 )
THEN
605 CALL clacpy(
'L', p-1, p-1, x11(2,1), ldx11, u1(2,2), ldu1 )
606 CALL cungqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
607 $ work(iorgqr), lorgqr, childinfo )
609 IF( wantu2 .AND. m-p .GT. 0 )
THEN
610 CALL clacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
611 CALL cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
612 $ work(iorgqr), lorgqr, childinfo )
614 IF( wantv1t .AND. q .GT. 0 )
THEN
615 CALL clacpy(
'U', p, q, x11, ldx11, v1t, ldv1t )
616 CALL cunglq( q, q, r, v1t, ldv1t, work(itauq1),
617 $ work(iorglq), lorglq, childinfo )
622 CALL cbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
623 $ rwork(iphi), v1t, ldv1t, cdum, 1, u1, ldu1, u2,
624 $ ldu2, rwork(ib11d), rwork(ib11e), rwork(ib12d),
625 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
626 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd), lbbcsd,
632 IF( q .GT. 0 .AND. wantu2 )
THEN
634 iwork(i) = m - p - q + i
639 CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
641 ELSE IF( r .EQ. m-p )
THEN
647 CALL cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
648 $ rwork(iphi), work(itaup1), work(itaup2),
649 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
653 IF( wantu1 .AND. p .GT. 0 )
THEN
654 CALL clacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
655 CALL cungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
656 $ lorgqr, childinfo )
658 IF( wantu2 .AND. m-p .GT. 0 )
THEN
664 CALL clacpy(
'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
666 CALL cungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
667 $ work(itaup2), work(iorgqr), lorgqr, childinfo )
669 IF( wantv1t .AND. q .GT. 0 )
THEN
670 CALL clacpy(
'U', m-p, q, x21, ldx21, v1t, ldv1t )
671 CALL cunglq( q, q, r, v1t, ldv1t, work(itauq1),
672 $ work(iorglq), lorglq, childinfo )
677 CALL cbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
678 $ theta, rwork(iphi), cdum, 1, v1t, ldv1t, u2, ldu2,
679 $ u1, ldu1, rwork(ib11d), rwork(ib11e),
680 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
681 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
682 $ rwork(ibbcsd), lbbcsd, childinfo )
695 CALL clapmt( .false., p, q, u1, ldu1, iwork )
698 CALL clapmr( .false., q, q, v1t, ldv1t, iwork )
707 CALL cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
708 $ rwork(iphi), work(itaup1), work(itaup2),
709 $ work(itauq1), work(iorbdb), work(iorbdb+m),
710 $ lorbdb-m, childinfo )
715 IF( wantu2 .AND. m-p .GT. 0 )
THEN
716 CALL ccopy( m-p, work(iorbdb+p), 1, u2, 1 )
718 IF( wantu1 .AND. p .GT. 0 )
THEN
719 CALL ccopy( p, work(iorbdb), 1, u1, 1 )
723 CALL clacpy(
'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
725 CALL cungqr( p, p, m-q, u1, ldu1, work(itaup1),
726 $ work(iorgqr), lorgqr, childinfo )
728 IF( wantu2 .AND. m-p .GT. 0 )
THEN
732 CALL clacpy(
'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
734 CALL cungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
735 $ work(iorgqr), lorgqr, childinfo )
737 IF( wantv1t .AND. q .GT. 0 )
THEN
738 CALL clacpy(
'U', m-q, q, x21, ldx21, v1t, ldv1t )
739 CALL clacpy(
'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,
740 $ v1t(m-q+1,m-q+1), ldv1t )
741 CALL clacpy(
'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
742 $ v1t(p+1,p+1), ldv1t )
743 CALL cunglq( q, q, q, v1t, ldv1t, work(itauq1),
744 $ work(iorglq), lorglq, childinfo )
749 CALL cbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
750 $ theta, rwork(iphi), u2, ldu2, u1, ldu1, cdum, 1,
751 $ v1t, ldv1t, rwork(ib11d), rwork(ib11e),
752 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
753 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
754 $ rwork(ibbcsd), lbbcsd, childinfo )
767 CALL clapmt( .false., p, p, u1, ldu1, iwork )
770 CALL clapmr( .false., p, q, v1t, ldv1t, 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 ccopy(n, cx, incx, cy, incy)
CCOPY
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.
subroutine cunbdb1(m, p, q, x11, ldx11, x21, ldx21, theta, phi, taup1, taup2, tauq1, work, lwork, info)
CUNBDB1
subroutine cunbdb2(m, p, q, x11, ldx11, x21, ldx21, theta, phi, taup1, taup2, tauq1, work, lwork, info)
CUNBDB2
subroutine cunbdb3(m, p, q, x11, ldx11, x21, ldx21, theta, phi, taup1, taup2, tauq1, work, lwork, info)
CUNBDB3
subroutine cunbdb4(m, p, q, x11, ldx11, x21, ldx21, theta, phi, taup1, taup2, tauq1, phantom, work, lwork, info)
CUNBDB4
subroutine cuncsd2by1(jobu1, jobu2, jobv1t, m, p, q, x11, ldx11, x21, ldx21, theta, u1, ldu1, u2, ldu2, v1t, ldv1t, work, lwork, rwork, lrwork, iwork, info)
CUNCSD2BY1
subroutine cunglq(m, n, k, a, lda, tau, work, lwork, info)
CUNGLQ
subroutine cungqr(m, n, k, a, lda, tau, work, lwork, info)
CUNGQR