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