text: 
  #define NRANSI
  #include "nrutil.h"
  #define NPRE 1
  #define NPOST 1
  #define ALPHA 0.33
  #define NGMAX 15
  
  void mgfas(double **u, int n, int maxcyc)
  {
  	double anorm2(double **a, int n);
  	void copy(double **aout, double **ain, int n);
  	void interp(double **uf, double **uc, int nf);
  	void lop(double **out, double **u, int n);
  	void matadd(double **a, double **b, double **c, int n);
  	void matsub(double **a, double **b, double **c, int n);
  	void relax2(double **u, double **rhs, int n);
  	void rstrct(double **uc, double **uf, int nc);
  	void slvsm2(double **u, double **rhs);
  	unsigned int j,jcycle,jj,jm1,jpost,jpre,nf,ng=0,ngrid,nn;
  	double **irho[NGMAX+1],**irhs[NGMAX+1],**itau[NGMAX+1],
  		**itemp[NGMAX+1],**iu[NGMAX+1];
  	double res,trerr;
  
  	nn=n;
  	while (nn >>= 1) ng++;
  	if (n != 1+(1L << ng)) nrerror("n-1 must be a power of 2 in mgfas.");
  	if (ng > NGMAX) nrerror("increase NGMAX in mglin.");
  	nn=n/2+1;
  	ngrid=ng-1;
  	irho[ngrid]=dmatrix(1,nn,1,nn);
  	rstrct(irho[ngrid],u,nn);
  	while (nn > 3) {
  		nn=nn/2+1;
  		irho[--ngrid]=dmatrix(1,nn,1,nn);
  		rstrct(irho[ngrid],irho[ngrid+1],nn);
  	}
  	nn=3;
  	iu[1]=dmatrix(1,nn,1,nn);
  	irhs[1]=dmatrix(1,nn,1,nn);
  	itau[1]=dmatrix(1,nn,1,nn);
  	itemp[1]=dmatrix(1,nn,1,nn);
  	slvsm2(iu[1],irho[1]);
  	free_dmatrix(irho[1],1,nn,1,nn);
  	ngrid=ng;
  	for (j=2;j<=ngrid;j++) {
  		nn=2*nn-1;
  		iu[j]=dmatrix(1,nn,1,nn);
  		irhs[j]=dmatrix(1,nn,1,nn);
  		itau[j]=dmatrix(1,nn,1,nn);
  		itemp[j]=dmatrix(1,nn,1,nn);
  		interp(iu[j],iu[j-1],nn);
  		copy(irhs[j],(j != ngrid ? irho[j] : u),nn);
  		for (jcycle=1;jcycle<=maxcyc;jcycle++) {
  		nf=nn;
  			for (jj=j;jj>=2;jj--) {
  				for (jpre=1;jpre<=NPRE;jpre++)
  					relax2(iu[jj],irhs[jj],nf);
  				lop(itemp[jj],iu[jj],nf);
  				nf=nf/2+1;
  				jm1=jj-1;
  				rstrct(itemp[jm1],itemp[jj],nf);
  				rstrct(iu[jm1],iu[jj],nf);
  				lop(itau[jm1],iu[jm1],nf);
  				matsub(itau[jm1],itemp[jm1],itau[jm1],nf);
  				if (jj == j)
  					trerr=ALPHA*anorm2(itau[jm1],nf);
  				rstrct(irhs[jm1],irhs[jj],nf);
  				matadd(irhs[jm1],itau[jm1],irhs[jm1],nf);
  			}
  			slvsm2(iu[1],irhs[1]);
  			nf=3;
  			for (jj=2;jj<=j;jj++) {
  			jm1=jj-1;
  			rstrct(itemp[jm1],iu[jj],nf);
  			matsub(iu[jm1],itemp[jm1],itemp[jm1],nf);
  			nf=2*nf-1;
  			interp(itau[jj],itemp[jm1],nf);
  			matadd(iu[jj],itau[jj],iu[jj],nf);
  			for (jpost=1;jpost<=NPOST;jpost++)
  				relax2(iu[jj],irhs[jj],nf);
  			}
  			lop(itemp[j],iu[j],nf);
  			matsub(itemp[j],irhs[j],itemp[j],nf);
  			res=anorm2(itemp[j],nf);
  			if (res < trerr) break;
  		}
  	}
  	copy(u,iu[ngrid],n);
  	for (nn=n,j=ng;j>=1;j--,nn=nn/2+1) {
  		free_dmatrix(itemp[j],1,nn,1,nn);
  		free_dmatrix(itau[j],1,nn,1,nn);
  		free_dmatrix(irhs[j],1,nn,1,nn);
  		free_dmatrix(iu[j],1,nn,1,nn);
  		if (j != ng && j != 1) free_dmatrix(irho[j],1,nn,1,nn);
  	}
  }
  #undef NGMAX
  #undef NPRE
  #undef NPOST
  #undef ALPHA
  #undef NRANSI
  