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

📄 s_las1.cc

📁 矩阵奇异分解(svd)最新c++版本
💻 CC
📖 第 1 页 / 共 3 页
字号:
      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]);	    r = pythag(g, 1.0);	    g = d[m] - p + e[l] / (g + fsign(r, g));	    s = 1.0;	    c = 1.0;	    p = 0.0;	    underflow = FALSE;	    i = m - 1;	    while (underflow == FALSE && i >= l) {	       f = s * e[i];	       b = c * e[i];	       r = pythag(f, g);	       e[i+1] = r;	       if (r == 0.0) underflow = TRUE;	       else {		  s = f / r;		  c = g / r;		  g = d[i+1] - p;		  r = (d[i] - g) * s + 2.0 * c * b;		  p = s * r;		  d[i+1] = g + p;		  g = c * r - b;		  f = bnd[i+1];		  bnd[i+1] = s * bnd[i] + c * f;		  bnd[i] = c * bnd[i] - s * f;		  i--;	       }	    }       /* end while (underflow != FALSE && i >= l) */	    /*........ recover from underflow .........*/	    if (underflow) {	       d[i+1] -= p;	       e[m] = 0.0;	    }	    else {	       d[l] -= p;	       e[l] = g;	       e[m] = 0.0;	    }	 } 		       		   /* end if (m != l) */	 else {            /* order the eigenvalues */	    exchange = TRUE;	    if (l != 0) {	       i = l;	       while (i >= 1 && exchange == TRUE) {	          if (p < d[i-1]) {		     d[i] = d[i-1];		     bnd[i] = bnd[i-1];	             i--;	          }	          else exchange = FALSE;	       }	    }	    if (exchange) i = 0;	    d[i] = p;	    bnd[i] = f; 	    iteration = 31;	 }      }			       /* end while (iteration <= 30) */   }				   /* end for (l=0; l<n; l++) */   return;}/*********************************************************************** *                                                                     * *			lanczos_step()                                 * *                                                                     * ***********************************************************************//***********************************************************************   Description   -----------   Function embodies a single Lanczos step   Arguments    ---------   (input)   n        dimension of the eigenproblem for matrix B   first    start of index through loop				         last     end of index through loop				        wptr	    array of pointers pointing to work space		       alf	    array to hold diagonal of the tridiagonal matrix T   eta      orthogonality estimate of Lanczos vectors at step j      oldeta   orthogonality estimate of Lanczos vectors at step j-1   bet      array to hold off-diagonal of T                        ll       number of intitial Lanczos vectors in local orthog.               (has value of 0, 1 or 2)			   enough   stop flag			   Functions used   --------------   BLAS		ddot, dscal, daxpy, datx, dcopy   USER		store   LAS		purge, ortbnd, startv   UTILITY	imin, imax ***********************************************************************/void s_las1::lanczos_step(long n, long first, long last, double *wptr[],		  double *alf, double *eta, double *oldeta,		  double *bet, long *ll, long *enough){   double t, *mid;   long i;   for (j=first; j<last; j++) {      mid     = wptr[2];      wptr[2] = wptr[1];      wptr[1] = mid;      mid     = wptr[3];      wptr[3] = wptr[4];      wptr[4] = mid;      store(n, STORQ, j-1, wptr[2]);      if (j-1 < MAXLL) store(n, STORP, j-1, wptr[4]);      bet[j] = rnm;      /* restart if invariant subspace is found */      if (!bet[j]) {	 rnm = startv(n, wptr);	 if (ierr) return;	 if (!rnm) *enough = TRUE;      }      if (*enough) break;      /* take a lanczos step */      t = 1.0 / rnm;      datx(n, t, wptr[0], 1, wptr[1], 1);      dscal(n, t, wptr[3], 1);      opb(n, wptr[3], wptr[0]);      daxpy(n, -rnm, wptr[2], 1, wptr[0], 1);      alf[j] = ddot(n, wptr[0], 1, wptr[3], 1);      daxpy(n, -alf[j], wptr[1], 1, wptr[0], 1);      /* orthogonalize against initial lanczos vectors */      if (j <= MAXLL && (fabs(alf[j-1]) > 4.0 * fabs(alf[j])))	 *ll = j;        for (i=0; i < imin(*ll, j-1); i++) {	 store(n, RETRP, i, wptr[5]);	 t = ddot(n, wptr[5], 1, wptr[0], 1);	 store(n, RETRQ, i, wptr[5]);         daxpy(n, -t, wptr[5], 1, wptr[0], 1);	 eta[i] = eps1;	 oldeta[i] = eps1;      }      /* extended local reorthogonalization */      t = ddot(n, wptr[0], 1, wptr[4], 1);      daxpy(n, -t, wptr[2], 1, wptr[0], 1);      if (bet[j] > 0.0) bet[j] = bet[j] + t;      t = ddot(n, wptr[0], 1, wptr[3], 1);      daxpy(n, -t, wptr[1], 1, wptr[0], 1);      alf[j] = alf[j] + t;      dcopy(n, wptr[0], 1, wptr[4], 1);      rnm = sqrt(ddot(n, wptr[0], 1, wptr[4], 1));      anorm = bet[j] + fabs(alf[j]) + rnm;      tol = reps * anorm;      /* update the orthogonality bounds */      ortbnd(alf, eta, oldeta, bet);      /* restore the orthogonality state when needed */      purge(n,*ll,wptr[0],wptr[1],wptr[4],wptr[3],wptr[5],eta,oldeta);      if (rnm <= tol) rnm = 0.0;   }   return;}/*********************************************************************** *                                                                     * *                          ortbnd()                                   * *                                                                     * ***********************************************************************//***********************************************************************   Description   -----------   Funtion updates the eta recurrence   Arguments    ---------   (input)   alf      array to hold diagonal of the tridiagonal matrix T            eta      orthogonality estimate of Lanczos vectors at step j           oldeta   orthogonality estimate of Lanczos vectors at step j-1        bet      array to hold off-diagonal of T                             n        dimension of the eigenproblem for matrix B		       j        dimension of T					     rnm	    norm of the next residual vector			    eps1	    roundoff estimate for dot product of two unit vectors   (output)   eta      orthogonality estimate of Lanczos vectors at step j+1        oldeta   orthogonality estimate of Lanczos vectors at step j           Functions used   --------------   BLAS		dswap ***********************************************************************/void s_las1::ortbnd(double *alf, double *eta, double *oldeta, double *bet){   long i;   if (j < 1) return;   if (rnm) {      if (j > 1) {	 oldeta[0] = (bet[1] * eta[1] + (alf[0]-alf[j]) * eta[0] -		      bet[j] * oldeta[0]) / rnm + eps1;      }      for (i=1; i<=j-2; i++) 	 oldeta[i] = (bet[i+1] * eta[i+1] + (alf[i]-alf[j]) * eta[i] +		      bet[i] * eta[i-1] - bet[j] * oldeta[i])/rnm + eps1;   }   oldeta[j-1] = eps1;   dswap(j, oldeta, 1, eta, 1);     eta[j] = eps1;   return;}/*********************************************************************** *                                                                     * *				purge()                                * *                                                                     * ***********************************************************************//***********************************************************************   Description   -----------   Function examines the state of orthogonality between the new Lanczos   vector and the previous ones to decide whether re-orthogonalization    should be performed   Arguments    ---------   (input)   n        dimension of the eigenproblem for matrix B		          ll       number of intitial Lanczos vectors in local orthog.          r        residual vector to become next Lanczos vector               q        current Lanczos vector			              ra       previous Lanczos vector   qa       previous Lanczos vector   wrk      temporary vector to hold the previous Lanczos vector   eta      state of orthogonality between r and prev. Lanczos vectors    oldeta   state of orthogonality between q and prev. Lanczos vectors   j        current Lanczos step				        (output)   r	    residual vector orthogonalized against previous Lanczos 	      vectors   q        current Lanczos vector orthogonalized against previous ones   Functions used   --------------   BLAS		daxpy,  dcopy,  idamax,  ddot   USER		store ***********************************************************************/void s_las1::purge(long n, long ll, double *r, double *q, double *ra,  	   double *qa, double *wrk, double *eta, double *oldeta){   double t, tq, tr, reps1;   long k, iteration, flag, i;   if (j < ll+2) return;    k = idamax(j - (ll+1), &eta[ll], 1) + ll;   if (fabs(eta[k]) > reps) {      reps1 = eps1 / reps;      iteration = 0;      flag = TRUE;      while (iteration < 2 && flag) {	 if (rnm > tol) {	    /* bring in a lanczos vector t and orthogonalize both 	     * r and q against it */	    tq = 0.0;	    tr = 0.0;            for (i = ll; i < j; i++) {	       store(n,  RETRQ,  i,  wrk);	       t   = -ddot(n, qa, 1, wrk, 1);	       tq += fabs(t);	       daxpy(n,  t,  wrk,  1,  q,  1);	       t   = -ddot(n, ra, 1, wrk, 1);	       tr += fabs(t);	       daxpy(n, t, wrk, 1, r, 1);	    }	    dcopy(n, q, 1, qa, 1);	    t   = -ddot(n, r, 1, qa, 1);	    tr += fabs(t);	    daxpy(n, t, q, 1, r, 1);	    dcopy(n, r, 1, ra, 1);	    rnm = sqrt(ddot(n, ra, 1, r, 1));	    if (tq <= reps1 && tr <= reps1 * rnm) flag = FALSE;	 }	 iteration++;      }      for (i = ll; i <= j; i++) { 	 eta[i] = eps1;	 oldeta[i] = eps1;      }   }   return;}/*****************************************************************  * Function finds the index of element having max. absolute value* * based on FORTRAN 77 routine from Linpack by J. Dongarra       * *****************************************************************/ long s_las1::idamax(long n,double *dx,long incx){   long ix,i,imax;   double dtemp, dmax;   if (n < 1) return(-1);   if (n == 1) return(0);   if (incx == 0) return(-1);   if (incx < 0) ix = (-n+1) * incx;   else ix = 0;   imax = ix;   dx += ix;   dmax = fabs(*dx);   for (i=1; i < n; i++) {      ix += incx;      dx += incx;      dtemp = fabs(*dx);      if (dtemp > dmax) {	 dmax = dtemp;	 imax = ix;      }   }   return(imax);}/*********************************************************************** *                                                                     * *			error_bound()                                  * *                                                                     * ***********************************************************************//***********************************************************************   Description   -----------   Function massages error bounds for very close ritz values by placing    a gap between them.  The error bounds are then refined to reflect    this.

⌨️ 快捷键说明

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