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