297 RECURSIVE SUBROUTINE dorcsd( JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS,
298 $ signs, m, p, q, x11, ldx11, x12,
299 $ ldx12, x21, ldx21, x22, ldx22, theta,
300 $ u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
301 $ ldv2t, work, lwork, iwork, info )
309 CHARACTER jobu1, jobu2, jobv1t, jobv2t, signs, trans
310 INTEGER info, ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12,
311 $ ldx21, ldx22, lwork, m, p, q
315 DOUBLE PRECISION theta( * )
316 DOUBLE PRECISION u1( ldu1, * ), u2( ldu2, * ), v1t( ldv1t, * ),
317 $ v2t( ldv2t, * ), work( * ), x11( ldx11, * ),
318 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
325 DOUBLE PRECISION one, zero
326 parameter( one = 1.0d0,
330 CHARACTER transt, signst
331 INTEGER childinfo, i, ib11d, ib11e, ib12d, ib12e,
332 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
333 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
334 $ itauq2, j, lbbcsdwork, lbbcsdworkmin,
335 $ lbbcsdworkopt, lorbdbwork, lorbdbworkmin,
336 $ lorbdbworkopt, lorglqwork, lorglqworkmin,
337 $ lorglqworkopt, lorgqrwork, lorgqrworkmin,
338 $ lorgqrworkopt, lworkmin, lworkopt
339 LOGICAL colmajor, defaultsigns, lquery, wantu1, wantu2,
351 INTRINSIC int, max, min
358 wantu1 =
lsame( jobu1,
'Y' )
359 wantu2 =
lsame( jobu2,
'Y' )
360 wantv1t =
lsame( jobv1t,
'Y' )
361 wantv2t =
lsame( jobv2t,
'Y' )
362 colmajor = .NOT.
lsame( trans,
'T' )
363 defaultsigns = .NOT.
lsame( signs,
'O' )
364 lquery = lwork .EQ. -1
367 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
369 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
371 ELSE IF( ( colmajor .AND. ldx11 .LT. max(1,p) ) .OR.
372 $ ( .NOT.colmajor .AND. ldx11 .LT. max(1,q) ) )
THEN
374 ELSE IF( wantu1 .AND. ldu1 .LT. p )
THEN
376 ELSE IF( wantu2 .AND. ldu2 .LT. m-p )
THEN
378 ELSE IF( wantv1t .AND. ldv1t .LT. q )
THEN
380 ELSE IF( wantv2t .AND. ldv2t .LT. m-q )
THEN
386 IF( info .EQ. 0 .AND. min( p, m-p ) .LT. min( q, m-q ) )
THEN
392 IF( defaultsigns )
THEN
397 CALL
dorcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,
398 $ q, p, x11, ldx11, x21, ldx21, x12, ldx12, x22,
399 $ ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,
400 $ u2, ldu2, work, lwork, iwork, info )
407 IF( info .EQ. 0 .AND. m-q .LT. q )
THEN
408 IF( defaultsigns )
THEN
413 CALL
dorcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,
414 $ m-p, m-q, x22, ldx22, x21, ldx21, x12, ldx12, x11,
415 $ ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, v1t,
416 $ ldv1t, work, lwork, iwork, info )
422 IF( info .EQ. 0 )
THEN
425 itaup1 = iphi + max( 1, q - 1 )
426 itaup2 = itaup1 + max( 1, p )
427 itauq1 = itaup2 + max( 1, m - p )
428 itauq2 = itauq1 + max( 1, q )
429 iorgqr = itauq2 + max( 1, m - q )
430 CALL
dorgqr( m-q, m-q, m-q, 0, max(1,m-q), 0, work, -1,
432 lorgqrworkopt = int( work(1) )
433 lorgqrworkmin = max( 1, m - q )
434 iorglq = itauq2 + max( 1, m - q )
435 CALL
dorglq( m-q, m-q, m-q, 0, max(1,m-q), 0, work, -1,
437 lorglqworkopt = int( work(1) )
438 lorglqworkmin = max( 1, m - q )
439 iorbdb = itauq2 + max( 1, m - q )
440 CALL
dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
441 $ x21, ldx21, x22, ldx22, 0, 0, 0, 0, 0, 0, work,
443 lorbdbworkopt = int( work(1) )
444 lorbdbworkmin = lorbdbworkopt
445 ib11d = itauq2 + max( 1, m - q )
446 ib11e = ib11d + max( 1, q )
447 ib12d = ib11e + max( 1, q - 1 )
448 ib12e = ib12d + max( 1, q )
449 ib21d = ib12e + max( 1, q - 1 )
450 ib21e = ib21d + max( 1, q )
451 ib22d = ib21e + max( 1, q - 1 )
452 ib22e = ib22d + max( 1, q )
453 ibbcsd = ib22e + max( 1, q - 1 )
454 CALL
dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, 0,
455 $ 0, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t, ldv2t, 0,
456 $ 0, 0, 0, 0, 0, 0, 0, work, -1, childinfo )
457 lbbcsdworkopt = int( work(1) )
458 lbbcsdworkmin = lbbcsdworkopt
459 lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,
460 $ iorbdb + lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1
461 lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,
462 $ iorbdb + lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1
463 work(1) = max(lworkopt,lworkmin)
465 IF( lwork .LT. lworkmin .AND. .NOT. lquery )
THEN
468 lorgqrwork = lwork - iorgqr + 1
469 lorglqwork = lwork - iorglq + 1
470 lorbdbwork = lwork - iorbdb + 1
471 lbbcsdwork = lwork - ibbcsd + 1
477 IF( info .NE. 0 )
THEN
478 CALL
xerbla(
'DORCSD', -info )
480 ELSE IF( lquery )
THEN
486 CALL
dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,
487 $ ldx21, x22, ldx22, theta, work(iphi), work(itaup1),
488 $ work(itaup2), work(itauq1), work(itauq2),
489 $ work(iorbdb), lorbdbwork, childinfo )
494 IF( wantu1 .AND. p .GT. 0 )
THEN
495 CALL
dlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
496 CALL
dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
499 IF( wantu2 .AND. m-p .GT. 0 )
THEN
500 CALL
dlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
501 CALL
dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
502 $ work(iorgqr), lorgqrwork, info )
504 IF( wantv1t .AND. q .GT. 0 )
THEN
505 CALL
dlacpy(
'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
512 CALL
dorglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
513 $ work(iorglq), lorglqwork, info )
515 IF( wantv2t .AND. m-q .GT. 0 )
THEN
516 CALL
dlacpy(
'U', p, m-q, x12, ldx12, v2t, ldv2t )
517 CALL
dlacpy(
'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
518 $ v2t(p+1,p+1), ldv2t )
519 CALL
dorglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
520 $ work(iorglq), lorglqwork, info )
523 IF( wantu1 .AND. p .GT. 0 )
THEN
524 CALL
dlacpy(
'U', q, p, x11, ldx11, u1, ldu1 )
525 CALL
dorglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),
528 IF( wantu2 .AND. m-p .GT. 0 )
THEN
529 CALL
dlacpy(
'U', q, m-p, x21, ldx21, u2, ldu2 )
530 CALL
dorglq( m-p, m-p, q, u2, ldu2, work(itaup2),
531 $ work(iorglq), lorglqwork, info )
533 IF( wantv1t .AND. q .GT. 0 )
THEN
534 CALL
dlacpy(
'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
541 CALL
dorgqr( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
542 $ work(iorgqr), lorgqrwork, info )
544 IF( wantv2t .AND. m-q .GT. 0 )
THEN
545 CALL
dlacpy(
'L', m-q, p, x12, ldx12, v2t, ldv2t )
546 CALL
dlacpy(
'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,
547 $ v2t(p+1,p+1), ldv2t )
548 CALL
dorgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
549 $ work(iorgqr), lorgqrwork, info )
555 CALL
dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,
556 $ work(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
557 $ ldv2t, work(ib11d), work(ib11e), work(ib12d),
558 $ work(ib12e), work(ib21d), work(ib21e), work(ib22d),
559 $ work(ib22e), work(ibbcsd), lbbcsdwork, info )
566 IF( q .GT. 0 .AND. wantu2 )
THEN
568 iwork(i) = m - p - q + i
574 CALL
dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
576 CALL
dlapmr( .false., m-p, m-p, u2, ldu2, iwork )
579 IF( m .GT. 0 .AND. wantv2t )
THEN
581 iwork(i) = m - p - q + i
586 IF( .NOT. colmajor )
THEN
587 CALL
dlapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
589 CALL
dlapmr( .false., m-q, m-q, v2t, ldv2t, iwork )