295 RECURSIVE SUBROUTINE sorcsd( 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
313 REAL u1( ldu1, * ), u2( ldu2, * ), v1t( ldv1t, * ),
314 $ v2t( ldv2t, * ), work( * ), x11( ldx11, * ),
315 $ x12( ldx12, * ), x21( ldx21, * ), x22( ldx22,
323 PARAMETER ( one = 1.0e+0,
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 ) )
THEN
373 ELSE IF (.NOT. colmajor .AND. ldx11 .LT. max( 1, q ) )
THEN
375 ELSE IF (colmajor .AND. ldx12 .LT. max( 1, p ) )
THEN
377 ELSE IF (.NOT. colmajor .AND. ldx12 .LT. max( 1, m-q ) )
THEN
379 ELSE IF (colmajor .AND. ldx21 .LT. max( 1, m-p ) )
THEN
381 ELSE IF (.NOT. colmajor .AND. ldx21 .LT. max( 1, q ) )
THEN
383 ELSE IF (colmajor .AND. ldx22 .LT. max( 1, m-p ) )
THEN
385 ELSE IF (.NOT. colmajor .AND. ldx22 .LT. max( 1, m-q ) )
THEN
387 ELSE IF( wantu1 .AND. ldu1 .LT. p )
THEN
389 ELSE IF( wantu2 .AND. ldu2 .LT. m-p )
THEN
391 ELSE IF( wantv1t .AND. ldv1t .LT. q )
THEN
393 ELSE IF( wantv2t .AND. ldv2t .LT. m-q )
THEN
399 IF( info .EQ. 0 .AND. min( p, m-p ) .LT. min( q, m-q ) )
THEN
405 IF( defaultsigns )
THEN
410 CALL sorcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,
411 $ q, p, x11, ldx11, x21, ldx21, x12, ldx12, x22,
412 $ ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,
413 $ u2, ldu2, work, lwork, iwork, info )
420 IF( info .EQ. 0 .AND. m-q .LT. q )
THEN
421 IF( defaultsigns )
THEN
426 CALL sorcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,
427 $ m-p, m-q, x22, ldx22, x21, ldx21, x12, ldx12, x11,
428 $ ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, v1t,
429 $ ldv1t, work, lwork, iwork, info )
435 IF( info .EQ. 0 )
THEN
438 itaup1 = iphi + max( 1, q - 1 )
439 itaup2 = itaup1 + max( 1, p )
440 itauq1 = itaup2 + max( 1, m - p )
441 itauq2 = itauq1 + max( 1, q )
442 iorgqr = itauq2 + max( 1, m - q )
443 CALL sorgqr( m-q, m-q, m-q, dummy, max(1,m-q), dummy, work, -1,
445 lorgqrworkopt = int( work(1) )
446 lorgqrworkmin = max( 1, m - q )
447 iorglq = itauq2 + max( 1, m - q )
448 CALL sorglq( m-q, m-q, m-q, dummy, max(1,m-q), dummy, work, -1,
450 lorglqworkopt = int( work(1) )
451 lorglqworkmin = max( 1, m - q )
452 iorbdb = itauq2 + max( 1, m - q )
453 CALL sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,
454 $ x21, ldx21, x22, ldx22, dummy, dummy, dummy, dummy, dummy,
455 $ dummy,work,-1,childinfo )
456 lorbdbworkopt = int( work(1) )
457 lorbdbworkmin = lorbdbworkopt
458 ib11d = itauq2 + max( 1, m - q )
459 ib11e = ib11d + max( 1, q )
460 ib12d = ib11e + max( 1, q - 1 )
461 ib12e = ib12d + max( 1, q )
462 ib21d = ib12e + max( 1, q - 1 )
463 ib21e = ib21d + max( 1, q )
464 ib22d = ib21e + max( 1, q - 1 )
465 ib22e = ib22d + max( 1, q )
466 ibbcsd = ib22e + max( 1, q - 1 )
467 CALL sbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,
468 $ dummy, dummy, u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
469 $ ldv2t, dummy, dummy, dummy, dummy, dummy, dummy,
470 $ dummy, dummy, work, -1, childinfo )
471 lbbcsdworkopt = int( work(1) )
472 lbbcsdworkmin = lbbcsdworkopt
473 lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,
474 $ iorbdb + lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1
475 lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,
476 $ iorbdb + lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1
477 work(1) = max(lworkopt,lworkmin)
479 IF( lwork .LT. lworkmin .AND. .NOT. lquery )
THEN
482 lorgqrwork = lwork - iorgqr + 1
483 lorglqwork = lwork - iorglq + 1
484 lorbdbwork = lwork - iorbdb + 1
485 lbbcsdwork = lwork - ibbcsd + 1
491 IF( info .NE. 0 )
THEN
492 CALL xerbla(
'SORCSD', -info )
494 ELSE IF( lquery )
THEN
500 CALL sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,
501 $ ldx21, x22, ldx22, theta, work(iphi), work(itaup1),
502 $ work(itaup2), work(itauq1), work(itauq2),
503 $ work(iorbdb), lorbdbwork, childinfo )
508 IF( wantu1 .AND. p .GT. 0 )
THEN
509 CALL slacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
510 CALL sorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
513 IF( wantu2 .AND. m-p .GT. 0 )
THEN
514 CALL slacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
515 CALL sorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
516 $ work(iorgqr), lorgqrwork, info )
518 IF( wantv1t .AND. q .GT. 0 )
THEN
519 CALL slacpy(
'U', q-1, q-1, x11(1,2), ldx11, v1t(2,2),
526 CALL sorglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
527 $ work(iorglq), lorglqwork, info )
529 IF( wantv2t .AND. m-q .GT. 0 )
THEN
530 CALL slacpy(
'U', p, m-q, x12, ldx12, v2t, ldv2t )
531 CALL slacpy(
'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,
532 $ v2t(p+1,p+1), ldv2t )
533 CALL sorglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
534 $ work(iorglq), lorglqwork, info )
537 IF( wantu1 .AND. p .GT. 0 )
THEN
538 CALL slacpy(
'U', q, p, x11, ldx11, u1, ldu1 )
539 CALL sorglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),
542 IF( wantu2 .AND. m-p .GT. 0 )
THEN
543 CALL slacpy(
'U', q, m-p, x21, ldx21, u2, ldu2 )
544 CALL sorglq( m-p, m-p, q, u2, ldu2, work(itaup2),
545 $ work(iorglq), lorglqwork, info )
547 IF( wantv1t .AND. q .GT. 0 )
THEN
548 CALL slacpy(
'L', q-1, q-1, x11(2,1), ldx11, v1t(2,2),
555 CALL sorgqr( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
556 $ work(iorgqr), lorgqrwork, info )
558 IF( wantv2t .AND. m-q .GT. 0 )
THEN
559 CALL slacpy(
'L', m-q, p, x12, ldx12, v2t, ldv2t )
560 CALL slacpy(
'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,
561 $ v2t(p+1,p+1), ldv2t )
562 CALL sorgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),
563 $ work(iorgqr), lorgqrwork, info )
569 CALL sbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,
570 $ work(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,
571 $ ldv2t, work(ib11d), work(ib11e), work(ib12d),
572 $ work(ib12e), work(ib21d), work(ib21e), work(ib22d),
573 $ work(ib22e), work(ibbcsd), lbbcsdwork, info )
580 IF( q .GT. 0 .AND. wantu2 )
THEN
582 iwork(i) = m - p - q + i
588 CALL slapmt( .false., m-p, m-p, u2, ldu2, iwork )
590 CALL slapmr( .false., m-p, m-p, u2, ldu2, iwork )
593 IF( m .GT. 0 .AND. wantv2t )
THEN
595 iwork(i) = m - p - q + i
600 IF( .NOT. colmajor )
THEN
601 CALL slapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
603 CALL slapmr( .false., m-q, m-q, v2t, ldv2t, iwork )
subroutine xerbla(srname, info)
subroutine sbbcsd(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)
SBBCSD
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
subroutine slapmr(forwrd, m, n, x, ldx, k)
SLAPMR rearranges rows of a matrix as specified by a permutation vector.
subroutine slapmt(forwrd, m, n, x, ldx, k)
SLAPMT performs a forward or backward permutation of the columns of a matrix.
logical function lsame(ca, cb)
LSAME
subroutine sorbdb(trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21, ldx21, x22, ldx22, theta, phi, taup1, taup2, tauq1, tauq2, work, lwork, info)
SORBDB
recursive subroutine sorcsd(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)
SORCSD
subroutine sorglq(m, n, k, a, lda, tau, work, lwork, info)
SORGLQ
subroutine sorgqr(m, n, k, a, lda, tau, work, lwork, info)
SORGQR