cheev.c
Go to the documentation of this file.
00001 /* cheev.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Table of constant values */
00017 
00018 static integer c__1 = 1;
00019 static integer c_n1 = -1;
00020 static integer c__0 = 0;
00021 static real c_b18 = 1.f;
00022 
00023 /* Subroutine */ int cheev_(char *jobz, char *uplo, integer *n, complex *a, 
00024         integer *lda, real *w, complex *work, integer *lwork, real *rwork, 
00025         integer *info)
00026 {
00027     /* System generated locals */
00028     integer a_dim1, a_offset, i__1, i__2;
00029     real r__1;
00030 
00031     /* Builtin functions */
00032     double sqrt(doublereal);
00033 
00034     /* Local variables */
00035     integer nb;
00036     real eps;
00037     integer inde;
00038     real anrm;
00039     integer imax;
00040     real rmin, rmax, sigma;
00041     extern logical lsame_(char *, char *);
00042     integer iinfo;
00043     extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *);
00044     logical lower, wantz;
00045     extern doublereal clanhe_(char *, char *, integer *, complex *, integer *, 
00046              real *);
00047     integer iscale;
00048     extern /* Subroutine */ int clascl_(char *, integer *, integer *, real *, 
00049             real *, integer *, integer *, complex *, integer *, integer *);
00050     extern doublereal slamch_(char *);
00051     extern /* Subroutine */ int chetrd_(char *, integer *, complex *, integer 
00052             *, real *, real *, complex *, complex *, integer *, integer *);
00053     real safmin;
00054     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
00055             integer *, integer *);
00056     extern /* Subroutine */ int xerbla_(char *, integer *);
00057     real bignum;
00058     integer indtau, indwrk;
00059     extern /* Subroutine */ int csteqr_(char *, integer *, real *, real *, 
00060             complex *, integer *, real *, integer *), cungtr_(char *, 
00061             integer *, complex *, integer *, complex *, complex *, integer *, 
00062             integer *), ssterf_(integer *, real *, real *, integer *);
00063     integer llwork;
00064     real smlnum;
00065     integer lwkopt;
00066     logical lquery;
00067 
00068 
00069 /*  -- LAPACK driver routine (version 3.2) -- */
00070 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00071 /*     November 2006 */
00072 
00073 /*     .. Scalar Arguments .. */
00074 /*     .. */
00075 /*     .. Array Arguments .. */
00076 /*     .. */
00077 
00078 /*  Purpose */
00079 /*  ======= */
00080 
00081 /*  CHEEV computes all eigenvalues and, optionally, eigenvectors of a */
00082 /*  complex Hermitian matrix A. */
00083 
00084 /*  Arguments */
00085 /*  ========= */
00086 
00087 /*  JOBZ    (input) CHARACTER*1 */
00088 /*          = 'N':  Compute eigenvalues only; */
00089 /*          = 'V':  Compute eigenvalues and eigenvectors. */
00090 
00091 /*  UPLO    (input) CHARACTER*1 */
00092 /*          = 'U':  Upper triangle of A is stored; */
00093 /*          = 'L':  Lower triangle of A is stored. */
00094 
00095 /*  N       (input) INTEGER */
00096 /*          The order of the matrix A.  N >= 0. */
00097 
00098 /*  A       (input/output) COMPLEX array, dimension (LDA, N) */
00099 /*          On entry, the Hermitian matrix A.  If UPLO = 'U', the */
00100 /*          leading N-by-N upper triangular part of A contains the */
00101 /*          upper triangular part of the matrix A.  If UPLO = 'L', */
00102 /*          the leading N-by-N lower triangular part of A contains */
00103 /*          the lower triangular part of the matrix A. */
00104 /*          On exit, if JOBZ = 'V', then if INFO = 0, A contains the */
00105 /*          orthonormal eigenvectors of the matrix A. */
00106 /*          If JOBZ = 'N', then on exit the lower triangle (if UPLO='L') */
00107 /*          or the upper triangle (if UPLO='U') of A, including the */
00108 /*          diagonal, is destroyed. */
00109 
00110 /*  LDA     (input) INTEGER */
00111 /*          The leading dimension of the array A.  LDA >= max(1,N). */
00112 
00113 /*  W       (output) REAL array, dimension (N) */
00114 /*          If INFO = 0, the eigenvalues in ascending order. */
00115 
00116 /*  WORK    (workspace/output) COMPLEX array, dimension (MAX(1,LWORK)) */
00117 /*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
00118 
00119 /*  LWORK   (input) INTEGER */
00120 /*          The length of the array WORK.  LWORK >= max(1,2*N-1). */
00121 /*          For optimal efficiency, LWORK >= (NB+1)*N, */
00122 /*          where NB is the blocksize for CHETRD returned by ILAENV. */
00123 
00124 /*          If LWORK = -1, then a workspace query is assumed; the routine */
00125 /*          only calculates the optimal size of the WORK array, returns */
00126 /*          this value as the first entry of the WORK array, and no error */
00127 /*          message related to LWORK is issued by XERBLA. */
00128 
00129 /*  RWORK   (workspace) REAL array, dimension (max(1, 3*N-2)) */
00130 
00131 /*  INFO    (output) INTEGER */
00132 /*          = 0:  successful exit */
00133 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
00134 /*          > 0:  if INFO = i, the algorithm failed to converge; i */
00135 /*                off-diagonal elements of an intermediate tridiagonal */
00136 /*                form did not converge to zero. */
00137 
00138 /*  ===================================================================== */
00139 
00140 /*     .. Parameters .. */
00141 /*     .. */
00142 /*     .. Local Scalars .. */
00143 /*     .. */
00144 /*     .. External Functions .. */
00145 /*     .. */
00146 /*     .. External Subroutines .. */
00147 /*     .. */
00148 /*     .. Intrinsic Functions .. */
00149 /*     .. */
00150 /*     .. Executable Statements .. */
00151 
00152 /*     Test the input parameters. */
00153 
00154     /* Parameter adjustments */
00155     a_dim1 = *lda;
00156     a_offset = 1 + a_dim1;
00157     a -= a_offset;
00158     --w;
00159     --work;
00160     --rwork;
00161 
00162     /* Function Body */
00163     wantz = lsame_(jobz, "V");
00164     lower = lsame_(uplo, "L");
00165     lquery = *lwork == -1;
00166 
00167     *info = 0;
00168     if (! (wantz || lsame_(jobz, "N"))) {
00169         *info = -1;
00170     } else if (! (lower || lsame_(uplo, "U"))) {
00171         *info = -2;
00172     } else if (*n < 0) {
00173         *info = -3;
00174     } else if (*lda < max(1,*n)) {
00175         *info = -5;
00176     }
00177 
00178     if (*info == 0) {
00179         nb = ilaenv_(&c__1, "CHETRD", uplo, n, &c_n1, &c_n1, &c_n1);
00180 /* Computing MAX */
00181         i__1 = 1, i__2 = (nb + 1) * *n;
00182         lwkopt = max(i__1,i__2);
00183         work[1].r = (real) lwkopt, work[1].i = 0.f;
00184 
00185 /* Computing MAX */
00186         i__1 = 1, i__2 = (*n << 1) - 1;
00187         if (*lwork < max(i__1,i__2) && ! lquery) {
00188             *info = -8;
00189         }
00190     }
00191 
00192     if (*info != 0) {
00193         i__1 = -(*info);
00194         xerbla_("CHEEV ", &i__1);
00195         return 0;
00196     } else if (lquery) {
00197         return 0;
00198     }
00199 
00200 /*     Quick return if possible */
00201 
00202     if (*n == 0) {
00203         return 0;
00204     }
00205 
00206     if (*n == 1) {
00207         i__1 = a_dim1 + 1;
00208         w[1] = a[i__1].r;
00209         work[1].r = 1.f, work[1].i = 0.f;
00210         if (wantz) {
00211             i__1 = a_dim1 + 1;
00212             a[i__1].r = 1.f, a[i__1].i = 0.f;
00213         }
00214         return 0;
00215     }
00216 
00217 /*     Get machine constants. */
00218 
00219     safmin = slamch_("Safe minimum");
00220     eps = slamch_("Precision");
00221     smlnum = safmin / eps;
00222     bignum = 1.f / smlnum;
00223     rmin = sqrt(smlnum);
00224     rmax = sqrt(bignum);
00225 
00226 /*     Scale matrix to allowable range, if necessary. */
00227 
00228     anrm = clanhe_("M", uplo, n, &a[a_offset], lda, &rwork[1]);
00229     iscale = 0;
00230     if (anrm > 0.f && anrm < rmin) {
00231         iscale = 1;
00232         sigma = rmin / anrm;
00233     } else if (anrm > rmax) {
00234         iscale = 1;
00235         sigma = rmax / anrm;
00236     }
00237     if (iscale == 1) {
00238         clascl_(uplo, &c__0, &c__0, &c_b18, &sigma, n, n, &a[a_offset], lda, 
00239                 info);
00240     }
00241 
00242 /*     Call CHETRD to reduce Hermitian matrix to tridiagonal form. */
00243 
00244     inde = 1;
00245     indtau = 1;
00246     indwrk = indtau + *n;
00247     llwork = *lwork - indwrk + 1;
00248     chetrd_(uplo, n, &a[a_offset], lda, &w[1], &rwork[inde], &work[indtau], &
00249             work[indwrk], &llwork, &iinfo);
00250 
00251 /*     For eigenvalues only, call SSTERF.  For eigenvectors, first call */
00252 /*     CUNGTR to generate the unitary matrix, then call CSTEQR. */
00253 
00254     if (! wantz) {
00255         ssterf_(n, &w[1], &rwork[inde], info);
00256     } else {
00257         cungtr_(uplo, n, &a[a_offset], lda, &work[indtau], &work[indwrk], &
00258                 llwork, &iinfo);
00259         indwrk = inde + *n;
00260         csteqr_(jobz, n, &w[1], &rwork[inde], &a[a_offset], lda, &rwork[
00261                 indwrk], info);
00262     }
00263 
00264 /*     If matrix was scaled, then rescale eigenvalues appropriately. */
00265 
00266     if (iscale == 1) {
00267         if (*info == 0) {
00268             imax = *n;
00269         } else {
00270             imax = *info - 1;
00271         }
00272         r__1 = 1.f / sigma;
00273         sscal_(&imax, &r__1, &w[1], &c__1);
00274     }
00275 
00276 /*     Set WORK(1) to optimal complex workspace size. */
00277 
00278     work[1].r = (real) lwkopt, work[1].i = 0.f;
00279 
00280     return 0;
00281 
00282 /*     End of CHEEV */
00283 
00284 } /* cheev_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:28