From fbb6c62b7434f86e309313709f6b385f6e6c0178 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (laptop)" <j.wuttke@fz-juelich.de> Date: Thu, 6 May 2010 23:22:09 +0200 Subject: [PATCH] important clarification: separate tree_val according to typ --- pub/src/expr.cpp | 660 ++++++++++++++++++++++++----------------------- pub/src/expr.h | 17 +- pub/src/opr.cpp | 4 +- 3 files changed, 357 insertions(+), 324 deletions(-) diff --git a/pub/src/expr.cpp b/pub/src/expr.cpp index ce5cd369..a3219963 100644 --- a/pub/src/expr.cpp +++ b/pub/src/expr.cpp @@ -216,8 +216,7 @@ uint CRef::get_k( const CContext& ctx ) const else k = ctx.k; if ( k==(uint)-1 ) - throw string( "k-dependent expression out of context or " - "k out of bounds" ); + throw string( "missing or invalid k" ); if ( k>=NOlm::MOM.size()) throw string( "index k=" + strg(k) + " out of bounds" ); @@ -236,21 +235,20 @@ uint CRef::get_j( const CContext& ctx ) const j = ctx.j; } if ( j==(uint)-1 ) - throw string( "j-dependent expression out of context or " - "j out of bounds" ); + throw string( "missing or invalid j" ); return j; } //! Evaluate this reference in given context. Result returned in ret. -void CRef::ref_val( CTOut *ret, const CContext& ctx ) const +void CRef::ref_val( CTOut& ret, const CContext& ctx ) const { uint k = get_k( ctx ); // Return k-dependent reference: if ( typ == _K ) { - ret->set_u( k ); + ret.set_u( k ); return; } @@ -262,15 +260,15 @@ void CRef::ref_val( CTOut *ret, const CContext& ctx ) const // Return k-j-dependent reference: if ( typ == _J ) { - ret->set_u( ctx.j ); + ret.set_u( ctx.j ); return; } else if ( typ==_NJ ) { - ret->set_u( f->nJ() ); + ret.set_u( f->nJ() ); return; } else if ( typ == _Z ) { if ( num>= f->nZ() ) throw ( "invalid reference " + var_info() ); - ret->set_d( f->V[j]->z[num] ); + ret.set_d( f->V[j]->z[num] ); return; } @@ -293,25 +291,25 @@ void CRef::ref_val( CTOut *ret, const CContext& ctx ) const if( i>= sj->size() ) throw string( "i out of range" ); if ( typ == _I ) { - ret->set_u( i ); + ret.set_u( i ); } else if ( typ == _X ) { - ret->set_d( sj->x[i] ); + ret.set_d( sj->x[i] ); } else if ( typ == _Y ) { - ret->set_d( sj->y[i] ); + ret.set_d( sj->y[i] ); if ( ctx.want_error && sj->dy.size() ) - ret->dd = sj->dy[i]; + ret.dd = sj->dy[i]; } else if ( typ == _DY ) { - ret->set_d( sj->dy[i] ); + ret.set_d( sj->dy[i] ); } } else if ( ctx.dim_vi() ) { - ret->preset_vd( ctx.nv ); + ret.preset_vd( ctx.nv ); if ( ti ) { // is this also true when just "i" is given ?? CContext myctx = ctx; myctx.reqDim = CContext::_1; if ( ctx.want_error && sj->dy.size() ) - ret->dvd.resize( ctx.nv ); + ret.dvd.resize( ctx.nv ); else - ret->dvd.clear(); + ret.dvd.clear(); for( uint ii=0; ii<ctx.nv; ++ii ){ myctx.i = ii; uint i; @@ -319,15 +317,15 @@ void CRef::ref_val( CTOut *ret, const CContext& ctx ) const if( i >= sj->size() ) throw string( "i out of range" ); if ( typ == _I ) { - ret->vd[ii] = i; + ret.vd[ii] = i; } else if ( typ == _X ) { - ret->vd[ii] = sj->x[i]; + ret.vd[ii] = sj->x[i]; } else if ( typ == _Y ) { - ret->vd[ii] = sj->y[i]; - if ( ret->dvd.size() ) - ret->dvd[ii] = sj->dy[i]; + ret.vd[ii] = sj->y[i]; + if ( ret.dvd.size() ) + ret.dvd[ii] = sj->dy[i]; } else if ( typ == _DY ) { - ret->vd[ii] = sj->dy[i]; + ret.vd[ii] = sj->dy[i]; } } } else { @@ -337,20 +335,20 @@ void CRef::ref_val( CTOut *ret, const CContext& ctx ) const strg( sj->size() ); if ( typ == _I ) { for( uint i=0; i<ctx.nv; ++i ) - ret->vd[i] = i; + ret.vd[i] = i; } else if ( typ == _X ) { - ret->vd = sj->x; + ret.vd = sj->x; } else if ( typ == _Y ) { - ret->vd = sj->y; + ret.vd = sj->y; if ( ctx.want_error ) - ret->dvd = sj->dy; + ret.dvd = sj->dy; } else if ( typ == _DY ) { - ret->vd = sj->dy; + ret.vd = sj->dy; } } } } else if ( typ == _NI ) { - ret->set_d( sj->size() ); + ret.set_d( sj->size() ); } else throw( "invalid ref(" + var_info() + ") in data file" ); return; @@ -363,11 +361,11 @@ void CRef::ref_val( CTOut *ret, const CContext& ctx ) const if ( typ == _FP ) { if ( num>= fc->nPar() ) throw( "invalid p ref(" + var_info() + ") in curve file" ); - ret->set_d( cj->P[num] ); + ret.set_d( cj->P[num] ); } else if ( typ == _FM ) { if ( num >= CCurve::mQuality ) throw( "invalid fm ref(" + var_info() + ") in curve file" ); - ret->set_d( cj->Quality[num] ); + ret.set_d( cj->Quality[num] ); } else throw( "invalid ref(" + var_info() + ") in curve file" ); return; @@ -377,16 +375,16 @@ void CRef::ref_val( CTOut *ret, const CContext& ctx ) const //! Description of reference (for use in ??) -void CRef::coord( CCoord *ret, uint k_in ) const +void CRef::coord( CCoord& ret, uint k_in ) const { if ( typ == _K ) { - *ret = CCoord("k",""); + ret = CCoord("k",""); return; } else if ( typ == _J ) { - *ret = CCoord("j",""); + ret = CCoord("j",""); return; } else if ( typ == _I ) { - *ret = CCoord("i",""); + ret = CCoord("i",""); return; } @@ -411,30 +409,30 @@ void CRef::coord( CCoord *ret, uint k_in ) const POlc fc = P2C( f ); if ( fd ) { if ( typ == _X ) - *ret = fd->xco; + ret = fd->xco; else if ( typ == _Y ) - *ret = fd->yco; + ret = fd->yco; else if ( typ == _Z ) { if (num>=fd->ZCo.size()) throw( "coord: " + strg(num) + " undefined" ); - *ret = fd->ZCo[num]; + ret = fd->ZCo[num]; } else if ( typ == _NJ ) - *ret = CCoord("#spectra", ""); + ret = CCoord("#spectra", ""); else if ( typ == _NI ) - *ret = CCoord("#points", ""); + ret = CCoord("#points", ""); else throw( "Reference " + var_info() + " not allowed in data file" ); } else if ( fc ) { if ( typ == _FP ) - *ret = fc->PCo[num]; + ret = fc->PCo[num]; else if ( typ == _FM ) - *ret = CCoord("fqi_"+strg(num), ""); // fit quality indicator + ret = CCoord("fqi_"+strg(num), ""); // fit quality indicator else if ( typ == _Z ) - *ret = fc->ZCo[num]; + ret = fc->ZCo[num]; else if ( typ == _FC ) - *ret = CCoord(fc->expr,""); + ret = CCoord(fc->expr,""); else if ( typ == _NJ ) - *ret = CCoord("#spectra", ""); + ret = CCoord("#spectra", ""); else throw( "Reference " + var_info() + " not allowed in curve file" ); } else @@ -553,7 +551,7 @@ double tree_conv_eval( double tt, void *data ) vector<double> t1(1); t1[0] = mydata->t - tt; mydata->cvctx.fargs = &t1; - mydata->arg->tree_val( &(mydata->r), mydata->cvctx ); + mydata->arg->tree_val( mydata->r, mydata->cvctx ); return mydata->r.to_d(0) * mydata->sv->intpol( tt ); } @@ -563,7 +561,7 @@ double tree_conv_eval( double tt, void *data ) void CTree::tree_uival( uint *ret, const CContext& ctx ) const { CTOut val; - tree_val( &val, ctx ); + tree_val( val, ctx ); // since we have no integer data type, convert real by rounding *ret = (uint) ( val.d + 0.5); } @@ -571,287 +569,317 @@ void CTree::tree_uival( uint *ret, const CContext& ctx ) const //! Evaluate tree. Private. User calls pass through API implemented below. -void CTree::tree_val( CTOut *ret, const CContext& ctx ) const +void CTree::tree_val( CTOut& ret, const CContext& ctx ) const { - if ( typ == _OP ) { - CTOut r[maxarg]; - // evaluate arguments - for ( uint iarg=0; iarg<narg; ++iarg ) - arg[iarg]->tree_val( r+iarg, ctx ); - // scalar arguments ? - bool is_scalar = true; + switch ( typ ) { + case _OP: + tree_op( ret, ctx ); + break; + case _CONV: case _DIRAC: + tree_conv( ret, ctx ); + break; + case _VAL: + ret.set_d( val ); + break; + case _FARG: + if ( !(ctx.fargs) ) + throw string( "BUG: tree_val with *fargs=0" ); + ret.set_vd( *(ctx.fargs) ); + break; + case _REF: + ref->ref_val( ret, ctx ); + break; + case _FRF: + tree_frf( ret, ctx ); + break; + default: + throw string( "BUG: unexpected tree type" ); + } +} + + +//! A function of 1,2,.. arguments (including operators like +,-,.. ). + +void CTree::tree_op( CTOut& ret, const CContext& ctx ) const +{ + CTOut r[maxarg]; + // evaluate arguments + for ( uint iarg=0; iarg<narg; ++iarg ) + arg[iarg]->tree_val( r[iarg], ctx ); + // scalar arguments ? + bool is_scalar = true; + for ( uint iarg=0; iarg<narg; ++iarg ) { + if ( r[iarg].is_scalar() ) + continue; + if ( !r[iarg].is_vector() ) + throw string( "invalid data type in func arg" ); + is_scalar = false; + } + // size of vectorial arguments + int n=0; + if( !is_scalar ) { for ( uint iarg=0; iarg<narg; ++iarg ) { if ( r[iarg].is_scalar() ) continue; - if ( !r[iarg].is_vector() ) - throw string( "invalid data type in func arg" ); - is_scalar = false; + if ( n==0 ) + n = r[iarg].vd.size(); + else if ( r[iarg].vd.size() != n ) + throw string( "vector arguments have different size" ); } - // size of vectorial arguments - int n=0; - if( !is_scalar ) { - for ( uint iarg=0; iarg<narg; ++iarg ) { - if ( r[iarg].is_scalar() ) - continue; - if ( n==0 ) - n = r[iarg].vd.size(); - else if ( r[iarg].vd.size() != n ) - throw string( "vector arguments have different size" ); - } - ret->preset_vd( n ); + ret.preset_vd( n ); + if( ctx.want_error ) + ret.dvd = vector<double>( n, 0. ); + else + ret.dvd.clear(); + } + // now evaluate the function + if ( narg==1 ) { + if ( is_scalar ) if( ctx.want_error ) - ret->dvd = vector<double>( n, 0. ); + ret.set_d( (*(fun->f1))( r[0].d ) ); else - ret->dvd.clear(); + ret.set_d( (*(fun->f1))( r[0].d ) ); + else + for ( int i=0; i<n; ++i ) + ret.vd[i] = (*(fun->f1))( r[0].vd[i] ); + } else if ( narg==2 ) { + if ( r[0].is_scalar() && r[1].is_scalar() ) + ret.set_d( (*(fun->f2))( r[0].d, r[1].d ) ); + else if ( r[0].is_scalar() && r[1].is_vector() ) { + for ( int i=0; i<n; ++i ) + ret.vd[i] = (*(fun->f2))( r[0].d, r[1].vd[i] ); + } else if ( r[0].is_vector() && r[1].is_scalar() ) { + for ( int i=0; i<n; ++i ) + ret.vd[i] = (*(fun->f2))( r[0].vd[i], r[1].d ); + } else if ( r[0].is_vector() && r[1].is_vector() ) { + for ( int i=0; i<n; ++i ) + ret.vd[i] = (*(fun->f2))( r[0].vd[i], r[1].vd[i] ); } - // now evaluate the function - if ( narg==1 ) { - if ( is_scalar ) - if( ctx.want_error ) - ret->set_d( (*(fun->f1))( r[0].d ) ); - else - ret->set_d( (*(fun->f1))( r[0].d ) ); - else - for ( int i=0; i<n; ++i ) - ret->vd[i] = (*(fun->f1))( r[0].vd[i] ); - } else if ( narg==2 ) { - if ( r[0].is_scalar() && r[1].is_scalar() ) - ret->set_d( (*(fun->f2))( r[0].d, r[1].d ) ); - else if ( r[0].is_scalar() && r[1].is_vector() ) { - for ( int i=0; i<n; ++i ) - ret->vd[i] = (*(fun->f2))( r[0].d, r[1].vd[i] ); - } else if ( r[0].is_vector() && r[1].is_scalar() ) { - for ( int i=0; i<n; ++i ) - ret->vd[i] = (*(fun->f2))( r[0].vd[i], r[1].d ); - } else if ( r[0].is_vector() && r[1].is_vector() ) { - for ( int i=0; i<n; ++i ) - ret->vd[i] = (*(fun->f2))( r[0].vd[i], r[1].vd[i] ); - } - } else if ( narg==3 ) { - if ( is_scalar ) - ret->set_d( (*(fun->f3))( r[0].d, r[1].d, r[2].d ) ); - else { - for ( int i=0; i<n; ++i ) - ret->vd[i] = (*(fun->f3))( - r[0].to_d(i), r[1].to_d(i), r[2].to_d(i) ); - } + } else if ( narg==3 ) { + if ( is_scalar ) + ret.set_d( (*(fun->f3))( r[0].d, r[1].d, r[2].d ) ); + else { + for ( int i=0; i<n; ++i ) + ret.vd[i] = (*(fun->f3))( + r[0].to_d(i), r[1].to_d(i), r[2].to_d(i) ); } - } else if ( typ == _CONV || typ == _DIRAC ) { - // Return values are requested for n values of _FARG ( = t ): - if ( !(ctx.fargs) ) - throw string( "BUG: treeval(conv,dirac) with *fargs=0" ); - uint n = ctx.fargs->size(); - ret->preset_vd( n ); - ret->dvd.clear(); - // Resolution is given by context 'ctx': - uint kconv = setConvK( ctx.k ); - uint jconv = kconv == -1 ? -1 : setConvJ( ctx.k, ctx.j, kconv ); - double conv_norm; // normalization constant (integral of resolution) - double conv_step; // step in x/t, if equidistant - PSpec sv; - int nv; /* declaring this as unsigned lead to wrong wrapping */ - if( kconv!=-1 ){ - // Check whether return grid is equidistant - if( n>1 ){ - conv_step = ((*(ctx.fargs))[n-1]-(*(ctx.fargs))[0]) / (n-1); - if( conv_step<0 ) - conv_step = 0; - else { - for( int i=0; i<n-1; ++i ) { - if( fabs((*(ctx.fargs))[i+1]-(*(ctx.fargs))[i] - -conv_step)>1e-8*conv_step ){ - conv_step = 0; // not equidistant - break; - } + } +} + + +//! Convolution or Dirac function: conv(f, shift), dirac(shift). + +void CTree::tree_conv( CTOut& ret, const CContext& ctx ) const +{ + // Return values are requested for n values of _FARG ( = t ): + if ( !(ctx.fargs) ) + throw string( "BUG: treeval(conv,dirac) with *fargs=0" ); + uint n = ctx.fargs->size(); + ret.preset_vd( n ); + ret.dvd.clear(); + // Resolution is given by context 'ctx': + uint kconv = setConvK( ctx.k ); + uint jconv = kconv == -1 ? -1 : setConvJ( ctx.k, ctx.j, kconv ); + double conv_norm; // normalization constant (integral of resolution) + double conv_step; // step in x/t, if equidistant + PSpec sv; + int nv; /* declaring this as unsigned lead to wrong wrapping */ + if( kconv!=-1 ){ + // Check whether return grid is equidistant + if( n>1 ){ + conv_step = ((*(ctx.fargs))[n-1]-(*(ctx.fargs))[0]) / (n-1); + if( conv_step<0 ) + conv_step = 0; + else { + for( int i=0; i<n-1; ++i ) { + if( fabs((*(ctx.fargs))[i+1]-(*(ctx.fargs))[i] + -conv_step)>1e-8*conv_step ){ + conv_step = 0; // not equidistant + break; } } - } else - conv_step = 0; - // Preset fv,sv,nv. - POld fv = P2D( NOlm::MOM[kconv] ); - if ( !fv ) - throw "Resolution " + strg(kconv) + "is not a data file"; - sv = fv->VS(jconv); - nv = sv->size(); - if ( nv < 2 ) - throw "Resolution " + strg(kconv) + ", spectrum " + - strg(jconv) + ", has only " + strg(nv) + " points"; - // Calculate normalization integral. - // At this occasion, assert that x is ordered, - conv_norm = 0; - double dx; - // special treatment for first and last step: - dx = sv->x[1] - sv->x[0]; - if ( dx <= 0 ) - throw "Resolution " + strg(kconv) + ", spectrum " + - strg(jconv) + ", not ordered in x"; - conv_norm += sv->y[0] * dx; - dx = sv->x[nv-1] - sv->x[nv-2]; + } + } else + conv_step = 0; + // Preset fv,sv,nv. + POld fv = P2D( NOlm::MOM[kconv] ); + if ( !fv ) + throw "Resolution " + strg(kconv) + "is not a data file"; + sv = fv->VS(jconv); + nv = sv->size(); + if ( nv < 2 ) + throw "Resolution " + strg(kconv) + ", spectrum " + + strg(jconv) + ", has only " + strg(nv) + " points"; + // Calculate normalization integral. + // At this occasion, assert that x is ordered, + conv_norm = 0; + double dx; + // special treatment for first and last step: + dx = sv->x[1] - sv->x[0]; + if ( dx <= 0 ) + throw "Resolution " + strg(kconv) + ", spectrum " + + strg(jconv) + ", not ordered in x"; + conv_norm += sv->y[0] * dx; + dx = sv->x[nv-1] - sv->x[nv-2]; + if ( dx <= 0 ) + throw "Resolution " + strg(kconv) + ", spectrum " + + strg(jconv) + ", not ordered in x"; + conv_norm += sv->y[nv-1] * dx; + // the other steps: + for( int i=1; i<nv-1; ++i ) { + dx = ( sv->x[i+1] - sv->x[i-1] ) / 2; if ( dx <= 0 ) throw "Resolution " + strg(kconv) + ", spectrum " + strg(jconv) + ", not ordered in x"; - conv_norm += sv->y[nv-1] * dx; - // the other steps: - for( int i=1; i<nv-1; ++i ) { - dx = ( sv->x[i+1] - sv->x[i-1] ) / 2; - if ( dx <= 0 ) - throw "Resolution " + strg(kconv) + ", spectrum " + - strg(jconv) + ", not ordered in x"; - conv_norm += sv->y[i] * dx; - } - // check result: - if ( conv_norm <= 0 ) - throw "Resolution " + strg(kconv) + ", spectrum " + - strg(jconv) + ", has non-positive norm " + strg(conv_norm); - // Check whether x is equidistant - if( conv_step ){ - for( int i=0; i<nv-1; ++i ) { - if( fabs(sv->x[i+1]-sv->x[i]-conv_step)>1e-8*conv_step ){ - conv_step = 0; // not equidistant - break; - } + conv_norm += sv->y[i] * dx; + } + // check result: + if ( conv_norm <= 0 ) + throw "Resolution " + strg(kconv) + ", spectrum " + + strg(jconv) + ", has non-positive norm " + strg(conv_norm); + // Check whether x is equidistant + if( conv_step ){ + for( int i=0; i<nv-1; ++i ) { + if( fabs(sv->x[i+1]-sv->x[i]-conv_step)>1e-8*conv_step ){ + conv_step = 0; // not equidistant + break; } } - if( !conv_step && !allow_slow_conv ) - throw string( - "not equidistant and slow convolution not allowed" ); } - // The actual computation is rather different for _CONV and _DIRAC: - if ( typ == _CONV ) { - if( narg!=2 ) - throw string( "BUG: convolution requires 2 args" ); + if( !conv_step && !allow_slow_conv ) + throw string( + "not equidistant and slow convolution not allowed" ); + } + // The actual computation is rather different for _CONV and _DIRAC: + if ( typ == _CONV ) { + if( narg!=2 ) + throw string( "BUG: convolution requires 2 args" ); + CTOut r; + arg[1]->tree_val( r, ctx ); + if ( !r.is_scalar() ) + throw string( "2nd arg of conv must be scalar shift" ); + double shift = r.d; + if ( kconv==-1 ) { + // Copy convolutand (= unconvoluted theory). CTOut r; - arg[1]->tree_val( &r, ctx ); - if ( !r.is_scalar() ) - throw string( "2nd arg of conv must be scalar shift" ); - double shift = r.d; - if ( kconv==-1 ) { - // Copy convolutand (= unconvoluted theory). - CTOut r; - // unconvoluted theory given by arg[0]: - arg[0]->tree_val( &r, ctx ); - for ( int i=0; i<n; ++i ) - ret->vd[i] = r.to_d(i); - } else if ( NRead::iofmac("\\cv_mode")==-1 ) { - CTOut r; - CContext cvctx(ctx); - vector<double> tt; - cvctx.fargs = &tt; - // Convolute theory with resolution. - if( conv_step ){ - // Accelerated version with equidistant grids - int ntt = n + nv - 1; - tt.resize(ntt); - for ( int ii=0; ii<ntt; ++ii ) // ii=(nv-1)+i-iv - tt[ii] = (*(ctx.fargs))[0] - sv->x[0] - shift + - (ii-(nv-1))*conv_step; - arg[0]->tree_val( &r, cvctx ); - for ( int i=0; i<n; ++i ){ - ret->vd[i] = 0; - for ( int iv=0; iv<nv; ++iv ) - ret->vd[i] += r.to_d(nv-1+i-iv) * sv->y[iv]; - ret->vd[i] *= conv_step / conv_norm; - } - } else { - // Simplest version: non-equidistant x_out and x_res. - for ( int i=0; i<n; ++i ) - ret->vd[i] = 0; - tt.resize(n); - for ( int iv=0; iv<nv; ++iv ) { - double dx; - 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.fargs))[i] - sv->x[iv] - shift; - arg[0]->tree_val( &r, cvctx ); - for ( int i=0; i<n; ++i ) - ret->vd[i] += r.to_d(i) * sv->y[iv] * - dx / conv_norm; - } + // unconvoluted theory given by arg[0]: + arg[0]->tree_val( r, ctx ); + for ( int i=0; i<n; ++i ) + ret.vd[i] = r.to_d(i); + } else if ( NRead::iofmac("\\cv_mode")==-1 ) { + CTOut r; + CContext cvctx(ctx); + vector<double> tt; + cvctx.fargs = &tt; + // Convolute theory with resolution. + if( conv_step ){ + // Accelerated version with equidistant grids + int ntt = n + nv - 1; + tt.resize(ntt); + for ( int ii=0; ii<ntt; ++ii ) // ii=(nv-1)+i-iv + tt[ii] = (*(ctx.fargs))[0] - sv->x[0] - shift + + (ii-(nv-1))*conv_step; + arg[0]->tree_val( r, cvctx ); + for ( int i=0; i<n; ++i ){ + ret.vd[i] = 0; + for ( int iv=0; iv<nv; ++iv ) + ret.vd[i] += r.to_d(nv-1+i-iv) * sv->y[iv]; + ret.vd[i] *= conv_step / conv_norm; } } else { - // Convolute theory with resolution. - // Generic integration. - ConvDatTyp conv_data; - conv_data.sv = sv; - conv_data.nv = nv; - conv_data.arg = arg[0]; - conv_data.cvctx = ctx; - for ( int i=0; i<n; ++i ) { - conv_data.t = (*(ctx.fargs))[i] - shift; - ret->vd[i] = - mystd::Integrate( &tree_conv_eval, - (void *) &conv_data, - sv->x[0], sv->x[nv-1], - NRead::iofmac( "\\cv_mode" ), - NRead::dofmac( "\\cv_epsabs" ), - NRead::dofmac( "\\cv_epsrel" ) ) / - conv_norm; + // Simplest version: non-equidistant x_out and x_res. + for ( int i=0; i<n; ++i ) + ret.vd[i] = 0; + tt.resize(n); + for ( int iv=0; iv<nv; ++iv ) { + double dx; + 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.fargs))[i] - sv->x[iv] - shift; + arg[0]->tree_val( r, cvctx ); + for ( int i=0; i<n; ++i ) + ret.vd[i] += r.to_d(i) * sv->y[iv] * + dx / conv_norm; } } - - } else if ( typ == _DIRAC ) { - CTOut r; - // center of delta function given by arg[0]: - arg[0]->tree_val( &r, ctx ); - if ( !r.is_scalar() ) - throw string( "dirac function requires scalar argument" ); - if ( kconv==-1 ) { - // Naive representation of delta function. - for ( int i=0; i<n; ++i ) - ret->vd[i] = fabs((*(ctx.fargs))[i]-r.to_d(i))<1e-2 ? - 1e2 : 0; - } else { - // Delta function copies resolution. - vector<double> tt(n), yy(n); - // shift in t - for ( int i=0; i<n; ++i ) - tt[i] = (*(ctx.fargs))[i]-r.d; - // interpolation - sv->intpol( tt, yy ); - // normalization - for ( int i=0; i<n; ++i ) - ret->vd[i] = yy[i] / conv_norm; + } else { + // Convolute theory with resolution. + // Generic integration. + ConvDatTyp conv_data; + conv_data.sv = sv; + conv_data.nv = nv; + conv_data.arg = arg[0]; + conv_data.cvctx = ctx; + for ( int i=0; i<n; ++i ) { + conv_data.t = (*(ctx.fargs))[i] - shift; + ret.vd[i] = + mystd::Integrate( &tree_conv_eval, + (void *) &conv_data, + sv->x[0], sv->x[nv-1], + NRead::iofmac( "\\cv_mode" ), + NRead::dofmac( "\\cv_epsabs" ), + NRead::dofmac( "\\cv_epsrel" ) ) / + conv_norm; } - } else - throw string( "FATAL: unexpected typ" ); - } else if ( typ == _VAL ) { - ret->set_d( val ); - } else if ( typ == _FARG ) { - if ( !(ctx.fargs) ) - throw string( "BUG: tree_val with *fargs=0" ); - ret->set_vd( *(ctx.fargs) ); - } else if ( typ == _REF ) { - ref->ref_val( ret, ctx ); - } else if ( typ == _FRF ) { - // evaluate function argument: - CTOut rarg; - arg[0]->tree_val( &rarg, ctx ); - vector<double> vt; - if ( rarg.is_scalar() ) { - vt.resize(1); - vt[0] = rarg.d; + } + + } else if ( typ == _DIRAC ) { + CTOut r; + // center of delta function given by arg[0]: + arg[0]->tree_val( r, ctx ); + if ( !r.is_scalar() ) + throw string( "dirac function requires scalar argument" ); + if ( kconv==-1 ) { + // Naive representation of delta function. + for ( int i=0; i<n; ++i ) + ret.vd[i] = fabs((*(ctx.fargs))[i]-r.to_d(i))<1e-2 ? + 1e2 : 0; } else { - vt.resize(rarg.vd.size()); - vt = rarg.vd; + // Delta function copies resolution. + vector<double> tt(n), yy(n); + // shift in t + for ( int i=0; i<n; ++i ) + tt[i] = (*(ctx.fargs))[i]-r.d; + // interpolation + sv->intpol( tt, yy ); + // normalization + for ( int i=0; i<n; ++i ) + ret.vd[i] = yy[i] / conv_norm; } - // evaluate function: - CContext cu_ctx; - uint k = ref->get_k( ctx ); - uint j = ref->get_j( ctx ); - cu_ctx.request_vector_of_farg( k, j, &vt ); - POlc fc = P2C( NOlm::MOM[k] ); - fc->T->tree_val( ret, cu_ctx ); - if ( rarg.is_scalar() ) - ret->set_d( ret->vd[0] ); - } else if ( typ == _NOTREE ) - throw string( "BUG: tree_val(tree_typ=NOTREE)" ); - else - throw string( "BUG: tree_val(tree_typ=UNDEF)" ); + } +} + + +//! A curve evaluation: fc[k,j](arg). + +void CTree::tree_frf( CTOut& ret, const CContext& ctx ) const +{ + // evaluate and pack function argument: + CTOut rarg; + arg[0]->tree_val( rarg, ctx ); + vector<double> vt; + if ( rarg.is_scalar() ) { + vt.resize(1); + vt[0] = rarg.d; + } else { + vt.resize(rarg.vd.size()); + vt = rarg.vd; + } + // evaluate function: + CContext cu_ctx; + uint k = ref->get_k( ctx ); + uint j = ref->get_j( ctx ); + cu_ctx.request_vector_of_farg( k, j, &vt ); + POlc fc = P2C( NOlm::MOM[k] ); + fc->T->tree_val( ret, cu_ctx ); + // transcribe result: + if ( rarg.is_scalar() ) + ret.set_d( ret.vd[0] ); } @@ -864,7 +892,7 @@ void CTree::tree_point_val( ctx.request_scalar( k, j, i ); ctx.want_error = (bool)dret; CTOut val; - tree_val( &val, ctx ); + tree_val( val, ctx ); if ( !val.is_scalar() ) throw "tree_point_val got " + val.info(); *ret = val.d; @@ -880,7 +908,7 @@ void CTree::tree_vec_val( CContext ctx; ctx.request_vector_of_indx( k, j, ret->size() ); ctx.want_error = (bool)dret; - tree_val( &val, ctx ); + tree_val( val, ctx ); if( dret && !ctx.want_error ) dret->clear(); if ( val.is_vector() ){ @@ -900,7 +928,7 @@ void CTree::tree_vec_val( //! Evaluate a curve, vectorial version. Used in fitting and in plotting. void CTree::tree_curve_val_vec( - vector<double> *ret, // output: the values y(t) + vector<double>* ret, // output: the values y(t) const vector<double>& fargs, // input: the function arguments i uint k, uint j // input: used to find the parameters ) const @@ -911,13 +939,13 @@ void CTree::tree_curve_val_vec( CContext ctx; if ( !has_farg ) { // curve does not depend on t ctx.request_scalar( k, j ); - tree_val( &val, ctx ); + tree_val( val, ctx ); if ( !val.is_scalar() ) throw "tree_curve_val (sca) got " + val.info(); (*ret)[0] = val.d; } else { ctx.request_vector_of_farg( k, j, &fargs ); - tree_val( &val, ctx ); + tree_val( val, ctx ); if ( !val.is_vector() ) throw "tree_curve_val (vec) got " + val.info(); *ret = val.vd; @@ -982,30 +1010,30 @@ uint CTree::setConvJ( uint k, uint j, uint kconv ) //! Compose coordinate names and units according to the tree. -void CTree::coord( CCoord *ret, uint k ) const +void CTree::coord( CCoord& ret, uint k ) const { CCoord r[maxarg]; if ( typ == _OP ) { for ( uint iarg=0; iarg<narg; ++iarg ) - arg[iarg]->coord( &(r[iarg]), k ); + arg[iarg]->coord( r[iarg], k ); if ( narg==1 ) - *ret = fun->coord( r+0); + ret = fun->coord( r+0); else if ( narg==2 ) - *ret = fun->coord( r+0, r+1 ); + ret = fun->coord( r+0, r+1 ); else if ( narg==3 ) - *ret = fun->coord( r+0, r+1, r+2 ); + ret = fun->coord( r+0, r+1, r+2 ); } else if ( typ == _CONV ) arg[0]->coord( ret, k ); else if ( typ == _DIRAC ) - *ret = CCoord("dirac", ""); + ret = CCoord("dirac", ""); else if ( typ == _VAL ) - *ret = CCoord(strg(val), ""); + ret = CCoord(strg(val), ""); else if ( typ == _REF ) ref->coord(ret,k); else if ( typ == _FRF ) { // ref->coord(ret,k); - *ret = CCoord( "f", "" ); // primitiver gehts nicht + ret = CCoord( "f", "" ); // primitiver gehts nicht } else throw string( "BUG: tree::coord(tree_typ=UNDEF)" ); } diff --git a/pub/src/expr.h b/pub/src/expr.h index 2d941ceb..c092b808 100644 --- a/pub/src/expr.h +++ b/pub/src/expr.h @@ -107,8 +107,8 @@ class CRef: public CVariable { uint get_k( const CContext& ctx ) const; uint get_j( const CContext& ctx ) const; - void ref_val( CTOut* ret, const CContext& ctx ) const; - void coord( CCoord *ret, uint k ) const; + void ref_val( CTOut& ret, const CContext& ctx ) const; + void coord( CCoord& ret, uint k ) const; }; @@ -153,7 +153,10 @@ class CTree { uint npar() const; - void tree_val( CTOut *ret, const CContext& ctx ) const; + void tree_val ( CTOut& ret, const CContext& ctx ) const; + void tree_op ( CTOut& ret, const CContext& ctx ) const; + void tree_conv ( CTOut& ret, const CContext& ctx ) const; + void tree_frf ( CTOut& ret, const CContext& ctx ) const; void tree_uival( uint *ret, const CContext& ctx ) const; void tree_point_val( double *ret, double *dret, @@ -161,13 +164,15 @@ class CTree { void tree_vec_val( vector<double> *ret, vector<double> *dret, uint k=(uint)-1, uint j=(uint)-1 ) const; - void tree_curve_val_vec( vector<double> *ret, const vector<double>& farg, - uint k, uint j ) const; + void tree_curve_val_vec( + vector<double> *ret, const vector<double>& farg, + uint k, uint j ) const; double tree_curve_val_sca( double farg, uint k, uint j ) const; - void coord( CCoord *ret, uint k=(uint)-1 ) const; + void coord( CCoord& ret, uint k=(uint)-1 ) const; string tree_info() const; private: void npar_exec( uint *np ) const; }; + diff --git a/pub/src/opr.cpp b/pub/src/opr.cpp index 614b4067..5d706d2d 100644 --- a/pub/src/opr.cpp +++ b/pub/src/opr.cpp @@ -174,7 +174,7 @@ void NOperate::Pointwise( string llabel ) throw string( "no pointwise operation on curve" ); CCoord co; - T->coord( &co, k ); + T->coord( co, k ); if ( lref.typ==CVariable::_X ) { fout->xco = co; } else if ( lref.typ==CVariable::_Y ) { @@ -264,7 +264,7 @@ void NOperate::Integral(void) fout->ZCo.pop_back(); fout->xco = fin->ZCo.back(); - T->coord( &(fout->yco), k ); + T->coord( fout->yco, k ); PSpec sout( new CSpec ); sout->z = fin->V[0]->z; -- GitLab