3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download CBDSQR + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cbdsqr.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cbdsqr.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cbdsqr.f">
21 * SUBROUTINE CBDSQR( UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U,
22 * LDU, C, LDC, RWORK, INFO )
24 * .. Scalar Arguments ..
26 * INTEGER INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU
28 * .. Array Arguments ..
29 * REAL D( * ), E( * ), RWORK( * )
30 * COMPLEX C( LDC, * ), U( LDU, * ), VT( LDVT, * )
39 *> CBDSQR computes the singular values and, optionally, the right and/or
40 *> left singular vectors from the singular value decomposition (SVD) of
41 *> a real N-by-N (upper or lower) bidiagonal matrix B using the implicit
42 *> zero-shift QR algorithm. The SVD of B has the form
46 *> where S is the diagonal matrix of singular values, Q is an orthogonal
47 *> matrix of left singular vectors, and P is an orthogonal matrix of
48 *> right singular vectors. If left singular vectors are requested, this
49 *> subroutine actually returns U*Q instead of Q, and, if right singular
50 *> vectors are requested, this subroutine returns P**H*VT instead of
51 *> P**H, for given complex input matrices U and VT. When U and VT are
52 *> the unitary matrices that reduce a general matrix A to bidiagonal
53 *> form: A = U*B*VT, as computed by CGEBRD, then
55 *> A = (U*Q) * S * (P**H*VT)
57 *> is the SVD of A. Optionally, the subroutine may also compute Q**H*C
58 *> for a given complex input matrix C.
60 *> See "Computing Small Singular Values of Bidiagonal Matrices With
61 *> Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,
62 *> LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11,
63 *> no. 5, pp. 873-912, Sept 1990) and
64 *> "Accurate singular values and differential qd algorithms," by
65 *> B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics
66 *> Department, University of California at Berkeley, July 1992
67 *> for a detailed description of the algorithm.
75 *> UPLO is CHARACTER*1
76 *> = 'U': B is upper bidiagonal;
77 *> = 'L': B is lower bidiagonal.
83 *> The order of the matrix B. N >= 0.
89 *> The number of columns of the matrix VT. NCVT >= 0.
95 *> The number of rows of the matrix U. NRU >= 0.
101 *> The number of columns of the matrix C. NCC >= 0.
106 *> D is REAL array, dimension (N)
107 *> On entry, the n diagonal elements of the bidiagonal matrix B.
108 *> On exit, if INFO=0, the singular values of B in decreasing
114 *> E is REAL array, dimension (N-1)
115 *> On entry, the N-1 offdiagonal elements of the bidiagonal
117 *> On exit, if INFO = 0, E is destroyed; if INFO > 0, D and E
118 *> will contain the diagonal and superdiagonal elements of a
119 *> bidiagonal matrix orthogonally equivalent to the one given
125 *> VT is COMPLEX array, dimension (LDVT, NCVT)
126 *> On entry, an N-by-NCVT matrix VT.
127 *> On exit, VT is overwritten by P**H * VT.
128 *> Not referenced if NCVT = 0.
134 *> The leading dimension of the array VT.
135 *> LDVT >= max(1,N) if NCVT > 0; LDVT >= 1 if NCVT = 0.
140 *> U is COMPLEX array, dimension (LDU, N)
141 *> On entry, an NRU-by-N matrix U.
142 *> On exit, U is overwritten by U * Q.
143 *> Not referenced if NRU = 0.
149 *> The leading dimension of the array U. LDU >= max(1,NRU).
154 *> C is COMPLEX array, dimension (LDC, NCC)
155 *> On entry, an N-by-NCC matrix C.
156 *> On exit, C is overwritten by Q**H * C.
157 *> Not referenced if NCC = 0.
163 *> The leading dimension of the array C.
164 *> LDC >= max(1,N) if NCC > 0; LDC >=1 if NCC = 0.
169 *> RWORK is REAL array, dimension (4*N)
175 *> = 0: successful exit
176 *> < 0: If INFO = -i, the i-th argument had an illegal value
177 *> > 0: the algorithm did not converge; D and E contain the
178 *> elements of a bidiagonal matrix which is orthogonally
179 *> similar to the input matrix B; if INFO = i, i
180 *> elements of E have not converged to zero.
183 *> \par Internal Parameters:
184 * =========================
187 *> TOLMUL REAL, default = max(10,min(100,EPS**(-1/8)))
188 *> TOLMUL controls the convergence criterion of the QR loop.
189 *> If it is positive, TOLMUL*EPS is the desired relative
190 *> precision in the computed singular values.
191 *> If it is negative, abs(TOLMUL*EPS*sigma_max) is the
192 *> desired absolute accuracy in the computed singular
193 *> values (corresponds to relative accuracy
194 *> abs(TOLMUL*EPS) in the largest singular value.
195 *> abs(TOLMUL) should be between 1 and 1/EPS, and preferably
196 *> between 10 (for fast convergence) and .1/EPS
197 *> (for there to be some accuracy in the results).
198 *> Default is to lose at either one eighth or 2 of the
199 *> available decimal digits in each computed singular value
200 *> (whichever is smaller).
202 *> MAXITR INTEGER, default = 6
203 *> MAXITR controls the maximum number of passes of the
204 *> algorithm through its inner loop. The algorithms stops
205 *> (and so fails to converge) if the number of passes
206 *> through the inner loop exceeds MAXITR*N**2.
212 *> \author Univ. of Tennessee
213 *> \author Univ. of California Berkeley
214 *> \author Univ. of Colorado Denver
217 *> \date November 2015
219 *> \ingroup complexOTHERcomputational
221 * =====================================================================
222 SUBROUTINE CBDSQR( UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U,
223 $ LDU, C, LDC, RWORK, INFO )
225 * -- LAPACK computational routine (version 3.6.0) --
226 * -- LAPACK is a software package provided by Univ. of Tennessee, --
227 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
230 * .. Scalar Arguments ..
232 INTEGER INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU
234 * .. Array Arguments ..
235 REAL D( * ), E( * ), RWORK( * )
236 COMPLEX C( LDC, * ), U( LDU, * ), VT( LDVT, * )
239 * =====================================================================
243 PARAMETER ( ZERO = 0.0E0 )
245 PARAMETER ( ONE = 1.0E0 )
247 PARAMETER ( NEGONE = -1.0E0 )
249 PARAMETER ( HNDRTH = 0.01E0 )
251 PARAMETER ( TEN = 10.0E0 )
253 PARAMETER ( HNDRD = 100.0E0 )
255 PARAMETER ( MEIGTH = -0.125E0 )
257 PARAMETER ( MAXITR = 6 )
259 * .. Local Scalars ..
260 LOGICAL LOWER, ROTATE
261 INTEGER I, IDIR, ISUB, ITER, J, LL, LLL, M, MAXIT, NM1,
262 $ NM12, NM13, OLDLL, OLDM
263 REAL ABSE, ABSS, COSL, COSR, CS, EPS, F, G, H, MU,
264 $ OLDCS, OLDSN, R, SHIFT, SIGMN, SIGMX, SINL,
265 $ SINR, SLL, SMAX, SMIN, SMINL, SMINOA,
266 $ SN, THRESH, TOL, TOLMUL, UNFL
268 * .. External Functions ..
271 EXTERNAL LSAME, SLAMCH
273 * .. External Subroutines ..
274 EXTERNAL CLASR, CSROT, CSSCAL, CSWAP, SLARTG, SLAS2,
275 $ SLASQ1, SLASV2, XERBLA
277 * .. Intrinsic Functions ..
278 INTRINSIC ABS, MAX, MIN, REAL, SIGN, SQRT
280 * .. Executable Statements ..
282 * Test the input parameters.
285 LOWER = LSAME( UPLO, 'L' )
286 IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LOWER ) THEN
288 ELSE IF( N.LT.0 ) THEN
290 ELSE IF( NCVT.LT.0 ) THEN
292 ELSE IF( NRU.LT.0 ) THEN
294 ELSE IF( NCC.LT.0 ) THEN
296 ELSE IF( ( NCVT.EQ.0 .AND. LDVT.LT.1 ) .OR.
297 $ ( NCVT.GT.0 .AND. LDVT.LT.MAX( 1, N ) ) ) THEN
299 ELSE IF( LDU.LT.MAX( 1, NRU ) ) THEN
301 ELSE IF( ( NCC.EQ.0 .AND. LDC.LT.1 ) .OR.
302 $ ( NCC.GT.0 .AND. LDC.LT.MAX( 1, N ) ) ) THEN
306 CALL XERBLA( 'CBDSQR', -INFO )
314 * ROTATE is true if any singular vectors desired, false otherwise
316 ROTATE = ( NCVT.GT.0 ) .OR. ( NRU.GT.0 ) .OR. ( NCC.GT.0 )
318 * If no singular vectors desired, use qd algorithm
320 IF( .NOT.ROTATE ) THEN
321 CALL SLASQ1( N, D, E, RWORK, INFO )
323 * If INFO equals 2, dqds didn't finish, try to finish
325 IF( INFO .NE. 2 ) RETURN
334 * Get machine constants
336 EPS = SLAMCH( 'Epsilon' )
337 UNFL = SLAMCH( 'Safe minimum' )
339 * If matrix lower bidiagonal, rotate to be upper bidiagonal
340 * by applying Givens rotations on the left
344 CALL SLARTG( D( I ), E( I ), CS, SN, R )
347 D( I+1 ) = CS*D( I+1 )
352 * Update singular vectors if desired
355 $ CALL CLASR( 'R', 'V', 'F', NRU, N, RWORK( 1 ), RWORK( N ),
358 $ CALL CLASR( 'L', 'V', 'F', N, NCC, RWORK( 1 ), RWORK( N ),
362 * Compute singular values to relative accuracy TOL
363 * (By setting TOL to be negative, algorithm will compute
364 * singular values to absolute accuracy ABS(TOL)*norm(input matrix))
366 TOLMUL = MAX( TEN, MIN( HNDRD, EPS**MEIGTH ) )
369 * Compute approximate maximum, minimum singular values
373 SMAX = MAX( SMAX, ABS( D( I ) ) )
376 SMAX = MAX( SMAX, ABS( E( I ) ) )
379 IF( TOL.GE.ZERO ) THEN
381 * Relative accuracy desired
383 SMINOA = ABS( D( 1 ) )
388 MU = ABS( D( I ) )*( MU / ( MU+ABS( E( I-1 ) ) ) )
389 SMINOA = MIN( SMINOA, MU )
394 SMINOA = SMINOA / SQRT( REAL( N ) )
395 THRESH = MAX( TOL*SMINOA, MAXITR*N*N*UNFL )
398 * Absolute accuracy desired
400 THRESH = MAX( ABS( TOL )*SMAX, MAXITR*N*N*UNFL )
403 * Prepare for main iteration loop for the singular values
404 * (MAXIT is the maximum number of passes through the inner
405 * loop permitted before nonconvergence signalled.)
412 * M points to last element of unconverged part of matrix
416 * Begin main iteration loop
420 * Check for convergence or exceeding iteration count
427 * Find diagonal block of matrix to work on
429 IF( TOL.LT.ZERO .AND. ABS( D( M ) ).LE.THRESH )
435 ABSS = ABS( D( LL ) )
436 ABSE = ABS( E( LL ) )
437 IF( TOL.LT.ZERO .AND. ABSS.LE.THRESH )
441 SMIN = MIN( SMIN, ABSS )
442 SMAX = MAX( SMAX, ABSS, ABSE )
449 * Matrix splits since E(LL) = 0
453 * Convergence of bottom singular value, return to top of loop
461 * E(LL) through E(M-1) are nonzero, E(LL-1) is zero
465 * 2 by 2 block, handle separately
467 CALL SLASV2( D( M-1 ), E( M-1 ), D( M ), SIGMN, SIGMX, SINR,
473 * Compute singular vectors, if desired
476 $ CALL CSROT( NCVT, VT( M-1, 1 ), LDVT, VT( M, 1 ), LDVT,
479 $ CALL CSROT( NRU, U( 1, M-1 ), 1, U( 1, M ), 1, COSL, SINL )
481 $ CALL CSROT( NCC, C( M-1, 1 ), LDC, C( M, 1 ), LDC, COSL,
487 * If working on new submatrix, choose shift direction
488 * (from larger end diagonal element towards smaller)
490 IF( LL.GT.OLDM .OR. M.LT.OLDLL ) THEN
491 IF( ABS( D( LL ) ).GE.ABS( D( M ) ) ) THEN
493 * Chase bulge from top (big end) to bottom (small end)
498 * Chase bulge from bottom (big end) to top (small end)
504 * Apply convergence tests
508 * Run convergence test in forward direction
509 * First apply standard test to bottom of matrix
511 IF( ABS( E( M-1 ) ).LE.ABS( TOL )*ABS( D( M ) ) .OR.
512 $ ( TOL.LT.ZERO .AND. ABS( E( M-1 ) ).LE.THRESH ) ) THEN
517 IF( TOL.GE.ZERO ) THEN
519 * If relative accuracy desired,
520 * apply convergence criterion forward
524 DO 100 LLL = LL, M - 1
525 IF( ABS( E( LLL ) ).LE.TOL*MU ) THEN
529 MU = ABS( D( LLL+1 ) )*( MU / ( MU+ABS( E( LLL ) ) ) )
530 SMINL = MIN( SMINL, MU )
536 * Run convergence test in backward direction
537 * First apply standard test to top of matrix
539 IF( ABS( E( LL ) ).LE.ABS( TOL )*ABS( D( LL ) ) .OR.
540 $ ( TOL.LT.ZERO .AND. ABS( E( LL ) ).LE.THRESH ) ) THEN
545 IF( TOL.GE.ZERO ) THEN
547 * If relative accuracy desired,
548 * apply convergence criterion backward
552 DO 110 LLL = M - 1, LL, -1
553 IF( ABS( E( LLL ) ).LE.TOL*MU ) THEN
557 MU = ABS( D( LLL ) )*( MU / ( MU+ABS( E( LLL ) ) ) )
558 SMINL = MIN( SMINL, MU )
565 * Compute shift. First, test if shifting would ruin relative
566 * accuracy, and if so set the shift to zero.
568 IF( TOL.GE.ZERO .AND. N*TOL*( SMINL / SMAX ).LE.
569 $ MAX( EPS, HNDRTH*TOL ) ) THEN
571 * Use a zero shift to avoid loss of relative accuracy
576 * Compute the shift from 2-by-2 block at end of matrix
580 CALL SLAS2( D( M-1 ), E( M-1 ), D( M ), SHIFT, R )
583 CALL SLAS2( D( LL ), E( LL ), D( LL+1 ), SHIFT, R )
586 * Test if shift negligible, and if so set to zero
588 IF( SLL.GT.ZERO ) THEN
589 IF( ( SHIFT / SLL )**2.LT.EPS )
594 * Increment iteration count
598 * If SHIFT = 0, do simplified QR iteration
600 IF( SHIFT.EQ.ZERO ) THEN
603 * Chase bulge from top to bottom
604 * Save cosines and sines for later singular vector updates
609 CALL SLARTG( D( I )*CS, E( I ), CS, SN, R )
612 CALL SLARTG( OLDCS*R, D( I+1 )*SN, OLDCS, OLDSN, D( I ) )
614 RWORK( I-LL+1+NM1 ) = SN
615 RWORK( I-LL+1+NM12 ) = OLDCS
616 RWORK( I-LL+1+NM13 ) = OLDSN
622 * Update singular vectors
625 $ CALL CLASR( 'L', 'V', 'F', M-LL+1, NCVT, RWORK( 1 ),
626 $ RWORK( N ), VT( LL, 1 ), LDVT )
628 $ CALL CLASR( 'R', 'V', 'F', NRU, M-LL+1, RWORK( NM12+1 ),
629 $ RWORK( NM13+1 ), U( 1, LL ), LDU )
631 $ CALL CLASR( 'L', 'V', 'F', M-LL+1, NCC, RWORK( NM12+1 ),
632 $ RWORK( NM13+1 ), C( LL, 1 ), LDC )
636 IF( ABS( E( M-1 ) ).LE.THRESH )
641 * Chase bulge from bottom to top
642 * Save cosines and sines for later singular vector updates
646 DO 130 I = M, LL + 1, -1
647 CALL SLARTG( D( I )*CS, E( I-1 ), CS, SN, R )
650 CALL SLARTG( OLDCS*R, D( I-1 )*SN, OLDCS, OLDSN, D( I ) )
652 RWORK( I-LL+NM1 ) = -SN
653 RWORK( I-LL+NM12 ) = OLDCS
654 RWORK( I-LL+NM13 ) = -OLDSN
660 * Update singular vectors
663 $ CALL CLASR( 'L', 'V', 'B', M-LL+1, NCVT, RWORK( NM12+1 ),
664 $ RWORK( NM13+1 ), VT( LL, 1 ), LDVT )
666 $ CALL CLASR( 'R', 'V', 'B', NRU, M-LL+1, RWORK( 1 ),
667 $ RWORK( N ), U( 1, LL ), LDU )
669 $ CALL CLASR( 'L', 'V', 'B', M-LL+1, NCC, RWORK( 1 ),
670 $ RWORK( N ), C( LL, 1 ), LDC )
674 IF( ABS( E( LL ) ).LE.THRESH )
683 * Chase bulge from top to bottom
684 * Save cosines and sines for later singular vector updates
686 F = ( ABS( D( LL ) )-SHIFT )*
687 $ ( SIGN( ONE, D( LL ) )+SHIFT / D( LL ) )
690 CALL SLARTG( F, G, COSR, SINR, R )
693 F = COSR*D( I ) + SINR*E( I )
694 E( I ) = COSR*E( I ) - SINR*D( I )
696 D( I+1 ) = COSR*D( I+1 )
697 CALL SLARTG( F, G, COSL, SINL, R )
699 F = COSL*E( I ) + SINL*D( I+1 )
700 D( I+1 ) = COSL*D( I+1 ) - SINL*E( I )
703 E( I+1 ) = COSL*E( I+1 )
705 RWORK( I-LL+1 ) = COSR
706 RWORK( I-LL+1+NM1 ) = SINR
707 RWORK( I-LL+1+NM12 ) = COSL
708 RWORK( I-LL+1+NM13 ) = SINL
712 * Update singular vectors
715 $ CALL CLASR( 'L', 'V', 'F', M-LL+1, NCVT, RWORK( 1 ),
716 $ RWORK( N ), VT( LL, 1 ), LDVT )
718 $ CALL CLASR( 'R', 'V', 'F', NRU, M-LL+1, RWORK( NM12+1 ),
719 $ RWORK( NM13+1 ), U( 1, LL ), LDU )
721 $ CALL CLASR( 'L', 'V', 'F', M-LL+1, NCC, RWORK( NM12+1 ),
722 $ RWORK( NM13+1 ), C( LL, 1 ), LDC )
726 IF( ABS( E( M-1 ) ).LE.THRESH )
731 * Chase bulge from bottom to top
732 * Save cosines and sines for later singular vector updates
734 F = ( ABS( D( M ) )-SHIFT )*( SIGN( ONE, D( M ) )+SHIFT /
737 DO 150 I = M, LL + 1, -1
738 CALL SLARTG( F, G, COSR, SINR, R )
741 F = COSR*D( I ) + SINR*E( I-1 )
742 E( I-1 ) = COSR*E( I-1 ) - SINR*D( I )
744 D( I-1 ) = COSR*D( I-1 )
745 CALL SLARTG( F, G, COSL, SINL, R )
747 F = COSL*E( I-1 ) + SINL*D( I-1 )
748 D( I-1 ) = COSL*D( I-1 ) - SINL*E( I-1 )
751 E( I-2 ) = COSL*E( I-2 )
754 RWORK( I-LL+NM1 ) = -SINR
755 RWORK( I-LL+NM12 ) = COSL
756 RWORK( I-LL+NM13 ) = -SINL
762 IF( ABS( E( LL ) ).LE.THRESH )
765 * Update singular vectors if desired
768 $ CALL CLASR( 'L', 'V', 'B', M-LL+1, NCVT, RWORK( NM12+1 ),
769 $ RWORK( NM13+1 ), VT( LL, 1 ), LDVT )
771 $ CALL CLASR( 'R', 'V', 'B', NRU, M-LL+1, RWORK( 1 ),
772 $ RWORK( N ), U( 1, LL ), LDU )
774 $ CALL CLASR( 'L', 'V', 'B', M-LL+1, NCC, RWORK( 1 ),
775 $ RWORK( N ), C( LL, 1 ), LDC )
779 * QR iteration finished, go back and check convergence
783 * All singular values converged, so make them positive
787 IF( D( I ).LT.ZERO ) THEN
790 * Change sign of singular vectors, if desired
793 $ CALL CSSCAL( NCVT, NEGONE, VT( I, 1 ), LDVT )
797 * Sort the singular values into decreasing order (insertion sort on
798 * singular values, but only one transposition per singular vector)
802 * Scan for smallest D(I)
806 DO 180 J = 2, N + 1 - I
807 IF( D( J ).LE.SMIN ) THEN
812 IF( ISUB.NE.N+1-I ) THEN
814 * Swap singular values and vectors
816 D( ISUB ) = D( N+1-I )
819 $ CALL CSWAP( NCVT, VT( ISUB, 1 ), LDVT, VT( N+1-I, 1 ),
822 $ CALL CSWAP( NRU, U( 1, ISUB ), 1, U( 1, N+1-I ), 1 )
824 $ CALL CSWAP( NCC, C( ISUB, 1 ), LDC, C( N+1-I, 1 ), LDC )
829 * Maximum number of iterations exceeded, failure to converge