295 RECURSIVE SUBROUTINE dorcsd( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS,
296 $ SIGNS, M, P, Q, X11, LDX11, X12,
297 $ LDX12, X21, LDX21, X22, LDX22, THETA,
298 $ U1, LDU1, U2, LDU2, V1T, LDV1T, V2T,
299 $ LDV2T, WORK, LWORK, IWORK, INFO )
306 CHARACTER jobu1, jobu2, jobv1t, jobv2t, signs, trans
307 INTEGER info, ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12,
308 $ ldx21, ldx22, lwork, m, p, q
312 DOUBLE PRECISION theta( * )
313 DOUBLE PRECISION u1( ldu1, * ), u2( ldu2, * ), v1t( ldv1t, * ),
314 $ v2t( ldv2t, * ), work( * ), x11( ldx11, * ),
315 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
322 DOUBLE PRECISION one, zero
323 PARAMETER ( one = 1.0d0,
327 CHARACTER transt, signst
328 INTEGER childinfo, i, ib11d, ib11e, ib12d, ib12e,
329 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
330 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
331 $ itauq2, j, lbbcsdwork, lbbcsdworkmin,
332 $ lbbcsdworkopt, lorbdbwork, lorbdbworkmin,
333 $ lorbdbworkopt, lorglqwork, lorglqworkmin,
334 $ lorglqworkopt, lorgqrwork, lorgqrworkmin,
335 $ lorgqrworkopt, lworkmin, lworkopt
336 LOGICAL colmajor, defaultsigns, lquery, wantu1, wantu2,
348 INTRINSIC int, max, min
355 wantu1 =
lsame( jobu1,
'Y' )
356 wantu2 =
lsame( jobu2,
'Y' )
357 wantv1t =
lsame( jobv1t,
'Y' )
358 wantv2t =
lsame( jobv2t,
'Y' )
359 colmajor = .NOT.
lsame( trans,
'T' )
360 defaultsigns = .NOT.
lsame( signs,
'O' )
361 lquery = lwork .EQ. -1
364 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
366 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
368 ELSE IF ( colmajor .AND. ldx11 .LT. max( 1, p ) )
THEN
370 ELSE IF (.NOT. colmajor .AND. ldx11 .LT. max( 1, q ) )
THEN
372 ELSE IF (colmajor .AND. ldx12 .LT. max( 1, p ) )
THEN
374 ELSE IF (.NOT. colmajor .AND. ldx12 .LT. max( 1, m-q ) )
THEN
376 ELSE IF (colmajor .AND. ldx21 .LT. max( 1, m-p ) )
THEN
378 ELSE IF (.NOT. colmajor .AND. ldx21 .LT. max( 1, q ) )
THEN
380 ELSE IF (colmajor .AND. ldx22 .LT. max( 1, m-p ) )
THEN
382 ELSE IF (.NOT. colmajor .AND. ldx22 .LT. max( 1, m-q ) )
THEN
384 ELSE IF( wantu1 .AND. ldu1 .LT. p )
THEN
386 ELSE IF( wantu2 .AND. ldu2 .LT. m-p )
THEN
388 ELSE IF( wantv1t .AND. ldv1t .LT. q )
THEN
390 ELSE IF( wantv2t .AND. ldv2t .LT. m-q )
THEN
396 IF( info .EQ. 0 .AND. min( p, m-p ) .LT. min( q, m-q ) )
THEN
402 IF( defaultsigns )
THEN
407 CALL dorcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,
408 $ q, p, x11, ldx11, x21, ldx21, x12, ldx12, x22,
409 $ ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,
410 $ u2, ldu2, work, lwork, iwork, info )
417 IF( info .EQ. 0 .AND. m-q .LT. q )
THEN
418 IF( defaultsigns )
THEN
423 CALL dorcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,
424 $ m-p, m-q, x22, ldx22, x21, ldx21, x12, ldx12, x11,
425 $ ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, v1t,
426 $ ldv1t, work, lwork, iwork, info )
432 IF( info .EQ. 0 )
THEN
435 itaup1 = iphi + max( 1, q - 1 )
436 itaup2 = itaup1 + max( 1, p )
437 itauq1 = itaup2 + max( 1, m - p )
438 itauq2 = itauq1 + max( 1, q )
439 iorgqr = itauq2 + max( 1, m - q )
440 CALL dorgqr( m-q, m-q, m-q, u1, max(1,m-q), u1, work, -1,
442 lorgqrworkopt = int( work(1) )
443 lorgqrworkmin = max( 1, m - q )
444 iorglq = itauq2 + max( 1, m - q )
445 CALL dorglq( m-q, m-q, m-q, u1, max(1,m-q), u1, work, -1,
447 lorglqworkopt = int( work(1) )
448 lorglqworkmin = max( 1, m - q )
449 iorbdb = itauq2 + max( 1, m - q )
450 CALL dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
451 $ x21, ldx21, x22, ldx22, theta, v1t, u1, u2, v1t,
452 $ v2t, work, -1, childinfo )
453 lorbdbworkopt = int( work(1) )
454 lorbdbworkmin = lorbdbworkopt
455 ib11d = itauq2 + max( 1, m - q )
456 ib11e = ib11d + max( 1, q )
457 ib12d = ib11e + max( 1, q - 1 )
458 ib12e = ib12d + max( 1, q )
459 ib21d = ib12e + max( 1, q - 1 )
460 ib21e = ib21d + max( 1, q )
461 ib22d = ib21e + max( 1, q - 1 )
462 ib22e = ib22d + max( 1, q )
463 ibbcsd = ib22e + max( 1, q - 1 )
464 CALL dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,
465 $ theta, theta, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
466 $ ldv2t, u1, u1, u1, u1, u1, u1, u1, u1, work, -1,
468 lbbcsdworkopt = int( work(1) )
469 lbbcsdworkmin = lbbcsdworkopt
470 lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,
471 $ iorbdb + lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1
472 lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,
473 $ iorbdb + lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1
474 work(1) = max(lworkopt,lworkmin)
476 IF( lwork .LT. lworkmin .AND. .NOT. lquery )
THEN
479 lorgqrwork = lwork - iorgqr + 1
480 lorglqwork = lwork - iorglq + 1
481 lorbdbwork = lwork - iorbdb + 1
482 lbbcsdwork = lwork - ibbcsd + 1
488 IF( info .NE. 0 )
THEN
489 CALL xerbla(
'DORCSD', -info )
491 ELSE IF( lquery )
THEN
497 CALL dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,
498 $ ldx21, x22, ldx22, theta, work(iphi), work(itaup1),
499 $ work(itaup2), work(itauq1), work(itauq2),
500 $ work(iorbdb), lorbdbwork, childinfo )
505 IF( wantu1 .AND. p .GT. 0 )
THEN
506 CALL dlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
507 CALL dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
510 IF( wantu2 .AND. m-p .GT. 0 )
THEN
511 CALL dlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
512 CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
513 $ work(iorgqr), lorgqrwork, info )
515 IF( wantv1t .AND. q .GT. 0 )
THEN
516 CALL dlacpy(
'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
523 CALL dorglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
524 $ work(iorglq), lorglqwork, info )
526 IF( wantv2t .AND. m-q .GT. 0 )
THEN
527 CALL dlacpy(
'U', p, m-q, x12, ldx12, v2t, ldv2t )
529 CALL dlacpy(
'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
530 $ v2t(p+1,p+1), ldv2t )
533 CALL dorglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
534 $ work(iorglq), lorglqwork, info )
538 IF( wantu1 .AND. p .GT. 0 )
THEN
539 CALL dlacpy(
'U', q, p, x11, ldx11, u1, ldu1 )
540 CALL dorglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),
543 IF( wantu2 .AND. m-p .GT. 0 )
THEN
544 CALL dlacpy(
'U', q, m-p, x21, ldx21, u2, ldu2 )
545 CALL dorglq( m-p, m-p, q, u2, ldu2, work(itaup2),
546 $ work(iorglq), lorglqwork, info )
548 IF( wantv1t .AND. q .GT. 0 )
THEN
549 CALL dlacpy(
'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
556 CALL dorgqr( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
557 $ work(iorgqr), lorgqrwork, info )
559 IF( wantv2t .AND. m-q .GT. 0 )
THEN
560 CALL dlacpy(
'L', m-q, p, x12, ldx12, v2t, ldv2t )
561 CALL dlacpy(
'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,
562 $ v2t(p+1,p+1), ldv2t )
563 CALL dorgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
564 $ work(iorgqr), lorgqrwork, info )
570 CALL dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,
571 $ work(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
572 $ ldv2t, work(ib11d), work(ib11e), work(ib12d),
573 $ work(ib12e), work(ib21d), work(ib21e), work(ib22d),
574 $ work(ib22e), work(ibbcsd), lbbcsdwork, info )
581 IF( q .GT. 0 .AND. wantu2 )
THEN
583 iwork(i) = m - p - q + i
589 CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
591 CALL dlapmr( .false., m-p, m-p, u2, ldu2, iwork )
594 IF( m .GT. 0 .AND. wantv2t )
THEN
596 iwork(i) = m - p - q + i
601 IF( .NOT. colmajor )
THEN
602 CALL dlapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
604 CALL dlapmr( .false., m-q, m-q, v2t, ldv2t, iwork )
subroutine xerbla(srname, info)
subroutine dbbcsd(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, work, lwork, info)
DBBCSD
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlapmr(forwrd, m, n, x, ldx, k)
DLAPMR rearranges rows of a matrix as specified by a permutation vector.
subroutine dlapmt(forwrd, m, n, x, ldx, k)
DLAPMT performs a forward or backward permutation of the columns of a matrix.
logical function lsame(ca, cb)
LSAME
subroutine dorbdb(trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21, ldx21, x22, ldx22, theta, phi, taup1, taup2, tauq1, tauq2, work, lwork, info)
DORBDB
recursive subroutine dorcsd(jobu1, jobu2, jobv1t, jobv2t, trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21, ldx21, x22, ldx22, theta, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t, ldv2t, work, lwork, iwork, info)
DORCSD
subroutine dorglq(m, n, k, a, lda, tau, work, lwork, info)
DORGLQ
subroutine dorgqr(m, n, k, a, lda, tau, work, lwork, info)
DORGQR