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

📄 s_las2.cc

📁 矩阵奇异分解(svd)最新c++版本
💻 CC
📖 第 1 页 / 共 3 页
字号:
// File: s_las2.cc -- Implements the las2 class// Author: Suvrit Sra// Date: 14 nov, 2003/************************************************************************* THE ORIGINAL SVDPAKC COPYRIGHT                           (c) Copyright 1993                        University of Tennessee                          All Rights Reserved                           *************************************************************************/#include <cstdio>#include <cmath>#include <cerrno>#include <cstdlib>#include <cstring>#include <unistd.h>#include <fcntl.h>#include "s_las2.h"#define STORQ 1#define RETRQ 2#define STORP 3#define RETRP 4#define MAXLL 2using namespace ssvd;/*********************************************************************** *                                                                     * *				landr()				       * *        Lanczos algorithm with selective orthogonalization           * *                    Using Simon's Recurrence                         * *                       (double precision)                            * *                                                                     * ***********************************************************************//***********************************************************************   Description   -----------   landr() is the LAS2 driver routine that, upon entry,     (1)  checks for the validity of input parameters of the 	  B-eigenproblem      (2)  determines several machine constants     (3)  makes a Lanczos run     (4)  calculates B-eigenvectors (singular vectors of A) if requested 	  by user   arguments   ---------   (input)   n        dimension of the eigenproblem for A'A   lanmax   upper limit of desired number of Lanczos steps   maxprs   upper limit of desired number of eigenpairs   nnzero   number of nonzeros in matrix A   endl     left end of interval containing unwanted eigenvalues of B   endr     right end of interval containing unwanted eigenvalues of B   vectors  1 indicates both eigenvalues and eigenvectors are wanted              and they can be found in output file lav2; 	    0 indicates only eigenvalues are wanted   kappa    relative accuracy of ritz values acceptable as eigenvalues	      of B (singular values of A)   r        work array   (output)   j        number of Lanczos steps actually taken                        neig     number of ritz values stabilized                              ritz     array to hold the ritz values                                 bnd      array to hold the error bounds   External parameters   -------------------   Defined and documented in las2.h   local parameters   -------------------   ibeta    radix for the floating-point representation   it       number of base ibeta digits in the floating-point significand   irnd     floating-point addition rounded or chopped   machep   machine relative precision or round-off error   negeps   largest negative integer   wptr	    array of pointers each pointing to a work space   Functions used   --------------   MISC         dmax, machar, check_parameters   LAS2         ritvec, lanso ***********************************************************************/long s_las2::landr(long fpo2, FILE* fp, bool ascii, long n, 		   long lanmax, long maxprs, long nnzero, double endl,  		   double endr, bool vectors, double kappa, double *ritz, 		   double *bnd, double *r){   long i, size, ibeta, it, irnd, machep, negep;   double *wptr[10], *tptr, *tptr2;   /* data validation */   if (check_parameters(maxprs, lanmax, n, endl, endr, vectors, nnzero))      return(-1);   /* Compute machine precision */    machar(&ibeta, &it, &irnd, &machep, &negep);   eps1 = eps * sqrt( (double) n );   reps = sqrt(eps);   eps34 = reps * sqrt(reps);   /* allocate work area and initialize pointers         *    * ptr             symbolic name         size         *    * wptr[0]             r                  n           *    * wptr[1]             q		     n           *    * wptr[2]             q_previous         n           *    * wptr[3]             p		     n           *    * wptr[4]             p_previous         n           *    * wptr[5]             wrk                n           *    * wptr[6]             alf              lanmax        *    * wptr[7]             eta              lanmax        *    * wptr[8]             oldeta           lanmax        *    * wptr[9]             bet              lanmax+1      */   //fprintf(stderr, "s_las2::landr() about to start doing computation\n");   size = 5 * n + (lanmax * 4 + 1);   tptr = NULL;   if (!(tptr = (double *) malloc(size * sizeof(double)))){      perror("FIRST MALLOC FAILED in LANDR()");      exit(errno);   }   tptr2 = tptr;   wptr[0] = r;   for (i = 1; i <= 5; i++) {      wptr[i] = tptr;      tptr += n;   }   for (i = 6; i <= 9; i++) {      wptr[i] = tptr;      tptr += lanmax;   }   lanso(n, lanmax, maxprs, endl, endr, ritz, bnd, wptr);   /* compute eigenvectors */   if (vectors) {      if (!(xv1 = (double *) malloc((nrow+ncol)*(j+1)*sizeof(double))) ||	  !(xv2 = (double *) malloc(ncol * sizeof(double)))) {	  perror("SECOND MALLOC FAILED in LANDR()");	  exit(errno);	 }      kappa = dmax(fabs(kappa), eps34);      ritvec(fpo2, fp, ascii, n, kappa, ritz, bnd, wptr[6], wptr[9], wptr[4], wptr[5]);   }   free(tptr2);   return(0);}/*********************************************************************** *                                                                     * *                         stpone()                                    * *                                                                     * ***********************************************************************//***********************************************************************   Description   -----------   Function performs the first step of the Lanczos algorithm.  It also   does a step of extended local re-orthogonalization.   Arguments    ---------   (input)   n      dimension of the eigenproblem for matrix B   (output)   ierr   error flag   wptr   array of pointers that point to work space that contains	    wptr[0]             r[j]	    wptr[1]             q[j]	    wptr[2]             q[j-1]	    wptr[3]             p	    wptr[4]             p[j-1]	    wptr[6]             diagonal elements of matrix T    Functions used   --------------   BLAS		daxpy, datx, dcopy, ddot, dscal   USER		store, opb   LAS		startv ***********************************************************************/void s_las2::stpone(long n, double *wrkptr[]){   double t, *alf;   alf = wrkptr[6];   /* get initial vector; default is random */   rnm = startv(n, wrkptr);   if (rnm == 0.0 || ierr != 0) return;   /* normalize starting vector */   t = 1.0 / rnm;   datx(n, t, wrkptr[0], 1, wrkptr[1], 1);   dscal(n, t, wrkptr[3], 1);   /* take the first step */   mopb(n, wrkptr[3], wrkptr[0]);   alf[0] = ddot(n, wrkptr[0], 1, wrkptr[3], 1);   daxpy(n, -alf[0], wrkptr[1], 1, wrkptr[0], 1);   t = ddot(n, wrkptr[0], 1, wrkptr[3], 1);   daxpy(n, -t, wrkptr[1], 1, wrkptr[0], 1);   alf[0] += t;   dcopy(n, wrkptr[0], 1, wrkptr[4], 1);   rnm = sqrt(ddot(n, wrkptr[0], 1, wrkptr[4], 1));   anorm = rnm + fabs(alf[0]);   tol = reps * anorm;   return;}/*********************************************************************** *                                                                     * *                         startv()                                    * *                                                                     * ***********************************************************************//***********************************************************************   Description   -----------   Function delivers a starting vector in r and returns |r|; it returns    zero if the range is spanned, and ierr is non-zero if no starting    vector within range of operator can be found.   Parameters    ---------   (input)   n      dimension of the eigenproblem matrix B   wptr   array of pointers that point to work space   j      starting index for a Lanczos run   eps    machine epsilon (relative precision)   (output)   wptr   array of pointers that point to work space that contains	  r[j], q[j], q[j-1], p[j], p[j-1]   ierr   error flag (nonzero if no starting vector can be found)   Functions used   --------------   BLAS		ddot, dcopy, daxpy   USER		opb, store   MISC		random ***********************************************************************/double s_las2::startv(long n, double *wptr[]){   double rnm2, *r, t;   long irand;   long id, i;   /* get initial vector; default is random */   rnm2 = ddot(n, wptr[0], 1, wptr[0], 1);   irand = 918273 + j;   r = wptr[0];   for (id = 0; id < 3; id++) {      if (id > 0 || j > 0 || rnm2 == 0) 	 for (i = 0; i < n; i++) r[i] = mrandom(&irand);      dcopy(n, wptr[0], 1, wptr[3], 1);      /* apply operator to put r in range (essential if m singular) */      mopb(n, wptr[3], wptr[0]);      dcopy(n, wptr[0], 1, wptr[3], 1);      rnm2 = ddot(n, wptr[0], 1, wptr[3], 1);      if (rnm2 > 0.0) break;   }   /* fatal error */   if (rnm2 <= 0.0) {      ierr = 8192;      return(-1);   }   if (j > 0) {      for (i = 0; i < j; i++) {         store(n, RETRQ, i, wptr[5]);	 t = -ddot(n, wptr[3], 1, wptr[5], 1);	 daxpy(n, t, wptr[5], 1, wptr[0], 1);      }      /* make sure q[j] is orthogonal to q[j-1] */      t = ddot(n, wptr[4], 1, wptr[0], 1);      daxpy(n, -t, wptr[2], 1, wptr[0], 1);      dcopy(n, wptr[0], 1, wptr[3], 1);      t = ddot(n, wptr[3], 1, wptr[0], 1);      if (t <= eps * rnm2) t = 0.0;      rnm2 = t;   }   return(sqrt(rnm2));}/*********************************************************************** *                                                                     * *				imtqlb()			       * *                                                                     * ***********************************************************************//***********************************************************************   Description   -----------   imtqlb() is a translation of a Fortran version of the Algol   procedure IMTQL1, Num. Math. 12, 377-383(1968) by Martin and    Wilkinson, as modified in Num. Math. 15, 450(1970) by Dubrulle.     Handbook for Auto. Comp., vol.II-Linear Algebra, 241-248(1971).     See also B. T. Smith et al, Eispack Guide, Lecture Notes in    Computer Science, Springer-Verlag, (1976).   The function finds the eigenvalues of a symmetric tridiagonal   matrix by the implicit QL method.   Arguments    ---------   (input)   n      order of the symmetric tridiagonal matrix                      d      contains the diagonal elements of the input matrix              e      contains the subdiagonal elements of the input matrix in its          last n-1 positions.  e[0] is arbitrary	                (output)   d      contains the eigenvalues in ascending order.  if an error            exit is made, the eigenvalues are correct and ordered for            indices 0,1,...ierr, but may not be the smallest eigenvalues.   e      has been destroyed.					       ierr   set to zero for normal return, j if the j-th eigenvalue has            not been determined after 30 iterations.		       Functions used   --------------   UTILITY	fsign   MISC		pythag ***********************************************************************/void s_las2::imtqlb(long n, double d[], double e[], double bnd[]){   long last, l, m, i, iteration;   /* various flags */   long exchange, convergence, underflow;	   double b, test, g, r, s, c, p, f;   if (n == 1) return;   ierr = 0;   bnd[0] = 1.0;   last = n - 1;   for (i = 1; i < n; i++) {      bnd[i] = 0.0;      e[i-1] = e[i];   }   e[last] = 0.0;   for (l = 0; l < n; l++) {      iteration = 0;      while (iteration <= 30) {	 for (m = l; m < n; m++) {	    convergence = FALSE;	    if (m == last) break;	    else {	       test = fabs(d[m]) + fabs(d[m+1]);	       if (test + fabs(e[m]) == test) convergence = TRUE;	    }	    if (convergence) break;	 }	    p = d[l]; 	    f = bnd[l]; 	 if (m != l) {	    if (iteration == 30) {	       ierr = l;	       return;	    }	    iteration += 1;	    /*........ form shift ........*/	    g = (d[l+1] - p) / (2.0 * e[l]);

⌨️ 快捷键说明

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