LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ dbbcsd()

subroutine dbbcsd ( character jobu1,
character jobu2,
character jobv1t,
character jobv2t,
character trans,
integer m,
integer p,
integer q,
double precision, dimension( * ) theta,
double precision, dimension( * ) phi,
double precision, dimension( ldu1, * ) u1,
integer ldu1,
double precision, dimension( ldu2, * ) u2,
integer ldu2,
double precision, dimension( ldv1t, * ) v1t,
integer ldv1t,
double precision, dimension( ldv2t, * ) v2t,
integer ldv2t,
double precision, dimension( * ) b11d,
double precision, dimension( * ) b11e,
double precision, dimension( * ) b12d,
double precision, dimension( * ) b12e,
double precision, dimension( * ) b21d,
double precision, dimension( * ) b21e,
double precision, dimension( * ) b22d,
double precision, dimension( * ) b22e,
double precision, dimension( * ) work,
integer lwork,
integer info )

DBBCSD

Download DBBCSD + dependencies [TGZ] [ZIP] [TXT]

Purpose:
!>
!> DBBCSD computes the CS decomposition of an orthogonal matrix in
!> bidiagonal-block form,
!>
!>
!>     [ B11 | B12 0  0 ]
!>     [  0  |  0 -I  0 ]
!> X = [----------------]
!>     [ B21 | B22 0  0 ]
!>     [  0  |  0  0  I ]
!>
!>                               [  C | -S  0  0 ]
!>                   [ U1 |    ] [  0 |  0 -I  0 ] [ V1 |    ]**T
!>                 = [---------] [---------------] [---------]   .
!>                   [    | U2 ] [  S |  C  0  0 ] [    | V2 ]
!>                               [  0 |  0  0  I ]
!>
!> X is M-by-M, its top-left block is P-by-Q, and Q must be no larger
!> than P, M-P, or M-Q. (If Q is not the smallest index, then X must be
!> transposed and/or permuted. This can be done in constant time using
!> the TRANS and SIGNS options. See DORCSD for details.)
!>
!> The bidiagonal matrices B11, B12, B21, and B22 are represented
!> implicitly by angles THETA(1:Q) and PHI(1:Q-1).
!>
!> The orthogonal matrices U1, U2, V1T, and V2T are input/output.
!> The input matrices are pre- or post-multiplied by the appropriate
!> singular vector matrices.
!> 
Parameters
[in]JOBU1
!>          JOBU1 is CHARACTER
!>          = 'Y':      U1 is updated;
!>          otherwise:  U1 is not updated.
!> 
[in]JOBU2
!>          JOBU2 is CHARACTER
!>          = 'Y':      U2 is updated;
!>          otherwise:  U2 is not updated.
!> 
[in]JOBV1T
!>          JOBV1T is CHARACTER
!>          = 'Y':      V1T is updated;
!>          otherwise:  V1T is not updated.
!> 
[in]JOBV2T
!>          JOBV2T is CHARACTER
!>          = 'Y':      V2T is updated;
!>          otherwise:  V2T is not updated.
!> 
[in]TRANS
!>          TRANS is CHARACTER
!>          = 'T':      X, U1, U2, V1T, and V2T are stored in row-major
!>                      order;
!>          otherwise:  X, U1, U2, V1T, and V2T are stored in column-
!>                      major order.
!> 
[in]M
!>          M is INTEGER
!>          The number of rows and columns in X, the orthogonal matrix in
!>          bidiagonal-block form.
!> 
[in]P
!>          P is INTEGER
!>          The number of rows in the top-left block of X. 0 <= P <= M.
!> 
[in]Q
!>          Q is INTEGER
!>          The number of columns in the top-left block of X.
!>          0 <= Q <= MIN(P,M-P,M-Q).
!> 
[in,out]THETA
!>          THETA is DOUBLE PRECISION array, dimension (Q)
!>          On entry, the angles THETA(1),...,THETA(Q) that, along with
!>          PHI(1), ...,PHI(Q-1), define the matrix in bidiagonal-block
!>          form. On exit, the angles whose cosines and sines define the
!>          diagonal blocks in the CS decomposition.
!> 
[in,out]PHI
!>          PHI is DOUBLE PRECISION array, dimension (Q-1)
!>          The angles PHI(1),...,PHI(Q-1) that, along with THETA(1),...,
!>          THETA(Q), define the matrix in bidiagonal-block form.
!> 
[in,out]U1
!>          U1 is DOUBLE PRECISION array, dimension (LDU1,P)
!>          On entry, a P-by-P matrix. On exit, U1 is postmultiplied
!>          by the left singular vector matrix common to [ B11 ; 0 ] and
!>          [ B12 0 0 ; 0 -I 0 0 ].
!> 
[in]LDU1
!>          LDU1 is INTEGER
!>          The leading dimension of the array U1, LDU1 >= MAX(1,P).
!> 
[in,out]U2
!>          U2 is DOUBLE PRECISION array, dimension (LDU2,M-P)
!>          On entry, an (M-P)-by-(M-P) matrix. On exit, U2 is
!>          postmultiplied by the left singular vector matrix common to
!>          [ B21 ; 0 ] and [ B22 0 0 ; 0 0 I ].
!> 
[in]LDU2
!>          LDU2 is INTEGER
!>          The leading dimension of the array U2, LDU2 >= MAX(1,M-P).
!> 
[in,out]V1T
!>          V1T is DOUBLE PRECISION array, dimension (LDV1T,Q)
!>          On entry, a Q-by-Q matrix. On exit, V1T is premultiplied
!>          by the transpose of the right singular vector
!>          matrix common to [ B11 ; 0 ] and [ B21 ; 0 ].
!> 
[in]LDV1T
!>          LDV1T is INTEGER
!>          The leading dimension of the array V1T, LDV1T >= MAX(1,Q).
!> 
[in,out]V2T
!>          V2T is DOUBLE PRECISION array, dimension (LDV2T,M-Q)
!>          On entry, an (M-Q)-by-(M-Q) matrix. On exit, V2T is
!>          premultiplied by the transpose of the right
!>          singular vector matrix common to [ B12 0 0 ; 0 -I 0 ] and
!>          [ B22 0 0 ; 0 0 I ].
!> 
[in]LDV2T
!>          LDV2T is INTEGER
!>          The leading dimension of the array V2T, LDV2T >= MAX(1,M-Q).
!> 
[out]B11D
!>          B11D is DOUBLE PRECISION array, dimension (Q)
!>          When DBBCSD converges, B11D contains the cosines of THETA(1),
!>          ..., THETA(Q). If DBBCSD fails to converge, then B11D
!>          contains the diagonal of the partially reduced top-left
!>          block.
!> 
[out]B11E
!>          B11E is DOUBLE PRECISION array, dimension (Q-1)
!>          When DBBCSD converges, B11E contains zeros. If DBBCSD fails
!>          to converge, then B11E contains the superdiagonal of the
!>          partially reduced top-left block.
!> 
[out]B12D
!>          B12D is DOUBLE PRECISION array, dimension (Q)
!>          When DBBCSD converges, B12D contains the negative sines of
!>          THETA(1), ..., THETA(Q). If DBBCSD fails to converge, then
!>          B12D contains the diagonal of the partially reduced top-right
!>          block.
!> 
[out]B12E
!>          B12E is DOUBLE PRECISION array, dimension (Q-1)
!>          When DBBCSD converges, B12E contains zeros. If DBBCSD fails
!>          to converge, then B12E contains the subdiagonal of the
!>          partially reduced top-right block.
!> 
[out]B21D
!>          B21D is DOUBLE PRECISION  array, dimension (Q)
!>          When DBBCSD converges, B21D contains the negative sines of
!>          THETA(1), ..., THETA(Q). If DBBCSD fails to converge, then
!>          B21D contains the diagonal of the partially reduced bottom-left
!>          block.
!> 
[out]B21E
!>          B21E is DOUBLE PRECISION  array, dimension (Q-1)
!>          When DBBCSD converges, B21E contains zeros. If DBBCSD fails
!>          to converge, then B21E contains the subdiagonal of the
!>          partially reduced bottom-left block.
!> 
[out]B22D
!>          B22D is DOUBLE PRECISION  array, dimension (Q)
!>          When DBBCSD converges, B22D contains the negative sines of
!>          THETA(1), ..., THETA(Q). If DBBCSD fails to converge, then
!>          B22D contains the diagonal of the partially reduced bottom-right
!>          block.
!> 
[out]B22E
!>          B22E is DOUBLE PRECISION  array, dimension (Q-1)
!>          When DBBCSD converges, B22E contains zeros. If DBBCSD fails
!>          to converge, then B22E contains the subdiagonal of the
!>          partially reduced bottom-right block.
!> 
[out]WORK
!>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
!>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
!> 
[in]LWORK
!>          LWORK is INTEGER
!>          The dimension of the array WORK. LWORK >= MAX(1,8*Q).
!>
!>          If LWORK = -1, then a workspace query is assumed; the
!>          routine only calculates the optimal size of the WORK array,
!>          returns this value as the first entry of the work array, and
!>          no error message related to LWORK is issued by XERBLA.
!> 
[out]INFO
!>          INFO is INTEGER
!>          = 0:  successful exit.
!>          < 0:  if INFO = -i, the i-th argument had an illegal value.
!>          > 0:  if DBBCSD did not converge, INFO specifies the number
!>                of nonzero entries in PHI, and B11D, B11E, etc.,
!>                contain the partially reduced matrix.
!> 
Internal Parameters:
!>  TOLMUL  DOUBLE PRECISION, default = MAX(10,MIN(100,EPS**(-1/8)))
!>          TOLMUL controls the convergence criterion of the QR loop.
!>          Angles THETA(i), PHI(i) are rounded to 0 or PI/2 when they
!>          are within TOLMUL*EPS of either bound.
!> 
References:
[1] Brian D. Sutton. Computing the complete CS decomposition. Numer. Algorithms, 50(1):33-65, 2009.
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.

Definition at line 326 of file dbbcsd.f.

331*
332* -- LAPACK computational routine --
333* -- LAPACK is a software package provided by Univ. of Tennessee, --
334* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
335*
336* .. Scalar Arguments ..
337 CHARACTER JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS
338 INTEGER INFO, LDU1, LDU2, LDV1T, LDV2T, LWORK, M, P, Q
339* ..
340* .. Array Arguments ..
341 DOUBLE PRECISION B11D( * ), B11E( * ), B12D( * ), B12E( * ),
342 $ B21D( * ), B21E( * ), B22D( * ), B22E( * ),
343 $ PHI( * ), THETA( * ), WORK( * )
344 DOUBLE PRECISION U1( LDU1, * ), U2( LDU2, * ), V1T( LDV1T, * ),
345 $ V2T( LDV2T, * )
346* ..
347*
348* ===================================================================
349*
350* .. Parameters ..
351 INTEGER MAXITR
352 parameter( maxitr = 6 )
353 DOUBLE PRECISION HUNDRED, MEIGHTH, ONE, TEN, ZERO
354 parameter( hundred = 100.0d0, meighth = -0.125d0,
355 $ one = 1.0d0, ten = 10.0d0, zero = 0.0d0 )
356 DOUBLE PRECISION NEGONE
357 parameter( negone = -1.0d0 )
358 DOUBLE PRECISION PIOVER2
359 parameter( piover2 = 1.57079632679489661923132169163975144210d0 )
360* ..
361* .. Local Scalars ..
362 LOGICAL COLMAJOR, LQUERY, RESTART11, RESTART12,
363 $ RESTART21, RESTART22, WANTU1, WANTU2, WANTV1T,
364 $ WANTV2T
365 INTEGER I, IMIN, IMAX, ITER, IU1CS, IU1SN, IU2CS,
366 $ IU2SN, IV1TCS, IV1TSN, IV2TCS, IV2TSN, J,
367 $ LWORKMIN, LWORKOPT, MAXIT, MINI
368 DOUBLE PRECISION B11BULGE, B12BULGE, B21BULGE, B22BULGE, DUMMY,
369 $ EPS, MU, NU, R, SIGMA11, SIGMA21,
370 $ TEMP, THETAMAX, THETAMIN, THRESH, TOL, TOLMUL,
371 $ UNFL, X1, X2, Y1, Y2
372*
373* .. External Subroutines ..
374 EXTERNAL dlasr, dscal, dswap, dlartgp, dlartgs,
375 $ dlas2,
376 $ xerbla
377* ..
378* .. External Functions ..
379 DOUBLE PRECISION DLAMCH
380 LOGICAL LSAME
381 EXTERNAL lsame, dlamch
382* ..
383* .. Intrinsic Functions ..
384 INTRINSIC abs, atan2, cos, max, min, sin, sqrt
385* ..
386* .. Executable Statements ..
387*
388* Test input arguments
389*
390 info = 0
391 lquery = lwork .EQ. -1
392 wantu1 = lsame( jobu1, 'Y' )
393 wantu2 = lsame( jobu2, 'Y' )
394 wantv1t = lsame( jobv1t, 'Y' )
395 wantv2t = lsame( jobv2t, 'Y' )
396 colmajor = .NOT. lsame( trans, 'T' )
397*
398 IF( m .LT. 0 ) THEN
399 info = -6
400 ELSE IF( p .LT. 0 .OR. p .GT. m ) THEN
401 info = -7
402 ELSE IF( q .LT. 0 .OR. q .GT. m ) THEN
403 info = -8
404 ELSE IF( q .GT. p .OR. q .GT. m-p .OR. q .GT. m-q ) THEN
405 info = -8
406 ELSE IF( wantu1 .AND. ldu1 .LT. p ) THEN
407 info = -12
408 ELSE IF( wantu2 .AND. ldu2 .LT. m-p ) THEN
409 info = -14
410 ELSE IF( wantv1t .AND. ldv1t .LT. q ) THEN
411 info = -16
412 ELSE IF( wantv2t .AND. ldv2t .LT. m-q ) THEN
413 info = -18
414 END IF
415*
416* Quick return if Q = 0
417*
418 IF( info .EQ. 0 .AND. q .EQ. 0 ) THEN
419 lworkmin = 1
420 work(1) = lworkmin
421 RETURN
422 END IF
423*
424* Compute workspace
425*
426 IF( info .EQ. 0 ) THEN
427 iu1cs = 1
428 iu1sn = iu1cs + q
429 iu2cs = iu1sn + q
430 iu2sn = iu2cs + q
431 iv1tcs = iu2sn + q
432 iv1tsn = iv1tcs + q
433 iv2tcs = iv1tsn + q
434 iv2tsn = iv2tcs + q
435 lworkopt = iv2tsn + q - 1
436 lworkmin = lworkopt
437 work(1) = lworkopt
438 IF( lwork .LT. lworkmin .AND. .NOT. lquery ) THEN
439 info = -28
440 END IF
441 END IF
442*
443 IF( info .NE. 0 ) THEN
444 CALL xerbla( 'DBBCSD', -info )
445 RETURN
446 ELSE IF( lquery ) THEN
447 RETURN
448 END IF
449*
450* Get machine constants
451*
452 eps = dlamch( 'Epsilon' )
453 unfl = dlamch( 'Safe minimum' )
454 tolmul = max( ten, min( hundred, eps**meighth ) )
455 tol = tolmul*eps
456 thresh = max( tol, maxitr*q*q*unfl )
457*
458* Test for negligible sines or cosines
459*
460 DO i = 1, q
461 IF( theta(i) .LT. thresh ) THEN
462 theta(i) = zero
463 ELSE IF( theta(i) .GT. piover2-thresh ) THEN
464 theta(i) = piover2
465 END IF
466 END DO
467 DO i = 1, q-1
468 IF( phi(i) .LT. thresh ) THEN
469 phi(i) = zero
470 ELSE IF( phi(i) .GT. piover2-thresh ) THEN
471 phi(i) = piover2
472 END IF
473 END DO
474*
475* Initial deflation
476*
477 imax = q
478 DO WHILE( imax .GT. 1 )
479 IF( phi(imax-1) .NE. zero ) THEN
480 EXIT
481 END IF
482 imax = imax - 1
483 END DO
484 imin = imax - 1
485 IF ( imin .GT. 1 ) THEN
486 DO WHILE( phi(imin-1) .NE. zero )
487 imin = imin - 1
488 IF ( imin .LE. 1 ) EXIT
489 END DO
490 END IF
491*
492* Initialize iteration counter
493*
494 maxit = maxitr*q*q
495 iter = 0
496*
497* Begin main iteration loop
498*
499 DO WHILE( imax .GT. 1 )
500*
501* Compute the matrix entries
502*
503 b11d(imin) = cos( theta(imin) )
504 b21d(imin) = -sin( theta(imin) )
505 DO i = imin, imax - 1
506 b11e(i) = -sin( theta(i) ) * sin( phi(i) )
507 b11d(i+1) = cos( theta(i+1) ) * cos( phi(i) )
508 b12d(i) = sin( theta(i) ) * cos( phi(i) )
509 b12e(i) = cos( theta(i+1) ) * sin( phi(i) )
510 b21e(i) = -cos( theta(i) ) * sin( phi(i) )
511 b21d(i+1) = -sin( theta(i+1) ) * cos( phi(i) )
512 b22d(i) = cos( theta(i) ) * cos( phi(i) )
513 b22e(i) = -sin( theta(i+1) ) * sin( phi(i) )
514 END DO
515 b12d(imax) = sin( theta(imax) )
516 b22d(imax) = cos( theta(imax) )
517*
518* Abort if not converging; otherwise, increment ITER
519*
520 IF( iter .GT. maxit ) THEN
521 info = 0
522 DO i = 1, q
523 IF( phi(i) .NE. zero )
524 $ info = info + 1
525 END DO
526 RETURN
527 END IF
528*
529 iter = iter + imax - imin
530*
531* Compute shifts
532*
533 thetamax = theta(imin)
534 thetamin = theta(imin)
535 DO i = imin+1, imax
536 IF( theta(i) > thetamax )
537 $ thetamax = theta(i)
538 IF( theta(i) < thetamin )
539 $ thetamin = theta(i)
540 END DO
541*
542 IF( thetamax .GT. piover2 - thresh ) THEN
543*
544* Zero on diagonals of B11 and B22; induce deflation with a
545* zero shift
546*
547 mu = zero
548 nu = one
549*
550 ELSE IF( thetamin .LT. thresh ) THEN
551*
552* Zero on diagonals of B12 and B22; induce deflation with a
553* zero shift
554*
555 mu = one
556 nu = zero
557*
558 ELSE
559*
560* Compute shifts for B11 and B21 and use the lesser
561*
562 CALL dlas2( b11d(imax-1), b11e(imax-1), b11d(imax),
563 $ sigma11,
564 $ dummy )
565 CALL dlas2( b21d(imax-1), b21e(imax-1), b21d(imax),
566 $ sigma21,
567 $ dummy )
568*
569 IF( sigma11 .LE. sigma21 ) THEN
570 mu = sigma11
571 nu = sqrt( one - mu**2 )
572 IF( mu .LT. thresh ) THEN
573 mu = zero
574 nu = one
575 END IF
576 ELSE
577 nu = sigma21
578 mu = sqrt( 1.0 - nu**2 )
579 IF( nu .LT. thresh ) THEN
580 mu = one
581 nu = zero
582 END IF
583 END IF
584 END IF
585*
586* Rotate to produce bulges in B11 and B21
587*
588 IF( mu .LE. nu ) THEN
589 CALL dlartgs( b11d(imin), b11e(imin), mu,
590 $ work(iv1tcs+imin-1), work(iv1tsn+imin-1) )
591 ELSE
592 CALL dlartgs( b21d(imin), b21e(imin), nu,
593 $ work(iv1tcs+imin-1), work(iv1tsn+imin-1) )
594 END IF
595*
596 temp = work(iv1tcs+imin-1)*b11d(imin) +
597 $ work(iv1tsn+imin-1)*b11e(imin)
598 b11e(imin) = work(iv1tcs+imin-1)*b11e(imin) -
599 $ work(iv1tsn+imin-1)*b11d(imin)
600 b11d(imin) = temp
601 b11bulge = work(iv1tsn+imin-1)*b11d(imin+1)
602 b11d(imin+1) = work(iv1tcs+imin-1)*b11d(imin+1)
603 temp = work(iv1tcs+imin-1)*b21d(imin) +
604 $ work(iv1tsn+imin-1)*b21e(imin)
605 b21e(imin) = work(iv1tcs+imin-1)*b21e(imin) -
606 $ work(iv1tsn+imin-1)*b21d(imin)
607 b21d(imin) = temp
608 b21bulge = work(iv1tsn+imin-1)*b21d(imin+1)
609 b21d(imin+1) = work(iv1tcs+imin-1)*b21d(imin+1)
610*
611* Compute THETA(IMIN)
612*
613 theta( imin ) = atan2( sqrt( b21d(imin)**2+b21bulge**2 ),
614 $ sqrt( b11d(imin)**2+b11bulge**2 ) )
615*
616* Chase the bulges in B11(IMIN+1,IMIN) and B21(IMIN+1,IMIN)
617*
618 IF( b11d(imin)**2+b11bulge**2 .GT. thresh**2 ) THEN
619 CALL dlartgp( b11bulge, b11d(imin), work(iu1sn+imin-1),
620 $ work(iu1cs+imin-1), r )
621 ELSE IF( mu .LE. nu ) THEN
622 CALL dlartgs( b11e( imin ), b11d( imin + 1 ), mu,
623 $ work(iu1cs+imin-1), work(iu1sn+imin-1) )
624 ELSE
625 CALL dlartgs( b12d( imin ), b12e( imin ), nu,
626 $ work(iu1cs+imin-1), work(iu1sn+imin-1) )
627 END IF
628 IF( b21d(imin)**2+b21bulge**2 .GT. thresh**2 ) THEN
629 CALL dlartgp( b21bulge, b21d(imin), work(iu2sn+imin-1),
630 $ work(iu2cs+imin-1), r )
631 ELSE IF( nu .LT. mu ) THEN
632 CALL dlartgs( b21e( imin ), b21d( imin + 1 ), nu,
633 $ work(iu2cs+imin-1), work(iu2sn+imin-1) )
634 ELSE
635 CALL dlartgs( b22d(imin), b22e(imin), mu,
636 $ work(iu2cs+imin-1), work(iu2sn+imin-1) )
637 END IF
638 work(iu2cs+imin-1) = -work(iu2cs+imin-1)
639 work(iu2sn+imin-1) = -work(iu2sn+imin-1)
640*
641 temp = work(iu1cs+imin-1)*b11e(imin) +
642 $ work(iu1sn+imin-1)*b11d(imin+1)
643 b11d(imin+1) = work(iu1cs+imin-1)*b11d(imin+1) -
644 $ work(iu1sn+imin-1)*b11e(imin)
645 b11e(imin) = temp
646 IF( imax .GT. imin+1 ) THEN
647 b11bulge = work(iu1sn+imin-1)*b11e(imin+1)
648 b11e(imin+1) = work(iu1cs+imin-1)*b11e(imin+1)
649 END IF
650 temp = work(iu1cs+imin-1)*b12d(imin) +
651 $ work(iu1sn+imin-1)*b12e(imin)
652 b12e(imin) = work(iu1cs+imin-1)*b12e(imin) -
653 $ work(iu1sn+imin-1)*b12d(imin)
654 b12d(imin) = temp
655 b12bulge = work(iu1sn+imin-1)*b12d(imin+1)
656 b12d(imin+1) = work(iu1cs+imin-1)*b12d(imin+1)
657 temp = work(iu2cs+imin-1)*b21e(imin) +
658 $ work(iu2sn+imin-1)*b21d(imin+1)
659 b21d(imin+1) = work(iu2cs+imin-1)*b21d(imin+1) -
660 $ work(iu2sn+imin-1)*b21e(imin)
661 b21e(imin) = temp
662 IF( imax .GT. imin+1 ) THEN
663 b21bulge = work(iu2sn+imin-1)*b21e(imin+1)
664 b21e(imin+1) = work(iu2cs+imin-1)*b21e(imin+1)
665 END IF
666 temp = work(iu2cs+imin-1)*b22d(imin) +
667 $ work(iu2sn+imin-1)*b22e(imin)
668 b22e(imin) = work(iu2cs+imin-1)*b22e(imin) -
669 $ work(iu2sn+imin-1)*b22d(imin)
670 b22d(imin) = temp
671 b22bulge = work(iu2sn+imin-1)*b22d(imin+1)
672 b22d(imin+1) = work(iu2cs+imin-1)*b22d(imin+1)
673*
674* Inner loop: chase bulges from B11(IMIN,IMIN+2),
675* B12(IMIN,IMIN+1), B21(IMIN,IMIN+2), and B22(IMIN,IMIN+1) to
676* bottom-right
677*
678 DO i = imin+1, imax-1
679*
680* Compute PHI(I-1)
681*
682 x1 = sin(theta(i-1))*b11e(i-1) + cos(theta(i-1))*b21e(i-1)
683 x2 = sin(theta(i-1))*b11bulge + cos(theta(i-1))*b21bulge
684 y1 = sin(theta(i-1))*b12d(i-1) + cos(theta(i-1))*b22d(i-1)
685 y2 = sin(theta(i-1))*b12bulge + cos(theta(i-1))*b22bulge
686*
687 phi(i-1) = atan2( sqrt(x1**2+x2**2), sqrt(y1**2+y2**2) )
688*
689* Determine if there are bulges to chase or if a new direct
690* summand has been reached
691*
692 restart11 = b11e(i-1)**2 + b11bulge**2 .LE. thresh**2
693 restart21 = b21e(i-1)**2 + b21bulge**2 .LE. thresh**2
694 restart12 = b12d(i-1)**2 + b12bulge**2 .LE. thresh**2
695 restart22 = b22d(i-1)**2 + b22bulge**2 .LE. thresh**2
696*
697* If possible, chase bulges from B11(I-1,I+1), B12(I-1,I),
698* B21(I-1,I+1), and B22(I-1,I). If necessary, restart bulge-
699* chasing by applying the original shift again.
700*
701 IF( .NOT. restart11 .AND. .NOT. restart21 ) THEN
702 CALL dlartgp( x2, x1, work(iv1tsn+i-1),
703 $ work(iv1tcs+i-1),
704 $ r )
705 ELSE IF( .NOT. restart11 .AND. restart21 ) THEN
706 CALL dlartgp( b11bulge, b11e(i-1), work(iv1tsn+i-1),
707 $ work(iv1tcs+i-1), r )
708 ELSE IF( restart11 .AND. .NOT. restart21 ) THEN
709 CALL dlartgp( b21bulge, b21e(i-1), work(iv1tsn+i-1),
710 $ work(iv1tcs+i-1), r )
711 ELSE IF( mu .LE. nu ) THEN
712 CALL dlartgs( b11d(i), b11e(i), mu, work(iv1tcs+i-1),
713 $ work(iv1tsn+i-1) )
714 ELSE
715 CALL dlartgs( b21d(i), b21e(i), nu, work(iv1tcs+i-1),
716 $ work(iv1tsn+i-1) )
717 END IF
718 work(iv1tcs+i-1) = -work(iv1tcs+i-1)
719 work(iv1tsn+i-1) = -work(iv1tsn+i-1)
720 IF( .NOT. restart12 .AND. .NOT. restart22 ) THEN
721 CALL dlartgp( y2, y1, work(iv2tsn+i-1-1),
722 $ work(iv2tcs+i-1-1), r )
723 ELSE IF( .NOT. restart12 .AND. restart22 ) THEN
724 CALL dlartgp( b12bulge, b12d(i-1), work(iv2tsn+i-1-1),
725 $ work(iv2tcs+i-1-1), r )
726 ELSE IF( restart12 .AND. .NOT. restart22 ) THEN
727 CALL dlartgp( b22bulge, b22d(i-1), work(iv2tsn+i-1-1),
728 $ work(iv2tcs+i-1-1), r )
729 ELSE IF( nu .LT. mu ) THEN
730 CALL dlartgs( b12e(i-1), b12d(i), nu,
731 $ work(iv2tcs+i-1-1),
732 $ work(iv2tsn+i-1-1) )
733 ELSE
734 CALL dlartgs( b22e(i-1), b22d(i), mu,
735 $ work(iv2tcs+i-1-1),
736 $ work(iv2tsn+i-1-1) )
737 END IF
738*
739 temp = work(iv1tcs+i-1)*b11d(i) + work(iv1tsn+i-1)*b11e(i)
740 b11e(i) = work(iv1tcs+i-1)*b11e(i) -
741 $ work(iv1tsn+i-1)*b11d(i)
742 b11d(i) = temp
743 b11bulge = work(iv1tsn+i-1)*b11d(i+1)
744 b11d(i+1) = work(iv1tcs+i-1)*b11d(i+1)
745 temp = work(iv1tcs+i-1)*b21d(i) + work(iv1tsn+i-1)*b21e(i)
746 b21e(i) = work(iv1tcs+i-1)*b21e(i) -
747 $ work(iv1tsn+i-1)*b21d(i)
748 b21d(i) = temp
749 b21bulge = work(iv1tsn+i-1)*b21d(i+1)
750 b21d(i+1) = work(iv1tcs+i-1)*b21d(i+1)
751 temp = work(iv2tcs+i-1-1)*b12e(i-1) +
752 $ work(iv2tsn+i-1-1)*b12d(i)
753 b12d(i) = work(iv2tcs+i-1-1)*b12d(i) -
754 $ work(iv2tsn+i-1-1)*b12e(i-1)
755 b12e(i-1) = temp
756 b12bulge = work(iv2tsn+i-1-1)*b12e(i)
757 b12e(i) = work(iv2tcs+i-1-1)*b12e(i)
758 temp = work(iv2tcs+i-1-1)*b22e(i-1) +
759 $ work(iv2tsn+i-1-1)*b22d(i)
760 b22d(i) = work(iv2tcs+i-1-1)*b22d(i) -
761 $ work(iv2tsn+i-1-1)*b22e(i-1)
762 b22e(i-1) = temp
763 b22bulge = work(iv2tsn+i-1-1)*b22e(i)
764 b22e(i) = work(iv2tcs+i-1-1)*b22e(i)
765*
766* Compute THETA(I)
767*
768 x1 = cos(phi(i-1))*b11d(i) + sin(phi(i-1))*b12e(i-1)
769 x2 = cos(phi(i-1))*b11bulge + sin(phi(i-1))*b12bulge
770 y1 = cos(phi(i-1))*b21d(i) + sin(phi(i-1))*b22e(i-1)
771 y2 = cos(phi(i-1))*b21bulge + sin(phi(i-1))*b22bulge
772*
773 theta(i) = atan2( sqrt(y1**2+y2**2), sqrt(x1**2+x2**2) )
774*
775* Determine if there are bulges to chase or if a new direct
776* summand has been reached
777*
778 restart11 = b11d(i)**2 + b11bulge**2 .LE. thresh**2
779 restart12 = b12e(i-1)**2 + b12bulge**2 .LE. thresh**2
780 restart21 = b21d(i)**2 + b21bulge**2 .LE. thresh**2
781 restart22 = b22e(i-1)**2 + b22bulge**2 .LE. thresh**2
782*
783* If possible, chase bulges from B11(I+1,I), B12(I+1,I-1),
784* B21(I+1,I), and B22(I+1,I-1). If necessary, restart bulge-
785* chasing by applying the original shift again.
786*
787 IF( .NOT. restart11 .AND. .NOT. restart12 ) THEN
788 CALL dlartgp( x2, x1, work(iu1sn+i-1),
789 $ work(iu1cs+i-1),
790 $ r )
791 ELSE IF( .NOT. restart11 .AND. restart12 ) THEN
792 CALL dlartgp( b11bulge, b11d(i), work(iu1sn+i-1),
793 $ work(iu1cs+i-1), r )
794 ELSE IF( restart11 .AND. .NOT. restart12 ) THEN
795 CALL dlartgp( b12bulge, b12e(i-1), work(iu1sn+i-1),
796 $ work(iu1cs+i-1), r )
797 ELSE IF( mu .LE. nu ) THEN
798 CALL dlartgs( b11e(i), b11d(i+1), mu, work(iu1cs+i-1),
799 $ work(iu1sn+i-1) )
800 ELSE
801 CALL dlartgs( b12d(i), b12e(i), nu, work(iu1cs+i-1),
802 $ work(iu1sn+i-1) )
803 END IF
804 IF( .NOT. restart21 .AND. .NOT. restart22 ) THEN
805 CALL dlartgp( y2, y1, work(iu2sn+i-1),
806 $ work(iu2cs+i-1),
807 $ r )
808 ELSE IF( .NOT. restart21 .AND. restart22 ) THEN
809 CALL dlartgp( b21bulge, b21d(i), work(iu2sn+i-1),
810 $ work(iu2cs+i-1), r )
811 ELSE IF( restart21 .AND. .NOT. restart22 ) THEN
812 CALL dlartgp( b22bulge, b22e(i-1), work(iu2sn+i-1),
813 $ work(iu2cs+i-1), r )
814 ELSE IF( nu .LT. mu ) THEN
815 CALL dlartgs( b21e(i), b21e(i+1), nu, work(iu2cs+i-1),
816 $ work(iu2sn+i-1) )
817 ELSE
818 CALL dlartgs( b22d(i), b22e(i), mu, work(iu2cs+i-1),
819 $ work(iu2sn+i-1) )
820 END IF
821 work(iu2cs+i-1) = -work(iu2cs+i-1)
822 work(iu2sn+i-1) = -work(iu2sn+i-1)
823*
824 temp = work(iu1cs+i-1)*b11e(i) + work(iu1sn+i-1)*b11d(i+1)
825 b11d(i+1) = work(iu1cs+i-1)*b11d(i+1) -
826 $ work(iu1sn+i-1)*b11e(i)
827 b11e(i) = temp
828 IF( i .LT. imax - 1 ) THEN
829 b11bulge = work(iu1sn+i-1)*b11e(i+1)
830 b11e(i+1) = work(iu1cs+i-1)*b11e(i+1)
831 END IF
832 temp = work(iu2cs+i-1)*b21e(i) + work(iu2sn+i-1)*b21d(i+1)
833 b21d(i+1) = work(iu2cs+i-1)*b21d(i+1) -
834 $ work(iu2sn+i-1)*b21e(i)
835 b21e(i) = temp
836 IF( i .LT. imax - 1 ) THEN
837 b21bulge = work(iu2sn+i-1)*b21e(i+1)
838 b21e(i+1) = work(iu2cs+i-1)*b21e(i+1)
839 END IF
840 temp = work(iu1cs+i-1)*b12d(i) + work(iu1sn+i-1)*b12e(i)
841 b12e(i) = work(iu1cs+i-1)*b12e(i) - work(iu1sn+i-1)*b12d(i)
842 b12d(i) = temp
843 b12bulge = work(iu1sn+i-1)*b12d(i+1)
844 b12d(i+1) = work(iu1cs+i-1)*b12d(i+1)
845 temp = work(iu2cs+i-1)*b22d(i) + work(iu2sn+i-1)*b22e(i)
846 b22e(i) = work(iu2cs+i-1)*b22e(i) - work(iu2sn+i-1)*b22d(i)
847 b22d(i) = temp
848 b22bulge = work(iu2sn+i-1)*b22d(i+1)
849 b22d(i+1) = work(iu2cs+i-1)*b22d(i+1)
850*
851 END DO
852*
853* Compute PHI(IMAX-1)
854*
855 x1 = sin(theta(imax-1))*b11e(imax-1) +
856 $ cos(theta(imax-1))*b21e(imax-1)
857 y1 = sin(theta(imax-1))*b12d(imax-1) +
858 $ cos(theta(imax-1))*b22d(imax-1)
859 y2 = sin(theta(imax-1))*b12bulge + cos(theta(imax-1))*b22bulge
860*
861 phi(imax-1) = atan2( abs(x1), sqrt(y1**2+y2**2) )
862*
863* Chase bulges from B12(IMAX-1,IMAX) and B22(IMAX-1,IMAX)
864*
865 restart12 = b12d(imax-1)**2 + b12bulge**2 .LE. thresh**2
866 restart22 = b22d(imax-1)**2 + b22bulge**2 .LE. thresh**2
867*
868 IF( .NOT. restart12 .AND. .NOT. restart22 ) THEN
869 CALL dlartgp( y2, y1, work(iv2tsn+imax-1-1),
870 $ work(iv2tcs+imax-1-1), r )
871 ELSE IF( .NOT. restart12 .AND. restart22 ) THEN
872 CALL dlartgp( b12bulge, b12d(imax-1),
873 $ work(iv2tsn+imax-1-1),
874 $ work(iv2tcs+imax-1-1), r )
875 ELSE IF( restart12 .AND. .NOT. restart22 ) THEN
876 CALL dlartgp( b22bulge, b22d(imax-1),
877 $ work(iv2tsn+imax-1-1),
878 $ work(iv2tcs+imax-1-1), r )
879 ELSE IF( nu .LT. mu ) THEN
880 CALL dlartgs( b12e(imax-1), b12d(imax), nu,
881 $ work(iv2tcs+imax-1-1), work(iv2tsn+imax-1-1) )
882 ELSE
883 CALL dlartgs( b22e(imax-1), b22d(imax), mu,
884 $ work(iv2tcs+imax-1-1), work(iv2tsn+imax-1-1) )
885 END IF
886*
887 temp = work(iv2tcs+imax-1-1)*b12e(imax-1) +
888 $ work(iv2tsn+imax-1-1)*b12d(imax)
889 b12d(imax) = work(iv2tcs+imax-1-1)*b12d(imax) -
890 $ work(iv2tsn+imax-1-1)*b12e(imax-1)
891 b12e(imax-1) = temp
892 temp = work(iv2tcs+imax-1-1)*b22e(imax-1) +
893 $ work(iv2tsn+imax-1-1)*b22d(imax)
894 b22d(imax) = work(iv2tcs+imax-1-1)*b22d(imax) -
895 $ work(iv2tsn+imax-1-1)*b22e(imax-1)
896 b22e(imax-1) = temp
897*
898* Update singular vectors
899*
900 IF( wantu1 ) THEN
901 IF( colmajor ) THEN
902 CALL dlasr( 'R', 'V', 'F', p, imax-imin+1,
903 $ work(iu1cs+imin-1), work(iu1sn+imin-1),
904 $ u1(1,imin), ldu1 )
905 ELSE
906 CALL dlasr( 'L', 'V', 'F', imax-imin+1, p,
907 $ work(iu1cs+imin-1), work(iu1sn+imin-1),
908 $ u1(imin,1), ldu1 )
909 END IF
910 END IF
911 IF( wantu2 ) THEN
912 IF( colmajor ) THEN
913 CALL dlasr( 'R', 'V', 'F', m-p, imax-imin+1,
914 $ work(iu2cs+imin-1), work(iu2sn+imin-1),
915 $ u2(1,imin), ldu2 )
916 ELSE
917 CALL dlasr( 'L', 'V', 'F', imax-imin+1, m-p,
918 $ work(iu2cs+imin-1), work(iu2sn+imin-1),
919 $ u2(imin,1), ldu2 )
920 END IF
921 END IF
922 IF( wantv1t ) THEN
923 IF( colmajor ) THEN
924 CALL dlasr( 'L', 'V', 'F', imax-imin+1, q,
925 $ work(iv1tcs+imin-1), work(iv1tsn+imin-1),
926 $ v1t(imin,1), ldv1t )
927 ELSE
928 CALL dlasr( 'R', 'V', 'F', q, imax-imin+1,
929 $ work(iv1tcs+imin-1), work(iv1tsn+imin-1),
930 $ v1t(1,imin), ldv1t )
931 END IF
932 END IF
933 IF( wantv2t ) THEN
934 IF( colmajor ) THEN
935 CALL dlasr( 'L', 'V', 'F', imax-imin+1, m-q,
936 $ work(iv2tcs+imin-1), work(iv2tsn+imin-1),
937 $ v2t(imin,1), ldv2t )
938 ELSE
939 CALL dlasr( 'R', 'V', 'F', m-q, imax-imin+1,
940 $ work(iv2tcs+imin-1), work(iv2tsn+imin-1),
941 $ v2t(1,imin), ldv2t )
942 END IF
943 END IF
944*
945* Fix signs on B11(IMAX-1,IMAX) and B21(IMAX-1,IMAX)
946*
947 IF( b11e(imax-1)+b21e(imax-1) .GT. 0 ) THEN
948 b11d(imax) = -b11d(imax)
949 b21d(imax) = -b21d(imax)
950 IF( wantv1t ) THEN
951 IF( colmajor ) THEN
952 CALL dscal( q, negone, v1t(imax,1), ldv1t )
953 ELSE
954 CALL dscal( q, negone, v1t(1,imax), 1 )
955 END IF
956 END IF
957 END IF
958*
959* Compute THETA(IMAX)
960*
961 x1 = cos(phi(imax-1))*b11d(imax) +
962 $ sin(phi(imax-1))*b12e(imax-1)
963 y1 = cos(phi(imax-1))*b21d(imax) +
964 $ sin(phi(imax-1))*b22e(imax-1)
965*
966 theta(imax) = atan2( abs(y1), abs(x1) )
967*
968* Fix signs on B11(IMAX,IMAX), B12(IMAX,IMAX-1), B21(IMAX,IMAX),
969* and B22(IMAX,IMAX-1)
970*
971 IF( b11d(imax)+b12e(imax-1) .LT. 0 ) THEN
972 b12d(imax) = -b12d(imax)
973 IF( wantu1 ) THEN
974 IF( colmajor ) THEN
975 CALL dscal( p, negone, u1(1,imax), 1 )
976 ELSE
977 CALL dscal( p, negone, u1(imax,1), ldu1 )
978 END IF
979 END IF
980 END IF
981 IF( b21d(imax)+b22e(imax-1) .GT. 0 ) THEN
982 b22d(imax) = -b22d(imax)
983 IF( wantu2 ) THEN
984 IF( colmajor ) THEN
985 CALL dscal( m-p, negone, u2(1,imax), 1 )
986 ELSE
987 CALL dscal( m-p, negone, u2(imax,1), ldu2 )
988 END IF
989 END IF
990 END IF
991*
992* Fix signs on B12(IMAX,IMAX) and B22(IMAX,IMAX)
993*
994 IF( b12d(imax)+b22d(imax) .LT. 0 ) THEN
995 IF( wantv2t ) THEN
996 IF( colmajor ) THEN
997 CALL dscal( m-q, negone, v2t(imax,1), ldv2t )
998 ELSE
999 CALL dscal( m-q, negone, v2t(1,imax), 1 )
1000 END IF
1001 END IF
1002 END IF
1003*
1004* Test for negligible sines or cosines
1005*
1006 DO i = imin, imax
1007 IF( theta(i) .LT. thresh ) THEN
1008 theta(i) = zero
1009 ELSE IF( theta(i) .GT. piover2-thresh ) THEN
1010 theta(i) = piover2
1011 END IF
1012 END DO
1013 DO i = imin, imax-1
1014 IF( phi(i) .LT. thresh ) THEN
1015 phi(i) = zero
1016 ELSE IF( phi(i) .GT. piover2-thresh ) THEN
1017 phi(i) = piover2
1018 END IF
1019 END DO
1020*
1021* Deflate
1022*
1023 IF (imax .GT. 1) THEN
1024 DO WHILE( phi(imax-1) .EQ. zero )
1025 imax = imax - 1
1026 IF (imax .LE. 1) EXIT
1027 END DO
1028 END IF
1029 IF( imin .GT. imax - 1 )
1030 $ imin = imax - 1
1031 IF (imin .GT. 1) THEN
1032 DO WHILE (phi(imin-1) .NE. zero)
1033 imin = imin - 1
1034 IF (imin .LE. 1) EXIT
1035 END DO
1036 END IF
1037*
1038* Repeat main iteration loop
1039*
1040 END DO
1041*
1042* Postprocessing: order THETA from least to greatest
1043*
1044 DO i = 1, q
1045*
1046 mini = i
1047 thetamin = theta(i)
1048 DO j = i+1, q
1049 IF( theta(j) .LT. thetamin ) THEN
1050 mini = j
1051 thetamin = theta(j)
1052 END IF
1053 END DO
1054*
1055 IF( mini .NE. i ) THEN
1056 theta(mini) = theta(i)
1057 theta(i) = thetamin
1058 IF( colmajor ) THEN
1059 IF( wantu1 )
1060 $ CALL dswap( p, u1(1,i), 1, u1(1,mini), 1 )
1061 IF( wantu2 )
1062 $ CALL dswap( m-p, u2(1,i), 1, u2(1,mini), 1 )
1063 IF( wantv1t )
1064 $ CALL dswap( q, v1t(i,1), ldv1t, v1t(mini,1),
1065 $ ldv1t )
1066 IF( wantv2t )
1067 $ CALL dswap( m-q, v2t(i,1), ldv2t, v2t(mini,1),
1068 $ ldv2t )
1069 ELSE
1070 IF( wantu1 )
1071 $ CALL dswap( p, u1(i,1), ldu1, u1(mini,1), ldu1 )
1072 IF( wantu2 )
1073 $ CALL dswap( m-p, u2(i,1), ldu2, u2(mini,1), ldu2 )
1074 IF( wantv1t )
1075 $ CALL dswap( q, v1t(1,i), 1, v1t(1,mini), 1 )
1076 IF( wantv2t )
1077 $ CALL dswap( m-q, v2t(1,i), 1, v2t(1,mini), 1 )
1078 END IF
1079 END IF
1080*
1081 END DO
1082*
1083 RETURN
1084*
1085* End of DBBCSD
1086*
subroutine xerbla(srname, info)
Definition cblat2.f:3285
double precision function dlamch(cmach)
DLAMCH
Definition dlamch.f:69
subroutine dlartgp(f, g, cs, sn, r)
DLARTGP generates a plane rotation so that the diagonal is nonnegative.
Definition dlartgp.f:93
subroutine dlartgs(x, y, sigma, cs, sn)
DLARTGS generates a plane rotation designed to introduce a bulge in implicit QR iteration for the bid...
Definition dlartgs.f:88
subroutine dlas2(f, g, h, ssmin, ssmax)
DLAS2 computes singular values of a 2-by-2 triangular matrix.
Definition dlas2.f:103
subroutine dlasr(side, pivot, direct, m, n, c, s, a, lda)
DLASR applies a sequence of plane rotations to a general rectangular matrix.
Definition dlasr.f:197
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
subroutine dscal(n, da, dx, incx)
DSCAL
Definition dscal.f:79
subroutine dswap(n, dx, incx, dy, incy)
DSWAP
Definition dswap.f:82
Here is the call graph for this function:
Here is the caller graph for this function: