double maxeig(double *xmat, mwSignedIndex n) { // xmat is symmetric n x n matrix mwSignedIndex incx=1,indmax,maxloop=10000,k=0; double alpha, beta, dmax, dmax_temp,dmax_tol; double *bufveca=(double *) calloc(n,sizeof(double)); double *bufvecb=(double *) calloc(n,sizeof(double)); dmax_tol=.001; // do power series to get approximation to max eigenvalue of A+X alpha=0.0;cblas_dscal(n,alpha,bufveca,incx);bufveca[0]=1.0; // x_0 = [1,0,0,...] do something better later beta=0.0;dmax=1.0;dmax_temp=0.0; while ((dabsf(dmax-dmax_temp)>dmax_tol)&&(k<=maxloop)){ dmax_temp=dmax; alpha=1.0; cblas_dgemv(CblasColMajor,CblasNoTrans,n,n,alpha,xmat,n,bufveca,incx,beta,bufvecb,incx); indmax=idxmax(bufvecb,n);dmax=bufvecb[indmax]; alpha=1.0/dmax;cblas_dscal(n,alpha,bufvecb,incx); cblas_dcopy(n,bufvecb,incx,bufveca,incx); k++; } alpha=1.0; // compute Rayleigh Quotient to approximate max eigenvalue of A+X cblas_dgemv(CblasColMajor,CblasNoTrans,n,n,alpha,xmat,n,bufvecb,incx,beta,bufveca,incx); dmax=doubdot(bufvecb,bufveca,n);alpha=doubnorm2(bufvecb,n);dmax=dmax/alpha/alpha; free(bufveca);free(bufvecb); return dmax; }
/* Input parameters: A : mxn matrix m : number of rows of A n : number of columns of A f : Right-hand side nx1 column vector s : nx1 start vector (the initial guess) tol : relative residual error tolerance for break condition maxiter : Maximum number of iterations to perform M : diag(M) is the inverse of the preconditioner where M is a vector */ void conjugate_gradient(double *A,ptrdiff_t m,ptrdiff_t n,double *D1,double *D2,double *f,double *s,double tol,int maxiter,double *M,double *xout,double *CGiters,double *flag) { double *u=(double *) calloc(n,sizeof(double)); // n x 1 solution vector double *r=(double *) calloc(n,sizeof(double)); // n x 1 residual vector double *p=(double *) calloc(n,sizeof(double)); // n x 1 direction vector double *veca=(double *) calloc(m,sizeof(double)); // mx1 temp vector double *vecb=(double *) calloc(n,sizeof(double)); // nx1 temp vector double *vecc=(double *) calloc(n,sizeof(double)); // nx1 temp vector double *vecd=(double *) calloc(m*n,sizeof(double)); // mxn temp matrix double alpha,beta,rho,rho_new,normr,normf; int niter=0,i,j; ptrdiff_t incx = 1; // initializations for (i=0;i<n;i++) for (j=0;j<m;j++) vecd[j+i*m]=A[j+i*m]*D1[j]; // vecd stores the matrix D1*A *flag=0; cblas_dcopy(n,s,incx,u,incx); alpha=1.0;beta=0.0;cblas_dgemv(CblasColMajor,CblasNoTrans,m,n,alpha,A,m,u,incx,beta,veca,incx); // veca contains A*s alpha=1.0;beta=0.0;cblas_dgemv(CblasColMajor,CblasTrans,m,n,alpha,vecd,m,veca,incx,beta,vecb,incx); // vecb contains A'*(D1*(A*s)) cblas_dcopy(n,f,incx,r,incx); alpha=-1.0;cblas_daxpy(n,alpha,vecb,incx,r,incx); // r contains f-A'*(D1*(A*s)) cblas_dcopy(n,s,incx,vecb,incx); component_mult(vecb,D2,n); // vecb contains D2*s alpha=-1.0;cblas_daxpy(n,alpha,vecb,incx,r,incx); // r contains f-A'*(D1*(A*s))-D2*s cblas_dcopy(n,r,incx,p,incx); component_mult(p,M,n); // p contains M*r rho=doubdot(p,r,n); // rho is r'*M*r normf=doubnorm2(f,n); if (normf<.0001) normf=1.0; normr=doubnorm2(r,n); while (normr/normf > tol) { // Test break condition alpha=1.0;beta=0.0;cblas_dgemv(CblasColMajor,CblasNoTrans,m,n,alpha,A,m,p,incx,beta,veca,incx); // veca contains A*p alpha=1.0;beta=0.0;cblas_dgemv(CblasColMajor,CblasTrans,m,n,alpha,vecd,m,veca,incx,beta,vecb,incx); // vecb contains A'*(D1*(A*p)) cblas_dcopy(n,p,incx,vecc,incx); component_mult(vecc,D2,n); // vecc contains D2*p alpha=1.0;cblas_daxpy(n,alpha,vecc,incx,vecb,incx); // vecb contains A'*(D1*(A*p))+D2*p alpha=rho/doubdot(vecb,p,n); cblas_daxpy(n,alpha,p,incx,u,incx); // u=u+alpha*p alpha=-1.0*alpha;cblas_daxpy(n,alpha,vecb,incx,r,incx); // r=r-alpha*vecb cblas_dcopy(n,r,incx,vecc,incx); component_mult(vecc,M,n); // vecc contains M*r rho_new=doubdot(vecc,r,n); // rho is r'*M*r alpha=rho_new/rho;cblas_dscal(n,alpha,p,incx); //p=rho_new/rho * p; alpha=1.0;cblas_daxpy(n,alpha,vecc,incx,p,incx); // p=(M*r)+p rho=rho_new; niter++; if (niter == maxiter) { //if max. number of iterations is reached, break. normr=doubnorm2(r,n); *flag = 1; break; } normr=doubnorm2(r,n); } cblas_dcopy(n,u,incx,xout,incx); *CGiters=niter; free(u); free(r); free(p); free(veca); free(vecb); free(vecc); free(vecd); }