1 /* ./src_f77/dsbgvx.f -- translated by f2c (version 20030320).
2 You must link the resulting object file with the libraries:
3 -lf2c -lm (in that order)
4 */
5
6 #include <punc/vf2c.h>
7
8 /* Table of constant values */
9
10 static integer c__1 = 1;
11 static doublereal c_b25 = 1.;
12 static doublereal c_b27 = 0.;
13
dsbgvx_(char * jobz,char * range,char * uplo,integer * n,integer * ka,integer * kb,doublereal * ab,integer * ldab,doublereal * bb,integer * ldbb,doublereal * q,integer * ldq,doublereal * vl,doublereal * vu,integer * il,integer * iu,doublereal * abstol,integer * m,doublereal * w,doublereal * z__,integer * ldz,doublereal * work,integer * iwork,integer * ifail,integer * info,ftnlen jobz_len,ftnlen range_len,ftnlen uplo_len)14 /* Subroutine */ int dsbgvx_(char *jobz, char *range, char *uplo, integer *n,
15 integer *ka, integer *kb, doublereal *ab, integer *ldab, doublereal *
16 bb, integer *ldbb, doublereal *q, integer *ldq, doublereal *vl,
17 doublereal *vu, integer *il, integer *iu, doublereal *abstol, integer
18 *m, doublereal *w, doublereal *z__, integer *ldz, doublereal *work,
19 integer *iwork, integer *ifail, integer *info, ftnlen jobz_len,
20 ftnlen range_len, ftnlen uplo_len)
21 {
22 /* System generated locals */
23 integer ab_dim1, ab_offset, bb_dim1, bb_offset, q_dim1, q_offset, z_dim1,
24 z_offset, i__1, i__2;
25
26 /* Local variables */
27 static integer i__, j, jj;
28 static doublereal tmp1;
29 static integer indd, inde;
30 static char vect[1];
31 static integer itmp1, indee;
32 extern logical lsame_(char *, char *, ftnlen, ftnlen);
33 extern /* Subroutine */ int dgemv_(char *, integer *, integer *,
34 doublereal *, doublereal *, integer *, doublereal *, integer *,
35 doublereal *, doublereal *, integer *, ftnlen);
36 static integer iinfo;
37 static char order[1];
38 extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *,
39 doublereal *, integer *), dswap_(integer *, doublereal *, integer
40 *, doublereal *, integer *);
41 static logical upper, wantz, alleig, indeig;
42 static integer indibl;
43 static logical valeig;
44 extern /* Subroutine */ int dlacpy_(char *, integer *, integer *,
45 doublereal *, integer *, doublereal *, integer *, ftnlen),
46 xerbla_(char *, integer *, ftnlen), dpbstf_(char *, integer *,
47 integer *, doublereal *, integer *, integer *, ftnlen), dsbtrd_(
48 char *, char *, integer *, integer *, doublereal *, integer *,
49 doublereal *, doublereal *, doublereal *, integer *, doublereal *,
50 integer *, ftnlen, ftnlen);
51 static integer indisp;
52 extern /* Subroutine */ int dsbgst_(char *, char *, integer *, integer *,
53 integer *, doublereal *, integer *, doublereal *, integer *,
54 doublereal *, integer *, doublereal *, integer *, ftnlen, ftnlen),
55 dstein_(integer *, doublereal *, doublereal *, integer *,
56 doublereal *, integer *, integer *, doublereal *, integer *,
57 doublereal *, integer *, integer *, integer *);
58 static integer indiwo;
59 extern /* Subroutine */ int dsterf_(integer *, doublereal *, doublereal *,
60 integer *), dstebz_(char *, char *, integer *, doublereal *,
61 doublereal *, integer *, integer *, doublereal *, doublereal *,
62 doublereal *, integer *, integer *, doublereal *, integer *,
63 integer *, doublereal *, integer *, integer *, ftnlen, ftnlen);
64 static integer indwrk;
65 extern /* Subroutine */ int dsteqr_(char *, integer *, doublereal *,
66 doublereal *, doublereal *, integer *, doublereal *, integer *,
67 ftnlen);
68 static integer nsplit;
69
70
71 /* -- LAPACK driver routine (version 3.0) -- */
72 /* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */
73 /* Courant Institute, Argonne National Lab, and Rice University */
74 /* June 30, 1999 */
75
76 /* .. Scalar Arguments .. */
77 /* .. */
78 /* .. Array Arguments .. */
79 /* .. */
80
81 /* Purpose */
82 /* ======= */
83
84 /* DSBGVX computes selected eigenvalues, and optionally, eigenvectors */
85 /* of a real generalized symmetric-definite banded eigenproblem, of */
86 /* the form A*x=(lambda)*B*x. Here A and B are assumed to be symmetric */
87 /* and banded, and B is also positive definite. Eigenvalues and */
88 /* eigenvectors can be selected by specifying either all eigenvalues, */
89 /* a range of values or a range of indices for the desired eigenvalues. */
90
91 /* Arguments */
92 /* ========= */
93
94 /* JOBZ (input) CHARACTER*1 */
95 /* = 'N': Compute eigenvalues only; */
96 /* = 'V': Compute eigenvalues and eigenvectors. */
97
98 /* RANGE (input) CHARACTER*1 */
99 /* = 'A': all eigenvalues will be found. */
100 /* = 'V': all eigenvalues in the half-open interval (VL,VU] */
101 /* will be found. */
102 /* = 'I': the IL-th through IU-th eigenvalues will be found. */
103
104 /* UPLO (input) CHARACTER*1 */
105 /* = 'U': Upper triangles of A and B are stored; */
106 /* = 'L': Lower triangles of A and B are stored. */
107
108 /* N (input) INTEGER */
109 /* The order of the matrices A and B. N >= 0. */
110
111 /* KA (input) INTEGER */
112 /* The number of superdiagonals of the matrix A if UPLO = 'U', */
113 /* or the number of subdiagonals if UPLO = 'L'. KA >= 0. */
114
115 /* KB (input) INTEGER */
116 /* The number of superdiagonals of the matrix B if UPLO = 'U', */
117 /* or the number of subdiagonals if UPLO = 'L'. KB >= 0. */
118
119 /* AB (input/output) DOUBLE PRECISION array, dimension (LDAB, N) */
120 /* On entry, the upper or lower triangle of the symmetric band */
121 /* matrix A, stored in the first ka+1 rows of the array. The */
122 /* j-th column of A is stored in the j-th column of the array AB */
123 /* as follows: */
124 /* if UPLO = 'U', AB(ka+1+i-j,j) = A(i,j) for max(1,j-ka)<=i<=j; */
125 /* if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+ka). */
126
127 /* On exit, the contents of AB are destroyed. */
128
129 /* LDAB (input) INTEGER */
130 /* The leading dimension of the array AB. LDAB >= KA+1. */
131
132 /* BB (input/output) DOUBLE PRECISION array, dimension (LDBB, N) */
133 /* On entry, the upper or lower triangle of the symmetric band */
134 /* matrix B, stored in the first kb+1 rows of the array. The */
135 /* j-th column of B is stored in the j-th column of the array BB */
136 /* as follows: */
137 /* if UPLO = 'U', BB(ka+1+i-j,j) = B(i,j) for max(1,j-kb)<=i<=j; */
138 /* if UPLO = 'L', BB(1+i-j,j) = B(i,j) for j<=i<=min(n,j+kb). */
139
140 /* On exit, the factor S from the split Cholesky factorization */
141 /* B = S**T*S, as returned by DPBSTF. */
142
143 /* LDBB (input) INTEGER */
144 /* The leading dimension of the array BB. LDBB >= KB+1. */
145
146 /* Q (output) DOUBLE PRECISION array, dimension (LDQ, N) */
147 /* If JOBZ = 'V', the n-by-n matrix used in the reduction of */
148 /* A*x = (lambda)*B*x to standard form, i.e. C*x = (lambda)*x, */
149 /* and consequently C to tridiagonal form. */
150 /* If JOBZ = 'N', the array Q is not referenced. */
151
152 /* LDQ (input) INTEGER */
153 /* The leading dimension of the array Q. If JOBZ = 'N', */
154 /* LDQ >= 1. If JOBZ = 'V', LDQ >= max(1,N). */
155
156 /* VL (input) DOUBLE PRECISION */
157 /* VU (input) DOUBLE PRECISION */
158 /* If RANGE='V', the lower and upper bounds of the interval to */
159 /* be searched for eigenvalues. VL < VU. */
160 /* Not referenced if RANGE = 'A' or 'I'. */
161
162 /* IL (input) INTEGER */
163 /* IU (input) INTEGER */
164 /* If RANGE='I', the indices (in ascending order) of the */
165 /* smallest and largest eigenvalues to be returned. */
166 /* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. */
167 /* Not referenced if RANGE = 'A' or 'V'. */
168
169 /* ABSTOL (input) DOUBLE PRECISION */
170 /* The absolute error tolerance for the eigenvalues. */
171 /* An approximate eigenvalue is accepted as converged */
172 /* when it is determined to lie in an interval [a,b] */
173 /* of width less than or equal to */
174
175 /* ABSTOL + EPS * max( |a|,|b| ) , */
176
177 /* where EPS is the machine precision. If ABSTOL is less than */
178 /* or equal to zero, then EPS*|T| will be used in its place, */
179 /* where |T| is the 1-norm of the tridiagonal matrix obtained */
180 /* by reducing A to tridiagonal form. */
181
182 /* Eigenvalues will be computed most accurately when ABSTOL is */
183 /* set to twice the underflow threshold 2*DLAMCH('S'), not zero. */
184 /* If this routine returns with INFO>0, indicating that some */
185 /* eigenvectors did not converge, try setting ABSTOL to */
186 /* 2*DLAMCH('S'). */
187
188 /* M (output) INTEGER */
189 /* The total number of eigenvalues found. 0 <= M <= N. */
190 /* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. */
191
192 /* W (output) DOUBLE PRECISION array, dimension (N) */
193 /* If INFO = 0, the eigenvalues in ascending order. */
194
195 /* Z (output) DOUBLE PRECISION array, dimension (LDZ, N) */
196 /* If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of */
197 /* eigenvectors, with the i-th column of Z holding the */
198 /* eigenvector associated with W(i). The eigenvectors are */
199 /* normalized so Z**T*B*Z = I. */
200 /* If JOBZ = 'N', then Z is not referenced. */
201
202 /* LDZ (input) INTEGER */
203 /* The leading dimension of the array Z. LDZ >= 1, and if */
204 /* JOBZ = 'V', LDZ >= max(1,N). */
205
206 /* WORK (workspace/output) DOUBLE PRECISION array, dimension (7N) */
207
208 /* IWORK (workspace/output) INTEGER array, dimension (5N) */
209
210 /* IFAIL (input) INTEGER array, dimension (M) */
211 /* If JOBZ = 'V', then if INFO = 0, the first M elements of */
212 /* IFAIL are zero. If INFO > 0, then IFAIL contains the */
213 /* indices of the eigenvalues that failed to converge. */
214 /* If JOBZ = 'N', then IFAIL is not referenced. */
215
216 /* INFO (output) INTEGER */
217 /* = 0 : successful exit */
218 /* < 0 : if INFO = -i, the i-th argument had an illegal value */
219 /* <= N: if INFO = i, then i eigenvectors failed to converge. */
220 /* Their indices are stored in IFAIL. */
221 /* > N : DPBSTF returned an error code; i.e., */
222 /* if INFO = N + i, for 1 <= i <= N, then the leading */
223 /* minor of order i of B is not positive definite. */
224 /* The factorization of B could not be completed and */
225 /* no eigenvalues or eigenvectors were computed. */
226
227 /* Further Details */
228 /* =============== */
229
230 /* Based on contributions by */
231 /* Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA */
232
233 /* ===================================================================== */
234
235 /* .. Parameters .. */
236 /* .. */
237 /* .. Local Scalars .. */
238 /* .. */
239 /* .. External Functions .. */
240 /* .. */
241 /* .. External Subroutines .. */
242 /* .. */
243 /* .. Intrinsic Functions .. */
244 /* .. */
245 /* .. Executable Statements .. */
246
247 /* Test the input parameters. */
248
249 /* Parameter adjustments */
250 ab_dim1 = *ldab;
251 ab_offset = 1 + ab_dim1;
252 ab -= ab_offset;
253 bb_dim1 = *ldbb;
254 bb_offset = 1 + bb_dim1;
255 bb -= bb_offset;
256 q_dim1 = *ldq;
257 q_offset = 1 + q_dim1;
258 q -= q_offset;
259 --w;
260 z_dim1 = *ldz;
261 z_offset = 1 + z_dim1;
262 z__ -= z_offset;
263 --work;
264 --iwork;
265 --ifail;
266
267 /* Function Body */
268 wantz = lsame_(jobz, "V", (ftnlen)1, (ftnlen)1);
269 upper = lsame_(uplo, "U", (ftnlen)1, (ftnlen)1);
270 alleig = lsame_(range, "A", (ftnlen)1, (ftnlen)1);
271 valeig = lsame_(range, "V", (ftnlen)1, (ftnlen)1);
272 indeig = lsame_(range, "I", (ftnlen)1, (ftnlen)1);
273
274 *info = 0;
275 if (! (wantz || lsame_(jobz, "N", (ftnlen)1, (ftnlen)1))) {
276 *info = -1;
277 } else if (! (alleig || valeig || indeig)) {
278 *info = -2;
279 } else if (! (upper || lsame_(uplo, "L", (ftnlen)1, (ftnlen)1))) {
280 *info = -3;
281 } else if (*n < 0) {
282 *info = -4;
283 } else if (*ka < 0) {
284 *info = -5;
285 } else if (*kb < 0 || *kb > *ka) {
286 *info = -6;
287 } else if (*ldab < *ka + 1) {
288 *info = -8;
289 } else if (*ldbb < *kb + 1) {
290 *info = -10;
291 } else if (*ldq < 1) {
292 *info = -12;
293 } else if (valeig && *n > 0 && *vu <= *vl) {
294 *info = -14;
295 } else if (indeig && *il < 1) {
296 *info = -15;
297 } else if (indeig && (*iu < min(*n,*il) || *iu > *n)) {
298 *info = -16;
299 } else if (*ldz < 1 || wantz && *ldz < *n) {
300 *info = -21;
301 }
302
303 if (*info != 0) {
304 i__1 = -(*info);
305 xerbla_("DSBGVX", &i__1, (ftnlen)6);
306 return 0;
307 }
308
309 /* Quick return if possible */
310
311 *m = 0;
312 if (*n == 0) {
313 work[1] = 1.;
314 return 0;
315 }
316
317 /* Form a split Cholesky factorization of B. */
318
319 dpbstf_(uplo, n, kb, &bb[bb_offset], ldbb, info, (ftnlen)1);
320 if (*info != 0) {
321 *info = *n + *info;
322 return 0;
323 }
324
325 /* Transform problem to standard eigenvalue problem. */
326
327 dsbgst_(jobz, uplo, n, ka, kb, &ab[ab_offset], ldab, &bb[bb_offset], ldbb,
328 &q[q_offset], ldq, &work[1], &iinfo, (ftnlen)1, (ftnlen)1);
329
330 /* Reduce symmetric band matrix to tridiagonal form. */
331
332 indd = 1;
333 inde = indd + *n;
334 indwrk = inde + *n;
335 if (wantz) {
336 *(unsigned char *)vect = 'U';
337 } else {
338 *(unsigned char *)vect = 'N';
339 }
340 dsbtrd_(vect, uplo, n, ka, &ab[ab_offset], ldab, &work[indd], &work[inde],
341 &q[q_offset], ldq, &work[indwrk], &iinfo, (ftnlen)1, (ftnlen)1);
342
343 /* If all eigenvalues are desired and ABSTOL is less than or equal */
344 /* to zero, then call DSTERF or SSTEQR. If this fails for some */
345 /* eigenvalue, then try DSTEBZ. */
346
347 if ((alleig || indeig && *il == 1 && *iu == *n) && *abstol <= 0.) {
348 dcopy_(n, &work[indd], &c__1, &w[1], &c__1);
349 indee = indwrk + (*n << 1);
350 i__1 = *n - 1;
351 dcopy_(&i__1, &work[inde], &c__1, &work[indee], &c__1);
352 if (! wantz) {
353 dsterf_(n, &w[1], &work[indee], info);
354 } else {
355 dlacpy_("A", n, n, &q[q_offset], ldq, &z__[z_offset], ldz, (
356 ftnlen)1);
357 dsteqr_(jobz, n, &w[1], &work[indee], &z__[z_offset], ldz, &work[
358 indwrk], info, (ftnlen)1);
359 if (*info == 0) {
360 i__1 = *n;
361 for (i__ = 1; i__ <= i__1; ++i__) {
362 ifail[i__] = 0;
363 /* L10: */
364 }
365 }
366 }
367 if (*info == 0) {
368 *m = *n;
369 goto L30;
370 }
371 *info = 0;
372 }
373
374 /* Otherwise, call DSTEBZ and, if eigenvectors are desired, */
375 /* call DSTEIN. */
376
377 if (wantz) {
378 *(unsigned char *)order = 'B';
379 } else {
380 *(unsigned char *)order = 'E';
381 }
382 indibl = 1;
383 indisp = indibl + *n;
384 indiwo = indisp + *n;
385 dstebz_(range, order, n, vl, vu, il, iu, abstol, &work[indd], &work[inde],
386 m, &nsplit, &w[1], &iwork[indibl], &iwork[indisp], &work[indwrk],
387 &iwork[indiwo], info, (ftnlen)1, (ftnlen)1);
388
389 if (wantz) {
390 dstein_(n, &work[indd], &work[inde], m, &w[1], &iwork[indibl], &iwork[
391 indisp], &z__[z_offset], ldz, &work[indwrk], &iwork[indiwo], &
392 ifail[1], info);
393
394 /* Apply transformation matrix used in reduction to tridiagonal */
395 /* form to eigenvectors returned by DSTEIN. */
396
397 i__1 = *m;
398 for (j = 1; j <= i__1; ++j) {
399 dcopy_(n, &z__[j * z_dim1 + 1], &c__1, &work[1], &c__1);
400 dgemv_("N", n, n, &c_b25, &q[q_offset], ldq, &work[1], &c__1, &
401 c_b27, &z__[j * z_dim1 + 1], &c__1, (ftnlen)1);
402 /* L20: */
403 }
404 }
405
406 L30:
407
408 /* If eigenvalues are not in order, then sort them, along with */
409 /* eigenvectors. */
410
411 if (wantz) {
412 i__1 = *m - 1;
413 for (j = 1; j <= i__1; ++j) {
414 i__ = 0;
415 tmp1 = w[j];
416 i__2 = *m;
417 for (jj = j + 1; jj <= i__2; ++jj) {
418 if (w[jj] < tmp1) {
419 i__ = jj;
420 tmp1 = w[jj];
421 }
422 /* L40: */
423 }
424
425 if (i__ != 0) {
426 itmp1 = iwork[indibl + i__ - 1];
427 w[i__] = w[j];
428 iwork[indibl + i__ - 1] = iwork[indibl + j - 1];
429 w[j] = tmp1;
430 iwork[indibl + j - 1] = itmp1;
431 dswap_(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[j * z_dim1 + 1],
432 &c__1);
433 if (*info != 0) {
434 itmp1 = ifail[i__];
435 ifail[i__] = ifail[j];
436 ifail[j] = itmp1;
437 }
438 }
439 /* L50: */
440 }
441 }
442
443 return 0;
444
445 /* End of DSBGVX */
446
447 } /* dsbgvx_ */
448
449