Annotation of rpl/lapack/lapack/dlaed7.f, revision 1.21
1.21 ! bertrand 1: *> \brief \b DLAED7 used by DSTEDC. Computes the updated eigensystem of a diagonal matrix after modification by a rank-one symmetric matrix. Used when the original matrix is dense.
1.9 bertrand 2: *
3: * =========== DOCUMENTATION ===========
4: *
1.18 bertrand 5: * Online html documentation available at
6: * http://www.netlib.org/lapack/explore-html/
1.9 bertrand 7: *
8: *> \htmlonly
1.18 bertrand 9: *> Download DLAED7 + dependencies
10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlaed7.f">
11: *> [TGZ]</a>
12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlaed7.f">
13: *> [ZIP]</a>
14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlaed7.f">
1.9 bertrand 15: *> [TXT]</a>
1.18 bertrand 16: *> \endhtmlonly
1.9 bertrand 17: *
18: * Definition:
19: * ===========
20: *
21: * SUBROUTINE DLAED7( ICOMPQ, N, QSIZ, TLVLS, CURLVL, CURPBM, D, Q,
22: * LDQ, INDXQ, RHO, CUTPNT, QSTORE, QPTR, PRMPTR,
23: * PERM, GIVPTR, GIVCOL, GIVNUM, WORK, IWORK,
24: * INFO )
1.18 bertrand 25: *
1.9 bertrand 26: * .. Scalar Arguments ..
27: * INTEGER CURLVL, CURPBM, CUTPNT, ICOMPQ, INFO, LDQ, N,
28: * $ QSIZ, TLVLS
29: * DOUBLE PRECISION RHO
30: * ..
31: * .. Array Arguments ..
32: * INTEGER GIVCOL( 2, * ), GIVPTR( * ), INDXQ( * ),
33: * $ IWORK( * ), PERM( * ), PRMPTR( * ), QPTR( * )
34: * DOUBLE PRECISION D( * ), GIVNUM( 2, * ), Q( LDQ, * ),
35: * $ QSTORE( * ), WORK( * )
36: * ..
1.18 bertrand 37: *
1.9 bertrand 38: *
39: *> \par Purpose:
40: * =============
41: *>
42: *> \verbatim
43: *>
44: *> DLAED7 computes the updated eigensystem of a diagonal
45: *> matrix after modification by a rank-one symmetric matrix. This
46: *> routine is used only for the eigenproblem which requires all
47: *> eigenvalues and optionally eigenvectors of a dense symmetric matrix
48: *> that has been reduced to tridiagonal form. DLAED1 handles
49: *> the case in which all eigenvalues and eigenvectors of a symmetric
50: *> tridiagonal matrix are desired.
51: *>
52: *> T = Q(in) ( D(in) + RHO * Z*Z**T ) Q**T(in) = Q(out) * D(out) * Q**T(out)
53: *>
54: *> where Z = Q**Tu, u is a vector of length N with ones in the
55: *> CUTPNT and CUTPNT + 1 th elements and zeros elsewhere.
56: *>
57: *> The eigenvectors of the original matrix are stored in Q, and the
58: *> eigenvalues are in D. The algorithm consists of three stages:
59: *>
60: *> The first stage consists of deflating the size of the problem
61: *> when there are multiple eigenvalues or if there is a zero in
1.16 bertrand 62: *> the Z vector. For each such occurrence the dimension of the
1.9 bertrand 63: *> secular equation problem is reduced by one. This stage is
64: *> performed by the routine DLAED8.
65: *>
66: *> The second stage consists of calculating the updated
67: *> eigenvalues. This is done by finding the roots of the secular
68: *> equation via the routine DLAED4 (as called by DLAED9).
69: *> This routine also calculates the eigenvectors of the current
70: *> problem.
71: *>
72: *> The final stage consists of computing the updated eigenvectors
73: *> directly using the updated eigenvalues. The eigenvectors for
74: *> the current problem are multiplied with the eigenvectors from
75: *> the overall problem.
76: *> \endverbatim
77: *
78: * Arguments:
79: * ==========
80: *
81: *> \param[in] ICOMPQ
82: *> \verbatim
83: *> ICOMPQ is INTEGER
84: *> = 0: Compute eigenvalues only.
85: *> = 1: Compute eigenvectors of original dense symmetric matrix
86: *> also. On entry, Q contains the orthogonal matrix used
87: *> to reduce the original matrix to tridiagonal form.
88: *> \endverbatim
89: *>
90: *> \param[in] N
91: *> \verbatim
92: *> N is INTEGER
93: *> The dimension of the symmetric tridiagonal matrix. N >= 0.
94: *> \endverbatim
95: *>
96: *> \param[in] QSIZ
97: *> \verbatim
98: *> QSIZ is INTEGER
99: *> The dimension of the orthogonal matrix used to reduce
100: *> the full matrix to tridiagonal form. QSIZ >= N if ICOMPQ = 1.
101: *> \endverbatim
102: *>
103: *> \param[in] TLVLS
104: *> \verbatim
105: *> TLVLS is INTEGER
106: *> The total number of merging levels in the overall divide and
107: *> conquer tree.
108: *> \endverbatim
109: *>
110: *> \param[in] CURLVL
111: *> \verbatim
112: *> CURLVL is INTEGER
113: *> The current level in the overall merge routine,
114: *> 0 <= CURLVL <= TLVLS.
115: *> \endverbatim
116: *>
117: *> \param[in] CURPBM
118: *> \verbatim
119: *> CURPBM is INTEGER
120: *> The current problem in the current level in the overall
121: *> merge routine (counting from upper left to lower right).
122: *> \endverbatim
123: *>
124: *> \param[in,out] D
125: *> \verbatim
126: *> D is DOUBLE PRECISION array, dimension (N)
127: *> On entry, the eigenvalues of the rank-1-perturbed matrix.
128: *> On exit, the eigenvalues of the repaired matrix.
129: *> \endverbatim
130: *>
131: *> \param[in,out] Q
132: *> \verbatim
133: *> Q is DOUBLE PRECISION array, dimension (LDQ, N)
134: *> On entry, the eigenvectors of the rank-1-perturbed matrix.
135: *> On exit, the eigenvectors of the repaired tridiagonal matrix.
136: *> \endverbatim
137: *>
138: *> \param[in] LDQ
139: *> \verbatim
140: *> LDQ is INTEGER
141: *> The leading dimension of the array Q. LDQ >= max(1,N).
142: *> \endverbatim
143: *>
144: *> \param[out] INDXQ
145: *> \verbatim
146: *> INDXQ is INTEGER array, dimension (N)
147: *> The permutation which will reintegrate the subproblem just
148: *> solved back into sorted order, i.e., D( INDXQ( I = 1, N ) )
149: *> will be in ascending order.
150: *> \endverbatim
151: *>
152: *> \param[in] RHO
153: *> \verbatim
154: *> RHO is DOUBLE PRECISION
155: *> The subdiagonal element used to create the rank-1
156: *> modification.
157: *> \endverbatim
158: *>
159: *> \param[in] CUTPNT
160: *> \verbatim
161: *> CUTPNT is INTEGER
162: *> Contains the location of the last eigenvalue in the leading
163: *> sub-matrix. min(1,N) <= CUTPNT <= N.
164: *> \endverbatim
165: *>
166: *> \param[in,out] QSTORE
167: *> \verbatim
168: *> QSTORE is DOUBLE PRECISION array, dimension (N**2+1)
169: *> Stores eigenvectors of submatrices encountered during
170: *> divide and conquer, packed together. QPTR points to
171: *> beginning of the submatrices.
172: *> \endverbatim
173: *>
174: *> \param[in,out] QPTR
175: *> \verbatim
176: *> QPTR is INTEGER array, dimension (N+2)
177: *> List of indices pointing to beginning of submatrices stored
178: *> in QSTORE. The submatrices are numbered starting at the
179: *> bottom left of the divide and conquer tree, from left to
180: *> right and bottom to top.
181: *> \endverbatim
182: *>
183: *> \param[in] PRMPTR
184: *> \verbatim
185: *> PRMPTR is INTEGER array, dimension (N lg N)
186: *> Contains a list of pointers which indicate where in PERM a
187: *> level's permutation is stored. PRMPTR(i+1) - PRMPTR(i)
188: *> indicates the size of the permutation and also the size of
189: *> the full, non-deflated problem.
190: *> \endverbatim
191: *>
192: *> \param[in] PERM
193: *> \verbatim
194: *> PERM is INTEGER array, dimension (N lg N)
195: *> Contains the permutations (from deflation and sorting) to be
196: *> applied to each eigenblock.
197: *> \endverbatim
198: *>
199: *> \param[in] GIVPTR
200: *> \verbatim
201: *> GIVPTR is INTEGER array, dimension (N lg N)
202: *> Contains a list of pointers which indicate where in GIVCOL a
203: *> level's Givens rotations are stored. GIVPTR(i+1) - GIVPTR(i)
204: *> indicates the number of Givens rotations.
205: *> \endverbatim
206: *>
207: *> \param[in] GIVCOL
208: *> \verbatim
209: *> GIVCOL is INTEGER array, dimension (2, N lg N)
210: *> Each pair of numbers indicates a pair of columns to take place
211: *> in a Givens rotation.
212: *> \endverbatim
213: *>
214: *> \param[in] GIVNUM
215: *> \verbatim
216: *> GIVNUM is DOUBLE PRECISION array, dimension (2, N lg N)
217: *> Each number indicates the S value to be used in the
218: *> corresponding Givens rotation.
219: *> \endverbatim
220: *>
221: *> \param[out] WORK
222: *> \verbatim
223: *> WORK is DOUBLE PRECISION array, dimension (3*N+2*QSIZ*N)
224: *> \endverbatim
225: *>
226: *> \param[out] IWORK
227: *> \verbatim
228: *> IWORK is INTEGER array, dimension (4*N)
229: *> \endverbatim
230: *>
231: *> \param[out] INFO
232: *> \verbatim
233: *> INFO is INTEGER
234: *> = 0: successful exit.
235: *> < 0: if INFO = -i, the i-th argument had an illegal value.
236: *> > 0: if INFO = 1, an eigenvalue did not converge
237: *> \endverbatim
238: *
239: * Authors:
240: * ========
241: *
1.18 bertrand 242: *> \author Univ. of Tennessee
243: *> \author Univ. of California Berkeley
244: *> \author Univ. of Colorado Denver
245: *> \author NAG Ltd.
1.9 bertrand 246: *
247: *> \ingroup auxOTHERcomputational
248: *
249: *> \par Contributors:
250: * ==================
251: *>
252: *> Jeff Rutter, Computer Science Division, University of California
253: *> at Berkeley, USA
254: *
255: * =====================================================================
1.1 bertrand 256: SUBROUTINE DLAED7( ICOMPQ, N, QSIZ, TLVLS, CURLVL, CURPBM, D, Q,
257: $ LDQ, INDXQ, RHO, CUTPNT, QSTORE, QPTR, PRMPTR,
258: $ PERM, GIVPTR, GIVCOL, GIVNUM, WORK, IWORK,
259: $ INFO )
260: *
1.21 ! bertrand 261: * -- LAPACK computational routine --
1.1 bertrand 262: * -- LAPACK is a software package provided by Univ. of Tennessee, --
263: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
264: *
265: * .. Scalar Arguments ..
266: INTEGER CURLVL, CURPBM, CUTPNT, ICOMPQ, INFO, LDQ, N,
267: $ QSIZ, TLVLS
268: DOUBLE PRECISION RHO
269: * ..
270: * .. Array Arguments ..
271: INTEGER GIVCOL( 2, * ), GIVPTR( * ), INDXQ( * ),
272: $ IWORK( * ), PERM( * ), PRMPTR( * ), QPTR( * )
273: DOUBLE PRECISION D( * ), GIVNUM( 2, * ), Q( LDQ, * ),
274: $ QSTORE( * ), WORK( * )
275: * ..
276: *
277: * =====================================================================
278: *
279: * .. Parameters ..
280: DOUBLE PRECISION ONE, ZERO
281: PARAMETER ( ONE = 1.0D0, ZERO = 0.0D0 )
282: * ..
283: * .. Local Scalars ..
284: INTEGER COLTYP, CURR, I, IDLMDA, INDX, INDXC, INDXP,
285: $ IQ2, IS, IW, IZ, K, LDQ2, N1, N2, PTR
286: * ..
287: * .. External Subroutines ..
288: EXTERNAL DGEMM, DLAED8, DLAED9, DLAEDA, DLAMRG, XERBLA
289: * ..
290: * .. Intrinsic Functions ..
291: INTRINSIC MAX, MIN
292: * ..
293: * .. Executable Statements ..
294: *
295: * Test the input parameters.
296: *
297: INFO = 0
298: *
299: IF( ICOMPQ.LT.0 .OR. ICOMPQ.GT.1 ) THEN
300: INFO = -1
301: ELSE IF( N.LT.0 ) THEN
302: INFO = -2
303: ELSE IF( ICOMPQ.EQ.1 .AND. QSIZ.LT.N ) THEN
1.15 bertrand 304: INFO = -3
1.1 bertrand 305: ELSE IF( LDQ.LT.MAX( 1, N ) ) THEN
306: INFO = -9
307: ELSE IF( MIN( 1, N ).GT.CUTPNT .OR. N.LT.CUTPNT ) THEN
308: INFO = -12
309: END IF
310: IF( INFO.NE.0 ) THEN
311: CALL XERBLA( 'DLAED7', -INFO )
312: RETURN
313: END IF
314: *
315: * Quick return if possible
316: *
317: IF( N.EQ.0 )
318: $ RETURN
319: *
320: * The following values are for bookkeeping purposes only. They are
321: * integer pointers which indicate the portion of the workspace
322: * used by a particular array in DLAED8 and DLAED9.
323: *
324: IF( ICOMPQ.EQ.1 ) THEN
325: LDQ2 = QSIZ
326: ELSE
327: LDQ2 = N
328: END IF
329: *
330: IZ = 1
331: IDLMDA = IZ + N
332: IW = IDLMDA + N
333: IQ2 = IW + N
334: IS = IQ2 + N*LDQ2
335: *
336: INDX = 1
337: INDXC = INDX + N
338: COLTYP = INDXC + N
339: INDXP = COLTYP + N
340: *
341: * Form the z-vector which consists of the last row of Q_1 and the
342: * first row of Q_2.
343: *
344: PTR = 1 + 2**TLVLS
345: DO 10 I = 1, CURLVL - 1
346: PTR = PTR + 2**( TLVLS-I )
347: 10 CONTINUE
348: CURR = PTR + CURPBM
349: CALL DLAEDA( N, TLVLS, CURLVL, CURPBM, PRMPTR, PERM, GIVPTR,
350: $ GIVCOL, GIVNUM, QSTORE, QPTR, WORK( IZ ),
351: $ WORK( IZ+N ), INFO )
352: *
353: * When solving the final problem, we no longer need the stored data,
354: * so we will overwrite the data from this level onto the previously
355: * used storage space.
356: *
357: IF( CURLVL.EQ.TLVLS ) THEN
358: QPTR( CURR ) = 1
359: PRMPTR( CURR ) = 1
360: GIVPTR( CURR ) = 1
361: END IF
362: *
363: * Sort and Deflate eigenvalues.
364: *
365: CALL DLAED8( ICOMPQ, K, N, QSIZ, D, Q, LDQ, INDXQ, RHO, CUTPNT,
366: $ WORK( IZ ), WORK( IDLMDA ), WORK( IQ2 ), LDQ2,
367: $ WORK( IW ), PERM( PRMPTR( CURR ) ), GIVPTR( CURR+1 ),
368: $ GIVCOL( 1, GIVPTR( CURR ) ),
369: $ GIVNUM( 1, GIVPTR( CURR ) ), IWORK( INDXP ),
370: $ IWORK( INDX ), INFO )
371: PRMPTR( CURR+1 ) = PRMPTR( CURR ) + N
372: GIVPTR( CURR+1 ) = GIVPTR( CURR+1 ) + GIVPTR( CURR )
373: *
374: * Solve Secular Equation.
375: *
376: IF( K.NE.0 ) THEN
377: CALL DLAED9( K, 1, K, N, D, WORK( IS ), K, RHO, WORK( IDLMDA ),
378: $ WORK( IW ), QSTORE( QPTR( CURR ) ), K, INFO )
379: IF( INFO.NE.0 )
380: $ GO TO 30
381: IF( ICOMPQ.EQ.1 ) THEN
382: CALL DGEMM( 'N', 'N', QSIZ, K, K, ONE, WORK( IQ2 ), LDQ2,
383: $ QSTORE( QPTR( CURR ) ), K, ZERO, Q, LDQ )
384: END IF
385: QPTR( CURR+1 ) = QPTR( CURR ) + K**2
386: *
387: * Prepare the INDXQ sorting permutation.
388: *
389: N1 = K
390: N2 = N - K
391: CALL DLAMRG( N1, N2, D, 1, -1, INDXQ )
392: ELSE
393: QPTR( CURR+1 ) = QPTR( CURR )
394: DO 20 I = 1, N
395: INDXQ( I ) = I
396: 20 CONTINUE
397: END IF
398: *
399: 30 CONTINUE
400: RETURN
401: *
402: * End of DLAED7
403: *
404: END
CVSweb interface <joel.bertrand@systella.fr>