matexp bugfix efficiency of polynom()
This commit is contained in:
1 parent
7efc12eb5e
commit
815d5b87a1
1 file changed
+17
-8
@@ -53,6 +53,8 @@ return y;
|
||||
|
||||
|
||||
//algorithm which minimazes number of multiplications, at the cost of storage
|
||||
//(block summation, Paterson-Stockmeyer): sum_i s_i (x^m)^i with s_i = sum_{j<m} c_{im+j} x^j
|
||||
//needs m-2+2*(n/m)-(n%m?0:1) multiplications instead of n of the horner scheme
|
||||
template<class T,class R>
|
||||
const T polynom(const T &x, const NRVec<R> &c)
|
||||
{
|
||||
@@ -65,7 +67,7 @@ if(n<=4) return polynom0(x,c); //here the horner scheme is optimal
|
||||
j=10*n;
|
||||
for(i=2;i<=n+1;i++)
|
||||
{
|
||||
t=i-2+2*(n/i)-(n%i)?0:1;
|
||||
t=i-2+2*(n/i)-((n%i)?0:1);
|
||||
if(t<j)
|
||||
{
|
||||
j=t;
|
||||
@@ -74,10 +76,11 @@ for(i=2;i<=n+1;i++)
|
||||
}
|
||||
|
||||
|
||||
//allocate array for powers up to m
|
||||
//allocate array for powers up to m (x^m only if there is more than one block)
|
||||
T *xpows = new T[m];
|
||||
xpows[0]=x;
|
||||
for(i=1;i<m;i++) xpows[i]=xpows[i-1]*x;
|
||||
for(i=1;i<m-1;i++) xpows[i]=xpows[i-1]*x;
|
||||
if(n>=m) xpows[m-1]=xpows[m-2]*x;
|
||||
|
||||
|
||||
//run the summation loop
|
||||
@@ -85,6 +88,11 @@ T r,s,f;
|
||||
k= -1;
|
||||
for(i=0; i<=n/m;i++)
|
||||
{
|
||||
if(i>0 && i*m==n) //last block with c[n] only: no multiplication needed
|
||||
{
|
||||
LA_traits<T>::axpy(r,f,c[n]);
|
||||
break;
|
||||
}
|
||||
for(j=0;j<m;j++)
|
||||
{
|
||||
k++;
|
||||
@@ -97,11 +105,11 @@ for(i=0; i<=n/m;i++)
|
||||
LA_traits<T>::axpy(s,xpows[j-1],c[k]); //general s+=xpows[j-1]*c[k]; but more efficient for matrices
|
||||
}
|
||||
|
||||
if(i==0) {r=s; f=xpows[m-1];}
|
||||
if(i==0) {r=s; if(n>=m) f=xpows[m-1];}
|
||||
else
|
||||
{
|
||||
r+= s*f;
|
||||
f=f*xpows[m-1];
|
||||
if(i<n/m) f=f*xpows[m-1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,9 +340,10 @@ for(i=0,t=1.;i<=n;i++)
|
||||
|
||||
|
||||
|
||||
//it seems that we do not gain anything by polynom vs polynom0, check the m-optimization!
|
||||
//polynom (default) needs about half the matrix multiplications of the horner scheme polynom0 at the same accuracy,
|
||||
//1.3-1.5x faster for dense matrices; use horner=true for sparse matrices (stored powers fill in)
|
||||
template<class T>
|
||||
const T exp(const T &x, bool horner=true, int maxpower= -1, int maxtaylor= -1 )
|
||||
const T exp(const T &x, bool horner=false, int maxpower= -1, int maxtaylor= -1 )
|
||||
{
|
||||
int power;
|
||||
|
||||
@@ -354,7 +363,7 @@ return r;
|
||||
|
||||
//make exp(iH) with real H in real arithmetics
|
||||
template<class T>
|
||||
void sincos(T &s, T &c, const T &x, bool horner=true, int maxpower= -1, int maxtaylor= -1 )
|
||||
void sincos(T &s, T &c, const T &x, bool horner=false, int maxpower= -1, int maxtaylor= -1 )
|
||||
{
|
||||
int power;
|
||||
|
||||
|
||||
Reference in new issue
Block a user