matexp bugfix efficiency of polynom()

This commit is contained in:
jiri committed 2026-10-30 21:06:33 +01:00
1 parent 7efc12eb5e
commit 815d5b87a1
1 file changed
+17 -8
+17 -8
View File
@@ -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;