add numerical recipes library
This commit is contained in:
49
lib/nr/cpp/recipes/laguer.cpp
Normal file
49
lib/nr/cpp/recipes/laguer.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <cmath>
|
||||
#include <complex>
|
||||
#include <limits>
|
||||
#include "nr.h"
|
||||
using namespace std;
|
||||
|
||||
void NR::laguer(Vec_I_CPLX_DP &a, complex<DP> &x, int &its)
|
||||
{
|
||||
const int MR=8,MT=10,MAXIT=MT*MR;
|
||||
const DP EPS=numeric_limits<DP>::epsilon();
|
||||
static const DP frac[MR+1]=
|
||||
{0.0,0.5,0.25,0.75,0.13,0.38,0.62,0.88,1.0};
|
||||
int iter,j;
|
||||
DP abx,abp,abm,err;
|
||||
complex<DP> dx,x1,b,d,f,g,h,sq,gp,gm,g2;
|
||||
|
||||
int m=a.size()-1;
|
||||
for (iter=1;iter<=MAXIT;iter++) {
|
||||
its=iter;
|
||||
b=a[m];
|
||||
err=abs(b);
|
||||
d=f=0.0;
|
||||
abx=abs(x);
|
||||
for (j=m-1;j>=0;j--) {
|
||||
f=x*f+d;
|
||||
d=x*d+b;
|
||||
b=x*b+a[j];
|
||||
err=abs(b)+abx*err;
|
||||
}
|
||||
err *= EPS;
|
||||
if (abs(b) <= err) return;
|
||||
g=d/b;
|
||||
g2=g*g;
|
||||
h=g2-2.0*f/b;
|
||||
sq=sqrt(DP(m-1)*(DP(m)*h-g2));
|
||||
gp=g+sq;
|
||||
gm=g-sq;
|
||||
abp=abs(gp);
|
||||
abm=abs(gm);
|
||||
if (abp < abm) gp=gm;
|
||||
dx=MAX(abp,abm) > 0.0 ? DP(m)/gp : polar(1+abx,DP(iter));
|
||||
x1=x-dx;
|
||||
if (x == x1) return;
|
||||
if (iter % MT != 0) x=x1;
|
||||
else x -= frac[iter/MT]*dx;
|
||||
}
|
||||
nrerror("too many iterations in laguer");
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user