89 lines
2.1 KiB
C++
89 lines
2.1 KiB
C++
#include <cmath>
|
|
#include "nr.h"
|
|
using namespace std;
|
|
|
|
void NR::miser(DP func(Vec_I_DP &), Vec_I_DP ®n, const int npts,
|
|
const DP dith, DP &ave, DP &var)
|
|
{
|
|
const int MNPT=15, MNBS=60;
|
|
const DP PFAC=0.1, TINY=1.0e-30, BIG=1.0e30;
|
|
static int iran=0;
|
|
int j,jb,n,ndim,npre,nptl,nptr;
|
|
DP avel,varl,fracl,fval,rgl,rgm,rgr,s,sigl,siglb,sigr,sigrb;
|
|
DP sum,sumb,summ,summ2;
|
|
|
|
ndim=regn.size()/2;
|
|
Vec_DP pt(ndim);
|
|
if (npts < MNBS) {
|
|
summ=summ2=0.0;
|
|
for (n=0;n<npts;n++) {
|
|
ranpt(pt,regn);
|
|
fval=func(pt);
|
|
summ += fval;
|
|
summ2 += fval * fval;
|
|
}
|
|
ave=summ/npts;
|
|
var=MAX(TINY,(summ2-summ*summ/npts)/(npts*npts));
|
|
} else {
|
|
Vec_DP rmid(ndim);
|
|
npre=MAX(int(npts*PFAC),int(MNPT));
|
|
Vec_DP fmaxl(ndim),fmaxr(ndim),fminl(ndim),fminr(ndim);
|
|
for (j=0;j<ndim;j++) {
|
|
iran=(iran*2661+36979) % 175000;
|
|
s=SIGN(dith,DP(iran-87500));
|
|
rmid[j]=(0.5+s)*regn[j]+(0.5-s)*regn[ndim+j];
|
|
fminl[j]=fminr[j]=BIG;
|
|
fmaxl[j]=fmaxr[j]=(-BIG);
|
|
}
|
|
for (n=0;n<npre;n++) {
|
|
ranpt(pt,regn);
|
|
fval=func(pt);
|
|
for (j=0;j<ndim;j++) {
|
|
if (pt[j]<=rmid[j]) {
|
|
fminl[j]=MIN(fminl[j],fval);
|
|
fmaxl[j]=MAX(fmaxl[j],fval);
|
|
} else {
|
|
fminr[j]=MIN(fminr[j],fval);
|
|
fmaxr[j]=MAX(fmaxr[j],fval);
|
|
}
|
|
}
|
|
}
|
|
sumb=BIG;
|
|
jb= -1;
|
|
siglb=sigrb=1.0;
|
|
for (j=0;j<ndim;j++) {
|
|
if (fmaxl[j] > fminl[j] && fmaxr[j] > fminr[j]) {
|
|
sigl=MAX(TINY,pow(fmaxl[j]-fminl[j],2.0/3.0));
|
|
sigr=MAX(TINY,pow(fmaxr[j]-fminr[j],2.0/3.0));
|
|
sum=sigl+sigr;
|
|
if (sum<=sumb) {
|
|
sumb=sum;
|
|
jb=j;
|
|
siglb=sigl;
|
|
sigrb=sigr;
|
|
}
|
|
}
|
|
}
|
|
if (jb == -1) jb=(ndim*iran)/175000;
|
|
rgl=regn[jb];
|
|
rgm=rmid[jb];
|
|
rgr=regn[ndim+jb];
|
|
fracl=fabs((rgm-rgl)/(rgr-rgl));
|
|
nptl=int(MNPT+(npts-npre-2*MNPT)*fracl*siglb
|
|
/(fracl*siglb+(1.0-fracl)*sigrb));
|
|
nptr=npts-npre-nptl;
|
|
Vec_DP regn_temp(2*ndim);
|
|
for (j=0;j<ndim;j++) {
|
|
regn_temp[j]=regn[j];
|
|
regn_temp[ndim+j]=regn[ndim+j];
|
|
}
|
|
regn_temp[ndim+jb]=rmid[jb];
|
|
miser(func,regn_temp,nptl,dith,avel,varl);
|
|
regn_temp[jb]=rmid[jb];
|
|
regn_temp[ndim+jb]=regn[ndim+jb];
|
|
miser(func,regn_temp,nptr,dith,ave,var);
|
|
ave=fracl*avel+(1-fracl)*ave;
|
|
var=fracl*fracl*varl+(1-fracl)*(1-fracl)*var;
|
|
}
|
|
}
|