243 CHARACTER jobu1, jobu2, jobv1t
244 INTEGER info, ldu1, ldu2, ldv1t, lwork, ldx11, ldx21,
248 DOUBLE PRECISION theta(*)
249 DOUBLE PRECISION u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*),
250 $ x11(ldx11,*), x21(ldx21,*)
257 DOUBLE PRECISION one, zero
258 parameter ( one = 1.0d0, zero = 0.0d0 )
261 INTEGER childinfo, i, ib11d, ib11e, ib12d, ib12e,
262 $ ib21d, ib21e, ib22d, ib22e, ibbcsd, iorbdb,
263 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
264 $ j, lbbcsd, lorbdb, lorglq, lorglqmin,
265 $ lorglqopt, lorgqr, lorgqrmin, lorgqropt,
266 $ lworkmin, lworkopt, r
267 LOGICAL lquery, wantu1, wantu2, wantv1t
270 DOUBLE PRECISION dum1(1), dum2(1,1)
282 INTRINSIC int, max, min
289 wantu1 =
lsame( jobu1,
'Y' )
290 wantu2 =
lsame( jobu2,
'Y' )
291 wantv1t =
lsame( jobv1t,
'Y' )
292 lquery = lwork .EQ. -1
296 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
298 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
300 ELSE IF( ldx11 .LT. max( 1, p ) )
THEN
302 ELSE IF( ldx21 .LT. max( 1, m-p ) )
THEN
304 ELSE IF( wantu1 .AND. ldu1 .LT. max( 1, p ) )
THEN
306 ELSE IF( wantu2 .AND. ldu2 .LT. max( 1, m - p ) )
THEN
308 ELSE IF( wantv1t .AND. ldv1t .LT. max( 1, q ) )
THEN
312 r = min( p, m-p, q, m-q )
333 IF( info .EQ. 0 )
THEN
335 ib11d = iphi + max( 1, r-1 )
336 ib11e = ib11d + max( 1, r )
337 ib12d = ib11e + max( 1, r - 1 )
338 ib12e = ib12d + max( 1, r )
339 ib21d = ib12e + max( 1, r - 1 )
340 ib21e = ib21d + max( 1, r )
341 ib22d = ib21e + max( 1, r - 1 )
342 ib22e = ib22d + max( 1, r )
343 ibbcsd = ib22e + max( 1, r - 1 )
344 itaup1 = iphi + max( 1, r-1 )
345 itaup2 = itaup1 + max( 1, p )
346 itauq1 = itaup2 + max( 1, m-p )
347 iorbdb = itauq1 + max( 1, q )
348 iorgqr = itauq1 + max( 1, q )
349 iorglq = itauq1 + max( 1, q )
355 CALL dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
356 $ dum1, dum1, dum1, dum1, work,
358 lorbdb = int( work(1) )
359 IF( wantu1 .AND. p .GT. 0 )
THEN
360 CALL dorgqr( p, p, q, u1, ldu1, dum1, work(1), -1,
362 lorgqrmin = max( lorgqrmin, p )
363 lorgqropt = max( lorgqropt, int( work(1) ) )
365 IF( wantu2 .AND. m-p .GT. 0 )
THEN
366 CALL dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1),
368 lorgqrmin = max( lorgqrmin, m-p )
369 lorgqropt = max( lorgqropt, int( work(1) ) )
371 IF( wantv1t .AND. q .GT. 0 )
THEN
372 CALL dorglq( q-1, q-1, q-1, v1t, ldv1t,
373 $ dum1, work(1), -1, childinfo )
374 lorglqmin = max( lorglqmin, q-1 )
375 lorglqopt = max( lorglqopt, int( work(1) ) )
377 CALL dbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
378 $ dum1, u1, ldu1, u2, ldu2, v1t, ldv1t,
379 $ dum2, 1, dum1, dum1, dum1,
380 $ dum1, dum1, dum1, dum1,
381 $ dum1, work(1), -1, childinfo )
382 lbbcsd = int( work(1) )
383 ELSE IF( r .EQ. p )
THEN
384 CALL dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
385 $ dum1, dum1, dum1, dum1,
386 $ work(1), -1, childinfo )
387 lorbdb = int( work(1) )
388 IF( wantu1 .AND. p .GT. 0 )
THEN
389 CALL dorgqr( p-1, p-1, p-1, u1(2,2), ldu1, dum1,
390 $ work(1), -1, childinfo )
391 lorgqrmin = max( lorgqrmin, p-1 )
392 lorgqropt = max( lorgqropt, int( work(1) ) )
394 IF( wantu2 .AND. m-p .GT. 0 )
THEN
395 CALL dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1),
397 lorgqrmin = max( lorgqrmin, m-p )
398 lorgqropt = max( lorgqropt, int( work(1) ) )
400 IF( wantv1t .AND. q .GT. 0 )
THEN
401 CALL dorglq( q, q, r, v1t, ldv1t, dum1, work(1), -1,
403 lorglqmin = max( lorglqmin, q )
404 lorglqopt = max( lorglqopt, int( work(1) ) )
406 CALL dbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
407 $ dum1, v1t, ldv1t, dum2, 1, u1, ldu1,
408 $ u2, ldu2, dum1, dum1, dum1,
409 $ dum1, dum1, dum1, dum1,
410 $ dum1, work(1), -1, childinfo )
411 lbbcsd = int( work(1) )
412 ELSE IF( r .EQ. m-p )
THEN
413 CALL dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
414 $ dum1, dum1, dum1, dum1,
415 $ work(1), -1, childinfo )
416 lorbdb = int( work(1) )
417 IF( wantu1 .AND. p .GT. 0 )
THEN
418 CALL dorgqr( p, p, q, u1, ldu1, dum1, work(1), -1,
420 lorgqrmin = max( lorgqrmin, p )
421 lorgqropt = max( lorgqropt, int( work(1) ) )
423 IF( wantu2 .AND. m-p .GT. 0 )
THEN
424 CALL dorgqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
425 $ dum1, work(1), -1, childinfo )
426 lorgqrmin = max( lorgqrmin, m-p-1 )
427 lorgqropt = max( lorgqropt, int( work(1) ) )
429 IF( wantv1t .AND. q .GT. 0 )
THEN
430 CALL dorglq( q, q, r, v1t, ldv1t, dum1, work(1), -1,
432 lorglqmin = max( lorglqmin, q )
433 lorglqopt = max( lorglqopt, int( work(1) ) )
435 CALL dbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
436 $ theta, dum1, dum2, 1, v1t, ldv1t, u2,
437 $ ldu2, u1, ldu1, dum1, dum1, dum1,
438 $ dum1, dum1, dum1, dum1,
439 $ dum1, work(1), -1, childinfo )
440 lbbcsd = int( work(1) )
442 CALL dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
443 $ dum1, dum1, dum1, dum1,
444 $ dum1, work(1), -1, childinfo )
445 lorbdb = m + int( work(1) )
446 IF( wantu1 .AND. p .GT. 0 )
THEN
447 CALL dorgqr( p, p, m-q, u1, ldu1, dum1, work(1), -1,
449 lorgqrmin = max( lorgqrmin, p )
450 lorgqropt = max( lorgqropt, int( work(1) ) )
452 IF( wantu2 .AND. m-p .GT. 0 )
THEN
453 CALL dorgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1),
455 lorgqrmin = max( lorgqrmin, m-p )
456 lorgqropt = max( lorgqropt, int( work(1) ) )
458 IF( wantv1t .AND. q .GT. 0 )
THEN
459 CALL dorglq( q, q, q, v1t, ldv1t, dum1, work(1), -1,
461 lorglqmin = max( lorglqmin, q )
462 lorglqopt = max( lorglqopt, int( work(1) ) )
464 CALL dbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
465 $ theta, dum1, u2, ldu2, u1, ldu1, dum2,
466 $ 1, v1t, ldv1t, dum1, dum1, dum1,
467 $ dum1, dum1, dum1, dum1,
468 $ dum1, work(1), -1, childinfo )
469 lbbcsd = int( work(1) )
471 lworkmin = max( iorbdb+lorbdb-1,
472 $ iorgqr+lorgqrmin-1,
473 $ iorglq+lorglqmin-1,
475 lworkopt = max( iorbdb+lorbdb-1,
476 $ iorgqr+lorgqropt-1,
477 $ iorglq+lorglqopt-1,
480 IF( lwork .LT. lworkmin .AND. .NOT.lquery )
THEN
484 IF( info .NE. 0 )
THEN
485 CALL xerbla(
'DORCSD2BY1', -info )
487 ELSE IF( lquery )
THEN
490 lorgqr = lwork-iorgqr+1
491 lorglq = lwork-iorglq+1
502 CALL dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
503 $ work(iphi), work(itaup1), work(itaup2),
504 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
508 IF( wantu1 .AND. p .GT. 0 )
THEN
509 CALL dlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
510 CALL dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
511 $ lorgqr, childinfo )
513 IF( wantu2 .AND. m-p .GT. 0 )
THEN
514 CALL dlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
515 CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
516 $ work(iorgqr), lorgqr, childinfo )
518 IF( wantv1t .AND. q .GT. 0 )
THEN
524 CALL dlacpy(
'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
526 CALL dorglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
527 $ work(iorglq), lorglq, childinfo )
532 CALL dbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
533 $ work(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t,
534 $ dum2, 1, work(ib11d), work(ib11e),
535 $ work(ib12d), work(ib12e), work(ib21d),
536 $ work(ib21e), work(ib22d), work(ib22e),
537 $ work(ibbcsd), lbbcsd, childinfo )
542 IF( q .GT. 0 .AND. wantu2 )
THEN
544 iwork(i) = m - p - q + i
549 CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
551 ELSE IF( r .EQ. p )
THEN
557 CALL dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
558 $ work(iphi), work(itaup1), work(itaup2),
559 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
563 IF( wantu1 .AND. p .GT. 0 )
THEN
569 CALL dlacpy(
'L', p-1, p-1, x11(2,1), ldx11, u1(2,2), ldu1 )
570 CALL dorgqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
571 $ work(iorgqr), lorgqr, childinfo )
573 IF( wantu2 .AND. m-p .GT. 0 )
THEN
574 CALL dlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
575 CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
576 $ work(iorgqr), lorgqr, childinfo )
578 IF( wantv1t .AND. q .GT. 0 )
THEN
579 CALL dlacpy(
'U', p, q, x11, ldx11, v1t, ldv1t )
580 CALL dorglq( q, q, r, v1t, ldv1t, work(itauq1),
581 $ work(iorglq), lorglq, childinfo )
586 CALL dbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
587 $ work(iphi), v1t, ldv1t, dum2, 1, u1, ldu1, u2,
588 $ ldu2, work(ib11d), work(ib11e), work(ib12d),
589 $ work(ib12e), work(ib21d), work(ib21e),
590 $ work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,
596 IF( q .GT. 0 .AND. wantu2 )
THEN
598 iwork(i) = m - p - q + i
603 CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
605 ELSE IF( r .EQ. m-p )
THEN
611 CALL dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
612 $ work(iphi), work(itaup1), work(itaup2),
613 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
617 IF( wantu1 .AND. p .GT. 0 )
THEN
618 CALL dlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
619 CALL dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
620 $ lorgqr, childinfo )
622 IF( wantu2 .AND. m-p .GT. 0 )
THEN
628 CALL dlacpy(
'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
630 CALL dorgqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
631 $ work(itaup2), work(iorgqr), lorgqr, childinfo )
633 IF( wantv1t .AND. q .GT. 0 )
THEN
634 CALL dlacpy(
'U', m-p, q, x21, ldx21, v1t, ldv1t )
635 CALL dorglq( q, q, r, v1t, ldv1t, work(itauq1),
636 $ work(iorglq), lorglq, childinfo )
641 CALL dbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
642 $ theta, work(iphi), dum2, 1, v1t, ldv1t, u2,
643 $ ldu2, u1, ldu1, work(ib11d), work(ib11e),
644 $ work(ib12d), work(ib12e), work(ib21d),
645 $ work(ib21e), work(ib22d), work(ib22e),
646 $ work(ibbcsd), lbbcsd, childinfo )
659 CALL dlapmt( .false., p, q, u1, ldu1, iwork )
662 CALL dlapmr( .false., q, q, v1t, ldv1t, iwork )
671 CALL dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
672 $ work(iphi), work(itaup1), work(itaup2),
673 $ work(itauq1), work(iorbdb), work(iorbdb+m),
674 $ lorbdb-m, childinfo )
678 IF( wantu1 .AND. p .GT. 0 )
THEN
679 CALL dcopy( p, work(iorbdb), 1, u1, 1 )
683 CALL dlacpy(
'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
685 CALL dorgqr( p, p, m-q, u1, ldu1, work(itaup1),
686 $ work(iorgqr), lorgqr, childinfo )
688 IF( wantu2 .AND. m-p .GT. 0 )
THEN
689 CALL dcopy( m-p, work(iorbdb+p), 1, u2, 1 )
693 CALL dlacpy(
'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
695 CALL dorgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
696 $ work(iorgqr), lorgqr, childinfo )
698 IF( wantv1t .AND. q .GT. 0 )
THEN
699 CALL dlacpy(
'U', m-q, q, x21, ldx21, v1t, ldv1t )
700 CALL dlacpy(
'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,
701 $ v1t(m-q+1,m-q+1), ldv1t )
702 CALL dlacpy(
'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
703 $ v1t(p+1,p+1), ldv1t )
704 CALL dorglq( q, q, q, v1t, ldv1t, work(itauq1),
705 $ work(iorglq), lorglq, childinfo )
710 CALL dbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
711 $ theta, work(iphi), u2, ldu2, u1, ldu1, dum2,
712 $ 1, v1t, ldv1t, work(ib11d), work(ib11e),
713 $ work(ib12d), work(ib12e), work(ib21d),
714 $ work(ib21e), work(ib22d), work(ib22e),
715 $ work(ibbcsd), lbbcsd, childinfo )
728 CALL dlapmt( .false., p, p, u1, ldu1, iwork )
731 CALL dlapmr( .false., p, q, v1t, ldv1t, iwork )
subroutine dcopy(N, DX, INCX, DY, INCY)
DCOPY
subroutine dorglq(M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
DORGLQ
subroutine dlacpy(UPLO, M, N, A, LDA, B, LDB)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlapmt(FORWRD, M, N, X, LDX, K)
DLAPMT performs a forward or backward permutation of the columns of a matrix.
subroutine xerbla(SRNAME, INFO)
XERBLA
subroutine dorbdb1(M, P, Q, X11, LDX11, X21, LDX21, THETA, PHI, TAUP1, TAUP2, TAUQ1, WORK, LWORK, INFO)
DORBDB1
subroutine dorbdb3(M, P, Q, X11, LDX11, X21, LDX21, THETA, PHI, TAUP1, TAUP2, TAUQ1, WORK, LWORK, INFO)
DORBDB3
subroutine dorbdb2(M, P, Q, X11, LDX11, X21, LDX21, THETA, PHI, TAUP1, TAUP2, TAUQ1, WORK, LWORK, INFO)
DORBDB2
subroutine dorbdb4(M, P, Q, X11, LDX11, X21, LDX21, THETA, PHI, TAUP1, TAUP2, TAUQ1, PHANTOM, WORK, LWORK, INFO)
DORBDB4
subroutine dlapmr(FORWRD, M, N, X, LDX, K)
DLAPMR rearranges rows of a matrix as specified by a permutation vector.
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
logical function lsame(CA, CB)
LSAME
subroutine dorgqr(M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
DORGQR