From 4606ebdbb3b5afd5254e9734ef237fbe1e7b75e3 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (laptop)" <j.wuttke@fz-juelich.de>
Date: Mon, 24 Sep 2012 23:06:16 +0200
Subject: [PATCH] yeeah! pconv works on first attempt (equidistant case, tested
 with atan)

---
 pub/src/expr.cpp   | 50 +++++++++++++++++++++++++++++++++-------------
 test/test1-fit.inp |  2 +-
 2 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/pub/src/expr.cpp b/pub/src/expr.cpp
index d883957c..eac26d73 100644
--- a/pub/src/expr.cpp
+++ b/pub/src/expr.cpp
@@ -940,20 +940,42 @@ void CNodePConv::convolve( CResult& ret, const CContext& ctx,
     vector<double> tt;
     cv_ctx.vt = &tt;
     // Convolute theory with resolution.
-    if( !conv_step )
-        throw "pconv not implemented for non-equidistant grid";
-    // both grids have step conv_step
-    int ntt = n + nv - 1;
-    tt.resize(ntt);
-    for ( int ii=0; ii<ntt; ++ii ) // ii=(nv-1)+i-iv
-        tt[ii] = (*(ctx.vt))[0] - sv->x[0] - theshift +
-            (ii-(nv-1))*conv_step;
-    theory->tree_val( res_theory, cv_ctx );
-    for ( int i=0; i<n; ++i ){
-        ret.v[i] = 0;
-        for ( int iv=0; iv<nv; ++iv )
-            ret.v[i] += res_theory.to_r(nv-1+i-iv) * sv->y[iv];
-        ret.v[i] *= conv_step / conv_norm;
+    if( conv_step ){ // accelerated version with equidistant grids
+        // precompute theory on unified grid
+        int ntt = n + nv;
+        tt.resize(ntt);
+        double tt0 = (*(ctx.vt))[0] - sv->x[0] - theshift - (nv-0.5)*conv_step;
+        for ( int ii=0; ii<ntt; ++ii ) // ii=(nv-1)+i-iv
+            tt[ii] = tt0 + ii*conv_step;
+        theory->tree_val( res_theory, cv_ctx );
+        // now convolve
+        for ( int i=0; i<n; ++i ){
+            ret.v[i] = 0;
+            for ( int iv=0; iv<nv; ++iv )
+                ret.v[i] += (res_theory.to_r(nv  +i-iv)-
+                             res_theory.to_r(nv-1+i-iv)) * sv->y[iv];
+            ret.v[i] *= conv_step / conv_norm;
+        }
+    } else { // simplest version: non-equidistant x_out and x_res.
+        throw "pconv non-eq conv not yet implemented";
+        for ( int i=0; i<n; ++i )
+            ret.v[i] = 0;
+        tt.resize(n);
+        for ( int iv=0; iv<nv; ++iv ) {
+            double dx; // variable step
+            if      ( iv==0 )
+                dx = sv->x[1] - sv->x[0];
+            else if ( iv==nv-1 )
+                dx = sv->x[nv-1] - sv->x[nv-2];
+            else
+                dx = ( sv->x[iv+1] - sv->x[iv-1] ) / 2;
+            for ( int i=0; i<n; ++i )
+                tt[i] = (*(ctx.vt))[i] - sv->x[iv] - theshift;
+            theory->tree_val( res_theory, cv_ctx );
+            for ( int i=0; i<n; ++i )
+                ret.v[i] += res_theory.to_r(i) * sv->y[iv] *
+                    dx / conv_norm;
+        }
     }
 }
 
diff --git a/test/test1-fit.inp b/test/test1-fit.inp
index a1f9bce2..9e5e7abb 100644
--- a/test/test1-fit.inp
+++ b/test/test1-fit.inp
@@ -1,7 +1,7 @@
 fl dat-res
 fl dat-qel
-1 cc p0+p1*resol(0)+p2*conv(cauchy(t,p3),0)
 1 cc p0+p1*resol+p2*conv(cauchy(t,p3))
+1 cc p0+p1*resol+p2*pconv(atan(p3*t))
 2,3 cv 0
 2,3 cf
 g2
-- 
GitLab