252 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
253 $ LDV1T, WORK, LWORK, RWORK, LRWORK, IWORK,
261 CHARACTER JOBU1, JOBU2, JOBV1T
262 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
264 INTEGER LRWORK, LRWORKMIN, LRWORKOPT
267 DOUBLE PRECISION RWORK(*)
268 DOUBLE PRECISION THETA(*)
269 COMPLEX*16 U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
270 $ X11(LDX11,*), X21(LDX21,*)
278 PARAMETER ( ONE = (1.0d0,0.0d0), zero = (0.0d0,0.0d0) )
281 INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
282 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
283 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
284 $ j, lbbcsd, lorbdb, lorglq, lorglqmin,
285 $ lorglqopt, lorgqr, lorgqrmin, lorgqropt,
286 $ lworkmin, lworkopt, r
287 LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
290 DOUBLE PRECISION DUM( 1 )
291 COMPLEX*16 CDUM( 1, 1 )
304 INTRINSIC int, max, min
311 wantu1 = lsame( jobu1,
'Y' )
312 wantu2 = lsame( jobu2,
'Y' )
313 wantv1t = lsame( jobv1t,
'Y' )
314 lquery = ( lwork.EQ.-1 ) .OR. ( lrwork.EQ.-1 )
318 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
320 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
322 ELSE IF( ldx11 .LT. max( 1, p ) )
THEN
324 ELSE IF( ldx21 .LT. max( 1, m-p ) )
THEN
326 ELSE IF( wantu1 .AND. ldu1 .LT. max( 1, p ) )
THEN
328 ELSE IF( wantu2 .AND. ldu2 .LT. max( 1, m - p ) )
THEN
330 ELSE IF( wantv1t .AND. ldv1t .LT. max( 1, q ) )
THEN
334 r = min( p, m-p, q, m-q )
369 IF( info .EQ. 0 )
THEN
371 ib11d = iphi + max( 1, r-1 )
372 ib11e = ib11d + max( 1, r )
373 ib12d = ib11e + max( 1, r - 1 )
374 ib12e = ib12d + max( 1, r )
375 ib21d = ib12e + max( 1, r - 1 )
376 ib21e = ib21d + max( 1, r )
377 ib22d = ib21e + max( 1, r - 1 )
378 ib22e = ib22d + max( 1, r )
379 ibbcsd = ib22e + max( 1, r - 1 )
381 itaup2 = itaup1 + max( 1, p )
382 itauq1 = itaup2 + max( 1, m-p )
383 iorbdb = itauq1 + max( 1, q )
384 iorgqr = itauq1 + max( 1, q )
385 iorglq = itauq1 + max( 1, q )
391 CALL zunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
393 $ cdum, cdum, cdum, work, -1, childinfo )
394 lorbdb = int( work(1) )
395 IF( wantu1 .AND. p .GT. 0 )
THEN
396 CALL zungqr( p, p, q, u1, ldu1, cdum, work(1), -1,
398 lorgqrmin = max( lorgqrmin, p )
399 lorgqropt = max( lorgqropt, int( work(1) ) )
401 IF( wantu2 .AND. m-p .GT. 0 )
THEN
402 CALL zungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
404 lorgqrmin = max( lorgqrmin, m-p )
405 lorgqropt = max( lorgqropt, int( work(1) ) )
407 IF( wantv1t .AND. q .GT. 0 )
THEN
408 CALL zunglq( q-1, q-1, q-1, v1t, ldv1t,
409 $ cdum, work(1), -1, childinfo )
410 lorglqmin = max( lorglqmin, q-1 )
411 lorglqopt = max( lorglqopt, int( work(1) ) )
413 CALL zbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q,
415 $ dum, u1, ldu1, u2, ldu2, v1t, ldv1t, cdum, 1,
416 $ dum, dum, dum, dum, dum, dum, dum, dum,
417 $ rwork(1), -1, childinfo )
418 lbbcsd = int( rwork(1) )
419 ELSE IF( r .EQ. p )
THEN
420 CALL zunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
422 $ cdum, cdum, cdum, work(1), -1, childinfo )
423 lorbdb = int( work(1) )
424 IF( wantu1 .AND. p .GT. 0 )
THEN
425 CALL zungqr( p-1, p-1, p-1, u1(2,2), ldu1, cdum,
428 lorgqrmin = max( lorgqrmin, p-1 )
429 lorgqropt = max( lorgqropt, int( work(1) ) )
431 IF( wantu2 .AND. m-p .GT. 0 )
THEN
432 CALL zungqr( m-p, m-p, q, u2, ldu2, cdum, work(1), -1,
434 lorgqrmin = max( lorgqrmin, m-p )
435 lorgqropt = max( lorgqropt, int( work(1) ) )
437 IF( wantv1t .AND. q .GT. 0 )
THEN
438 CALL zunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
440 lorglqmin = max( lorglqmin, q )
441 lorglqopt = max( lorglqopt, int( work(1) ) )
443 CALL zbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p,
445 $ dum, v1t, ldv1t, cdum, 1, u1, ldu1, u2, ldu2,
446 $ dum, dum, dum, dum, dum, dum, dum, dum,
447 $ rwork(1), -1, childinfo )
448 lbbcsd = int( rwork(1) )
449 ELSE IF( r .EQ. m-p )
THEN
450 CALL zunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
452 $ cdum, cdum, cdum, work(1), -1, childinfo )
453 lorbdb = int( work(1) )
454 IF( wantu1 .AND. p .GT. 0 )
THEN
455 CALL zungqr( p, p, q, u1, ldu1, cdum, work(1), -1,
457 lorgqrmin = max( lorgqrmin, p )
458 lorgqropt = max( lorgqropt, int( work(1) ) )
460 IF( wantu2 .AND. m-p .GT. 0 )
THEN
461 CALL zungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2, cdum,
462 $ work(1), -1, childinfo )
463 lorgqrmin = max( lorgqrmin, m-p-1 )
464 lorgqropt = max( lorgqropt, int( work(1) ) )
466 IF( wantv1t .AND. q .GT. 0 )
THEN
467 CALL zunglq( q, q, r, v1t, ldv1t, cdum, work(1), -1,
469 lorglqmin = max( lorglqmin, q )
470 lorglqopt = max( lorglqopt, int( work(1) ) )
472 CALL zbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
473 $ theta, dum, cdum, 1, v1t, ldv1t, u2, ldu2, u1,
474 $ ldu1, dum, dum, dum, dum, dum, dum, dum, dum,
475 $ rwork(1), -1, childinfo )
476 lbbcsd = int( rwork(1) )
478 CALL zunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
480 $ cdum, cdum, cdum, cdum, work(1), -1, childinfo
482 lorbdb = m + int( work(1) )
483 IF( wantu1 .AND. p .GT. 0 )
THEN
484 CALL zungqr( p, p, m-q, u1, ldu1, cdum, work(1), -1,
486 lorgqrmin = max( lorgqrmin, p )
487 lorgqropt = max( lorgqropt, int( work(1) ) )
489 IF( wantu2 .AND. m-p .GT. 0 )
THEN
490 CALL zungqr( m-p, m-p, m-q, u2, ldu2, cdum, work(1),
493 lorgqrmin = max( lorgqrmin, m-p )
494 lorgqropt = max( lorgqropt, int( work(1) ) )
496 IF( wantv1t .AND. q .GT. 0 )
THEN
497 CALL zunglq( q, q, q, v1t, ldv1t, cdum, work(1), -1,
499 lorglqmin = max( lorglqmin, q )
500 lorglqopt = max( lorglqopt, int( work(1) ) )
502 CALL zbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
503 $ theta, dum, u2, ldu2, u1, ldu1, cdum, 1, v1t,
504 $ ldv1t, dum, dum, dum, dum, dum, dum, dum, dum,
505 $ rwork(1), -1, childinfo )
506 lbbcsd = int( rwork(1) )
508 lrworkmin = ibbcsd+lbbcsd-1
509 lrworkopt = lrworkmin
511 lworkmin = max( iorbdb+lorbdb-1,
512 $ iorgqr+lorgqrmin-1,
513 $ iorglq+lorglqmin-1 )
514 lworkopt = max( iorbdb+lorbdb-1,
515 $ iorgqr+lorgqropt-1,
516 $ iorglq+lorglqopt-1 )
518 IF( lwork .LT. lworkmin .AND. .NOT.lquery )
THEN
521 IF( lrwork .LT. lrworkmin .AND. .NOT.lquery )
THEN
525 IF( info .NE. 0 )
THEN
526 CALL xerbla(
'ZUNCSD2BY1', -info )
528 ELSE IF( lquery )
THEN
531 lorgqr = lwork-iorgqr+1
532 lorglq = lwork-iorglq+1
543 CALL zunbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
544 $ rwork(iphi), work(itaup1), work(itaup2),
545 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
549 IF( wantu1 .AND. p .GT. 0 )
THEN
550 CALL zlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
551 CALL zungqr( p, p, q, u1, ldu1, work(itaup1),
553 $ lorgqr, childinfo )
555 IF( wantu2 .AND. m-p .GT. 0 )
THEN
556 CALL zlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
557 CALL zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
558 $ work(iorgqr), lorgqr, childinfo )
560 IF( wantv1t .AND. q .GT. 0 )
THEN
566 CALL zlacpy(
'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
568 CALL zunglq( q-1, q-1, q-1, v1t(2,2), ldv1t,
570 $ work(iorglq), lorglq, childinfo )
575 CALL zbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
576 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, cdum,
577 $ 1, rwork(ib11d), rwork(ib11e), rwork(ib12d),
578 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
579 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
580 $ lrwork-ibbcsd+1, childinfo )
585 IF( q .GT. 0 .AND. wantu2 )
THEN
587 iwork(i) = m - p - q + i
592 CALL zlapmt( .false., m-p, m-p, u2, ldu2, iwork )
594 ELSE IF( r .EQ. p )
THEN
600 CALL zunbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
601 $ rwork(iphi), work(itaup1), work(itaup2),
602 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
606 IF( wantu1 .AND. p .GT. 0 )
THEN
612 CALL zlacpy(
'L', p-1, p-1, x11(2,1), ldx11, u1(2,2),
614 CALL zungqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
615 $ work(iorgqr), lorgqr, childinfo )
617 IF( wantu2 .AND. m-p .GT. 0 )
THEN
618 CALL zlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
619 CALL zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
620 $ work(iorgqr), lorgqr, childinfo )
622 IF( wantv1t .AND. q .GT. 0 )
THEN
623 CALL zlacpy(
'U', p, q, x11, ldx11, v1t, ldv1t )
624 CALL zunglq( q, q, r, v1t, ldv1t, work(itauq1),
625 $ work(iorglq), lorglq, childinfo )
630 CALL zbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
631 $ rwork(iphi), v1t, ldv1t, cdum, 1, u1, ldu1, u2,
632 $ ldu2, rwork(ib11d), rwork(ib11e), rwork(ib12d),
633 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
634 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd), lbbcsd,
640 IF( q .GT. 0 .AND. wantu2 )
THEN
642 iwork(i) = m - p - q + i
647 CALL zlapmt( .false., m-p, m-p, u2, ldu2, iwork )
649 ELSE IF( r .EQ. m-p )
THEN
655 CALL zunbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
656 $ rwork(iphi), work(itaup1), work(itaup2),
657 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
661 IF( wantu1 .AND. p .GT. 0 )
THEN
662 CALL zlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
663 CALL zungqr( p, p, q, u1, ldu1, work(itaup1),
665 $ lorgqr, childinfo )
667 IF( wantu2 .AND. m-p .GT. 0 )
THEN
673 CALL zlacpy(
'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
675 CALL zungqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
676 $ work(itaup2), work(iorgqr), lorgqr, childinfo )
678 IF( wantv1t .AND. q .GT. 0 )
THEN
679 CALL zlacpy(
'U', m-p, q, x21, ldx21, v1t, ldv1t )
680 CALL zunglq( q, q, r, v1t, ldv1t, work(itauq1),
681 $ work(iorglq), lorglq, childinfo )
686 CALL zbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
687 $ theta, rwork(iphi), cdum, 1, v1t, ldv1t, u2, ldu2,
688 $ u1, ldu1, rwork(ib11d), rwork(ib11e),
689 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
690 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
691 $ rwork(ibbcsd), lbbcsd, childinfo )
704 CALL zlapmt( .false., p, q, u1, ldu1, iwork )
707 CALL zlapmr( .false., q, q, v1t, ldv1t, iwork )
716 CALL zunbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
717 $ rwork(iphi), work(itaup1), work(itaup2),
718 $ work(itauq1), work(iorbdb), work(iorbdb+m),
719 $ lorbdb-m, childinfo )
723 IF( wantu2 .AND. m-p .GT. 0 )
THEN
724 CALL zcopy( m-p, work(iorbdb+p), 1, u2, 1 )
726 IF( wantu1 .AND. p .GT. 0 )
THEN
727 CALL zcopy( p, work(iorbdb), 1, u1, 1 )
731 CALL zlacpy(
'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
733 CALL zungqr( p, p, m-q, u1, ldu1, work(itaup1),
734 $ work(iorgqr), lorgqr, childinfo )
736 IF( wantu2 .AND. m-p .GT. 0 )
THEN
740 CALL zlacpy(
'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
742 CALL zungqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
743 $ work(iorgqr), lorgqr, childinfo )
745 IF( wantv1t .AND. q .GT. 0 )
THEN
746 CALL zlacpy(
'U', m-q, q, x21, ldx21, v1t, ldv1t )
747 CALL zlacpy(
'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1),
749 $ v1t(m-q+1,m-q+1), ldv1t )
750 CALL zlacpy(
'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
751 $ v1t(p+1,p+1), ldv1t )
752 CALL zunglq( q, q, q, v1t, ldv1t, work(itauq1),
753 $ work(iorglq), lorglq, childinfo )
758 CALL zbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
759 $ theta, rwork(iphi), u2, ldu2, u1, ldu1, cdum, 1,
760 $ v1t, ldv1t, rwork(ib11d), rwork(ib11e),
761 $ rwork(ib12d), rwork(ib12e), rwork(ib21d),
762 $ rwork(ib21e), rwork(ib22d), rwork(ib22e),
763 $ rwork(ibbcsd), lbbcsd, childinfo )
776 CALL zlapmt( .false., p, p, u1, ldu1, iwork )
779 CALL zlapmr( .false., p, q, v1t, ldv1t, iwork )