Files
2025-02-Numerical/lib/nr/cpp/recipes/amebsa.cpp
2025-09-12 18:55:25 +09:00

90 lines
1.6 KiB
C++

#include <cmath>
#include "nr.h"
using namespace std;
namespace {
inline void get_psum(Mat_I_DP &p, Vec_O_DP &psum)
{
int n,m;
DP sum;
int mpts=p.nrows();
int ndim=p.ncols();
for (n=0;n<ndim;n++) {
for (sum=0.0,m=0;m<mpts;m++) sum += p[m][n];
psum[n]=sum;
}
}
}
extern int idum;
DP tt;
void NR::amebsa(Mat_IO_DP &p, Vec_IO_DP &y, Vec_O_DP &pb, DP &yb, const DP ftol,
DP funk(Vec_I_DP &), int &iter, const DP temptr)
{
int i,ihi,ilo,j,n;
DP rtol,yhi,ylo,ynhi,ysave,yt,ytry;
int mpts=p.nrows();
int ndim=p.ncols();
Vec_DP psum(ndim);
tt = -temptr;
get_psum(p,psum);
for (;;) {
ilo=0;
ihi=1;
ynhi=ylo=y[0]+tt*log(ran1(idum));
yhi=y[1]+tt*log(ran1(idum));
if (ylo > yhi) {
ihi=0;
ilo=1;
ynhi=yhi;
yhi=ylo;
ylo=ynhi;
}
for (i=3;i<=mpts;i++) {
yt=y[i-1]+tt*log(ran1(idum));
if (yt <= ylo) {
ilo=i-1;
ylo=yt;
}
if (yt > yhi) {
ynhi=yhi;
ihi=i-1;
yhi=yt;
} else if (yt > ynhi) {
ynhi=yt;
}
}
rtol=2.0*fabs(yhi-ylo)/(fabs(yhi)+fabs(ylo));
if (rtol < ftol || iter < 0) {
SWAP(y[0],y[ilo]);
for (n=0;n<ndim;n++)
SWAP(p[0][n],p[ilo][n]);
break;
}
iter -= 2;
ytry=amotsa(p,y,psum,pb,yb,funk,ihi,yhi,-1.0);
if (ytry <= ylo) {
ytry=amotsa(p,y,psum,pb,yb,funk,ihi,yhi,2.0);
} else if (ytry >= ynhi) {
ysave=yhi;
ytry=amotsa(p,y,psum,pb,yb,funk,ihi,yhi,0.5);
if (ytry >= ysave) {
for (i=0;i<mpts;i++) {
if (i != ilo) {
for (j=0;j<ndim;j++) {
psum[j]=0.5*(p[i][j]+p[ilo][j]);
p[i][j]=psum[j];
}
y[i]=funk(psum);
}
}
iter -= ndim;
get_psum(p,psum);
}
} else ++iter;
}
}