LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
dbdsdc.f
Go to the documentation of this file.
1*> \brief \b DBDSDC
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download DBDSDC + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dbdsdc.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dbdsdc.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dbdsdc.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE DBDSDC( UPLO, COMPQ, N, D, E, U, LDU, VT, LDVT, Q, IQ,
20* WORK, IWORK, INFO )
21*
22* .. Scalar Arguments ..
23* CHARACTER COMPQ, UPLO
24* INTEGER INFO, LDU, LDVT, N
25* ..
26* .. Array Arguments ..
27* INTEGER IQ( * ), IWORK( * )
28* DOUBLE PRECISION D( * ), E( * ), Q( * ), U( LDU, * ),
29* $ VT( LDVT, * ), WORK( * )
30* ..
31*
32*
33*> \par Purpose:
34* =============
35*>
36*> \verbatim
37*>
38*> DBDSDC computes the singular value decomposition (SVD) of a real
39*> N-by-N (upper or lower) bidiagonal matrix B: B = U * S * VT,
40*> using a divide and conquer method, where S is a diagonal matrix
41*> with non-negative diagonal elements (the singular values of B), and
42*> U and VT are orthogonal matrices of left and right singular vectors,
43*> respectively. DBDSDC can be used to compute all singular values,
44*> and optionally, singular vectors or singular vectors in compact form.
45*>
46*> The code currently calls DLASDQ if singular values only are desired.
47*> However, it can be slightly modified to compute singular values
48*> using the divide and conquer method.
49*> \endverbatim
50*
51* Arguments:
52* ==========
53*
54*> \param[in] UPLO
55*> \verbatim
56*> UPLO is CHARACTER*1
57*> = 'U': B is upper bidiagonal.
58*> = 'L': B is lower bidiagonal.
59*> \endverbatim
60*>
61*> \param[in] COMPQ
62*> \verbatim
63*> COMPQ is CHARACTER*1
64*> Specifies whether singular vectors are to be computed
65*> as follows:
66*> = 'N': Compute singular values only;
67*> = 'P': Compute singular values and compute singular
68*> vectors in compact form;
69*> = 'I': Compute singular values and singular vectors.
70*> \endverbatim
71*>
72*> \param[in] N
73*> \verbatim
74*> N is INTEGER
75*> The order of the matrix B. N >= 0.
76*> \endverbatim
77*>
78*> \param[in,out] D
79*> \verbatim
80*> D is DOUBLE PRECISION array, dimension (N)
81*> On entry, the n diagonal elements of the bidiagonal matrix B.
82*> On exit, if INFO=0, the singular values of B.
83*> \endverbatim
84*>
85*> \param[in,out] E
86*> \verbatim
87*> E is DOUBLE PRECISION array, dimension (N-1)
88*> On entry, the elements of E contain the offdiagonal
89*> elements of the bidiagonal matrix whose SVD is desired.
90*> On exit, E has been destroyed.
91*> \endverbatim
92*>
93*> \param[out] U
94*> \verbatim
95*> U is DOUBLE PRECISION array, dimension (LDU,N)
96*> If COMPQ = 'I', then:
97*> On exit, if INFO = 0, U contains the left singular vectors
98*> of the bidiagonal matrix.
99*> For other values of COMPQ, U is not referenced.
100*> \endverbatim
101*>
102*> \param[in] LDU
103*> \verbatim
104*> LDU is INTEGER
105*> The leading dimension of the array U. LDU >= 1.
106*> If singular vectors are desired, then LDU >= max( 1, N ).
107*> \endverbatim
108*>
109*> \param[out] VT
110*> \verbatim
111*> VT is DOUBLE PRECISION array, dimension (LDVT,N)
112*> If COMPQ = 'I', then:
113*> On exit, if INFO = 0, VT**T contains the right singular
114*> vectors of the bidiagonal matrix.
115*> For other values of COMPQ, VT is not referenced.
116*> \endverbatim
117*>
118*> \param[in] LDVT
119*> \verbatim
120*> LDVT is INTEGER
121*> The leading dimension of the array VT. LDVT >= 1.
122*> If singular vectors are desired, then LDVT >= max( 1, N ).
123*> \endverbatim
124*>
125*> \param[out] Q
126*> \verbatim
127*> Q is DOUBLE PRECISION array, dimension (LDQ)
128*> If COMPQ = 'P', then:
129*> On exit, if INFO = 0, Q and IQ contain the left
130*> and right singular vectors in a compact form,
131*> requiring O(N log N) space instead of 2*N**2.
132*> In particular, Q contains all the DOUBLE PRECISION data in
133*> LDQ >= N*(11 + 2*SMLSIZ + 8*INT(LOG_2(N/(SMLSIZ+1))))
134*> words of memory, where SMLSIZ is returned by ILAENV and
135*> is equal to the maximum size of the subproblems at the
136*> bottom of the computation tree (usually about 25).
137*> For other values of COMPQ, Q is not referenced.
138*> \endverbatim
139*>
140*> \param[out] IQ
141*> \verbatim
142*> IQ is INTEGER array, dimension (LDIQ)
143*> If COMPQ = 'P', then:
144*> On exit, if INFO = 0, Q and IQ contain the left
145*> and right singular vectors in a compact form,
146*> requiring O(N log N) space instead of 2*N**2.
147*> In particular, IQ contains all INTEGER data in
148*> LDIQ >= N*(3 + 3*INT(LOG_2(N/(SMLSIZ+1))))
149*> words of memory, where SMLSIZ is returned by ILAENV and
150*> is equal to the maximum size of the subproblems at the
151*> bottom of the computation tree (usually about 25).
152*> For other values of COMPQ, IQ is not referenced.
153*> \endverbatim
154*>
155*> \param[out] WORK
156*> \verbatim
157*> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
158*> If COMPQ = 'N' then LWORK >= (4 * N).
159*> If COMPQ = 'P' then LWORK >= (6 * N).
160*> If COMPQ = 'I' then LWORK >= (3 * N**2 + 4 * N).
161*> \endverbatim
162*>
163*> \param[out] IWORK
164*> \verbatim
165*> IWORK is INTEGER array, dimension (8*N)
166*> \endverbatim
167*>
168*> \param[out] INFO
169*> \verbatim
170*> INFO is INTEGER
171*> = 0: successful exit.
172*> < 0: if INFO = -i, the i-th argument had an illegal value.
173*> > 0: The algorithm failed to compute a singular value.
174*> The update process of divide and conquer failed.
175*> \endverbatim
176*
177* Authors:
178* ========
179*
180*> \author Univ. of Tennessee
181*> \author Univ. of California Berkeley
182*> \author Univ. of Colorado Denver
183*> \author NAG Ltd.
184*
185*> \ingroup bdsdc
186*
187*> \par Contributors:
188* ==================
189*>
190*> Ming Gu and Huan Ren, Computer Science Division, University of
191*> California at Berkeley, USA
192*>
193* =====================================================================
194 SUBROUTINE dbdsdc( UPLO, COMPQ, N, D, E, U, LDU, VT, LDVT, Q,
195 $ IQ,
196 $ WORK, IWORK, INFO )
197*
198* -- LAPACK computational routine --
199* -- LAPACK is a software package provided by Univ. of Tennessee, --
200* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
201*
202* .. Scalar Arguments ..
203 CHARACTER COMPQ, UPLO
204 INTEGER INFO, LDU, LDVT, N
205* ..
206* .. Array Arguments ..
207 INTEGER IQ( * ), IWORK( * )
208 DOUBLE PRECISION D( * ), E( * ), Q( * ), U( LDU, * ),
209 $ vt( ldvt, * ), work( * )
210* ..
211*
212* =====================================================================
213* Changed dimension statement in comment describing E from (N) to
214* (N-1). Sven, 17 Feb 05.
215* =====================================================================
216*
217* .. Parameters ..
218 DOUBLE PRECISION ZERO, ONE, TWO
219 PARAMETER ( ZERO = 0.0d+0, one = 1.0d+0, two = 2.0d+0 )
220* ..
221* .. Local Scalars ..
222 INTEGER DIFL, DIFR, GIVCOL, GIVNUM, GIVPTR, I, IC,
223 $ ICOMPQ, IERR, II, IS, IU, IUPLO, IVT, J, K, KK,
224 $ mlvl, nm1, nsize, perm, poles, qstart, smlsiz,
225 $ smlszp, sqre, start, wstart, z
226 DOUBLE PRECISION CS, EPS, ORGNRM, P, R, SN
227* ..
228* .. External Functions ..
229 LOGICAL LSAME
230 INTEGER ILAENV
231 DOUBLE PRECISION DLAMCH, DLANST
232 EXTERNAL lsame, ilaenv, dlamch, dlanst
233* ..
234* .. External Subroutines ..
235 EXTERNAL dcopy, dlartg, dlascl, dlasd0, dlasda,
236 $ dlasdq,
238* ..
239* .. Intrinsic Functions ..
240 INTRINSIC abs, dble, int, log, sign
241* ..
242* .. Executable Statements ..
243*
244* Test the input parameters.
245*
246 info = 0
247*
248 iuplo = 0
249 IF( lsame( uplo, 'U' ) )
250 $ iuplo = 1
251 IF( lsame( uplo, 'L' ) )
252 $ iuplo = 2
253 IF( lsame( compq, 'N' ) ) THEN
254 icompq = 0
255 ELSE IF( lsame( compq, 'P' ) ) THEN
256 icompq = 1
257 ELSE IF( lsame( compq, 'I' ) ) THEN
258 icompq = 2
259 ELSE
260 icompq = -1
261 END IF
262 IF( iuplo.EQ.0 ) THEN
263 info = -1
264 ELSE IF( icompq.LT.0 ) THEN
265 info = -2
266 ELSE IF( n.LT.0 ) THEN
267 info = -3
268 ELSE IF( ( ldu.LT.1 ) .OR. ( ( icompq.EQ.2 ) .AND. ( ldu.LT.
269 $ n ) ) ) THEN
270 info = -7
271 ELSE IF( ( ldvt.LT.1 ) .OR. ( ( icompq.EQ.2 ) .AND. ( ldvt.LT.
272 $ n ) ) ) THEN
273 info = -9
274 END IF
275 IF( info.NE.0 ) THEN
276 CALL xerbla( 'DBDSDC', -info )
277 RETURN
278 END IF
279*
280* Quick return if possible
281*
282 IF( n.EQ.0 )
283 $ RETURN
284 smlsiz = ilaenv( 9, 'DBDSDC', ' ', 0, 0, 0, 0 )
285 IF( n.EQ.1 ) THEN
286 IF( icompq.EQ.1 ) THEN
287 q( 1 ) = sign( one, d( 1 ) )
288 q( 1+smlsiz*n ) = one
289 ELSE IF( icompq.EQ.2 ) THEN
290 u( 1, 1 ) = sign( one, d( 1 ) )
291 vt( 1, 1 ) = one
292 END IF
293 d( 1 ) = abs( d( 1 ) )
294 RETURN
295 END IF
296 nm1 = n - 1
297*
298* If matrix lower bidiagonal, rotate to be upper bidiagonal
299* by applying Givens rotations on the left
300*
301 wstart = 1
302 qstart = 3
303 IF( icompq.EQ.1 ) THEN
304 CALL dcopy( n, d, 1, q( 1 ), 1 )
305 CALL dcopy( n-1, e, 1, q( n+1 ), 1 )
306 END IF
307 IF( iuplo.EQ.2 ) THEN
308 qstart = 5
309 IF( icompq .EQ. 2 ) wstart = 2*n - 1
310 DO 10 i = 1, n - 1
311 CALL dlartg( d( i ), e( i ), cs, sn, r )
312 d( i ) = r
313 e( i ) = sn*d( i+1 )
314 d( i+1 ) = cs*d( i+1 )
315 IF( icompq.EQ.1 ) THEN
316 q( i+2*n ) = cs
317 q( i+3*n ) = sn
318 ELSE IF( icompq.EQ.2 ) THEN
319 work( i ) = cs
320 work( nm1+i ) = -sn
321 END IF
322 10 CONTINUE
323 END IF
324*
325* If ICOMPQ = 0, use DLASDQ to compute the singular values.
326*
327 IF( icompq.EQ.0 ) THEN
328* Ignore WSTART, instead using WORK( 1 ), since the two vectors
329* for CS and -SN above are added only if ICOMPQ == 2,
330* and adding them exceeds documented WORK size of 4*n.
331 CALL dlasdq( 'U', 0, n, 0, 0, 0, d, e, vt, ldvt, u, ldu, u,
332 $ ldu, work( 1 ), info )
333 GO TO 40
334 END IF
335*
336* If N is smaller than the minimum divide size SMLSIZ, then solve
337* the problem with another solver.
338*
339 IF( n.LE.smlsiz ) THEN
340 IF( icompq.EQ.2 ) THEN
341 CALL dlaset( 'A', n, n, zero, one, u, ldu )
342 CALL dlaset( 'A', n, n, zero, one, vt, ldvt )
343 CALL dlasdq( 'U', 0, n, n, n, 0, d, e, vt, ldvt, u, ldu,
344 $ u,
345 $ ldu, work( wstart ), info )
346 ELSE IF( icompq.EQ.1 ) THEN
347 iu = 1
348 ivt = iu + n
349 CALL dlaset( 'A', n, n, zero, one,
350 $ q( iu+( qstart-1 )*n ),
351 $ n )
352 CALL dlaset( 'A', n, n, zero, one,
353 $ q( ivt+( qstart-1 )*n ),
354 $ n )
355 CALL dlasdq( 'U', 0, n, n, n, 0, d, e,
356 $ q( ivt+( qstart-1 )*n ), n,
357 $ q( iu+( qstart-1 )*n ), n,
358 $ q( iu+( qstart-1 )*n ), n, work( wstart ),
359 $ info )
360 END IF
361 GO TO 40
362 END IF
363*
364 IF( icompq.EQ.2 ) THEN
365 CALL dlaset( 'A', n, n, zero, one, u, ldu )
366 CALL dlaset( 'A', n, n, zero, one, vt, ldvt )
367 END IF
368*
369* Scale.
370*
371 orgnrm = dlanst( 'M', n, d, e )
372 IF( orgnrm.EQ.zero )
373 $ RETURN
374 CALL dlascl( 'G', 0, 0, orgnrm, one, n, 1, d, n, ierr )
375 CALL dlascl( 'G', 0, 0, orgnrm, one, nm1, 1, e, nm1, ierr )
376*
377 eps = (0.9d+0)*dlamch( 'Epsilon' )
378*
379 mlvl = int( log( dble( n ) / dble( smlsiz+1 ) ) / log( two ) ) + 1
380 smlszp = smlsiz + 1
381*
382 IF( icompq.EQ.1 ) THEN
383 iu = 1
384 ivt = 1 + smlsiz
385 difl = ivt + smlszp
386 difr = difl + mlvl
387 z = difr + mlvl*2
388 ic = z + mlvl
389 is = ic + 1
390 poles = is + 1
391 givnum = poles + 2*mlvl
392*
393 k = 1
394 givptr = 2
395 perm = 3
396 givcol = perm + mlvl
397 END IF
398*
399 DO 20 i = 1, n
400 IF( abs( d( i ) ).LT.eps ) THEN
401 d( i ) = sign( eps, d( i ) )
402 END IF
403 20 CONTINUE
404*
405 start = 1
406 sqre = 0
407*
408 DO 30 i = 1, nm1
409 IF( ( abs( e( i ) ).LT.eps ) .OR. ( i.EQ.nm1 ) ) THEN
410*
411* Subproblem found. First determine its size and then
412* apply divide and conquer on it.
413*
414 IF( i.LT.nm1 ) THEN
415*
416* A subproblem with E(I) small for I < NM1.
417*
418 nsize = i - start + 1
419 ELSE IF( abs( e( i ) ).GE.eps ) THEN
420*
421* A subproblem with E(NM1) not too small but I = NM1.
422*
423 nsize = n - start + 1
424 ELSE
425*
426* A subproblem with E(NM1) small. This implies an
427* 1-by-1 subproblem at D(N). Solve this 1-by-1 problem
428* first.
429*
430 nsize = i - start + 1
431 IF( icompq.EQ.2 ) THEN
432 u( n, n ) = sign( one, d( n ) )
433 vt( n, n ) = one
434 ELSE IF( icompq.EQ.1 ) THEN
435 q( n+( qstart-1 )*n ) = sign( one, d( n ) )
436 q( n+( smlsiz+qstart-1 )*n ) = one
437 END IF
438 d( n ) = abs( d( n ) )
439 END IF
440 IF( icompq.EQ.2 ) THEN
441 CALL dlasd0( nsize, sqre, d( start ), e( start ),
442 $ u( start, start ), ldu, vt( start, start ),
443 $ ldvt, smlsiz, iwork, work( wstart ), info )
444 ELSE
445 CALL dlasda( icompq, smlsiz, nsize, sqre, d( start ),
446 $ e( start ), q( start+( iu+qstart-2 )*n ), n,
447 $ q( start+( ivt+qstart-2 )*n ),
448 $ iq( start+k*n ), q( start+( difl+qstart-2 )*
449 $ n ), q( start+( difr+qstart-2 )*n ),
450 $ q( start+( z+qstart-2 )*n ),
451 $ q( start+( poles+qstart-2 )*n ),
452 $ iq( start+givptr*n ), iq( start+givcol*n ),
453 $ n, iq( start+perm*n ),
454 $ q( start+( givnum+qstart-2 )*n ),
455 $ q( start+( ic+qstart-2 )*n ),
456 $ q( start+( is+qstart-2 )*n ),
457 $ work( wstart ), iwork, info )
458 END IF
459 IF( info.NE.0 ) THEN
460 RETURN
461 END IF
462 start = i + 1
463 END IF
464 30 CONTINUE
465*
466* Unscale
467*
468 CALL dlascl( 'G', 0, 0, one, orgnrm, n, 1, d, n, ierr )
469 40 CONTINUE
470*
471* Use Selection Sort to minimize swaps of singular vectors
472*
473 DO 60 ii = 2, n
474 i = ii - 1
475 kk = i
476 p = d( i )
477 DO 50 j = ii, n
478 IF( d( j ).GT.p ) THEN
479 kk = j
480 p = d( j )
481 END IF
482 50 CONTINUE
483 IF( kk.NE.i ) THEN
484 d( kk ) = d( i )
485 d( i ) = p
486 IF( icompq.EQ.1 ) THEN
487 iq( i ) = kk
488 ELSE IF( icompq.EQ.2 ) THEN
489 CALL dswap( n, u( 1, i ), 1, u( 1, kk ), 1 )
490 CALL dswap( n, vt( i, 1 ), ldvt, vt( kk, 1 ), ldvt )
491 END IF
492 ELSE IF( icompq.EQ.1 ) THEN
493 iq( i ) = i
494 END IF
495 60 CONTINUE
496*
497* If ICOMPQ = 1, use IQ(N,1) as the indicator for UPLO
498*
499 IF( icompq.EQ.1 ) THEN
500 IF( iuplo.EQ.1 ) THEN
501 iq( n ) = 1
502 ELSE
503 iq( n ) = 0
504 END IF
505 END IF
506*
507* If B is lower bidiagonal, update U by those Givens rotations
508* which rotated B to be upper bidiagonal
509*
510 IF( ( iuplo.EQ.2 ) .AND. ( icompq.EQ.2 ) )
511 $ CALL dlasr( 'L', 'V', 'B', n, n, work( 1 ), work( n ), u,
512 $ ldu )
513*
514 RETURN
515*
516* End of DBDSDC
517*
518 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine dbdsdc(uplo, compq, n, d, e, u, ldu, vt, ldvt, q, iq, work, iwork, info)
DBDSDC
Definition dbdsdc.f:197
subroutine dcopy(n, dx, incx, dy, incy)
DCOPY
Definition dcopy.f:82
subroutine dlartg(f, g, c, s, r)
DLARTG generates a plane rotation with real cosine and real sine.
Definition dlartg.f90:111
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition dlascl.f:142
subroutine dlasd0(n, sqre, d, e, u, ldu, vt, ldvt, smlsiz, iwork, work, info)
DLASD0 computes the singular values of a real upper bidiagonal n-by-m matrix B with diagonal d and of...
Definition dlasd0.f:151
subroutine dlasda(icompq, smlsiz, n, sqre, d, e, u, ldu, vt, k, difl, difr, z, poles, givptr, givcol, ldgcol, perm, givnum, c, s, work, iwork, info)
DLASDA computes the singular value decomposition (SVD) of a real upper bidiagonal matrix with diagona...
Definition dlasda.f:272
subroutine dlasdq(uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
DLASDQ computes the SVD of a real bidiagonal matrix with diagonal d and off-diagonal e....
Definition dlasdq.f:210
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition dlaset.f:108
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
subroutine dswap(n, dx, incx, dy, incy)
DSWAP
Definition dswap.f:82