253 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
254 $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
262 CHARACTER JOBU1, JOBU2, JOBV1T
263 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
265 INTEGER LRWORK, LRWORKMIN, LRWORKOPT
270 COMPLEX U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
271 $ X11(LDX11,*), X21(LDX21,*)
279 PARAMETER ( ONE = (1.0e0,0.0e0), zero = (0.0e0,0.0e0) )
282 INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
283 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
284 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
285 $ j, lbbcsd, lorbdb, lorglq, lorglqmin,
286 $ lorglqopt, lorgqr, lorgqrmin, lorgqropt,
287 $ lworkmin, lworkopt, r
288 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,
417 $ dum(1), u1, ldu1, u2, ldu2, v1t, ldv1t, cdum,
418 $ 1, dum, dum, dum, dum, dum, dum, dum, dum,
419 $ rwork(1), -1, childinfo )
420 lbbcsd = int( rwork(1) )
421 ELSE IF( r .EQ. p )
THEN
422 CALL cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
424 $ cdum, cdum, cdum, work(1), -1, childinfo )
425 lorbdb = int( work(1) )
426 IF( wantu1 .AND. p .GT. 0 )
THEN
427 CALL cungqr( p-1, p-1, p-1, u1(2,2), ldu1, cdum,
430 lorgqrmin = max( lorgqrmin, p-1 )
431 lorgqropt = max( lorgqropt, int( work(1) ) )
433 IF( wantu2 .AND. m-p .GT. 0 )
THEN
434 CALL cungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
436 lorgqrmin = max( lorgqrmin, m-p )
437 lorgqropt = max( lorgqropt, int( work(1) ) )
439 IF( wantv1t .AND. q .GT. 0 )
THEN
440 CALL cunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
442 lorglqmin = max( lorglqmin, q )
443 lorglqopt = max( lorglqopt, int( work(1) ) )
445 CALL cbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p,
447 $ dum, v1t, ldv1t, cdum, 1, u1, ldu1, u2, ldu2,
448 $ dum, dum, dum, dum, dum, dum, dum, dum,
449 $ rwork(1), -1, childinfo )
450 lbbcsd = int( rwork(1) )
451 ELSE IF( r .EQ. m-p )
THEN
452 CALL cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
454 $ cdum, cdum, cdum, work(1), -1, childinfo )
455 lorbdb = int( work(1) )
456 IF( wantu1 .AND. p .GT. 0 )
THEN
457 CALL cungqr( p, p, q, u1, ldu1, cdum, work(1), -1,
459 lorgqrmin = max( lorgqrmin, p )
460 lorgqropt = max( lorgqropt, int( work(1) ) )
462 IF( wantu2 .AND. m-p .GT. 0 )
THEN
463 CALL cungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2, cdum,
464 $ work(1), -1, childinfo )
465 lorgqrmin = max( lorgqrmin, m-p-1 )
466 lorgqropt = max( lorgqropt, int( work(1) ) )
468 IF( wantv1t .AND. q .GT. 0 )
THEN
469 CALL cunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
471 lorglqmin = max( lorglqmin, q )
472 lorglqopt = max( lorglqopt, int( work(1) ) )
474 CALL cbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
475 $ theta, dum, cdum, 1, v1t, ldv1t, u2, ldu2, u1,
476 $ ldu1, dum, dum, dum, dum, dum, dum, dum, dum,
477 $ rwork(1), -1, childinfo )
478 lbbcsd = int( rwork(1) )
480 CALL cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
482 $ cdum, cdum, cdum, cdum, work(1), -1, childinfo
484 lorbdb = m + int( work(1) )
485 IF( wantu1 .AND. p .GT. 0 )
THEN
486 CALL cungqr( p, p, m-q, u1, ldu1, cdum, work(1), -1,
488 lorgqrmin = max( lorgqrmin, p )
489 lorgqropt = max( lorgqropt, int( work(1) ) )
491 IF( wantu2 .AND. m-p .GT. 0 )
THEN
492 CALL cungqr( m-p, m-p, m-q, u2, ldu2, cdum, work(1),
495 lorgqrmin = max( lorgqrmin, m-p )
496 lorgqropt = max( lorgqropt, int( work(1) ) )
498 IF( wantv1t .AND. q .GT. 0 )
THEN
499 CALL cunglq( q, q, q, v1t, ldv1t, cdum, work(1), -1,
501 lorglqmin = max( lorglqmin, q )
502 lorglqopt = max( lorglqopt, int( work(1) ) )
504 CALL cbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
505 $ theta, dum, u2, ldu2, u1, ldu1, cdum, 1, v1t,
506 $ ldv1t, dum, dum, dum, dum, dum, dum, dum, dum,
507 $ rwork(1), -1, childinfo )
508 lbbcsd = int( rwork(1) )
510 lrworkmin = ibbcsd+lbbcsd-1
511 lrworkopt = lrworkmin
512 rwork(1) = real( lrworkopt )
513 lworkmin = max( iorbdb+lorbdb-1,
514 $ iorgqr+lorgqrmin-1,
515 $ iorglq+lorglqmin-1 )
516 lworkopt = max( iorbdb+lorbdb-1,
517 $ iorgqr+lorgqropt-1,
518 $ iorglq+lorglqopt-1 )
519 work(1) = sroundup_lwork(lworkopt)
520 IF( lwork .LT. lworkmin .AND. .NOT.lquery )
THEN
523 IF( lrwork .LT. lrworkmin .AND. .NOT.lquery )
THEN
527 IF( info .NE. 0 )
THEN
528 CALL xerbla(
'CUNCSD2BY1', -info )
530 ELSE IF( lquery )
THEN
533 lorgqr = lwork-iorgqr+1
534 lorglq = lwork-iorglq+1
545 CALL cunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
546 $ rwork(iphi), work(itaup1), work(itaup2),
547 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
551 IF( wantu1 .AND. p .GT. 0 )
THEN
552 CALL clacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
553 CALL cungqr( p, p, q, u1, ldu1, work(itaup1),
555 $ lorgqr, childinfo )
557 IF( wantu2 .AND. m-p .GT. 0 )
THEN
558 CALL clacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
559 CALL cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
560 $ work(iorgqr), lorgqr, childinfo )
562 IF( wantv1t .AND. q .GT. 0 )
THEN
568 CALL clacpy(
'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
570 CALL cunglq( q-1, q-1, q-1, v1t(2,2), ldv1t,
572 $ work(iorglq), lorglq, childinfo )
577 CALL cbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
578 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, cdum,
579 $ 1, rwork(ib11d), rwork(ib11e), rwork(ib12d),
580 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
581 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
582 $ lrwork-ibbcsd+1, childinfo )
587 IF( q .GT. 0 .AND. wantu2 )
THEN
589 iwork(i) = m - p - q + i
594 CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
596 ELSE IF( r .EQ. p )
THEN
602 CALL cunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
603 $ rwork(iphi), work(itaup1), work(itaup2),
604 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
608 IF( wantu1 .AND. p .GT. 0 )
THEN
614 CALL clacpy(
'L', p-1, p-1, x11(2,1), ldx11, u1(2,2),
616 CALL cungqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
617 $ work(iorgqr), lorgqr, childinfo )
619 IF( wantu2 .AND. m-p .GT. 0 )
THEN
620 CALL clacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
621 CALL cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
622 $ work(iorgqr), lorgqr, childinfo )
624 IF( wantv1t .AND. q .GT. 0 )
THEN
625 CALL clacpy(
'U', p, q, x11, ldx11, v1t, ldv1t )
626 CALL cunglq( q, q, r, v1t, ldv1t, work(itauq1),
627 $ work(iorglq), lorglq, childinfo )
632 CALL cbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
633 $ rwork(iphi), v1t, ldv1t, cdum, 1, u1, ldu1, u2,
634 $ ldu2, rwork(ib11d), rwork(ib11e), rwork(ib12d),
635 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
636 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd), lbbcsd,
642 IF( q .GT. 0 .AND. wantu2 )
THEN
644 iwork(i) = m - p - q + i
649 CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
651 ELSE IF( r .EQ. m-p )
THEN
657 CALL cunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
658 $ rwork(iphi), work(itaup1), work(itaup2),
659 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
663 IF( wantu1 .AND. p .GT. 0 )
THEN
664 CALL clacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
665 CALL cungqr( p, p, q, u1, ldu1, work(itaup1),
667 $ lorgqr, childinfo )
669 IF( wantu2 .AND. m-p .GT. 0 )
THEN
675 CALL clacpy(
'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
677 CALL cungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
678 $ work(itaup2), work(iorgqr), lorgqr, childinfo )
680 IF( wantv1t .AND. q .GT. 0 )
THEN
681 CALL clacpy(
'U', m-p, q, x21, ldx21, v1t, ldv1t )
682 CALL cunglq( q, q, r, v1t, ldv1t, work(itauq1),
683 $ work(iorglq), lorglq, childinfo )
688 CALL cbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
689 $ theta, rwork(iphi), cdum, 1, v1t, ldv1t, u2, ldu2,
690 $ u1, ldu1, rwork(ib11d), rwork(ib11e),
691 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
692 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
693 $ rwork(ibbcsd), lbbcsd, childinfo )
706 CALL clapmt( .false., p, q, u1, ldu1, iwork )
709 CALL clapmr( .false., q, q, v1t, ldv1t, iwork )
718 CALL cunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
719 $ rwork(iphi), work(itaup1), work(itaup2),
720 $ work(itauq1), work(iorbdb), work(iorbdb+m),
721 $ lorbdb-m, childinfo )
726 IF( wantu2 .AND. m-p .GT. 0 )
THEN
727 CALL ccopy( m-p, work(iorbdb+p), 1, u2, 1 )
729 IF( wantu1 .AND. p .GT. 0 )
THEN
730 CALL ccopy( p, work(iorbdb), 1, u1, 1 )
734 CALL clacpy(
'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
736 CALL cungqr( p, p, m-q, u1, ldu1, work(itaup1),
737 $ work(iorgqr), lorgqr, childinfo )
739 IF( wantu2 .AND. m-p .GT. 0 )
THEN
743 CALL clacpy(
'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
745 CALL cungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
746 $ work(iorgqr), lorgqr, childinfo )
748 IF( wantv1t .AND. q .GT. 0 )
THEN
749 CALL clacpy(
'U', m-q, q, x21, ldx21, v1t, ldv1t )
750 CALL clacpy(
'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1),
752 $ v1t(m-q+1,m-q+1), ldv1t )
753 CALL clacpy(
'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
754 $ v1t(p+1,p+1), ldv1t )
755 CALL cunglq( q, q, q, v1t, ldv1t, work(itauq1),
756 $ work(iorglq), lorglq, childinfo )
761 CALL cbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
762 $ theta, rwork(iphi), u2, ldu2, u1, ldu1, cdum, 1,
763 $ v1t, ldv1t, rwork(ib11d), rwork(ib11e),
764 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
765 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
766 $ rwork(ibbcsd), lbbcsd, childinfo )
779 CALL clapmt( .false., p, p, u1, ldu1, iwork )
782 CALL clapmr( .false., p, q, v1t, ldv1t, iwork )