⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ep.c

📁 NIST Handwriting OCR Testbed
💻 C
字号:
/*# proc: la_eigen - Given a real positive definite symmetric matrix# proc:            produce the eigenvalues and eigenvectors.# proc: diag_mat - Finds eigenvalues and eigenvectors of a symmetric real# proc:            matrix.  (A wrapper for SSYEVX, a Fortran routine in# proc:            LAPACK.)  This doesn't allow all the possibilities of# proc:            SSYEVX, but hides some of the messiness associated with# proc:            using SSYEVX directly.)*/#include <stdio.h>#include <clapck.h>#include <defs.h>/******************************************************************/void la_eigen(const int nevtr, int *nevtf,              float **evts, float **evas, float *cov,              const int order){   int i, n;   float *tevas;   float *tevts;   int *ifail;   int nfail;   int good, bad;   float *pevts, *pevas;   diag_mat(order, cov, nevtr, &tevas, &tevts, &ifail, &nfail);   *nevtf = nevtr - nfail;   *evts = (float *)malloc(*nevtf * order * sizeof(float));   *evas = (float *)malloc(*nevtf * sizeof(float));   pevts = *evts;   pevas = *evas;   good = 0;   bad = 0;   for(i = 0; i < *nevtf; i++) {      if(nfail && ifail[bad] == i) {         fprintf(stderr, "failed convergence on evect %d ", i);         fprintf(stderr, "evect / eval pair deleted\n");         bad++;      }      else {         for (n = 0; n < order; n++)            pevts[good * order + n] = tevts[i * order + n];         pevas[good] = tevas[i];         good++;      }   }   free(tevas);   free(tevts);   free(ifail);   return;}/******************************************************************//* Finds eigenvalues and eigenvectors of a symmetric real matrix.  (Awrapper for SSYEVX, a Fortran routine in LAPACK.)  This doesn't allowall the possibilities of SSYEVX, but hides some of the messinessassociated with using SSYEVX directly.)  If n_find > order or if theargs given result in one of the Fortran routines -- ILAENV and SSYEVX-- getting an illegal argument, then an error message will be writtento stderr and the process will exit; otherwise the routine will return0 (normal) or a positive integer (some eigenvectors failed toconverge; see below under return value).Input args:  order: Order of matrix mat.  mat: Symmetric matrix of floats.  This is assumed to be a buffer of    order^2 floats, but only the the nonstrict lower triangle (when    interpreted as matrix in C or other row-major language; nonstrict    upper triangle to Fortran) need be filled in.    CAUTION: On return, the nonstrict lower triangle of mat will have    been destroyed (by SSYEVX).  n_find: Number of largest eigenvalues, and their corresponding    eigenvectors, that are to be found; must be <= order.  If n_find    exceeds the rank of the matrix, some of the resulting eigenvalues    and eigenvectors may be meaningless [?].  verbose: If nonzero, the routine writes a message when it starts,    and reports the clock time elapsed.Output args:  evals: The n_find largest eigenvalues, in decreasing order; this    routine causes the buffer to be malloced.  evecs: The corresponding eigenvectors, as the rows of an    n_find x order "matrix" in row-major order; this routine causes    the buffer to be malloced.  didnt_converge_indices: See below under return value positive.Return value:  0: Normal; evals and evecs contains the largest n_find eigenvalues    and the corresponding eigenvectors, and didnt_converge_indices    will not have been allocated (so no need to free it).  <a positive integer n>: n of the eigenvectors failed to converge;    their indices (with 1 subtracted to convert them from 1-based    Fortran to 0-based C indices) are stored in didnt_converge_indices;    this routine will have caused the buffer to be malloced; but if    you don't want to receive this list of indices in this event, just    use (int **)NULL for the didnt_converge_indices arg.  The    remaining eigenvalues and eigenvectors will be in evals and evecs.*/void diag_mat(const int order, float *mat, int nevtf,             float **evas, float **evts, int **ifail, int *info){   float *tevas;   float *tevts;   int nb;   int fw_len;   int iw_len;   float *fw;   int *iw;   int il, iu, tnevtf;   static char I, L, V, S;   int lda;   float abstol;   int *tifail;   int ie;   int i, j;   static int i1;   float a;   int *ffail;   char *routine = "ssytrd";   char *parms = "VIL";   int ord;   if (nevtf > order) {      fprintf(stderr, "nevtf (%d) > order (%d)\n", nevtf, order);      exit(-1);   }   *info = 0;   if((*evas = (float *)malloc(nevtf * sizeof(float))) == NULL) {      fprintf(stderr, "Error allocing evas\n");      exit(-1);   }   if((*evts = (float *)malloc(nevtf*order * sizeof(float))) == NULL) {      fprintf(stderr, "Error allocing evts\n");      exit(-1);   }   tevts = *evts;   tevas = *evas;   if((*ifail = (int *)malloc(order * sizeof(int))) == NULL) {      fprintf(stderr, "Error allocing ifail\n");      exit(-1);   }   i = 1;   j = -1;   ord = order;   nb = ilaenv_(&i, routine, parms, &ord, &j, &j, &j, 6L, 3L);/*printf("r = %s  p = %s  nb = %d\n", routine, parms, nb);*/   fw_len = max(8, nb + 3) * order;   iw_len = order * 5;/*printf("fwlen = %d  iwlen = %d\n", fw_len, iw_len);*/   if((tifail = (int *)malloc(order*sizeof(int))) == NULL) {      fprintf(stderr, "Error allocing tfail\n");      exit(-1);   }   if((fw = (float *)malloc(fw_len*sizeof(float))) == NULL) {      fprintf(stderr, "Error allocing fw\n");      exit(-1);   }   if((iw = (int *)malloc(iw_len*sizeof(int))) == NULL) {      fprintf(stderr, "Error allocing iw\n");      exit(-1);   }   il  = order - nevtf + 1;   iu  = order;   I = 'I';   /* means find evals on range il -> iu */   L = 'L';   /* means upper triang of "mat" is stored */   V = 'V';   /* compute evals AND evects. */   S = 'S';   /* set to a safe minimum */   tnevtf = 0;   lda = order;   abstol = 2.0 * (float)slamch_(&S);/*printf("abstol = %e\n", abstol);*/     /*   This LAPACK routine does the real work.   on the SGI (atef) run:   man ssyevx   */   ssyevx_(&V, &I, &L, &order, mat, &lda,       (float *)NULL,	/* lowerbound on EVA's to be found - not used with 'I' */       (float *)NULL,	/* upperbound on EVA's to be found - not used with 'I' */       &il,		/* upper and lower indices - in reverse order */       &iu,		/* of eigenvalues to be found. */       &abstol,		/* floating point tolerance set above */       &tnevtf,		/* number actually found */       tevas,		/* final evals in ascending order */       tevts,		/* final evects corresponding to EVA's */       &order,		/* leading dimension of evecs_yow */       fw, &fw_len,	/* workspace and it's length */       iw,		/* integer space */       tifail,		/* indices of failed-to-converge evects */       info);		/* error flag */   free(fw);   free(iw);/*printf("info = %d   tnevtf = %d\n", *info, tnevtf);*/   if (*info < 0 || nevtf != tnevtf) {      if (*info < 0)         fprintf(stderr,            "\nthe %d'th arg of ssyevx had an illegal value", -(*info));      if (nevtf != tnevtf)         fprintf(stderr,              "no. of eigen{value,vector}s requested %d != no. found, %d",               nevtf, tnevtf);        exit(-1);   }   /*   Rearrange eigenvalues and eigenvectors from their current   order -- increasing eigenvalue -- to decreasing eigenvalue,   which seems more convenient.   */   ie = nevtf / 2;   j = nevtf - 1;   i1 = 1;   for (i = 0; i < ie; i++, j--) {      a = tevas[i];      tevas[i] = tevas[j];      tevas[j] = a;      sswap_(&order, tevts + i * order, &i1,                     tevts + j * order, &i1);   }   if (*info) {  /* info > 0: then some (actually info) eigenvectors   		   failed to converge, and their indices are in indexfail. */      if (ifail) {	/* pointer acting as flag */         ffail = (int *)malloc(*info*sizeof(int));         /*         This handles for the reversal of the order of the         eigen{values,vectors}, and it converts from Fortran         1-based indices to C 0-based indices.         */         for (i = 0; i < *info ; i++)            ffail[i] = *info - tifail[i];         *ifail = ffail;      }   }   else {      *ifail = (int *)malloc(sizeof(int));      *ifail[0] = -1;   }   free(tifail);   return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -