1: SUBROUTINE ZLALS0( ICOMPQ, NL, NR, SQRE, NRHS, B, LDB, BX, LDBX,
2: $ PERM, GIVPTR, GIVCOL, LDGCOL, GIVNUM, LDGNUM,
3: $ POLES, DIFL, DIFR, Z, K, C, S, RWORK, INFO )
4: *
5: * -- LAPACK routine (version 3.2) --
6: * -- LAPACK is a software package provided by Univ. of Tennessee, --
7: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
8: * November 2006
9: *
10: * .. Scalar Arguments ..
11: INTEGER GIVPTR, ICOMPQ, INFO, K, LDB, LDBX, LDGCOL,
12: $ LDGNUM, NL, NR, NRHS, SQRE
13: DOUBLE PRECISION C, S
14: * ..
15: * .. Array Arguments ..
16: INTEGER GIVCOL( LDGCOL, * ), PERM( * )
17: DOUBLE PRECISION DIFL( * ), DIFR( LDGNUM, * ),
18: $ GIVNUM( LDGNUM, * ), POLES( LDGNUM, * ),
19: $ RWORK( * ), Z( * )
20: COMPLEX*16 B( LDB, * ), BX( LDBX, * )
21: * ..
22: *
23: * Purpose
24: * =======
25: *
26: * ZLALS0 applies back the multiplying factors of either the left or the
27: * right singular vector matrix of a diagonal matrix appended by a row
28: * to the right hand side matrix B in solving the least squares problem
29: * using the divide-and-conquer SVD approach.
30: *
31: * For the left singular vector matrix, three types of orthogonal
32: * matrices are involved:
33: *
34: * (1L) Givens rotations: the number of such rotations is GIVPTR; the
35: * pairs of columns/rows they were applied to are stored in GIVCOL;
36: * and the C- and S-values of these rotations are stored in GIVNUM.
37: *
38: * (2L) Permutation. The (NL+1)-st row of B is to be moved to the first
39: * row, and for J=2:N, PERM(J)-th row of B is to be moved to the
40: * J-th row.
41: *
42: * (3L) The left singular vector matrix of the remaining matrix.
43: *
44: * For the right singular vector matrix, four types of orthogonal
45: * matrices are involved:
46: *
47: * (1R) The right singular vector matrix of the remaining matrix.
48: *
49: * (2R) If SQRE = 1, one extra Givens rotation to generate the right
50: * null space.
51: *
52: * (3R) The inverse transformation of (2L).
53: *
54: * (4R) The inverse transformation of (1L).
55: *
56: * Arguments
57: * =========
58: *
59: * ICOMPQ (input) INTEGER
60: * Specifies whether singular vectors are to be computed in
61: * factored form:
62: * = 0: Left singular vector matrix.
63: * = 1: Right singular vector matrix.
64: *
65: * NL (input) INTEGER
66: * The row dimension of the upper block. NL >= 1.
67: *
68: * NR (input) INTEGER
69: * The row dimension of the lower block. NR >= 1.
70: *
71: * SQRE (input) INTEGER
72: * = 0: the lower block is an NR-by-NR square matrix.
73: * = 1: the lower block is an NR-by-(NR+1) rectangular matrix.
74: *
75: * The bidiagonal matrix has row dimension N = NL + NR + 1,
76: * and column dimension M = N + SQRE.
77: *
78: * NRHS (input) INTEGER
79: * The number of columns of B and BX. NRHS must be at least 1.
80: *
81: * B (input/output) COMPLEX*16 array, dimension ( LDB, NRHS )
82: * On input, B contains the right hand sides of the least
83: * squares problem in rows 1 through M. On output, B contains
84: * the solution X in rows 1 through N.
85: *
86: * LDB (input) INTEGER
87: * The leading dimension of B. LDB must be at least
88: * max(1,MAX( M, N ) ).
89: *
90: * BX (workspace) COMPLEX*16 array, dimension ( LDBX, NRHS )
91: *
92: * LDBX (input) INTEGER
93: * The leading dimension of BX.
94: *
95: * PERM (input) INTEGER array, dimension ( N )
96: * The permutations (from deflation and sorting) applied
97: * to the two blocks.
98: *
99: * GIVPTR (input) INTEGER
100: * The number of Givens rotations which took place in this
101: * subproblem.
102: *
103: * GIVCOL (input) INTEGER array, dimension ( LDGCOL, 2 )
104: * Each pair of numbers indicates a pair of rows/columns
105: * involved in a Givens rotation.
106: *
107: * LDGCOL (input) INTEGER
108: * The leading dimension of GIVCOL, must be at least N.
109: *
110: * GIVNUM (input) DOUBLE PRECISION array, dimension ( LDGNUM, 2 )
111: * Each number indicates the C or S value used in the
112: * corresponding Givens rotation.
113: *
114: * LDGNUM (input) INTEGER
115: * The leading dimension of arrays DIFR, POLES and
116: * GIVNUM, must be at least K.
117: *
118: * POLES (input) DOUBLE PRECISION array, dimension ( LDGNUM, 2 )
119: * On entry, POLES(1:K, 1) contains the new singular
120: * values obtained from solving the secular equation, and
121: * POLES(1:K, 2) is an array containing the poles in the secular
122: * equation.
123: *
124: * DIFL (input) DOUBLE PRECISION array, dimension ( K ).
125: * On entry, DIFL(I) is the distance between I-th updated
126: * (undeflated) singular value and the I-th (undeflated) old
127: * singular value.
128: *
129: * DIFR (input) DOUBLE PRECISION array, dimension ( LDGNUM, 2 ).
130: * On entry, DIFR(I, 1) contains the distances between I-th
131: * updated (undeflated) singular value and the I+1-th
132: * (undeflated) old singular value. And DIFR(I, 2) is the
133: * normalizing factor for the I-th right singular vector.
134: *
135: * Z (input) DOUBLE PRECISION array, dimension ( K )
136: * Contain the components of the deflation-adjusted updating row
137: * vector.
138: *
139: * K (input) INTEGER
140: * Contains the dimension of the non-deflated matrix,
141: * This is the order of the related secular equation. 1 <= K <=N.
142: *
143: * C (input) DOUBLE PRECISION
144: * C contains garbage if SQRE =0 and the C-value of a Givens
145: * rotation related to the right null space if SQRE = 1.
146: *
147: * S (input) DOUBLE PRECISION
148: * S contains garbage if SQRE =0 and the S-value of a Givens
149: * rotation related to the right null space if SQRE = 1.
150: *
151: * RWORK (workspace) DOUBLE PRECISION array, dimension
152: * ( K*(1+NRHS) + 2*NRHS )
153: *
154: * INFO (output) INTEGER
155: * = 0: successful exit.
156: * < 0: if INFO = -i, the i-th argument had an illegal value.
157: *
158: * Further Details
159: * ===============
160: *
161: * Based on contributions by
162: * Ming Gu and Ren-Cang Li, Computer Science Division, University of
163: * California at Berkeley, USA
164: * Osni Marques, LBNL/NERSC, USA
165: *
166: * =====================================================================
167: *
168: * .. Parameters ..
169: DOUBLE PRECISION ONE, ZERO, NEGONE
170: PARAMETER ( ONE = 1.0D0, ZERO = 0.0D0, NEGONE = -1.0D0 )
171: * ..
172: * .. Local Scalars ..
173: INTEGER I, J, JCOL, JROW, M, N, NLP1
174: DOUBLE PRECISION DIFLJ, DIFRJ, DJ, DSIGJ, DSIGJP, TEMP
175: * ..
176: * .. External Subroutines ..
177: EXTERNAL DGEMV, XERBLA, ZCOPY, ZDROT, ZDSCAL, ZLACPY,
178: $ ZLASCL
179: * ..
180: * .. External Functions ..
181: DOUBLE PRECISION DLAMC3, DNRM2
182: EXTERNAL DLAMC3, DNRM2
183: * ..
184: * .. Intrinsic Functions ..
185: INTRINSIC DBLE, DCMPLX, DIMAG, MAX
186: * ..
187: * .. Executable Statements ..
188: *
189: * Test the input parameters.
190: *
191: INFO = 0
192: *
193: IF( ( ICOMPQ.LT.0 ) .OR. ( ICOMPQ.GT.1 ) ) THEN
194: INFO = -1
195: ELSE IF( NL.LT.1 ) THEN
196: INFO = -2
197: ELSE IF( NR.LT.1 ) THEN
198: INFO = -3
199: ELSE IF( ( SQRE.LT.0 ) .OR. ( SQRE.GT.1 ) ) THEN
200: INFO = -4
201: END IF
202: *
203: N = NL + NR + 1
204: *
205: IF( NRHS.LT.1 ) THEN
206: INFO = -5
207: ELSE IF( LDB.LT.N ) THEN
208: INFO = -7
209: ELSE IF( LDBX.LT.N ) THEN
210: INFO = -9
211: ELSE IF( GIVPTR.LT.0 ) THEN
212: INFO = -11
213: ELSE IF( LDGCOL.LT.N ) THEN
214: INFO = -13
215: ELSE IF( LDGNUM.LT.N ) THEN
216: INFO = -15
217: ELSE IF( K.LT.1 ) THEN
218: INFO = -20
219: END IF
220: IF( INFO.NE.0 ) THEN
221: CALL XERBLA( 'ZLALS0', -INFO )
222: RETURN
223: END IF
224: *
225: M = N + SQRE
226: NLP1 = NL + 1
227: *
228: IF( ICOMPQ.EQ.0 ) THEN
229: *
230: * Apply back orthogonal transformations from the left.
231: *
232: * Step (1L): apply back the Givens rotations performed.
233: *
234: DO 10 I = 1, GIVPTR
235: CALL ZDROT( NRHS, B( GIVCOL( I, 2 ), 1 ), LDB,
236: $ B( GIVCOL( I, 1 ), 1 ), LDB, GIVNUM( I, 2 ),
237: $ GIVNUM( I, 1 ) )
238: 10 CONTINUE
239: *
240: * Step (2L): permute rows of B.
241: *
242: CALL ZCOPY( NRHS, B( NLP1, 1 ), LDB, BX( 1, 1 ), LDBX )
243: DO 20 I = 2, N
244: CALL ZCOPY( NRHS, B( PERM( I ), 1 ), LDB, BX( I, 1 ), LDBX )
245: 20 CONTINUE
246: *
247: * Step (3L): apply the inverse of the left singular vector
248: * matrix to BX.
249: *
250: IF( K.EQ.1 ) THEN
251: CALL ZCOPY( NRHS, BX, LDBX, B, LDB )
252: IF( Z( 1 ).LT.ZERO ) THEN
253: CALL ZDSCAL( NRHS, NEGONE, B, LDB )
254: END IF
255: ELSE
256: DO 100 J = 1, K
257: DIFLJ = DIFL( J )
258: DJ = POLES( J, 1 )
259: DSIGJ = -POLES( J, 2 )
260: IF( J.LT.K ) THEN
261: DIFRJ = -DIFR( J, 1 )
262: DSIGJP = -POLES( J+1, 2 )
263: END IF
264: IF( ( Z( J ).EQ.ZERO ) .OR. ( POLES( J, 2 ).EQ.ZERO ) )
265: $ THEN
266: RWORK( J ) = ZERO
267: ELSE
268: RWORK( J ) = -POLES( J, 2 )*Z( J ) / DIFLJ /
269: $ ( POLES( J, 2 )+DJ )
270: END IF
271: DO 30 I = 1, J - 1
272: IF( ( Z( I ).EQ.ZERO ) .OR.
273: $ ( POLES( I, 2 ).EQ.ZERO ) ) THEN
274: RWORK( I ) = ZERO
275: ELSE
276: RWORK( I ) = POLES( I, 2 )*Z( I ) /
277: $ ( DLAMC3( POLES( I, 2 ), DSIGJ )-
278: $ DIFLJ ) / ( POLES( I, 2 )+DJ )
279: END IF
280: 30 CONTINUE
281: DO 40 I = J + 1, K
282: IF( ( Z( I ).EQ.ZERO ) .OR.
283: $ ( POLES( I, 2 ).EQ.ZERO ) ) THEN
284: RWORK( I ) = ZERO
285: ELSE
286: RWORK( I ) = POLES( I, 2 )*Z( I ) /
287: $ ( DLAMC3( POLES( I, 2 ), DSIGJP )+
288: $ DIFRJ ) / ( POLES( I, 2 )+DJ )
289: END IF
290: 40 CONTINUE
291: RWORK( 1 ) = NEGONE
292: TEMP = DNRM2( K, RWORK, 1 )
293: *
294: * Since B and BX are complex, the following call to DGEMV
295: * is performed in two steps (real and imaginary parts).
296: *
297: * CALL DGEMV( 'T', K, NRHS, ONE, BX, LDBX, WORK, 1, ZERO,
298: * $ B( J, 1 ), LDB )
299: *
300: I = K + NRHS*2
301: DO 60 JCOL = 1, NRHS
302: DO 50 JROW = 1, K
303: I = I + 1
304: RWORK( I ) = DBLE( BX( JROW, JCOL ) )
305: 50 CONTINUE
306: 60 CONTINUE
307: CALL DGEMV( 'T', K, NRHS, ONE, RWORK( 1+K+NRHS*2 ), K,
308: $ RWORK( 1 ), 1, ZERO, RWORK( 1+K ), 1 )
309: I = K + NRHS*2
310: DO 80 JCOL = 1, NRHS
311: DO 70 JROW = 1, K
312: I = I + 1
313: RWORK( I ) = DIMAG( BX( JROW, JCOL ) )
314: 70 CONTINUE
315: 80 CONTINUE
316: CALL DGEMV( 'T', K, NRHS, ONE, RWORK( 1+K+NRHS*2 ), K,
317: $ RWORK( 1 ), 1, ZERO, RWORK( 1+K+NRHS ), 1 )
318: DO 90 JCOL = 1, NRHS
319: B( J, JCOL ) = DCMPLX( RWORK( JCOL+K ),
320: $ RWORK( JCOL+K+NRHS ) )
321: 90 CONTINUE
322: CALL ZLASCL( 'G', 0, 0, TEMP, ONE, 1, NRHS, B( J, 1 ),
323: $ LDB, INFO )
324: 100 CONTINUE
325: END IF
326: *
327: * Move the deflated rows of BX to B also.
328: *
329: IF( K.LT.MAX( M, N ) )
330: $ CALL ZLACPY( 'A', N-K, NRHS, BX( K+1, 1 ), LDBX,
331: $ B( K+1, 1 ), LDB )
332: ELSE
333: *
334: * Apply back the right orthogonal transformations.
335: *
336: * Step (1R): apply back the new right singular vector matrix
337: * to B.
338: *
339: IF( K.EQ.1 ) THEN
340: CALL ZCOPY( NRHS, B, LDB, BX, LDBX )
341: ELSE
342: DO 180 J = 1, K
343: DSIGJ = POLES( J, 2 )
344: IF( Z( J ).EQ.ZERO ) THEN
345: RWORK( J ) = ZERO
346: ELSE
347: RWORK( J ) = -Z( J ) / DIFL( J ) /
348: $ ( DSIGJ+POLES( J, 1 ) ) / DIFR( J, 2 )
349: END IF
350: DO 110 I = 1, J - 1
351: IF( Z( J ).EQ.ZERO ) THEN
352: RWORK( I ) = ZERO
353: ELSE
354: RWORK( I ) = Z( J ) / ( DLAMC3( DSIGJ, -POLES( I+1,
355: $ 2 ) )-DIFR( I, 1 ) ) /
356: $ ( DSIGJ+POLES( I, 1 ) ) / DIFR( I, 2 )
357: END IF
358: 110 CONTINUE
359: DO 120 I = J + 1, K
360: IF( Z( J ).EQ.ZERO ) THEN
361: RWORK( I ) = ZERO
362: ELSE
363: RWORK( I ) = Z( J ) / ( DLAMC3( DSIGJ, -POLES( I,
364: $ 2 ) )-DIFL( I ) ) /
365: $ ( DSIGJ+POLES( I, 1 ) ) / DIFR( I, 2 )
366: END IF
367: 120 CONTINUE
368: *
369: * Since B and BX are complex, the following call to DGEMV
370: * is performed in two steps (real and imaginary parts).
371: *
372: * CALL DGEMV( 'T', K, NRHS, ONE, B, LDB, WORK, 1, ZERO,
373: * $ BX( J, 1 ), LDBX )
374: *
375: I = K + NRHS*2
376: DO 140 JCOL = 1, NRHS
377: DO 130 JROW = 1, K
378: I = I + 1
379: RWORK( I ) = DBLE( B( JROW, JCOL ) )
380: 130 CONTINUE
381: 140 CONTINUE
382: CALL DGEMV( 'T', K, NRHS, ONE, RWORK( 1+K+NRHS*2 ), K,
383: $ RWORK( 1 ), 1, ZERO, RWORK( 1+K ), 1 )
384: I = K + NRHS*2
385: DO 160 JCOL = 1, NRHS
386: DO 150 JROW = 1, K
387: I = I + 1
388: RWORK( I ) = DIMAG( B( JROW, JCOL ) )
389: 150 CONTINUE
390: 160 CONTINUE
391: CALL DGEMV( 'T', K, NRHS, ONE, RWORK( 1+K+NRHS*2 ), K,
392: $ RWORK( 1 ), 1, ZERO, RWORK( 1+K+NRHS ), 1 )
393: DO 170 JCOL = 1, NRHS
394: BX( J, JCOL ) = DCMPLX( RWORK( JCOL+K ),
395: $ RWORK( JCOL+K+NRHS ) )
396: 170 CONTINUE
397: 180 CONTINUE
398: END IF
399: *
400: * Step (2R): if SQRE = 1, apply back the rotation that is
401: * related to the right null space of the subproblem.
402: *
403: IF( SQRE.EQ.1 ) THEN
404: CALL ZCOPY( NRHS, B( M, 1 ), LDB, BX( M, 1 ), LDBX )
405: CALL ZDROT( NRHS, BX( 1, 1 ), LDBX, BX( M, 1 ), LDBX, C, S )
406: END IF
407: IF( K.LT.MAX( M, N ) )
408: $ CALL ZLACPY( 'A', N-K, NRHS, B( K+1, 1 ), LDB, BX( K+1, 1 ),
409: $ LDBX )
410: *
411: * Step (3R): permute rows of B.
412: *
413: CALL ZCOPY( NRHS, BX( 1, 1 ), LDBX, B( NLP1, 1 ), LDB )
414: IF( SQRE.EQ.1 ) THEN
415: CALL ZCOPY( NRHS, BX( M, 1 ), LDBX, B( M, 1 ), LDB )
416: END IF
417: DO 190 I = 2, N
418: CALL ZCOPY( NRHS, BX( I, 1 ), LDBX, B( PERM( I ), 1 ), LDB )
419: 190 CONTINUE
420: *
421: * Step (4R): apply back the Givens rotations performed.
422: *
423: DO 200 I = GIVPTR, 1, -1
424: CALL ZDROT( NRHS, B( GIVCOL( I, 2 ), 1 ), LDB,
425: $ B( GIVCOL( I, 1 ), 1 ), LDB, GIVNUM( I, 2 ),
426: $ -GIVNUM( I, 1 ) )
427: 200 CONTINUE
428: END IF
429: *
430: RETURN
431: *
432: * End of ZLALS0
433: *
434: END
CVSweb interface <joel.bertrand@systella.fr>