1*> \brief \b SLASDQ computes the SVD of a real bidiagonal matrix with diagonal d and off-diagonal e. Used by sbdsdc.
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download SLASDQ + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slasdq.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slasdq.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slasdq.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       SUBROUTINE SLASDQ( UPLO, SQRE, N, NCVT, NRU, NCC, D, E, VT, LDVT,
22*                          U, LDU, C, LDC, WORK, INFO )
23*
24*       .. Scalar Arguments ..
25*       CHARACTER          UPLO
26*       INTEGER            INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU, SQRE
27*       ..
28*       .. Array Arguments ..
29*       REAL               C( LDC, * ), D( * ), E( * ), U( LDU, * ),
30*      $                   VT( LDVT, * ), WORK( * )
31*       ..
32*
33*
34*> \par Purpose:
35*  =============
36*>
37*> \verbatim
38*>
39*> SLASDQ computes the singular value decomposition (SVD) of a real
40*> (upper or lower) bidiagonal matrix with diagonal D and offdiagonal
41*> E, accumulating the transformations if desired. Letting B denote
42*> the input bidiagonal matrix, the algorithm computes orthogonal
43*> matrices Q and P such that B = Q * S * P**T (P**T denotes the transpose
44*> of P). The singular values S are overwritten on D.
45*>
46*> The input matrix U  is changed to U  * Q  if desired.
47*> The input matrix VT is changed to P**T * VT if desired.
48*> The input matrix C  is changed to Q**T * C  if desired.
49*>
50*> See "Computing  Small Singular Values of Bidiagonal Matrices With
51*> Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan,
52*> LAPACK Working Note #3, for a detailed description of the algorithm.
53*> \endverbatim
54*
55*  Arguments:
56*  ==========
57*
58*> \param[in] UPLO
59*> \verbatim
60*>          UPLO is CHARACTER*1
61*>        On entry, UPLO specifies whether the input bidiagonal matrix
62*>        is upper or lower bidiagonal, and wether it is square are
63*>        not.
64*>           UPLO = 'U' or 'u'   B is upper bidiagonal.
65*>           UPLO = 'L' or 'l'   B is lower bidiagonal.
66*> \endverbatim
67*>
68*> \param[in] SQRE
69*> \verbatim
70*>          SQRE is INTEGER
71*>        = 0: then the input matrix is N-by-N.
72*>        = 1: then the input matrix is N-by-(N+1) if UPLU = 'U' and
73*>             (N+1)-by-N if UPLU = 'L'.
74*>
75*>        The bidiagonal matrix has
76*>        N = NL + NR + 1 rows and
77*>        M = N + SQRE >= N columns.
78*> \endverbatim
79*>
80*> \param[in] N
81*> \verbatim
82*>          N is INTEGER
83*>        On entry, N specifies the number of rows and columns
84*>        in the matrix. N must be at least 0.
85*> \endverbatim
86*>
87*> \param[in] NCVT
88*> \verbatim
89*>          NCVT is INTEGER
90*>        On entry, NCVT specifies the number of columns of
91*>        the matrix VT. NCVT must be at least 0.
92*> \endverbatim
93*>
94*> \param[in] NRU
95*> \verbatim
96*>          NRU is INTEGER
97*>        On entry, NRU specifies the number of rows of
98*>        the matrix U. NRU must be at least 0.
99*> \endverbatim
100*>
101*> \param[in] NCC
102*> \verbatim
103*>          NCC is INTEGER
104*>        On entry, NCC specifies the number of columns of
105*>        the matrix C. NCC must be at least 0.
106*> \endverbatim
107*>
108*> \param[in,out] D
109*> \verbatim
110*>          D is REAL array, dimension (N)
111*>        On entry, D contains the diagonal entries of the
112*>        bidiagonal matrix whose SVD is desired. On normal exit,
113*>        D contains the singular values in ascending order.
114*> \endverbatim
115*>
116*> \param[in,out] E
117*> \verbatim
118*>          E is REAL array.
119*>        dimension is (N-1) if SQRE = 0 and N if SQRE = 1.
120*>        On entry, the entries of E contain the offdiagonal entries
121*>        of the bidiagonal matrix whose SVD is desired. On normal
122*>        exit, E will contain 0. If the algorithm does not converge,
123*>        D and E will contain the diagonal and superdiagonal entries
124*>        of a bidiagonal matrix orthogonally equivalent to the one
125*>        given as input.
126*> \endverbatim
127*>
128*> \param[in,out] VT
129*> \verbatim
130*>          VT is REAL array, dimension (LDVT, NCVT)
131*>        On entry, contains a matrix which on exit has been
132*>        premultiplied by P**T, dimension N-by-NCVT if SQRE = 0
133*>        and (N+1)-by-NCVT if SQRE = 1 (not referenced if NCVT=0).
134*> \endverbatim
135*>
136*> \param[in] LDVT
137*> \verbatim
138*>          LDVT is INTEGER
139*>        On entry, LDVT specifies the leading dimension of VT as
140*>        declared in the calling (sub) program. LDVT must be at
141*>        least 1. If NCVT is nonzero LDVT must also be at least N.
142*> \endverbatim
143*>
144*> \param[in,out] U
145*> \verbatim
146*>          U is REAL array, dimension (LDU, N)
147*>        On entry, contains a  matrix which on exit has been
148*>        postmultiplied by Q, dimension NRU-by-N if SQRE = 0
149*>        and NRU-by-(N+1) if SQRE = 1 (not referenced if NRU=0).
150*> \endverbatim
151*>
152*> \param[in] LDU
153*> \verbatim
154*>          LDU is INTEGER
155*>        On entry, LDU  specifies the leading dimension of U as
156*>        declared in the calling (sub) program. LDU must be at
157*>        least max( 1, NRU ) .
158*> \endverbatim
159*>
160*> \param[in,out] C
161*> \verbatim
162*>          C is REAL array, dimension (LDC, NCC)
163*>        On entry, contains an N-by-NCC matrix which on exit
164*>        has been premultiplied by Q**T  dimension N-by-NCC if SQRE = 0
165*>        and (N+1)-by-NCC if SQRE = 1 (not referenced if NCC=0).
166*> \endverbatim
167*>
168*> \param[in] LDC
169*> \verbatim
170*>          LDC is INTEGER
171*>        On entry, LDC  specifies the leading dimension of C as
172*>        declared in the calling (sub) program. LDC must be at
173*>        least 1. If NCC is nonzero, LDC must also be at least N.
174*> \endverbatim
175*>
176*> \param[out] WORK
177*> \verbatim
178*>          WORK is REAL array, dimension (4*N)
179*>        Workspace. Only referenced if one of NCVT, NRU, or NCC is
180*>        nonzero, and if N is at least 2.
181*> \endverbatim
182*>
183*> \param[out] INFO
184*> \verbatim
185*>          INFO is INTEGER
186*>        On exit, a value of 0 indicates a successful exit.
187*>        If INFO < 0, argument number -INFO is illegal.
188*>        If INFO > 0, the algorithm did not converge, and INFO
189*>        specifies how many superdiagonals did not converge.
190*> \endverbatim
191*
192*  Authors:
193*  ========
194*
195*> \author Univ. of Tennessee
196*> \author Univ. of California Berkeley
197*> \author Univ. of Colorado Denver
198*> \author NAG Ltd.
199*
200*> \date September 2012
201*
202*> \ingroup auxOTHERauxiliary
203*
204*> \par Contributors:
205*  ==================
206*>
207*>     Ming Gu and Huan Ren, Computer Science Division, University of
208*>     California at Berkeley, USA
209*>
210*  =====================================================================
211      SUBROUTINE SLASDQ( UPLO, SQRE, N, NCVT, NRU, NCC, D, E, VT, LDVT,
212     $                   U, LDU, C, LDC, WORK, INFO )
213*
214*  -- LAPACK auxiliary routine (version 3.4.2) --
215*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
216*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
217*     September 2012
218*
219*     .. Scalar Arguments ..
220      CHARACTER          UPLO
221      INTEGER            INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU, SQRE
222*     ..
223*     .. Array Arguments ..
224      REAL               C( LDC, * ), D( * ), E( * ), U( LDU, * ),
225     $                   VT( LDVT, * ), WORK( * )
226*     ..
227*
228*  =====================================================================
229*
230*     .. Parameters ..
231      REAL               ZERO
232      PARAMETER          ( ZERO = 0.0E+0 )
233*     ..
234*     .. Local Scalars ..
235      LOGICAL            ROTATE
236      INTEGER            I, ISUB, IUPLO, J, NP1, SQRE1
237      REAL               CS, R, SMIN, SN
238*     ..
239*     .. External Subroutines ..
240      EXTERNAL           SBDSQR, SLARTG, SLASR, SSWAP, XERBLA
241*     ..
242*     .. External Functions ..
243      LOGICAL            LSAME
244      EXTERNAL           LSAME
245*     ..
246*     .. Intrinsic Functions ..
247      INTRINSIC          MAX
248*     ..
249*     .. Executable Statements ..
250*
251*     Test the input parameters.
252*
253      INFO = 0
254      IUPLO = 0
255      IF( LSAME( UPLO, 'U' ) )
256     $   IUPLO = 1
257      IF( LSAME( UPLO, 'L' ) )
258     $   IUPLO = 2
259      IF( IUPLO.EQ.0 ) THEN
260         INFO = -1
261      ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THEN
262         INFO = -2
263      ELSE IF( N.LT.0 ) THEN
264         INFO = -3
265      ELSE IF( NCVT.LT.0 ) THEN
266         INFO = -4
267      ELSE IF( NRU.LT.0 ) THEN
268         INFO = -5
269      ELSE IF( NCC.LT.0 ) THEN
270         INFO = -6
271      ELSE IF( ( NCVT.EQ.0 .AND. LDVT.LT.1 ) .OR.
272     $         ( NCVT.GT.0 .AND. LDVT.LT.MAX( 1, N ) ) ) THEN
273         INFO = -10
274      ELSE IF( LDU.LT.MAX( 1, NRU ) ) THEN
275         INFO = -12
276      ELSE IF( ( NCC.EQ.0 .AND. LDC.LT.1 ) .OR.
277     $         ( NCC.GT.0 .AND. LDC.LT.MAX( 1, N ) ) ) THEN
278         INFO = -14
279      END IF
280      IF( INFO.NE.0 ) THEN
281         CALL XERBLA( 'SLASDQ', -INFO )
282         RETURN
283      END IF
284      IF( N.EQ.0 )
285     $   RETURN
286*
287*     ROTATE is true if any singular vectors desired, false otherwise
288*
289      ROTATE = ( NCVT.GT.0 ) .OR. ( NRU.GT.0 ) .OR. ( NCC.GT.0 )
290      NP1 = N + 1
291      SQRE1 = SQRE
292*
293*     If matrix non-square upper bidiagonal, rotate to be lower
294*     bidiagonal.  The rotations are on the right.
295*
296      IF( ( IUPLO.EQ.1 ) .AND. ( SQRE1.EQ.1 ) ) THEN
297         DO 10 I = 1, N - 1
298            CALL SLARTG( D( I ), E( I ), CS, SN, R )
299            D( I ) = R
300            E( I ) = SN*D( I+1 )
301            D( I+1 ) = CS*D( I+1 )
302            IF( ROTATE ) THEN
303               WORK( I ) = CS
304               WORK( N+I ) = SN
305            END IF
306   10    CONTINUE
307         CALL SLARTG( D( N ), E( N ), CS, SN, R )
308         D( N ) = R
309         E( N ) = ZERO
310         IF( ROTATE ) THEN
311            WORK( N ) = CS
312            WORK( N+N ) = SN
313         END IF
314         IUPLO = 2
315         SQRE1 = 0
316*
317*        Update singular vectors if desired.
318*
319         IF( NCVT.GT.0 )
320     $      CALL SLASR( 'L', 'V', 'F', NP1, NCVT, WORK( 1 ),
321     $                  WORK( NP1 ), VT, LDVT )
322      END IF
323*
324*     If matrix lower bidiagonal, rotate to be upper bidiagonal
325*     by applying Givens rotations on the left.
326*
327      IF( IUPLO.EQ.2 ) THEN
328         DO 20 I = 1, N - 1
329            CALL SLARTG( D( I ), E( I ), CS, SN, R )
330            D( I ) = R
331            E( I ) = SN*D( I+1 )
332            D( I+1 ) = CS*D( I+1 )
333            IF( ROTATE ) THEN
334               WORK( I ) = CS
335               WORK( N+I ) = SN
336            END IF
337   20    CONTINUE
338*
339*        If matrix (N+1)-by-N lower bidiagonal, one additional
340*        rotation is needed.
341*
342         IF( SQRE1.EQ.1 ) THEN
343            CALL SLARTG( D( N ), E( N ), CS, SN, R )
344            D( N ) = R
345            IF( ROTATE ) THEN
346               WORK( N ) = CS
347               WORK( N+N ) = SN
348            END IF
349         END IF
350*
351*        Update singular vectors if desired.
352*
353         IF( NRU.GT.0 ) THEN
354            IF( SQRE1.EQ.0 ) THEN
355               CALL SLASR( 'R', 'V', 'F', NRU, N, WORK( 1 ),
356     $                     WORK( NP1 ), U, LDU )
357            ELSE
358               CALL SLASR( 'R', 'V', 'F', NRU, NP1, WORK( 1 ),
359     $                     WORK( NP1 ), U, LDU )
360            END IF
361         END IF
362         IF( NCC.GT.0 ) THEN
363            IF( SQRE1.EQ.0 ) THEN
364               CALL SLASR( 'L', 'V', 'F', N, NCC, WORK( 1 ),
365     $                     WORK( NP1 ), C, LDC )
366            ELSE
367               CALL SLASR( 'L', 'V', 'F', NP1, NCC, WORK( 1 ),
368     $                     WORK( NP1 ), C, LDC )
369            END IF
370         END IF
371      END IF
372*
373*     Call SBDSQR to compute the SVD of the reduced real
374*     N-by-N upper bidiagonal matrix.
375*
376      CALL SBDSQR( 'U', N, NCVT, NRU, NCC, D, E, VT, LDVT, U, LDU, C,
377     $             LDC, WORK, INFO )
378*
379*     Sort the singular values into ascending order (insertion sort on
380*     singular values, but only one transposition per singular vector)
381*
382      DO 40 I = 1, N
383*
384*        Scan for smallest D(I).
385*
386         ISUB = I
387         SMIN = D( I )
388         DO 30 J = I + 1, N
389            IF( D( J ).LT.SMIN ) THEN
390               ISUB = J
391               SMIN = D( J )
392            END IF
393   30    CONTINUE
394         IF( ISUB.NE.I ) THEN
395*
396*           Swap singular values and vectors.
397*
398            D( ISUB ) = D( I )
399            D( I ) = SMIN
400            IF( NCVT.GT.0 )
401     $         CALL SSWAP( NCVT, VT( ISUB, 1 ), LDVT, VT( I, 1 ), LDVT )
402            IF( NRU.GT.0 )
403     $         CALL SSWAP( NRU, U( 1, ISUB ), 1, U( 1, I ), 1 )
404            IF( NCC.GT.0 )
405     $         CALL SSWAP( NCC, C( ISUB, 1 ), LDC, C( I, 1 ), LDC )
406         END IF
407   40 CONTINUE
408*
409      RETURN
410*
411*     End of SLASDQ
412*
413      END
414