LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
dlaed8.f
Go to the documentation of this file.
1*> \brief \b DLAED8 used by DSTEDC. Merges eigenvalues and deflates secular equation. Used when the original matrix is dense.
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download DLAED8 + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlaed8.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlaed8.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlaed8.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE DLAED8( ICOMPQ, K, N, QSIZ, D, Q, LDQ, INDXQ, RHO,
20* CUTPNT, Z, DLAMBDA, Q2, LDQ2, W, PERM, GIVPTR,
21* GIVCOL, GIVNUM, INDXP, INDX, INFO )
22*
23* .. Scalar Arguments ..
24* INTEGER CUTPNT, GIVPTR, ICOMPQ, INFO, K, LDQ, LDQ2, N,
25* $ QSIZ
26* DOUBLE PRECISION RHO
27* ..
28* .. Array Arguments ..
29* INTEGER GIVCOL( 2, * ), INDX( * ), INDXP( * ),
30* $ INDXQ( * ), PERM( * )
31* DOUBLE PRECISION D( * ), DLAMBDA( * ), GIVNUM( 2, * ),
32* $ Q( LDQ, * ), Q2( LDQ2, * ), W( * ), Z( * )
33* ..
34*
35*
36*> \par Purpose:
37* =============
38*>
39*> \verbatim
40*>
41*> DLAED8 merges the two sets of eigenvalues together into a single
42*> sorted set. Then it tries to deflate the size of the problem.
43*> There are two ways in which deflation can occur: when two or more
44*> eigenvalues are close together or if there is a tiny element in the
45*> Z vector. For each such occurrence the order of the related secular
46*> equation problem is reduced by one.
47*> \endverbatim
48*
49* Arguments:
50* ==========
51*
52*> \param[in] ICOMPQ
53*> \verbatim
54*> ICOMPQ is INTEGER
55*> = 0: Compute eigenvalues only.
56*> = 1: Compute eigenvectors of original dense symmetric matrix
57*> also. On entry, Q contains the orthogonal matrix used
58*> to reduce the original matrix to tridiagonal form.
59*> \endverbatim
60*>
61*> \param[out] K
62*> \verbatim
63*> K is INTEGER
64*> The number of non-deflated eigenvalues, and the order of the
65*> related secular equation.
66*> \endverbatim
67*>
68*> \param[in] N
69*> \verbatim
70*> N is INTEGER
71*> The dimension of the symmetric tridiagonal matrix. N >= 0.
72*> \endverbatim
73*>
74*> \param[in] QSIZ
75*> \verbatim
76*> QSIZ is INTEGER
77*> The dimension of the orthogonal matrix used to reduce
78*> the full matrix to tridiagonal form. QSIZ >= N if ICOMPQ = 1.
79*> \endverbatim
80*>
81*> \param[in,out] D
82*> \verbatim
83*> D is DOUBLE PRECISION array, dimension (N)
84*> On entry, the eigenvalues of the two submatrices to be
85*> combined. On exit, the trailing (N-K) updated eigenvalues
86*> (those which were deflated) sorted into increasing order.
87*> \endverbatim
88*>
89*> \param[in,out] Q
90*> \verbatim
91*> Q is DOUBLE PRECISION array, dimension (LDQ,N)
92*> If ICOMPQ = 0, Q is not referenced. Otherwise,
93*> on entry, Q contains the eigenvectors of the partially solved
94*> system which has been previously updated in matrix
95*> multiplies with other partially solved eigensystems.
96*> On exit, Q contains the trailing (N-K) updated eigenvectors
97*> (those which were deflated) in its last N-K columns.
98*> \endverbatim
99*>
100*> \param[in] LDQ
101*> \verbatim
102*> LDQ is INTEGER
103*> The leading dimension of the array Q. LDQ >= max(1,N).
104*> \endverbatim
105*>
106*> \param[in] INDXQ
107*> \verbatim
108*> INDXQ is INTEGER array, dimension (N)
109*> The permutation which separately sorts the two sub-problems
110*> in D into ascending order. Note that elements in the second
111*> half of this permutation must first have CUTPNT added to
112*> their values in order to be accurate.
113*> \endverbatim
114*>
115*> \param[in,out] RHO
116*> \verbatim
117*> RHO is DOUBLE PRECISION
118*> On entry, the off-diagonal element associated with the rank-1
119*> cut which originally split the two submatrices which are now
120*> being recombined.
121*> On exit, RHO has been modified to the value required by
122*> DLAED3.
123*> \endverbatim
124*>
125*> \param[in] CUTPNT
126*> \verbatim
127*> CUTPNT is INTEGER
128*> The location of the last eigenvalue in the leading
129*> sub-matrix. min(1,N) <= CUTPNT <= N.
130*> \endverbatim
131*>
132*> \param[in] Z
133*> \verbatim
134*> Z is DOUBLE PRECISION array, dimension (N)
135*> On entry, Z contains the updating vector (the last row of
136*> the first sub-eigenvector matrix and the first row of the
137*> second sub-eigenvector matrix).
138*> On exit, the contents of Z are destroyed by the updating
139*> process.
140*> \endverbatim
141*>
142*> \param[out] DLAMBDA
143*> \verbatim
144*> DLAMBDA is DOUBLE PRECISION array, dimension (N)
145*> A copy of the first K eigenvalues which will be used by
146*> DLAED3 to form the secular equation.
147*> \endverbatim
148*>
149*> \param[out] Q2
150*> \verbatim
151*> Q2 is DOUBLE PRECISION array, dimension (LDQ2,N)
152*> If ICOMPQ = 0, Q2 is not referenced. Otherwise,
153*> a copy of the first K eigenvectors which will be used by
154*> DLAED7 in a matrix multiply (DGEMM) to update the new
155*> eigenvectors.
156*> \endverbatim
157*>
158*> \param[in] LDQ2
159*> \verbatim
160*> LDQ2 is INTEGER
161*> The leading dimension of the array Q2. LDQ2 >= max(1,N).
162*> \endverbatim
163*>
164*> \param[out] W
165*> \verbatim
166*> W is DOUBLE PRECISION array, dimension (N)
167*> The first k values of the final deflation-altered z-vector and
168*> will be passed to DLAED3.
169*> \endverbatim
170*>
171*> \param[out] PERM
172*> \verbatim
173*> PERM is INTEGER array, dimension (N)
174*> The permutations (from deflation and sorting) to be applied
175*> to each eigenblock.
176*> \endverbatim
177*>
178*> \param[out] GIVPTR
179*> \verbatim
180*> GIVPTR is INTEGER
181*> The number of Givens rotations which took place in this
182*> subproblem.
183*> \endverbatim
184*>
185*> \param[out] GIVCOL
186*> \verbatim
187*> GIVCOL is INTEGER array, dimension (2, N)
188*> Each pair of numbers indicates a pair of columns to take place
189*> in a Givens rotation.
190*> \endverbatim
191*>
192*> \param[out] GIVNUM
193*> \verbatim
194*> GIVNUM is DOUBLE PRECISION array, dimension (2, N)
195*> Each number indicates the S value to be used in the
196*> corresponding Givens rotation.
197*> \endverbatim
198*>
199*> \param[out] INDXP
200*> \verbatim
201*> INDXP is INTEGER array, dimension (N)
202*> The permutation used to place deflated values of D at the end
203*> of the array. INDXP(1:K) points to the nondeflated D-values
204*> and INDXP(K+1:N) points to the deflated eigenvalues.
205*> \endverbatim
206*>
207*> \param[out] INDX
208*> \verbatim
209*> INDX is INTEGER array, dimension (N)
210*> The permutation used to sort the contents of D into ascending
211*> order.
212*> \endverbatim
213*>
214*> \param[out] INFO
215*> \verbatim
216*> INFO is INTEGER
217*> = 0: successful exit.
218*> < 0: if INFO = -i, the i-th argument had an illegal value.
219*> \endverbatim
220*
221* Authors:
222* ========
223*
224*> \author Univ. of Tennessee
225*> \author Univ. of California Berkeley
226*> \author Univ. of Colorado Denver
227*> \author NAG Ltd.
228*
229*> \ingroup laed8
230*
231*> \par Contributors:
232* ==================
233*>
234*> Jeff Rutter, Computer Science Division, University of California
235*> at Berkeley, USA
236*
237* =====================================================================
238 SUBROUTINE dlaed8( ICOMPQ, K, N, QSIZ, D, Q, LDQ, INDXQ, RHO,
239 $ CUTPNT, Z, DLAMBDA, Q2, LDQ2, W, PERM, GIVPTR,
240 $ GIVCOL, GIVNUM, INDXP, INDX, INFO )
241*
242* -- LAPACK computational routine --
243* -- LAPACK is a software package provided by Univ. of Tennessee, --
244* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
245*
246* .. Scalar Arguments ..
247 INTEGER CUTPNT, GIVPTR, ICOMPQ, INFO, K, LDQ, LDQ2, N,
248 $ QSIZ
249 DOUBLE PRECISION RHO
250* ..
251* .. Array Arguments ..
252 INTEGER GIVCOL( 2, * ), INDX( * ), INDXP( * ),
253 $ INDXQ( * ), PERM( * )
254 DOUBLE PRECISION D( * ), DLAMBDA( * ), GIVNUM( 2, * ),
255 $ Q( LDQ, * ), Q2( LDQ2, * ), W( * ), Z( * )
256* ..
257*
258* =====================================================================
259*
260* .. Parameters ..
261 DOUBLE PRECISION MONE, ZERO, ONE, TWO, EIGHT
262 PARAMETER ( MONE = -1.0d0, zero = 0.0d0, one = 1.0d0,
263 $ two = 2.0d0, eight = 8.0d0 )
264* ..
265* .. Local Scalars ..
266*
267 INTEGER I, IMAX, J, JLAM, JMAX, JP, K2, N1, N1P1, N2
268 DOUBLE PRECISION C, EPS, S, T, TAU, TOL
269* ..
270* .. External Functions ..
271 INTEGER IDAMAX
272 DOUBLE PRECISION DLAMCH, DLAPY2
273 EXTERNAL idamax, dlamch, dlapy2
274* ..
275* .. External Subroutines ..
276 EXTERNAL dcopy, dlacpy, dlamrg, drot, dscal,
277 $ xerbla
278* ..
279* .. Intrinsic Functions ..
280 INTRINSIC abs, max, min, sqrt
281* ..
282* .. Executable Statements ..
283*
284* Test the input parameters.
285*
286 info = 0
287*
288 IF( icompq.LT.0 .OR. icompq.GT.1 ) THEN
289 info = -1
290 ELSE IF( n.LT.0 ) THEN
291 info = -3
292 ELSE IF( icompq.EQ.1 .AND. qsiz.LT.n ) THEN
293 info = -4
294 ELSE IF( ldq.LT.max( 1, n ) ) THEN
295 info = -7
296 ELSE IF( cutpnt.LT.min( 1, n ) .OR. cutpnt.GT.n ) THEN
297 info = -10
298 ELSE IF( ldq2.LT.max( 1, n ) ) THEN
299 info = -14
300 END IF
301 IF( info.NE.0 ) THEN
302 CALL xerbla( 'DLAED8', -info )
303 RETURN
304 END IF
305*
306* Need to initialize GIVPTR to O here in case of quick exit
307* to prevent an unspecified code behavior (usually sigfault)
308* when IWORK array on entry to *stedc is not zeroed
309* (or at least some IWORK entries which used in *laed7 for GIVPTR).
310*
311 givptr = 0
312*
313* Quick return if possible
314*
315 IF( n.EQ.0 )
316 $ RETURN
317*
318 n1 = cutpnt
319 n2 = n - n1
320 n1p1 = n1 + 1
321*
322 IF( rho.LT.zero ) THEN
323 CALL dscal( n2, mone, z( n1p1 ), 1 )
324 END IF
325*
326* Normalize z so that norm(z) = 1
327*
328 t = one / sqrt( two )
329 DO 10 j = 1, n
330 indx( j ) = j
331 10 CONTINUE
332 CALL dscal( n, t, z, 1 )
333 rho = abs( two*rho )
334*
335* Sort the eigenvalues into increasing order
336*
337 DO 20 i = cutpnt + 1, n
338 indxq( i ) = indxq( i ) + cutpnt
339 20 CONTINUE
340 DO 30 i = 1, n
341 dlambda( i ) = d( indxq( i ) )
342 w( i ) = z( indxq( i ) )
343 30 CONTINUE
344 i = 1
345 j = cutpnt + 1
346 CALL dlamrg( n1, n2, dlambda, 1, 1, indx )
347 DO 40 i = 1, n
348 d( i ) = dlambda( indx( i ) )
349 z( i ) = w( indx( i ) )
350 40 CONTINUE
351*
352* Calculate the allowable deflation tolerance
353*
354 imax = idamax( n, z, 1 )
355 jmax = idamax( n, d, 1 )
356 eps = dlamch( 'Epsilon' )
357 tol = eight*eps*abs( d( jmax ) )
358*
359* If the rank-1 modifier is small enough, no more needs to be done
360* except to reorganize Q so that its columns correspond with the
361* elements in D.
362*
363 IF( rho*abs( z( imax ) ).LE.tol ) THEN
364 k = 0
365 IF( icompq.EQ.0 ) THEN
366 DO 50 j = 1, n
367 perm( j ) = indxq( indx( j ) )
368 50 CONTINUE
369 ELSE
370 DO 60 j = 1, n
371 perm( j ) = indxq( indx( j ) )
372 CALL dcopy( qsiz, q( 1, perm( j ) ), 1, q2( 1, j ),
373 $ 1 )
374 60 CONTINUE
375 CALL dlacpy( 'A', qsiz, n, q2( 1, 1 ), ldq2, q( 1, 1 ),
376 $ ldq )
377 END IF
378 RETURN
379 END IF
380*
381* If there are multiple eigenvalues then the problem deflates. Here
382* the number of equal eigenvalues are found. As each equal
383* eigenvalue is found, an elementary reflector is computed to rotate
384* the corresponding eigensubspace so that the corresponding
385* components of Z are zero in this new basis.
386*
387 k = 0
388 k2 = n + 1
389 DO 70 j = 1, n
390 IF( rho*abs( z( j ) ).LE.tol ) THEN
391*
392* Deflate due to small z component.
393*
394 k2 = k2 - 1
395 indxp( k2 ) = j
396 IF( j.EQ.n )
397 $ GO TO 110
398 ELSE
399 jlam = j
400 GO TO 80
401 END IF
402 70 CONTINUE
403 80 CONTINUE
404 j = j + 1
405 IF( j.GT.n )
406 $ GO TO 100
407 IF( rho*abs( z( j ) ).LE.tol ) THEN
408*
409* Deflate due to small z component.
410*
411 k2 = k2 - 1
412 indxp( k2 ) = j
413 ELSE
414*
415* Check if eigenvalues are close enough to allow deflation.
416*
417 s = z( jlam )
418 c = z( j )
419*
420* Find sqrt(a**2+b**2) without overflow or
421* destructive underflow.
422*
423 tau = dlapy2( c, s )
424 t = d( j ) - d( jlam )
425 c = c / tau
426 s = -s / tau
427 IF( abs( t*c*s ).LE.tol ) THEN
428*
429* Deflation is possible.
430*
431 z( j ) = tau
432 z( jlam ) = zero
433*
434* Record the appropriate Givens rotation
435*
436 givptr = givptr + 1
437 givcol( 1, givptr ) = indxq( indx( jlam ) )
438 givcol( 2, givptr ) = indxq( indx( j ) )
439 givnum( 1, givptr ) = c
440 givnum( 2, givptr ) = s
441 IF( icompq.EQ.1 ) THEN
442 CALL drot( qsiz, q( 1, indxq( indx( jlam ) ) ), 1,
443 $ q( 1, indxq( indx( j ) ) ), 1, c, s )
444 END IF
445 t = d( jlam )*c*c + d( j )*s*s
446 d( j ) = d( jlam )*s*s + d( j )*c*c
447 d( jlam ) = t
448 k2 = k2 - 1
449 i = 1
450 90 CONTINUE
451 IF( k2+i.LE.n ) THEN
452 IF( d( jlam ).LT.d( indxp( k2+i ) ) ) THEN
453 indxp( k2+i-1 ) = indxp( k2+i )
454 indxp( k2+i ) = jlam
455 i = i + 1
456 GO TO 90
457 ELSE
458 indxp( k2+i-1 ) = jlam
459 END IF
460 ELSE
461 indxp( k2+i-1 ) = jlam
462 END IF
463 jlam = j
464 ELSE
465 k = k + 1
466 w( k ) = z( jlam )
467 dlambda( k ) = d( jlam )
468 indxp( k ) = jlam
469 jlam = j
470 END IF
471 END IF
472 GO TO 80
473 100 CONTINUE
474*
475* Record the last eigenvalue.
476*
477 k = k + 1
478 w( k ) = z( jlam )
479 dlambda( k ) = d( jlam )
480 indxp( k ) = jlam
481*
482 110 CONTINUE
483*
484* Sort the eigenvalues and corresponding eigenvectors into DLAMBDA
485* and Q2 respectively. The eigenvalues/vectors which were not
486* deflated go into the first K slots of DLAMBDA and Q2 respectively,
487* while those which were deflated go into the last N - K slots.
488*
489 IF( icompq.EQ.0 ) THEN
490 DO 120 j = 1, n
491 jp = indxp( j )
492 dlambda( j ) = d( jp )
493 perm( j ) = indxq( indx( jp ) )
494 120 CONTINUE
495 ELSE
496 DO 130 j = 1, n
497 jp = indxp( j )
498 dlambda( j ) = d( jp )
499 perm( j ) = indxq( indx( jp ) )
500 CALL dcopy( qsiz, q( 1, perm( j ) ), 1, q2( 1, j ), 1 )
501 130 CONTINUE
502 END IF
503*
504* The deflated eigenvalues and their corresponding vectors go back
505* into the last N - K slots of D and Q respectively.
506*
507 IF( k.LT.n ) THEN
508 IF( icompq.EQ.0 ) THEN
509 CALL dcopy( n-k, dlambda( k+1 ), 1, d( k+1 ), 1 )
510 ELSE
511 CALL dcopy( n-k, dlambda( k+1 ), 1, d( k+1 ), 1 )
512 CALL dlacpy( 'A', qsiz, n-k, q2( 1, k+1 ), ldq2,
513 $ q( 1, k+1 ), ldq )
514 END IF
515 END IF
516*
517 RETURN
518*
519* End of DLAED8
520*
521 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine dcopy(n, dx, incx, dy, incy)
DCOPY
Definition dcopy.f:82
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
Definition dlacpy.f:101
subroutine dlaed8(icompq, k, n, qsiz, d, q, ldq, indxq, rho, cutpnt, z, dlambda, q2, ldq2, w, perm, givptr, givcol, givnum, indxp, indx, info)
DLAED8 used by DSTEDC. Merges eigenvalues and deflates secular equation. Used when the original matri...
Definition dlaed8.f:241
subroutine dlamrg(n1, n2, a, dtrd1, dtrd2, index)
DLAMRG creates a permutation list to merge the entries of two independently sorted sets into a single...
Definition dlamrg.f:97
subroutine drot(n, dx, incx, dy, incy, c, s)
DROT
Definition drot.f:92
subroutine dscal(n, da, dx, incx)
DSCAL
Definition dscal.f:79