LAPACK  3.6.1
LAPACK: Linear Algebra PACKage
dspevx.f
Go to the documentation of this file.
1 *> \brief <b> DSPEVX computes the eigenvalues and, optionally, the left and/or right eigenvectors for OTHER matrices</b>
2 *
3 * =========== DOCUMENTATION ===========
4 *
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
7 *
8 *> \htmlonly
9 *> Download DSPEVX + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dspevx.f">
11 *> [TGZ]</a>
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dspevx.f">
13 *> [ZIP]</a>
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspevx.f">
15 *> [TXT]</a>
16 *> \endhtmlonly
17 *
18 * Definition:
19 * ===========
20 *
21 * SUBROUTINE DSPEVX( JOBZ, RANGE, UPLO, N, AP, VL, VU, IL, IU,
22 * ABSTOL, M, W, Z, LDZ, WORK, IWORK, IFAIL,
23 * INFO )
24 *
25 * .. Scalar Arguments ..
26 * CHARACTER JOBZ, RANGE, UPLO
27 * INTEGER IL, INFO, IU, LDZ, M, N
28 * DOUBLE PRECISION ABSTOL, VL, VU
29 * ..
30 * .. Array Arguments ..
31 * INTEGER IFAIL( * ), IWORK( * )
32 * DOUBLE PRECISION AP( * ), W( * ), WORK( * ), Z( LDZ, * )
33 * ..
34 *
35 *
36 *> \par Purpose:
37 * =============
38 *>
39 *> \verbatim
40 *>
41 *> DSPEVX computes selected eigenvalues and, optionally, eigenvectors
42 *> of a real symmetric matrix A in packed storage. Eigenvalues/vectors
43 *> can be selected by specifying either a range of values or a range of
44 *> indices for the desired eigenvalues.
45 *> \endverbatim
46 *
47 * Arguments:
48 * ==========
49 *
50 *> \param[in] JOBZ
51 *> \verbatim
52 *> JOBZ is CHARACTER*1
53 *> = 'N': Compute eigenvalues only;
54 *> = 'V': Compute eigenvalues and eigenvectors.
55 *> \endverbatim
56 *>
57 *> \param[in] RANGE
58 *> \verbatim
59 *> RANGE is CHARACTER*1
60 *> = 'A': all eigenvalues will be found;
61 *> = 'V': all eigenvalues in the half-open interval (VL,VU]
62 *> will be found;
63 *> = 'I': the IL-th through IU-th eigenvalues will be found.
64 *> \endverbatim
65 *>
66 *> \param[in] UPLO
67 *> \verbatim
68 *> UPLO is CHARACTER*1
69 *> = 'U': Upper triangle of A is stored;
70 *> = 'L': Lower triangle of A is stored.
71 *> \endverbatim
72 *>
73 *> \param[in] N
74 *> \verbatim
75 *> N is INTEGER
76 *> The order of the matrix A. N >= 0.
77 *> \endverbatim
78 *>
79 *> \param[in,out] AP
80 *> \verbatim
81 *> AP is DOUBLE PRECISION array, dimension (N*(N+1)/2)
82 *> On entry, the upper or lower triangle of the symmetric matrix
83 *> A, packed columnwise in a linear array. The j-th column of A
84 *> is stored in the array AP as follows:
85 *> if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;
86 *> if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.
87 *>
88 *> On exit, AP is overwritten by values generated during the
89 *> reduction to tridiagonal form. If UPLO = 'U', the diagonal
90 *> and first superdiagonal of the tridiagonal matrix T overwrite
91 *> the corresponding elements of A, and if UPLO = 'L', the
92 *> diagonal and first subdiagonal of T overwrite the
93 *> corresponding elements of A.
94 *> \endverbatim
95 *>
96 *> \param[in] VL
97 *> \verbatim
98 *> VL is DOUBLE PRECISION
99 *> If RANGE='V', the lower bound of the interval to
100 *> be searched for eigenvalues. VL < VU.
101 *> Not referenced if RANGE = 'A' or 'I'.
102 *> \endverbatim
103 *>
104 *> \param[in] VU
105 *> \verbatim
106 *> VU is DOUBLE PRECISION
107 *> If RANGE='V', the upper bound of the interval to
108 *> be searched for eigenvalues. VL < VU.
109 *> Not referenced if RANGE = 'A' or 'I'.
110 *> \endverbatim
111 *>
112 *> \param[in] IL
113 *> \verbatim
114 *> IL is INTEGER
115 *> If RANGE='I', the index of the
116 *> smallest eigenvalue to be returned.
117 *> 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
118 *> Not referenced if RANGE = 'A' or 'V'.
119 *> \endverbatim
120 *>
121 *> \param[in] IU
122 *> \verbatim
123 *> IU is INTEGER
124 *> If RANGE='I', the index of the
125 *> largest eigenvalue to be returned.
126 *> 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
127 *> Not referenced if RANGE = 'A' or 'V'.
128 *> \endverbatim
129 *>
130 *> \param[in] ABSTOL
131 *> \verbatim
132 *> ABSTOL is DOUBLE PRECISION
133 *> The absolute error tolerance for the eigenvalues.
134 *> An approximate eigenvalue is accepted as converged
135 *> when it is determined to lie in an interval [a,b]
136 *> of width less than or equal to
137 *>
138 *> ABSTOL + EPS * max( |a|,|b| ) ,
139 *>
140 *> where EPS is the machine precision. If ABSTOL is less than
141 *> or equal to zero, then EPS*|T| will be used in its place,
142 *> where |T| is the 1-norm of the tridiagonal matrix obtained
143 *> by reducing AP to tridiagonal form.
144 *>
145 *> Eigenvalues will be computed most accurately when ABSTOL is
146 *> set to twice the underflow threshold 2*DLAMCH('S'), not zero.
147 *> If this routine returns with INFO>0, indicating that some
148 *> eigenvectors did not converge, try setting ABSTOL to
149 *> 2*DLAMCH('S').
150 *>
151 *> See "Computing Small Singular Values of Bidiagonal Matrices
152 *> with Guaranteed High Relative Accuracy," by Demmel and
153 *> Kahan, LAPACK Working Note #3.
154 *> \endverbatim
155 *>
156 *> \param[out] M
157 *> \verbatim
158 *> M is INTEGER
159 *> The total number of eigenvalues found. 0 <= M <= N.
160 *> If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
161 *> \endverbatim
162 *>
163 *> \param[out] W
164 *> \verbatim
165 *> W is DOUBLE PRECISION array, dimension (N)
166 *> If INFO = 0, the selected eigenvalues in ascending order.
167 *> \endverbatim
168 *>
169 *> \param[out] Z
170 *> \verbatim
171 *> Z is DOUBLE PRECISION array, dimension (LDZ, max(1,M))
172 *> If JOBZ = 'V', then if INFO = 0, the first M columns of Z
173 *> contain the orthonormal eigenvectors of the matrix A
174 *> corresponding to the selected eigenvalues, with the i-th
175 *> column of Z holding the eigenvector associated with W(i).
176 *> If an eigenvector fails to converge, then that column of Z
177 *> contains the latest approximation to the eigenvector, and the
178 *> index of the eigenvector is returned in IFAIL.
179 *> If JOBZ = 'N', then Z is not referenced.
180 *> Note: the user must ensure that at least max(1,M) columns are
181 *> supplied in the array Z; if RANGE = 'V', the exact value of M
182 *> is not known in advance and an upper bound must be used.
183 *> \endverbatim
184 *>
185 *> \param[in] LDZ
186 *> \verbatim
187 *> LDZ is INTEGER
188 *> The leading dimension of the array Z. LDZ >= 1, and if
189 *> JOBZ = 'V', LDZ >= max(1,N).
190 *> \endverbatim
191 *>
192 *> \param[out] WORK
193 *> \verbatim
194 *> WORK is DOUBLE PRECISION array, dimension (8*N)
195 *> \endverbatim
196 *>
197 *> \param[out] IWORK
198 *> \verbatim
199 *> IWORK is INTEGER array, dimension (5*N)
200 *> \endverbatim
201 *>
202 *> \param[out] IFAIL
203 *> \verbatim
204 *> IFAIL is INTEGER array, dimension (N)
205 *> If JOBZ = 'V', then if INFO = 0, the first M elements of
206 *> IFAIL are zero. If INFO > 0, then IFAIL contains the
207 *> indices of the eigenvectors that failed to converge.
208 *> If JOBZ = 'N', then IFAIL is not referenced.
209 *> \endverbatim
210 *>
211 *> \param[out] INFO
212 *> \verbatim
213 *> INFO is INTEGER
214 *> = 0: successful exit
215 *> < 0: if INFO = -i, the i-th argument had an illegal value
216 *> > 0: if INFO = i, then i eigenvectors failed to converge.
217 *> Their indices are stored in array IFAIL.
218 *> \endverbatim
219 *
220 * Authors:
221 * ========
222 *
223 *> \author Univ. of Tennessee
224 *> \author Univ. of California Berkeley
225 *> \author Univ. of Colorado Denver
226 *> \author NAG Ltd.
227 *
228 *> \date June 2016
229 *
230 *> \ingroup doubleOTHEReigen
231 *
232 * =====================================================================
233  SUBROUTINE dspevx( JOBZ, RANGE, UPLO, N, AP, VL, VU, IL, IU,
234  $ abstol, m, w, z, ldz, work, iwork, ifail,
235  $ info )
236 *
237 * -- LAPACK driver routine (version 3.6.1) --
238 * -- LAPACK is a software package provided by Univ. of Tennessee, --
239 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
240 * June 2016
241 *
242 * .. Scalar Arguments ..
243  CHARACTER JOBZ, RANGE, UPLO
244  INTEGER IL, INFO, IU, LDZ, M, N
245  DOUBLE PRECISION ABSTOL, VL, VU
246 * ..
247 * .. Array Arguments ..
248  INTEGER IFAIL( * ), IWORK( * )
249  DOUBLE PRECISION AP( * ), W( * ), WORK( * ), Z( ldz, * )
250 * ..
251 *
252 * =====================================================================
253 *
254 * .. Parameters ..
255  DOUBLE PRECISION ZERO, ONE
256  parameter ( zero = 0.0d0, one = 1.0d0 )
257 * ..
258 * .. Local Scalars ..
259  LOGICAL ALLEIG, INDEIG, TEST, VALEIG, WANTZ
260  CHARACTER ORDER
261  INTEGER I, IINFO, IMAX, INDD, INDE, INDEE, INDIBL,
262  $ indisp, indiwo, indtau, indwrk, iscale, itmp1,
263  $ j, jj, nsplit
264  DOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,
265  $ sigma, smlnum, tmp1, vll, vuu
266 * ..
267 * .. External Functions ..
268  LOGICAL LSAME
269  DOUBLE PRECISION DLAMCH, DLANSP
270  EXTERNAL lsame, dlamch, dlansp
271 * ..
272 * .. External Subroutines ..
273  EXTERNAL dcopy, dopgtr, dopmtr, dscal, dsptrd, dstebz,
275 * ..
276 * .. Intrinsic Functions ..
277  INTRINSIC max, min, sqrt
278 * ..
279 * .. Executable Statements ..
280 *
281 * Test the input parameters.
282 *
283  wantz = lsame( jobz, 'V' )
284  alleig = lsame( range, 'A' )
285  valeig = lsame( range, 'V' )
286  indeig = lsame( range, 'I' )
287 *
288  info = 0
289  IF( .NOT.( wantz .OR. lsame( jobz, 'N' ) ) ) THEN
290  info = -1
291  ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) ) THEN
292  info = -2
293  ELSE IF( .NOT.( lsame( uplo, 'L' ) .OR. lsame( uplo, 'U' ) ) )
294  $ THEN
295  info = -3
296  ELSE IF( n.LT.0 ) THEN
297  info = -4
298  ELSE
299  IF( valeig ) THEN
300  IF( n.GT.0 .AND. vu.LE.vl )
301  $ info = -7
302  ELSE IF( indeig ) THEN
303  IF( il.LT.1 .OR. il.GT.max( 1, n ) ) THEN
304  info = -8
305  ELSE IF( iu.LT.min( n, il ) .OR. iu.GT.n ) THEN
306  info = -9
307  END IF
308  END IF
309  END IF
310  IF( info.EQ.0 ) THEN
311  IF( ldz.LT.1 .OR. ( wantz .AND. ldz.LT.n ) )
312  $ info = -14
313  END IF
314 *
315  IF( info.NE.0 ) THEN
316  CALL xerbla( 'DSPEVX', -info )
317  RETURN
318  END IF
319 *
320 * Quick return if possible
321 *
322  m = 0
323  IF( n.EQ.0 )
324  $ RETURN
325 *
326  IF( n.EQ.1 ) THEN
327  IF( alleig .OR. indeig ) THEN
328  m = 1
329  w( 1 ) = ap( 1 )
330  ELSE
331  IF( vl.LT.ap( 1 ) .AND. vu.GE.ap( 1 ) ) THEN
332  m = 1
333  w( 1 ) = ap( 1 )
334  END IF
335  END IF
336  IF( wantz )
337  $ z( 1, 1 ) = one
338  RETURN
339  END IF
340 *
341 * Get machine constants.
342 *
343  safmin = dlamch( 'Safe minimum' )
344  eps = dlamch( 'Precision' )
345  smlnum = safmin / eps
346  bignum = one / smlnum
347  rmin = sqrt( smlnum )
348  rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
349 *
350 * Scale matrix to allowable range, if necessary.
351 *
352  iscale = 0
353  abstll = abstol
354  IF( valeig ) THEN
355  vll = vl
356  vuu = vu
357  ELSE
358  vll = zero
359  vuu = zero
360  END IF
361  anrm = dlansp( 'M', uplo, n, ap, work )
362  IF( anrm.GT.zero .AND. anrm.LT.rmin ) THEN
363  iscale = 1
364  sigma = rmin / anrm
365  ELSE IF( anrm.GT.rmax ) THEN
366  iscale = 1
367  sigma = rmax / anrm
368  END IF
369  IF( iscale.EQ.1 ) THEN
370  CALL dscal( ( n*( n+1 ) ) / 2, sigma, ap, 1 )
371  IF( abstol.GT.0 )
372  $ abstll = abstol*sigma
373  IF( valeig ) THEN
374  vll = vl*sigma
375  vuu = vu*sigma
376  END IF
377  END IF
378 *
379 * Call DSPTRD to reduce symmetric packed matrix to tridiagonal form.
380 *
381  indtau = 1
382  inde = indtau + n
383  indd = inde + n
384  indwrk = indd + n
385  CALL dsptrd( uplo, n, ap, work( indd ), work( inde ),
386  $ work( indtau ), iinfo )
387 *
388 * If all eigenvalues are desired and ABSTOL is less than or equal
389 * to zero, then call DSTERF or DOPGTR and SSTEQR. If this fails
390 * for some eigenvalue, then try DSTEBZ.
391 *
392  test = .false.
393  IF (indeig) THEN
394  IF (il.EQ.1 .AND. iu.EQ.n) THEN
395  test = .true.
396  END IF
397  END IF
398  IF ((alleig .OR. test) .AND. (abstol.LE.zero)) THEN
399  CALL dcopy( n, work( indd ), 1, w, 1 )
400  indee = indwrk + 2*n
401  IF( .NOT.wantz ) THEN
402  CALL dcopy( n-1, work( inde ), 1, work( indee ), 1 )
403  CALL dsterf( n, w, work( indee ), info )
404  ELSE
405  CALL dopgtr( uplo, n, ap, work( indtau ), z, ldz,
406  $ work( indwrk ), iinfo )
407  CALL dcopy( n-1, work( inde ), 1, work( indee ), 1 )
408  CALL dsteqr( jobz, n, w, work( indee ), z, ldz,
409  $ work( indwrk ), info )
410  IF( info.EQ.0 ) THEN
411  DO 10 i = 1, n
412  ifail( i ) = 0
413  10 CONTINUE
414  END IF
415  END IF
416  IF( info.EQ.0 ) THEN
417  m = n
418  GO TO 20
419  END IF
420  info = 0
421  END IF
422 *
423 * Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN.
424 *
425  IF( wantz ) THEN
426  order = 'B'
427  ELSE
428  order = 'E'
429  END IF
430  indibl = 1
431  indisp = indibl + n
432  indiwo = indisp + n
433  CALL dstebz( range, order, n, vll, vuu, il, iu, abstll,
434  $ work( indd ), work( inde ), m, nsplit, w,
435  $ iwork( indibl ), iwork( indisp ), work( indwrk ),
436  $ iwork( indiwo ), info )
437 *
438  IF( wantz ) THEN
439  CALL dstein( n, work( indd ), work( inde ), m, w,
440  $ iwork( indibl ), iwork( indisp ), z, ldz,
441  $ work( indwrk ), iwork( indiwo ), ifail, info )
442 *
443 * Apply orthogonal matrix used in reduction to tridiagonal
444 * form to eigenvectors returned by DSTEIN.
445 *
446  CALL dopmtr( 'L', uplo, 'N', n, m, ap, work( indtau ), z, ldz,
447  $ work( indwrk ), iinfo )
448  END IF
449 *
450 * If matrix was scaled, then rescale eigenvalues appropriately.
451 *
452  20 CONTINUE
453  IF( iscale.EQ.1 ) THEN
454  IF( info.EQ.0 ) THEN
455  imax = m
456  ELSE
457  imax = info - 1
458  END IF
459  CALL dscal( imax, one / sigma, w, 1 )
460  END IF
461 *
462 * If eigenvalues are not in order, then sort them, along with
463 * eigenvectors.
464 *
465  IF( wantz ) THEN
466  DO 40 j = 1, m - 1
467  i = 0
468  tmp1 = w( j )
469  DO 30 jj = j + 1, m
470  IF( w( jj ).LT.tmp1 ) THEN
471  i = jj
472  tmp1 = w( jj )
473  END IF
474  30 CONTINUE
475 *
476  IF( i.NE.0 ) THEN
477  itmp1 = iwork( indibl+i-1 )
478  w( i ) = w( j )
479  iwork( indibl+i-1 ) = iwork( indibl+j-1 )
480  w( j ) = tmp1
481  iwork( indibl+j-1 ) = itmp1
482  CALL dswap( n, z( 1, i ), 1, z( 1, j ), 1 )
483  IF( info.NE.0 ) THEN
484  itmp1 = ifail( i )
485  ifail( i ) = ifail( j )
486  ifail( j ) = itmp1
487  END IF
488  END IF
489  40 CONTINUE
490  END IF
491 *
492  RETURN
493 *
494 * End of DSPEVX
495 *
496  END
subroutine dsterf(N, D, E, INFO)
DSTERF
Definition: dsterf.f:88
subroutine dstebz(RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E, M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK, INFO)
DSTEBZ
Definition: dstebz.f:275
subroutine dcopy(N, DX, INCX, DY, INCY)
DCOPY
Definition: dcopy.f:53
subroutine dopmtr(SIDE, UPLO, TRANS, M, N, AP, TAU, C, LDC, WORK, INFO)
DOPMTR
Definition: dopmtr.f:152
subroutine dsteqr(COMPZ, N, D, E, Z, LDZ, WORK, INFO)
DSTEQR
Definition: dsteqr.f:133
subroutine xerbla(SRNAME, INFO)
XERBLA
Definition: xerbla.f:62
subroutine dswap(N, DX, INCX, DY, INCY)
DSWAP
Definition: dswap.f:53
subroutine dspevx(JOBZ, RANGE, UPLO, N, AP, VL, VU, IL, IU, ABSTOL, M, W, Z, LDZ, WORK, IWORK, IFAIL, INFO)
DSPEVX computes the eigenvalues and, optionally, the left and/or right eigenvectors for OTHER matric...
Definition: dspevx.f:236
subroutine dscal(N, DA, DX, INCX)
DSCAL
Definition: dscal.f:55
subroutine dsptrd(UPLO, N, AP, D, E, TAU, INFO)
DSPTRD
Definition: dsptrd.f:152
subroutine dopgtr(UPLO, N, AP, TAU, Q, LDQ, WORK, INFO)
DOPGTR
Definition: dopgtr.f:116
subroutine dstein(N, D, E, M, W, IBLOCK, ISPLIT, Z, LDZ, WORK, IWORK, IFAIL, INFO)
DSTEIN
Definition: dstein.f:176