316 RECURSIVE SUBROUTINE zuncsd( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS,
317 $ signs, m, p, q, x11, ldx11, x12,
318 $ ldx12, x21, ldx21, x22, ldx22, theta,
319 $ u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
320 $ ldv2t, work, lwork, rwork, lrwork,
329 CHARACTER jobu1, jobu2, jobv1t, jobv2t, signs, trans
330 INTEGER info, ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12,
331 $ ldx21, ldx22, lrwork, lwork, m, p, q
335 DOUBLE PRECISION theta( * )
336 DOUBLE PRECISION rwork( * )
337 COMPLEX*16 u1( ldu1, * ), u2( ldu2, * ), v1t( ldv1t, * ),
338 $ v2t( ldv2t, * ), work( * ), x11( ldx11, * ),
339 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
347 parameter( one = (1.0d0,0.0d0),
348 $ zero = (0.0d0,0.0d0) )
351 CHARACTER transt, signst
352 INTEGER childinfo, i, ib11d, ib11e, ib12d, ib12e,
353 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
354 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
355 $ itauq2, j, lbbcsdwork, lbbcsdworkmin,
356 $ lbbcsdworkopt, lorbdbwork, lorbdbworkmin,
357 $ lorbdbworkopt, lorglqwork, lorglqworkmin,
358 $ lorglqworkopt, lorgqrwork, lorgqrworkmin,
359 $ lorgqrworkopt, lworkmin, lworkopt
360 LOGICAL colmajor, defaultsigns, lquery, wantu1, wantu2,
362 INTEGER lrworkmin, lrworkopt
374 INTRINSIC cos, int, max, min, sin
381 wantu1 =
lsame( jobu1,
'Y' )
382 wantu2 =
lsame( jobu2,
'Y' )
383 wantv1t =
lsame( jobv1t,
'Y' )
384 wantv2t =
lsame( jobv2t,
'Y' )
385 colmajor = .NOT.
lsame( trans,
'T' )
386 defaultsigns = .NOT.
lsame( signs,
'O' )
387 lquery = lwork .EQ. -1
388 lrquery = lrwork .EQ. -1
391 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
393 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
395 ELSE IF( ( colmajor .AND. ldx11 .LT. max(1,p) ) .OR.
396 $ ( .NOT.colmajor .AND. ldx11 .LT. max(1,q) ) )
THEN
398 ELSE IF( wantu1 .AND. ldu1 .LT. p )
THEN
400 ELSE IF( wantu2 .AND. ldu2 .LT. m-p )
THEN
402 ELSE IF( wantv1t .AND. ldv1t .LT. q )
THEN
404 ELSE IF( wantv2t .AND. ldv2t .LT. m-q )
THEN
410 IF( info .EQ. 0 .AND. min( p, m-p ) .LT. min( q, m-q ) )
THEN
416 IF( defaultsigns )
THEN
421 CALL
zuncsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,
422 $ q, p, x11, ldx11, x21, ldx21, x12, ldx12, x22,
423 $ ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,
424 $ u2, ldu2, work, lwork, rwork, lrwork, iwork,
432 IF( info .EQ. 0 .AND. m-q .LT. q )
THEN
433 IF( defaultsigns )
THEN
438 CALL
zuncsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,
439 $ m-p, m-q, x22, ldx22, x21, ldx21, x12, ldx12, x11,
440 $ ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, v1t,
441 $ ldv1t, work, lwork, rwork, lrwork, iwork, info )
447 IF( info .EQ. 0 )
THEN
452 ib11d = iphi + max( 1, q - 1 )
453 ib11e = ib11d + max( 1, q )
454 ib12d = ib11e + max( 1, q - 1 )
455 ib12e = ib12d + max( 1, q )
456 ib21d = ib12e + max( 1, q - 1 )
457 ib21e = ib21d + max( 1, q )
458 ib22d = ib21e + max( 1, q - 1 )
459 ib22e = ib22d + max( 1, q )
460 ibbcsd = ib22e + max( 1, q - 1 )
461 CALL
zbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, 0,
462 $ 0, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t, ldv2t, 0,
463 $ 0, 0, 0, 0, 0, 0, 0, rwork, -1, childinfo )
464 lbbcsdworkopt = int( rwork(1) )
465 lbbcsdworkmin = lbbcsdworkopt
466 lrworkopt = ibbcsd + lbbcsdworkopt - 1
467 lrworkmin = ibbcsd + lbbcsdworkmin - 1
473 itaup2 = itaup1 + max( 1, p )
474 itauq1 = itaup2 + max( 1, m - p )
475 itauq2 = itauq1 + max( 1, q )
476 iorgqr = itauq2 + max( 1, m - q )
477 CALL
zungqr( m-q, m-q, m-q, 0, max(1,m-q), 0, work, -1,
479 lorgqrworkopt = int( work(1) )
480 lorgqrworkmin = max( 1, m - q )
481 iorglq = itauq2 + max( 1, m - q )
482 CALL
zunglq( m-q, m-q, m-q, 0, max(1,m-q), 0, work, -1,
484 lorglqworkopt = int( work(1) )
485 lorglqworkmin = max( 1, m - q )
486 iorbdb = itauq2 + max( 1, m - q )
487 CALL
zunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
488 $ x21, ldx21, x22, ldx22, 0, 0, 0, 0, 0, 0, work,
490 lorbdbworkopt = int( work(1) )
491 lorbdbworkmin = lorbdbworkopt
492 lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,
493 $ iorbdb + lorbdbworkopt ) - 1
494 lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,
495 $ iorbdb + lorbdbworkmin ) - 1
496 work(1) = max(lworkopt,lworkmin)
498 IF( lwork .LT. lworkmin
499 $ .AND. .NOT. ( lquery .OR. lrquery ) )
THEN
501 ELSE IF( lrwork .LT. lrworkmin
502 $ .AND. .NOT. ( lquery .OR. lrquery ) )
THEN
505 lorgqrwork = lwork - iorgqr + 1
506 lorglqwork = lwork - iorglq + 1
507 lorbdbwork = lwork - iorbdb + 1
508 lbbcsdwork = lrwork - ibbcsd + 1
514 IF( info .NE. 0 )
THEN
515 CALL
xerbla(
'ZUNCSD', -info )
517 ELSE IF( lquery .OR. lrquery )
THEN
523 CALL
zunbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,
524 $ ldx21, x22, ldx22, theta, rwork(iphi), work(itaup1),
525 $ work(itaup2), work(itauq1), work(itauq2),
526 $ work(iorbdb), lorbdbwork, childinfo )
531 IF( wantu1 .AND. p .GT. 0 )
THEN
532 CALL
zlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
533 CALL
zungqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
536 IF( wantu2 .AND. m-p .GT. 0 )
THEN
537 CALL
zlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
538 CALL
zungqr( m-p, m-p, q, u2, ldu2, work(itaup2),
539 $ work(iorgqr), lorgqrwork, info )
541 IF( wantv1t .AND. q .GT. 0 )
THEN
542 CALL
zlacpy(
'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
549 CALL
zunglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
550 $ work(iorglq), lorglqwork, info )
552 IF( wantv2t .AND. m-q .GT. 0 )
THEN
553 CALL
zlacpy(
'U', p, m-q, x12, ldx12, v2t, ldv2t )
554 CALL
zlacpy(
'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
555 $ v2t(p+1,p+1), ldv2t )
556 CALL
zunglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
557 $ work(iorglq), lorglqwork, info )
560 IF( wantu1 .AND. p .GT. 0 )
THEN
561 CALL
zlacpy(
'U', q, p, x11, ldx11, u1, ldu1 )
562 CALL
zunglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),
565 IF( wantu2 .AND. m-p .GT. 0 )
THEN
566 CALL
zlacpy(
'U', q, m-p, x21, ldx21, u2, ldu2 )
567 CALL
zunglq( m-p, m-p, q, u2, ldu2, work(itaup2),
568 $ work(iorglq), lorglqwork, info )
570 IF( wantv1t .AND. q .GT. 0 )
THEN
571 CALL
zlacpy(
'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
578 CALL
zungqr( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
579 $ work(iorgqr), lorgqrwork, info )
581 IF( wantv2t .AND. m-q .GT. 0 )
THEN
582 CALL
zlacpy(
'L', m-q, p, x12, ldx12, v2t, ldv2t )
583 CALL
zlacpy(
'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,
584 $ v2t(p+1,p+1), ldv2t )
585 CALL
zungqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
586 $ work(iorgqr), lorgqrwork, info )
592 CALL
zbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,
593 $ rwork(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
594 $ ldv2t, rwork(ib11d), rwork(ib11e), rwork(ib12d),
595 $ rwork(ib12e), rwork(ib21d), rwork(ib21e),
596 $ rwork(ib22d), rwork(ib22e), rwork(ibbcsd),
604 IF( q .GT. 0 .AND. wantu2 )
THEN
606 iwork(i) = m - p - q + i
612 CALL
zlapmt( .false., m-p, m-p, u2, ldu2, iwork )
614 CALL
zlapmr( .false., m-p, m-p, u2, ldu2, iwork )
617 IF( m .GT. 0 .AND. wantv2t )
THEN
619 iwork(i) = m - p - q + i
624 IF( .NOT. colmajor )
THEN
625 CALL
zlapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
627 CALL
zlapmr( .false., m-q, m-q, v2t, ldv2t, iwork )