LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
slalsd.f
Go to the documentation of this file.
1*> \brief \b SLALSD uses the singular value decomposition of A to solve the least squares problem.
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download SLALSD + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slalsd.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slalsd.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slalsd.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE SLALSD( UPLO, SMLSIZ, N, NRHS, D, E, B, LDB, RCOND,
20* RANK, WORK, IWORK, INFO )
21*
22* .. Scalar Arguments ..
23* CHARACTER UPLO
24* INTEGER INFO, LDB, N, NRHS, RANK, SMLSIZ
25* REAL RCOND
26* ..
27* .. Array Arguments ..
28* INTEGER IWORK( * )
29* REAL B( LDB, * ), D( * ), E( * ), WORK( * )
30* ..
31*
32*
33*> \par Purpose:
34* =============
35*>
36*> \verbatim
37*>
38*> SLALSD uses the singular value decomposition of A to solve the least
39*> squares problem of finding X to minimize the Euclidean norm of each
40*> column of A*X-B, where A is N-by-N upper bidiagonal, and X and B
41*> are N-by-NRHS. The solution X overwrites B.
42*>
43*> The singular values of A smaller than RCOND times the largest
44*> singular value are treated as zero in solving the least squares
45*> problem; in this case a minimum norm solution is returned.
46*> The actual singular values are returned in D in ascending order.
47*>
48*> \endverbatim
49*
50* Arguments:
51* ==========
52*
53*> \param[in] UPLO
54*> \verbatim
55*> UPLO is CHARACTER*1
56*> = 'U': D and E define an upper bidiagonal matrix.
57*> = 'L': D and E define a lower bidiagonal matrix.
58*> \endverbatim
59*>
60*> \param[in] SMLSIZ
61*> \verbatim
62*> SMLSIZ is INTEGER
63*> The maximum size of the subproblems at the bottom of the
64*> computation tree.
65*> \endverbatim
66*>
67*> \param[in] N
68*> \verbatim
69*> N is INTEGER
70*> The dimension of the bidiagonal matrix. N >= 0.
71*> \endverbatim
72*>
73*> \param[in] NRHS
74*> \verbatim
75*> NRHS is INTEGER
76*> The number of columns of B. NRHS must be at least 1.
77*> \endverbatim
78*>
79*> \param[in,out] D
80*> \verbatim
81*> D is REAL array, dimension (N)
82*> On entry D contains the main diagonal of the bidiagonal
83*> matrix. On exit, if INFO = 0, D contains its singular values.
84*> \endverbatim
85*>
86*> \param[in,out] E
87*> \verbatim
88*> E is REAL array, dimension (N-1)
89*> Contains the super-diagonal entries of the bidiagonal matrix.
90*> On exit, E has been destroyed.
91*> \endverbatim
92*>
93*> \param[in,out] B
94*> \verbatim
95*> B is REAL array, dimension (LDB,NRHS)
96*> On input, B contains the right hand sides of the least
97*> squares problem. On output, B contains the solution X.
98*> \endverbatim
99*>
100*> \param[in] LDB
101*> \verbatim
102*> LDB is INTEGER
103*> The leading dimension of B in the calling subprogram.
104*> LDB must be at least max(1,N).
105*> \endverbatim
106*>
107*> \param[in] RCOND
108*> \verbatim
109*> RCOND is REAL
110*> The singular values of A less than or equal to RCOND times
111*> the largest singular value are treated as zero in solving
112*> the least squares problem. If RCOND is negative,
113*> machine precision is used instead.
114*> For example, if diag(S)*X=B were the least squares problem,
115*> where diag(S) is a diagonal matrix of singular values, the
116*> solution would be X(i) = B(i) / S(i) if S(i) is greater than
117*> RCOND*max(S), and X(i) = 0 if S(i) is less than or equal to
118*> RCOND*max(S).
119*> \endverbatim
120*>
121*> \param[out] RANK
122*> \verbatim
123*> RANK is INTEGER
124*> The number of singular values of A greater than RCOND times
125*> the largest singular value.
126*> \endverbatim
127*>
128*> \param[out] WORK
129*> \verbatim
130*> WORK is REAL array, dimension at least
131*> (9*N + 2*N*SMLSIZ + 8*N*NLVL + N*NRHS + (SMLSIZ+1)**2),
132*> where NLVL = max(0, INT(log_2 (N/(SMLSIZ+1))) + 1).
133*> \endverbatim
134*>
135*> \param[out] IWORK
136*> \verbatim
137*> IWORK is INTEGER array, dimension at least
138*> (3*N*NLVL + 11*N)
139*> \endverbatim
140*>
141*> \param[out] INFO
142*> \verbatim
143*> INFO is INTEGER
144*> = 0: successful exit.
145*> < 0: if INFO = -i, the i-th argument had an illegal value.
146*> > 0: The algorithm failed to compute a singular value while
147*> working on the submatrix lying in rows and columns
148*> INFO/(N+1) through MOD(INFO,N+1).
149*> \endverbatim
150*
151* Authors:
152* ========
153*
154*> \author Univ. of Tennessee
155*> \author Univ. of California Berkeley
156*> \author Univ. of Colorado Denver
157*> \author NAG Ltd.
158*
159*> \ingroup lalsd
160*
161*> \par Contributors:
162* ==================
163*>
164*> Ming Gu and Ren-Cang Li, Computer Science Division, University of
165*> California at Berkeley, USA \n
166*> Osni Marques, LBNL/NERSC, USA \n
167*
168* =====================================================================
169 SUBROUTINE slalsd( UPLO, SMLSIZ, N, NRHS, D, E, B, LDB, RCOND,
170 $ RANK, WORK, IWORK, INFO )
171*
172* -- LAPACK computational routine --
173* -- LAPACK is a software package provided by Univ. of Tennessee, --
174* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
175*
176* .. Scalar Arguments ..
177 CHARACTER UPLO
178 INTEGER INFO, LDB, N, NRHS, RANK, SMLSIZ
179 REAL RCOND
180* ..
181* .. Array Arguments ..
182 INTEGER IWORK( * )
183 REAL B( LDB, * ), D( * ), E( * ), WORK( * )
184* ..
185*
186* =====================================================================
187*
188* .. Parameters ..
189 REAL ZERO, ONE, TWO
190 parameter( zero = 0.0e0, one = 1.0e0, two = 2.0e0 )
191* ..
192* .. Local Scalars ..
193 INTEGER BX, BXST, C, DIFL, DIFR, GIVCOL, GIVNUM,
194 $ givptr, i, icmpq1, icmpq2, iwk, j, k, nlvl,
195 $ nm1, nsize, nsub, nwork, perm, poles, s, sizei,
196 $ smlszp, sqre, st, st1, u, vt, z
197 REAL CS, EPS, ORGNRM, R, RCND, SN, TOL
198* ..
199* .. External Functions ..
200 INTEGER ISAMAX
201 REAL SLAMCH, SLANST
202 EXTERNAL isamax, slamch, slanst
203* ..
204* .. External Subroutines ..
205 EXTERNAL scopy, sgemm, slacpy, slalsa, slartg,
206 $ slascl,
208* ..
209* .. Intrinsic Functions ..
210 INTRINSIC abs, int, log, real, sign
211* ..
212* .. Executable Statements ..
213*
214* Test the input parameters.
215*
216 info = 0
217*
218 IF( n.LT.0 ) THEN
219 info = -3
220 ELSE IF( nrhs.LT.1 ) THEN
221 info = -4
222 ELSE IF( ( ldb.LT.1 ) .OR. ( ldb.LT.n ) ) THEN
223 info = -8
224 END IF
225 IF( info.NE.0 ) THEN
226 CALL xerbla( 'SLALSD', -info )
227 RETURN
228 END IF
229*
230 eps = slamch( 'Epsilon' )
231*
232* Set up the tolerance.
233*
234 IF( ( rcond.LE.zero ) .OR. ( rcond.GE.one ) ) THEN
235 rcnd = eps
236 ELSE
237 rcnd = rcond
238 END IF
239*
240 rank = 0
241*
242* Quick return if possible.
243*
244 IF( n.EQ.0 ) THEN
245 RETURN
246 ELSE IF( n.EQ.1 ) THEN
247 IF( d( 1 ).EQ.zero ) THEN
248 CALL slaset( 'A', 1, nrhs, zero, zero, b, ldb )
249 ELSE
250 rank = 1
251 CALL slascl( 'G', 0, 0, d( 1 ), one, 1, nrhs, b, ldb,
252 $ info )
253 d( 1 ) = abs( d( 1 ) )
254 END IF
255 RETURN
256 END IF
257*
258* Rotate the matrix if it is lower bidiagonal.
259*
260 IF( uplo.EQ.'L' ) THEN
261 DO 10 i = 1, n - 1
262 CALL slartg( d( i ), e( i ), cs, sn, r )
263 d( i ) = r
264 e( i ) = sn*d( i+1 )
265 d( i+1 ) = cs*d( i+1 )
266 IF( nrhs.EQ.1 ) THEN
267 CALL srot( 1, b( i, 1 ), 1, b( i+1, 1 ), 1, cs, sn )
268 ELSE
269 work( i*2-1 ) = cs
270 work( i*2 ) = sn
271 END IF
272 10 CONTINUE
273 IF( nrhs.GT.1 ) THEN
274 DO 30 i = 1, nrhs
275 DO 20 j = 1, n - 1
276 cs = work( j*2-1 )
277 sn = work( j*2 )
278 CALL srot( 1, b( j, i ), 1, b( j+1, i ), 1, cs,
279 $ sn )
280 20 CONTINUE
281 30 CONTINUE
282 END IF
283 END IF
284*
285* Scale.
286*
287 nm1 = n - 1
288 orgnrm = slanst( 'M', n, d, e )
289 IF( orgnrm.EQ.zero ) THEN
290 CALL slaset( 'A', n, nrhs, zero, zero, b, ldb )
291 RETURN
292 END IF
293*
294 CALL slascl( 'G', 0, 0, orgnrm, one, n, 1, d, n, info )
295 CALL slascl( 'G', 0, 0, orgnrm, one, nm1, 1, e, nm1, info )
296*
297* If N is smaller than the minimum divide size SMLSIZ, then solve
298* the problem with another solver.
299*
300 IF( n.LE.smlsiz ) THEN
301 nwork = 1 + n*n
302 CALL slaset( 'A', n, n, zero, one, work, n )
303 CALL slasdq( 'U', 0, n, n, 0, nrhs, d, e, work, n, work, n,
304 $ b,
305 $ ldb, work( nwork ), info )
306 IF( info.NE.0 ) THEN
307 RETURN
308 END IF
309 tol = rcnd*abs( d( isamax( n, d, 1 ) ) )
310 DO 40 i = 1, n
311 IF( d( i ).LE.tol ) THEN
312 CALL slaset( 'A', 1, nrhs, zero, zero, b( i, 1 ),
313 $ ldb )
314 ELSE
315 CALL slascl( 'G', 0, 0, d( i ), one, 1, nrhs, b( i,
316 $ 1 ),
317 $ ldb, info )
318 rank = rank + 1
319 END IF
320 40 CONTINUE
321 CALL sgemm( 'T', 'N', n, nrhs, n, one, work, n, b, ldb,
322 $ zero,
323 $ work( nwork ), n )
324 CALL slacpy( 'A', n, nrhs, work( nwork ), n, b, ldb )
325*
326* Unscale.
327*
328 CALL slascl( 'G', 0, 0, one, orgnrm, n, 1, d, n, info )
329 CALL slasrt( 'D', n, d, info )
330 CALL slascl( 'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
331*
332 RETURN
333 END IF
334*
335* Book-keeping and setting up some constants.
336*
337 nlvl = int( log( real( n ) / real( smlsiz+1 ) ) / log( two ) ) + 1
338*
339 smlszp = smlsiz + 1
340*
341 u = 1
342 vt = 1 + smlsiz*n
343 difl = vt + smlszp*n
344 difr = difl + nlvl*n
345 z = difr + nlvl*n*2
346 c = z + nlvl*n
347 s = c + n
348 poles = s + n
349 givnum = poles + 2*nlvl*n
350 bx = givnum + 2*nlvl*n
351 nwork = bx + n*nrhs
352*
353 sizei = 1 + n
354 k = sizei + n
355 givptr = k + n
356 perm = givptr + n
357 givcol = perm + nlvl*n
358 iwk = givcol + nlvl*n*2
359*
360 st = 1
361 sqre = 0
362 icmpq1 = 1
363 icmpq2 = 0
364 nsub = 0
365*
366 DO 50 i = 1, n
367 IF( abs( d( i ) ).LT.eps ) THEN
368 d( i ) = sign( eps, d( i ) )
369 END IF
370 50 CONTINUE
371*
372 DO 60 i = 1, nm1
373 IF( ( abs( e( i ) ).LT.eps ) .OR. ( i.EQ.nm1 ) ) THEN
374 nsub = nsub + 1
375 iwork( nsub ) = st
376*
377* Subproblem found. First determine its size and then
378* apply divide and conquer on it.
379*
380 IF( i.LT.nm1 ) THEN
381*
382* A subproblem with E(I) small for I < NM1.
383*
384 nsize = i - st + 1
385 iwork( sizei+nsub-1 ) = nsize
386 ELSE IF( abs( e( i ) ).GE.eps ) THEN
387*
388* A subproblem with E(NM1) not too small but I = NM1.
389*
390 nsize = n - st + 1
391 iwork( sizei+nsub-1 ) = nsize
392 ELSE
393*
394* A subproblem with E(NM1) small. This implies an
395* 1-by-1 subproblem at D(N), which is not solved
396* explicitly.
397*
398 nsize = i - st + 1
399 iwork( sizei+nsub-1 ) = nsize
400 nsub = nsub + 1
401 iwork( nsub ) = n
402 iwork( sizei+nsub-1 ) = 1
403 CALL scopy( nrhs, b( n, 1 ), ldb, work( bx+nm1 ), n )
404 END IF
405 st1 = st - 1
406 IF( nsize.EQ.1 ) THEN
407*
408* This is a 1-by-1 subproblem and is not solved
409* explicitly.
410*
411 CALL scopy( nrhs, b( st, 1 ), ldb, work( bx+st1 ), n )
412 ELSE IF( nsize.LE.smlsiz ) THEN
413*
414* This is a small subproblem and is solved by SLASDQ.
415*
416 CALL slaset( 'A', nsize, nsize, zero, one,
417 $ work( vt+st1 ), n )
418 CALL slasdq( 'U', 0, nsize, nsize, 0, nrhs, d( st ),
419 $ e( st ), work( vt+st1 ), n, work( nwork ),
420 $ n, b( st, 1 ), ldb, work( nwork ), info )
421 IF( info.NE.0 ) THEN
422 RETURN
423 END IF
424 CALL slacpy( 'A', nsize, nrhs, b( st, 1 ), ldb,
425 $ work( bx+st1 ), n )
426 ELSE
427*
428* A large problem. Solve it using divide and conquer.
429*
430 CALL slasda( icmpq1, smlsiz, nsize, sqre, d( st ),
431 $ e( st ), work( u+st1 ), n, work( vt+st1 ),
432 $ iwork( k+st1 ), work( difl+st1 ),
433 $ work( difr+st1 ), work( z+st1 ),
434 $ work( poles+st1 ), iwork( givptr+st1 ),
435 $ iwork( givcol+st1 ), n, iwork( perm+st1 ),
436 $ work( givnum+st1 ), work( c+st1 ),
437 $ work( s+st1 ), work( nwork ), iwork( iwk ),
438 $ info )
439 IF( info.NE.0 ) THEN
440 RETURN
441 END IF
442 bxst = bx + st1
443 CALL slalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1 ),
444 $ ldb, work( bxst ), n, work( u+st1 ), n,
445 $ work( vt+st1 ), iwork( k+st1 ),
446 $ work( difl+st1 ), work( difr+st1 ),
447 $ work( z+st1 ), work( poles+st1 ),
448 $ iwork( givptr+st1 ), iwork( givcol+st1 ), n,
449 $ iwork( perm+st1 ), work( givnum+st1 ),
450 $ work( c+st1 ), work( s+st1 ), work( nwork ),
451 $ iwork( iwk ), info )
452 IF( info.NE.0 ) THEN
453 RETURN
454 END IF
455 END IF
456 st = i + 1
457 END IF
458 60 CONTINUE
459*
460* Apply the singular values and treat the tiny ones as zero.
461*
462 tol = rcnd*abs( d( isamax( n, d, 1 ) ) )
463*
464 DO 70 i = 1, n
465*
466* Some of the elements in D can be negative because 1-by-1
467* subproblems were not solved explicitly.
468*
469 IF( abs( d( i ) ).LE.tol ) THEN
470 CALL slaset( 'A', 1, nrhs, zero, zero, work( bx+i-1 ),
471 $ n )
472 ELSE
473 rank = rank + 1
474 CALL slascl( 'G', 0, 0, d( i ), one, 1, nrhs,
475 $ work( bx+i-1 ), n, info )
476 END IF
477 d( i ) = abs( d( i ) )
478 70 CONTINUE
479*
480* Now apply back the right singular vectors.
481*
482 icmpq2 = 1
483 DO 80 i = 1, nsub
484 st = iwork( i )
485 st1 = st - 1
486 nsize = iwork( sizei+i-1 )
487 bxst = bx + st1
488 IF( nsize.EQ.1 ) THEN
489 CALL scopy( nrhs, work( bxst ), n, b( st, 1 ), ldb )
490 ELSE IF( nsize.LE.smlsiz ) THEN
491 CALL sgemm( 'T', 'N', nsize, nrhs, nsize, one,
492 $ work( vt+st1 ), n, work( bxst ), n, zero,
493 $ b( st, 1 ), ldb )
494 ELSE
495 CALL slalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ),
496 $ n,
497 $ b( st, 1 ), ldb, work( u+st1 ), n,
498 $ work( vt+st1 ), iwork( k+st1 ),
499 $ work( difl+st1 ), work( difr+st1 ),
500 $ work( z+st1 ), work( poles+st1 ),
501 $ iwork( givptr+st1 ), iwork( givcol+st1 ), n,
502 $ iwork( perm+st1 ), work( givnum+st1 ),
503 $ work( c+st1 ), work( s+st1 ), work( nwork ),
504 $ iwork( iwk ), info )
505 IF( info.NE.0 ) THEN
506 RETURN
507 END IF
508 END IF
509 80 CONTINUE
510*
511* Unscale and sort the singular values.
512*
513 CALL slascl( 'G', 0, 0, one, orgnrm, n, 1, d, n, info )
514 CALL slasrt( 'D', n, d, info )
515 CALL slascl( 'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
516*
517 RETURN
518*
519* End of SLALSD
520*
521 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
Definition scopy.f:82
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
Definition sgemm.f:188
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
Definition slacpy.f:101
subroutine slalsa(icompq, smlsiz, n, nrhs, b, ldb, bx, ldbx, u, ldu, vt, k, difl, difr, z, poles, givptr, givcol, ldgcol, perm, givnum, c, s, work, iwork, info)
SLALSA computes the SVD of the coefficient matrix in compact form. Used by sgelsd.
Definition slalsa.f:266
subroutine slalsd(uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond, rank, work, iwork, info)
SLALSD uses the singular value decomposition of A to solve the least squares problem.
Definition slalsd.f:171
subroutine slartg(f, g, c, s, r)
SLARTG generates a plane rotation with real cosine and real sine.
Definition slartg.f90:111
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition slascl.f:142
subroutine slasda(icompq, smlsiz, n, sqre, d, e, u, ldu, vt, k, difl, difr, z, poles, givptr, givcol, ldgcol, perm, givnum, c, s, work, iwork, info)
SLASDA computes the singular value decomposition (SVD) of a real upper bidiagonal matrix with diagona...
Definition slasda.f:272
subroutine slasdq(uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
SLASDQ computes the SVD of a real bidiagonal matrix with diagonal d and off-diagonal e....
Definition slasdq.f:210
subroutine slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition slaset.f:108
subroutine slasrt(id, n, d, info)
SLASRT sorts numbers in increasing or decreasing order.
Definition slasrt.f:86
subroutine srot(n, sx, incx, sy, incy, c, s)
SROT
Definition srot.f:92