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


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:14