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,
328 INTEGER childinfo, i, ib11d, ib11e, ib12d, ib12e,
329 $ ib21d, ib21e, ib22d,
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,
355 wantu1 =
lsame( jobu1,
'Y' )
356 wantu2 =
lsame( jobu2,
'Y' )
357 wantv1t =
lsame( jobv1t,
'Y' )
358 wantv2t =
lsame( jobv2t,
'Y' )
359 colmajor = .NOT.
lsame'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
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
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 )