comparison libcruft/lapack/dlalsd.f @ 7072:b48d486f641d

[project @ 2007-10-26 15:52:57 by jwe]
author jwe
date Fri, 26 Oct 2007 15:52:58 +0000
parents
children
comparison
equal deleted inserted replaced
7071:c3b479e753dd 7072:b48d486f641d
1 SUBROUTINE DLALSD( UPLO, SMLSIZ, N, NRHS, D, E, B, LDB, RCOND,
2 $ RANK, WORK, IWORK, INFO )
3 *
4 * -- LAPACK routine (version 3.1) --
5 * Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
6 * November 2006
7 *
8 * .. Scalar Arguments ..
9 CHARACTER UPLO
10 INTEGER INFO, LDB, N, NRHS, RANK, SMLSIZ
11 DOUBLE PRECISION RCOND
12 * ..
13 * .. Array Arguments ..
14 INTEGER IWORK( * )
15 DOUBLE PRECISION B( LDB, * ), D( * ), E( * ), WORK( * )
16 * ..
17 *
18 * Purpose
19 * =======
20 *
21 * DLALSD uses the singular value decomposition of A to solve the least
22 * squares problem of finding X to minimize the Euclidean norm of each
23 * column of A*X-B, where A is N-by-N upper bidiagonal, and X and B
24 * are N-by-NRHS. The solution X overwrites B.
25 *
26 * The singular values of A smaller than RCOND times the largest
27 * singular value are treated as zero in solving the least squares
28 * problem; in this case a minimum norm solution is returned.
29 * The actual singular values are returned in D in ascending order.
30 *
31 * This code makes very mild assumptions about floating point
32 * arithmetic. It will work on machines with a guard digit in
33 * add/subtract, or on those binary machines without guard digits
34 * which subtract like the Cray XMP, Cray YMP, Cray C 90, or Cray 2.
35 * It could conceivably fail on hexadecimal or decimal machines
36 * without guard digits, but we know of none.
37 *
38 * Arguments
39 * =========
40 *
41 * UPLO (input) CHARACTER*1
42 * = 'U': D and E define an upper bidiagonal matrix.
43 * = 'L': D and E define a lower bidiagonal matrix.
44 *
45 * SMLSIZ (input) INTEGER
46 * The maximum size of the subproblems at the bottom of the
47 * computation tree.
48 *
49 * N (input) INTEGER
50 * The dimension of the bidiagonal matrix. N >= 0.
51 *
52 * NRHS (input) INTEGER
53 * The number of columns of B. NRHS must be at least 1.
54 *
55 * D (input/output) DOUBLE PRECISION array, dimension (N)
56 * On entry D contains the main diagonal of the bidiagonal
57 * matrix. On exit, if INFO = 0, D contains its singular values.
58 *
59 * E (input/output) DOUBLE PRECISION array, dimension (N-1)
60 * Contains the super-diagonal entries of the bidiagonal matrix.
61 * On exit, E has been destroyed.
62 *
63 * B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
64 * On input, B contains the right hand sides of the least
65 * squares problem. On output, B contains the solution X.
66 *
67 * LDB (input) INTEGER
68 * The leading dimension of B in the calling subprogram.
69 * LDB must be at least max(1,N).
70 *
71 * RCOND (input) DOUBLE PRECISION
72 * The singular values of A less than or equal to RCOND times
73 * the largest singular value are treated as zero in solving
74 * the least squares problem. If RCOND is negative,
75 * machine precision is used instead.
76 * For example, if diag(S)*X=B were the least squares problem,
77 * where diag(S) is a diagonal matrix of singular values, the
78 * solution would be X(i) = B(i) / S(i) if S(i) is greater than
79 * RCOND*max(S), and X(i) = 0 if S(i) is less than or equal to
80 * RCOND*max(S).
81 *
82 * RANK (output) INTEGER
83 * The number of singular values of A greater than RCOND times
84 * the largest singular value.
85 *
86 * WORK (workspace) DOUBLE PRECISION array, dimension at least
87 * (9*N + 2*N*SMLSIZ + 8*N*NLVL + N*NRHS + (SMLSIZ+1)**2),
88 * where NLVL = max(0, INT(log_2 (N/(SMLSIZ+1))) + 1).
89 *
90 * IWORK (workspace) INTEGER array, dimension at least
91 * (3*N*NLVL + 11*N)
92 *
93 * INFO (output) INTEGER
94 * = 0: successful exit.
95 * < 0: if INFO = -i, the i-th argument had an illegal value.
96 * > 0: The algorithm failed to compute an singular value while
97 * working on the submatrix lying in rows and columns
98 * INFO/(N+1) through MOD(INFO,N+1).
99 *
100 * Further Details
101 * ===============
102 *
103 * Based on contributions by
104 * Ming Gu and Ren-Cang Li, Computer Science Division, University of
105 * California at Berkeley, USA
106 * Osni Marques, LBNL/NERSC, USA
107 *
108 * =====================================================================
109 *
110 * .. Parameters ..
111 DOUBLE PRECISION ZERO, ONE, TWO
112 PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 )
113 * ..
114 * .. Local Scalars ..
115 INTEGER BX, BXST, C, DIFL, DIFR, GIVCOL, GIVNUM,
116 $ GIVPTR, I, ICMPQ1, ICMPQ2, IWK, J, K, NLVL,
117 $ NM1, NSIZE, NSUB, NWORK, PERM, POLES, S, SIZEI,
118 $ SMLSZP, SQRE, ST, ST1, U, VT, Z
119 DOUBLE PRECISION CS, EPS, ORGNRM, R, RCND, SN, TOL
120 * ..
121 * .. External Functions ..
122 INTEGER IDAMAX
123 DOUBLE PRECISION DLAMCH, DLANST
124 EXTERNAL IDAMAX, DLAMCH, DLANST
125 * ..
126 * .. External Subroutines ..
127 EXTERNAL DCOPY, DGEMM, DLACPY, DLALSA, DLARTG, DLASCL,
128 $ DLASDA, DLASDQ, DLASET, DLASRT, DROT, XERBLA
129 * ..
130 * .. Intrinsic Functions ..
131 INTRINSIC ABS, DBLE, INT, LOG, SIGN
132 * ..
133 * .. Executable Statements ..
134 *
135 * Test the input parameters.
136 *
137 INFO = 0
138 *
139 IF( N.LT.0 ) THEN
140 INFO = -3
141 ELSE IF( NRHS.LT.1 ) THEN
142 INFO = -4
143 ELSE IF( ( LDB.LT.1 ) .OR. ( LDB.LT.N ) ) THEN
144 INFO = -8
145 END IF
146 IF( INFO.NE.0 ) THEN
147 CALL XERBLA( 'DLALSD', -INFO )
148 RETURN
149 END IF
150 *
151 EPS = DLAMCH( 'Epsilon' )
152 *
153 * Set up the tolerance.
154 *
155 IF( ( RCOND.LE.ZERO ) .OR. ( RCOND.GE.ONE ) ) THEN
156 RCND = EPS
157 ELSE
158 RCND = RCOND
159 END IF
160 *
161 RANK = 0
162 *
163 * Quick return if possible.
164 *
165 IF( N.EQ.0 ) THEN
166 RETURN
167 ELSE IF( N.EQ.1 ) THEN
168 IF( D( 1 ).EQ.ZERO ) THEN
169 CALL DLASET( 'A', 1, NRHS, ZERO, ZERO, B, LDB )
170 ELSE
171 RANK = 1
172 CALL DLASCL( 'G', 0, 0, D( 1 ), ONE, 1, NRHS, B, LDB, INFO )
173 D( 1 ) = ABS( D( 1 ) )
174 END IF
175 RETURN
176 END IF
177 *
178 * Rotate the matrix if it is lower bidiagonal.
179 *
180 IF( UPLO.EQ.'L' ) THEN
181 DO 10 I = 1, N - 1
182 CALL DLARTG( D( I ), E( I ), CS, SN, R )
183 D( I ) = R
184 E( I ) = SN*D( I+1 )
185 D( I+1 ) = CS*D( I+1 )
186 IF( NRHS.EQ.1 ) THEN
187 CALL DROT( 1, B( I, 1 ), 1, B( I+1, 1 ), 1, CS, SN )
188 ELSE
189 WORK( I*2-1 ) = CS
190 WORK( I*2 ) = SN
191 END IF
192 10 CONTINUE
193 IF( NRHS.GT.1 ) THEN
194 DO 30 I = 1, NRHS
195 DO 20 J = 1, N - 1
196 CS = WORK( J*2-1 )
197 SN = WORK( J*2 )
198 CALL DROT( 1, B( J, I ), 1, B( J+1, I ), 1, CS, SN )
199 20 CONTINUE
200 30 CONTINUE
201 END IF
202 END IF
203 *
204 * Scale.
205 *
206 NM1 = N - 1
207 ORGNRM = DLANST( 'M', N, D, E )
208 IF( ORGNRM.EQ.ZERO ) THEN
209 CALL DLASET( 'A', N, NRHS, ZERO, ZERO, B, LDB )
210 RETURN
211 END IF
212 *
213 CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, N, 1, D, N, INFO )
214 CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, NM1, 1, E, NM1, INFO )
215 *
216 * If N is smaller than the minimum divide size SMLSIZ, then solve
217 * the problem with another solver.
218 *
219 IF( N.LE.SMLSIZ ) THEN
220 NWORK = 1 + N*N
221 CALL DLASET( 'A', N, N, ZERO, ONE, WORK, N )
222 CALL DLASDQ( 'U', 0, N, N, 0, NRHS, D, E, WORK, N, WORK, N, B,
223 $ LDB, WORK( NWORK ), INFO )
224 IF( INFO.NE.0 ) THEN
225 RETURN
226 END IF
227 TOL = RCND*ABS( D( IDAMAX( N, D, 1 ) ) )
228 DO 40 I = 1, N
229 IF( D( I ).LE.TOL ) THEN
230 CALL DLASET( 'A', 1, NRHS, ZERO, ZERO, B( I, 1 ), LDB )
231 ELSE
232 CALL DLASCL( 'G', 0, 0, D( I ), ONE, 1, NRHS, B( I, 1 ),
233 $ LDB, INFO )
234 RANK = RANK + 1
235 END IF
236 40 CONTINUE
237 CALL DGEMM( 'T', 'N', N, NRHS, N, ONE, WORK, N, B, LDB, ZERO,
238 $ WORK( NWORK ), N )
239 CALL DLACPY( 'A', N, NRHS, WORK( NWORK ), N, B, LDB )
240 *
241 * Unscale.
242 *
243 CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
244 CALL DLASRT( 'D', N, D, INFO )
245 CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )
246 *
247 RETURN
248 END IF
249 *
250 * Book-keeping and setting up some constants.
251 *
252 NLVL = INT( LOG( DBLE( N ) / DBLE( SMLSIZ+1 ) ) / LOG( TWO ) ) + 1
253 *
254 SMLSZP = SMLSIZ + 1
255 *
256 U = 1
257 VT = 1 + SMLSIZ*N
258 DIFL = VT + SMLSZP*N
259 DIFR = DIFL + NLVL*N
260 Z = DIFR + NLVL*N*2
261 C = Z + NLVL*N
262 S = C + N
263 POLES = S + N
264 GIVNUM = POLES + 2*NLVL*N
265 BX = GIVNUM + 2*NLVL*N
266 NWORK = BX + N*NRHS
267 *
268 SIZEI = 1 + N
269 K = SIZEI + N
270 GIVPTR = K + N
271 PERM = GIVPTR + N
272 GIVCOL = PERM + NLVL*N
273 IWK = GIVCOL + NLVL*N*2
274 *
275 ST = 1
276 SQRE = 0
277 ICMPQ1 = 1
278 ICMPQ2 = 0
279 NSUB = 0
280 *
281 DO 50 I = 1, N
282 IF( ABS( D( I ) ).LT.EPS ) THEN
283 D( I ) = SIGN( EPS, D( I ) )
284 END IF
285 50 CONTINUE
286 *
287 DO 60 I = 1, NM1
288 IF( ( ABS( E( I ) ).LT.EPS ) .OR. ( I.EQ.NM1 ) ) THEN
289 NSUB = NSUB + 1
290 IWORK( NSUB ) = ST
291 *
292 * Subproblem found. First determine its size and then
293 * apply divide and conquer on it.
294 *
295 IF( I.LT.NM1 ) THEN
296 *
297 * A subproblem with E(I) small for I < NM1.
298 *
299 NSIZE = I - ST + 1
300 IWORK( SIZEI+NSUB-1 ) = NSIZE
301 ELSE IF( ABS( E( I ) ).GE.EPS ) THEN
302 *
303 * A subproblem with E(NM1) not too small but I = NM1.
304 *
305 NSIZE = N - ST + 1
306 IWORK( SIZEI+NSUB-1 ) = NSIZE
307 ELSE
308 *
309 * A subproblem with E(NM1) small. This implies an
310 * 1-by-1 subproblem at D(N), which is not solved
311 * explicitly.
312 *
313 NSIZE = I - ST + 1
314 IWORK( SIZEI+NSUB-1 ) = NSIZE
315 NSUB = NSUB + 1
316 IWORK( NSUB ) = N
317 IWORK( SIZEI+NSUB-1 ) = 1
318 CALL DCOPY( NRHS, B( N, 1 ), LDB, WORK( BX+NM1 ), N )
319 END IF
320 ST1 = ST - 1
321 IF( NSIZE.EQ.1 ) THEN
322 *
323 * This is a 1-by-1 subproblem and is not solved
324 * explicitly.
325 *
326 CALL DCOPY( NRHS, B( ST, 1 ), LDB, WORK( BX+ST1 ), N )
327 ELSE IF( NSIZE.LE.SMLSIZ ) THEN
328 *
329 * This is a small subproblem and is solved by DLASDQ.
330 *
331 CALL DLASET( 'A', NSIZE, NSIZE, ZERO, ONE,
332 $ WORK( VT+ST1 ), N )
333 CALL DLASDQ( 'U', 0, NSIZE, NSIZE, 0, NRHS, D( ST ),
334 $ E( ST ), WORK( VT+ST1 ), N, WORK( NWORK ),
335 $ N, B( ST, 1 ), LDB, WORK( NWORK ), INFO )
336 IF( INFO.NE.0 ) THEN
337 RETURN
338 END IF
339 CALL DLACPY( 'A', NSIZE, NRHS, B( ST, 1 ), LDB,
340 $ WORK( BX+ST1 ), N )
341 ELSE
342 *
343 * A large problem. Solve it using divide and conquer.
344 *
345 CALL DLASDA( ICMPQ1, SMLSIZ, NSIZE, SQRE, D( ST ),
346 $ E( ST ), WORK( U+ST1 ), N, WORK( VT+ST1 ),
347 $ IWORK( K+ST1 ), WORK( DIFL+ST1 ),
348 $ WORK( DIFR+ST1 ), WORK( Z+ST1 ),
349 $ WORK( POLES+ST1 ), IWORK( GIVPTR+ST1 ),
350 $ IWORK( GIVCOL+ST1 ), N, IWORK( PERM+ST1 ),
351 $ WORK( GIVNUM+ST1 ), WORK( C+ST1 ),
352 $ WORK( S+ST1 ), WORK( NWORK ), IWORK( IWK ),
353 $ INFO )
354 IF( INFO.NE.0 ) THEN
355 RETURN
356 END IF
357 BXST = BX + ST1
358 CALL DLALSA( ICMPQ2, SMLSIZ, NSIZE, NRHS, B( ST, 1 ),
359 $ LDB, WORK( BXST ), N, WORK( U+ST1 ), N,
360 $ WORK( VT+ST1 ), IWORK( K+ST1 ),
361 $ WORK( DIFL+ST1 ), WORK( DIFR+ST1 ),
362 $ WORK( Z+ST1 ), WORK( POLES+ST1 ),
363 $ IWORK( GIVPTR+ST1 ), IWORK( GIVCOL+ST1 ), N,
364 $ IWORK( PERM+ST1 ), WORK( GIVNUM+ST1 ),
365 $ WORK( C+ST1 ), WORK( S+ST1 ), WORK( NWORK ),
366 $ IWORK( IWK ), INFO )
367 IF( INFO.NE.0 ) THEN
368 RETURN
369 END IF
370 END IF
371 ST = I + 1
372 END IF
373 60 CONTINUE
374 *
375 * Apply the singular values and treat the tiny ones as zero.
376 *
377 TOL = RCND*ABS( D( IDAMAX( N, D, 1 ) ) )
378 *
379 DO 70 I = 1, N
380 *
381 * Some of the elements in D can be negative because 1-by-1
382 * subproblems were not solved explicitly.
383 *
384 IF( ABS( D( I ) ).LE.TOL ) THEN
385 CALL DLASET( 'A', 1, NRHS, ZERO, ZERO, WORK( BX+I-1 ), N )
386 ELSE
387 RANK = RANK + 1
388 CALL DLASCL( 'G', 0, 0, D( I ), ONE, 1, NRHS,
389 $ WORK( BX+I-1 ), N, INFO )
390 END IF
391 D( I ) = ABS( D( I ) )
392 70 CONTINUE
393 *
394 * Now apply back the right singular vectors.
395 *
396 ICMPQ2 = 1
397 DO 80 I = 1, NSUB
398 ST = IWORK( I )
399 ST1 = ST - 1
400 NSIZE = IWORK( SIZEI+I-1 )
401 BXST = BX + ST1
402 IF( NSIZE.EQ.1 ) THEN
403 CALL DCOPY( NRHS, WORK( BXST ), N, B( ST, 1 ), LDB )
404 ELSE IF( NSIZE.LE.SMLSIZ ) THEN
405 CALL DGEMM( 'T', 'N', NSIZE, NRHS, NSIZE, ONE,
406 $ WORK( VT+ST1 ), N, WORK( BXST ), N, ZERO,
407 $ B( ST, 1 ), LDB )
408 ELSE
409 CALL DLALSA( ICMPQ2, SMLSIZ, NSIZE, NRHS, WORK( BXST ), N,
410 $ B( ST, 1 ), LDB, WORK( U+ST1 ), N,
411 $ WORK( VT+ST1 ), IWORK( K+ST1 ),
412 $ WORK( DIFL+ST1 ), WORK( DIFR+ST1 ),
413 $ WORK( Z+ST1 ), WORK( POLES+ST1 ),
414 $ IWORK( GIVPTR+ST1 ), IWORK( GIVCOL+ST1 ), N,
415 $ IWORK( PERM+ST1 ), WORK( GIVNUM+ST1 ),
416 $ WORK( C+ST1 ), WORK( S+ST1 ), WORK( NWORK ),
417 $ IWORK( IWK ), INFO )
418 IF( INFO.NE.0 ) THEN
419 RETURN
420 END IF
421 END IF
422 80 CONTINUE
423 *
424 * Unscale and sort the singular values.
425 *
426 CALL DLASCL( 'G', 0, 0, ONE, ORGNRM, N, 1, D, N, INFO )
427 CALL DLASRT( 'D', N, D, INFO )
428 CALL DLASCL( 'G', 0, 0, ORGNRM, ONE, N, NRHS, B, LDB, INFO )
429 *
430 RETURN
431 *
432 * End of DLALSD
433 *
434 END