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
|
//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>
|
template<class T,class R>
|
||||||
const T polynom(const T &x, const NRVec<R> &c)
|
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;
|
j=10*n;
|
||||||
for(i=2;i<=n+1;i++)
|
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)
|
if(t<j)
|
||||||
{
|
{
|
||||||
j=t;
|
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];
|
T *xpows = new T[m];
|
||||||
xpows[0]=x;
|
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
|
//run the summation loop
|
||||||
@@ -85,6 +88,11 @@ T r,s,f;
|
|||||||
k= -1;
|
k= -1;
|
||||||
for(i=0; i<=n/m;i++)
|
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++)
|
for(j=0;j<m;j++)
|
||||||
{
|
{
|
||||||
k++;
|
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
|
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
|
else
|
||||||
{
|
{
|
||||||
r+= s*f;
|
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>
|
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;
|
int power;
|
||||||
|
|
||||||
@@ -354,7 +363,7 @@ return r;
|
|||||||
|
|
||||||
//make exp(iH) with real H in real arithmetics
|
//make exp(iH) with real H in real arithmetics
|
||||||
template<class T>
|
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;
|
int power;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user