312 RECURSIVE SUBROUTINE cuncsd( JOBU1, JOBU2, JOBV1T, JOBV2T,
314 $ SIGNS, M, P, Q, X11, LDX11, X12,
315 $ LDX12, X21, LDX21, X22, LDX22, THETA,
316 $ U1, LDU1, U2, LDU2, V1T, LDV1T, V2T,
317 $ LDV2T, WORK, LWORK, RWORK, LRWORK,
325 CHARACTER jobu1, jobu2, jobv1t, jobv2t, signs, trans
326 INTEGER info, ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12,
327 $ ldx21, ldx22, lrwork, lwork, m, p, q
333 COMPLEX u1( ldu1, * ), u2( ldu2, * ), v1t( ldv1t, * ),
334 $ v2t( ldv2t, * ), work( * ), x11( ldx11, * ),
335 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
343 PARAMETER ( one = (1.0e0,0.0e0),
344 $ zero = (0.0e0,0.0e0) )
347 CHARACTER transt, signst
348 INTEGER childinfo, i, ib11d, ib11e, ib12d, ib12e,
349 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
350 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
351 $ itauq2, j, lbbcsdwork, lbbcsdworkmin,
352 $ lbbcsdworkopt, lorbdbwork, lorbdbworkmin,
353 $ lorbdbworkopt, lorglqwork, lorglqworkmin,
354 $ lorglqworkopt, lorgqrwork, lorgqrworkmin,
355 $ lorgqrworkopt, lworkmin, lworkopt, p1, q1
356 LOGICAL colmajor, defaultsigns, lquery, wantu1, wantu2,
358 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,
434 $ q, p, x11, ldx11, x21, ldx21, x12, ldx12, x22,
435 $ ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,
436 $ u2, ldu2, work, lwork, rwork, lrwork, iwork,
444 IF( info .EQ. 0 .AND. m-q .LT. q )
THEN
445 IF( defaultsigns )
THEN
450 CALL cuncsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,
451 $ m-p, m-q, x22, ldx22, x21, ldx21, x12, ldx12, x11,
452 $ ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, v1t,
453 $ ldv1t, work, lwork, rwork, lrwork, iwork, info )
459 IF( info .EQ. 0 )
THEN
464 ib11d = iphi + max( 1, q - 1 )
465 ib11e = ib11d + max( 1, q )
466 ib12d = ib11e + max( 1, q - 1 )
467 ib12e = ib12d + max( 1, q )
468 ib21d = ib12e + max( 1, q - 1 )
469 ib21e = ib21d + max( 1, q )
470 ib22d = ib21e + max( 1, q - 1 )
471 ib22e = ib22d + max( 1, q )
472 ibbcsd = ib22e + max( 1, q - 1 )
473 CALL cbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,
474 $ theta, theta, u1, ldu1, u2, ldu2, v1t, ldv1t,
475 $ v2t, ldv2t, theta, theta, theta, theta, theta,
476 $ theta, theta, theta, rwork, -1, childinfo )
477 lbbcsdworkopt = int( rwork(1) )
478 lbbcsdworkmin = lbbcsdworkopt
479 lrworkopt = ibbcsd + lbbcsdworkopt - 1
480 lrworkmin = ibbcsd + lbbcsdworkmin - 1
481 rwork(1) = real( lrworkopt )
486 itaup2 = itaup1 + max( 1, p )
487 itauq1 = itaup2 + max( 1, m - p )
488 itauq2 = itauq1 + max( 1, q )
489 iorgqr = itauq2 + max( 1, m - q )
490 CALL cungqr( m-q, m-q, m-q, u1, max(1,m-q), u1, work, -1,
492 lorgqrworkopt = int( work(1) )
493 lorgqrworkmin = max( 1, m - q )
494 iorglq = itauq2 + max( 1, m - q )
495 CALL cunglq( m-q, m-q, m-q, u1, max(1,m-q), u1, work, -1,
497 lorglqworkopt = int( work(1) )
498 lorglqworkmin = max( 1, m - q )
499 iorbdb = itauq2 + max( 1, m - q )
500 CALL cunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
501 $ x21, ldx21, x22, ldx22, theta, theta, u1, u2,
502 $ v1t, v2t, work, -1, childinfo )
503 lorbdbworkopt = int( work(1) )
504 lorbdbworkmin = lorbdbworkopt
505 lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,
506 $ iorbdb + lorbdbworkopt ) - 1
507 lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,
508 $ iorbdb + lorbdbworkmin ) - 1
509 lworkopt = max(lworkopt,lworkmin)
512 IF( lwork .LT. lworkmin
513 $ .AND. .NOT. ( lquery .OR. lrquery ) )
THEN
515 ELSE IF( lrwork .LT. lrworkmin
516 $ .AND. .NOT. ( lquery .OR. lrquery ) )
THEN
519 lorgqrwork = lwork - iorgqr + 1
520 lorglqwork = lwork - iorglq + 1
521 lorbdbwork = lwork - iorbdb + 1
522 lbbcsdwork = lrwork - ibbcsd + 1
528 IF( info .NE. 0 )
THEN
529 CALL xerbla(
'CUNCSD', -info )
531 ELSE IF( lquery .OR. lrquery )
THEN
537 CALL cunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
539 $ ldx21, x22, ldx22, theta, rwork(iphi), work(itaup1),
540 $ work(itaup2), work(itauq1), work(itauq2),
541 $ work(iorbdb), lorbdbwork, childinfo )
546 IF( wantu1 .AND. p .GT. 0 )
THEN
547 CALL clacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
548 CALL cungqr( p, p, q, u1, ldu1, work(itaup1),
552 IF( wantu2 .AND. m-p .GT. 0 )
THEN
553 CALL clacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
554 CALL cungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
555 $ work(iorgqr), lorgqrwork, info )
557 IF( wantv1t .AND. q .GT. 0 )
THEN
558 CALL clacpy(
'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
565 CALL cunglq( q-1, q-1, q-1, v1t(2,2), ldv1t,
567 $ work(iorglq), lorglqwork, info )
569 IF( wantv2t .AND. m-q .GT. 0 )
THEN
570 CALL clacpy(
'U', p, m-q, x12, ldx12, v2t, ldv2t )
571 IF( m-p .GT. q )
THEN
572 CALL clacpy(
'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
573 $ v2t(p+1,p+1), ldv2t )
576 CALL cunglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
577 $ work(iorglq), lorglqwork, info )
581 IF( wantu1 .AND. p .GT. 0 )
THEN
582 CALL clacpy(
'U', q, p, x11, ldx11, u1, ldu1 )
583 CALL cunglq( p, p, q, u1, ldu1, work(itaup1),
587 IF( wantu2 .AND. m-p .GT. 0 )
THEN
588 CALL clacpy(
'U', q, m-p, x21, ldx21, u2, ldu2 )
589 CALL cunglq( m-p, m-p, q, u2, ldu2, work(itaup2),
590 $ work(iorglq), lorglqwork, info )
592 IF( wantv1t .AND. q .GT. 0 )
THEN
593 CALL clacpy(
'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
600 CALL cungqr( q-1, q-1, q-1, v1t(2,2), ldv1t,
602 $ work(iorgqr), lorgqrwork, info )
604 IF( wantv2t .AND. m-q .GT. 0 )
THEN
607 CALL clacpy(
'L', m-q, p, x12, ldx12, v2t, ldv2t )
608 IF ( m .GT. p+q )
THEN
609 CALL clacpy(
'L', m-p-q, m-p-q, x22(p1,q1), ldx22,
610 $ v2t(p+1,p+1), ldv2t )
612 CALL cungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
613 $ work(iorgqr), lorgqrwork, info )
619 CALL cbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,
621 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
622 $ ldv2t, rwork(ib11d), rwork(ib11e), rwork(ib12d),
623 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
624 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
632 IF( q .GT. 0 .AND. wantu2 )
THEN
634 iwork(i) = m - p - q + i
640 CALL clapmt( .false., m-p, m-p, u2, ldu2, iwork )
642 CALL clapmr( .false., m-p, m-p, u2, ldu2, iwork )
645 IF( m .GT. 0 .AND. wantv2t )
THEN
647 iwork(i) = m - p - q + i
652 IF( .NOT. colmajor )
THEN
653 CALL clapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
655 CALL clapmr( .false., m-q, m-q, v2t, ldv2t, iwork )