diff --git a/src/curve.cpp b/src/curve.cpp index ee3a1de688c3586c5233bbdb2980f8366c657e4a..cf256604dc57c4fc3027070347be6306df79e644 100644 --- a/src/curve.cpp +++ b/src/curve.cpp @@ -13,6 +13,7 @@ #include <algorithm> #include "olm.h" // includes also curve.h +#include "readln.h" #include "asi.h" #include "../../lmfit/lmmin.h" #include "xax.h" @@ -465,8 +466,9 @@ namespace NCurveFile double NumericIntegral( const COlc *fc, const CCurve *c, const int k, const int j ); // parameters for numeric integration: - double numint_bound_low=0, numint_bound_hig=0; + string numint_bound_low="!", numint_bound_hig="!"; // tuning parameters: + int numint_mode=4; double numint_epsabs=1e-10, numint_epsrel=1e-10; }; @@ -476,44 +478,56 @@ namespace NCurveFile void NCurveFile::SetIntTuningPars( string which ) { if ( which=="?" ) - printf( "Numeric integration setup:\n epsabs=%g\n epsrel=%g\n", - numint_epsabs, numint_epsrel ); + printf( "Numeric integration setup:\n epsabs=%g\n epsrel=%g\n" + " mode: %d\n", + numint_epsabs, numint_epsrel, numint_mode ); else if ( which=="a" ) numint_epsabs = iask( "Espilon abs", numint_epsabs ); else if ( which=="r" ) numint_epsrel = iask( "Epsilon rel", numint_epsrel ); + else if ( which=="m" ) + cout << "Numeric integration modes (ignored for infinite intervals):\n" + " 0: non-adaptive Gauss-Kronod-87 for very smooth functions\n" + " 1: adaptive Gauss-Kronod-61 for smooth functions\n" + " ...\n" + " 6: adaptive Gauss-Kronod-15 for not so smooth functions\n" + " 7: adaptive for functions with singularities\n"; + numint_mode = iask( "Option", numint_mode ); } //! Outer wrapper: dialog, loop over files and parameters void NCurveFile::Integrate(void) { - cout << "Generate integral file:\n" - " <list of numbers> extract curve parameters\n" - " * extract all curve parameters\n" - " q0 | q1 | q2 extract fit metrics\n" - " i numeric integral\n"; + if( NRead::empty() ) + cout << "Generate integral file:\n" + " <list of numbers> extract curve parameters\n" + " * extract all curve parameters\n" + " q0 | q1 | q2 extract fit metrics\n" + " i numeric integral\n"; static string mode = "*"; mode = wask( "Option", mode ); if ( mode==" " ) return; else if ( mode=="i" ){ - numint_bound_low = dask( "integrate from", numint_bound_low ); - numint_bound_hig = dask( "integrate to", numint_bound_hig ); + if( NRead::empty() ) + cout << "integration bounds: use ! for +/- infinity\n"; + numint_bound_low = wask( "Integrate from", numint_bound_low ); + numint_bound_hig = wask( "Integrate to", numint_bound_hig ); } NOlm::IterateC fiter; const COlc* fin; while( (fin=fiter()) ){ - if( isdigit(mode[0]) || mode=="*" ){ + if( isdigit(mode[0]) || mode=="*" ){ // extract parameter(s) // decode list of parameter numbers CList parsel( mode, CLimits( 0, fin->nPar()-1 ) ); for( uint iv=0; iv<parsel.n(); ++iv ){ int iP = parsel.V[iv]; IntegrateFile( fin, fiter.SelNo(), "p", iP, "p"+strg(iP) ); } - } else + } else // other integrals IntegrateFile( fin, fiter.SelNo(), mode, -1, mode ); } } @@ -559,6 +573,9 @@ void NCurveFile::IntegrateFile( const COlc *fin, const int k, val = fin->VC[j].Quality[2]; else if ( mode=="i" ) val = NumericIntegral( fin, &(fin->VC[j]), k, j ); + else + throw string("invalid mode"); + // print out ? if (!savable) { cout << fin->name << ": " << name << " = " << val << "\n"; @@ -601,9 +618,51 @@ double NCurveFile::NumericIntegral( const COlc *fc, const CCurve *c, F.params = &data; gsl_integration_workspace *work = gsl_integration_workspace_alloc( nwork ); double val, err; - - gsl_integration_qag( &F, numint_bound_low, numint_bound_hig, - numint_epsabs, numint_epsrel, nwork, - GSL_INTEG_GAUSS31, work, &val, &err ); - cout << "val="<<val<<", err="<<err<<"\n"; + int rule; + size_t neval; + + double low, hig; + + if( numint_bound_low!="!" && !mystd::any2dbl( numint_bound_low, &low ) ) + throw string( "invalid lower integration bound" ); + if( numint_bound_hig!="!" && !mystd::any2dbl( numint_bound_hig, &hig ) ) + throw string( "invalid upper integration bound" ); + + if ( numint_bound_low=="!" && numint_bound_hig=="!" ) + gsl_integration_qagi( &F, + numint_epsabs, numint_epsrel, nwork, + work, &val, &err ); + else if ( numint_bound_low=="!" ) + gsl_integration_qagil( &F, hig, + numint_epsabs, numint_epsrel, nwork, + work, &val, &err ); + else if ( numint_bound_hig=="!" ) + gsl_integration_qagiu( &F, low, + numint_epsabs, numint_epsrel, nwork, + work, &val, &err ); + else if ( numint_mode==0 ) + gsl_integration_qng( &F, low, hig, + numint_epsabs, numint_epsrel, + &val, &err, &neval ); + else if ( numint_mode>0 && numint_mode<7 ){ + switch( numint_mode ){ + case 1: rule = GSL_INTEG_GAUSS61; break; + case 2: rule = GSL_INTEG_GAUSS51; break; + case 3: rule = GSL_INTEG_GAUSS41; break; + case 4: rule = GSL_INTEG_GAUSS31; break; + case 5: rule = GSL_INTEG_GAUSS21; break; + case 6: rule = GSL_INTEG_GAUSS15; break; + } + gsl_integration_qag( &F, low, hig, + numint_epsabs, numint_epsrel, nwork, + rule, work, &val, &err ); + } + else if ( numint_mode==7 ) + gsl_integration_qags( &F, low, hig, + numint_epsabs, numint_epsrel, nwork, + work, &val, &err ); + else + throw string( "invalid case in NumericIntegral" ); + + return val; } diff --git a/src/expr.cpp b/src/expr.cpp index abcdbc58f18fa6c29c9e218575922b97905b8eaa..3289d58e1b779fc007c8553ea2d3e1dca8c38baf 100644 --- a/src/expr.cpp +++ b/src/expr.cpp @@ -763,7 +763,7 @@ void NCalc::Calculator() // if there is an expression on the stack, then // evaluate just this single expression; // otherwise start a loop and request input - bool expr_on_stack = NRead::nonempty(); + bool expr_on_stack = !NRead::empty(); while (1) { if( expr_on_stack ){ diff --git a/src/func.cpp b/src/func.cpp index 494ee6d939e93e774bc18e74b4f4d1090dc06c77..949d7b7924c099bcc531b84527d3c090682c10b8 100644 --- a/src/func.cpp +++ b/src/func.cpp @@ -106,6 +106,8 @@ double func_min (double v, double a) { return v<a ? v : a; } double func_max (double v, double a) { return v>a ? v : a; } double func_gauss (double x, double s) { return s==0 ? 0 : exp(-x*x/(2*s*s))/sqrt(twopi)/s; } +double func_cauchy (double x, double s) { return s==0 ? 0 : + 2*s/twopi/(x*x+s*s); } double func_ran (double v, double a) { // a random number between v and a : @@ -207,6 +209,7 @@ void NFunctions::Register(void) { fmap.insert(make_pair(string("min"), CFunc("min", func_min))); fmap.insert(make_pair(string("max"), CFunc("max", func_max))); fmap.insert(make_pair(string("gauss"),CFunc("gauss", func_gauss))); + fmap.insert(make_pair(string("cauchy"),CFunc("cauchy", func_cauchy))); fmap.insert(make_pair(string("ran"), CFunc("ran", func_ran))); diff --git a/src/func.h b/src/func.h index 369dcea62deb36d5235dca69310fec71737b9679..eddf3de28085106d64b5cf57a34cceeade1e1150 100644 --- a/src/func.h +++ b/src/func.h @@ -108,9 +108,10 @@ extern double func_in( double, vector<double> ); extern double func_min(double,double); extern double func_max(double,double); extern double func_gauss(double,double); +extern double func_cauchy(double,double); extern double func_ran(double,double); -extern double func_condass(double,double,double); +extern double func_condass(double,double,double); // conditional assignement extern double func_q4w(double,double,double); diff --git a/src/readln.cpp b/src/readln.cpp index e5741546733cbae9360c5302b06ca136f5d9bbd1..1364596677f5db71776ddf4cf22d6e227543b9af 100644 --- a/src/readln.cpp +++ b/src/readln.cpp @@ -48,7 +48,7 @@ namespace NRead { int iofmac( const string in, int *out ); int dofmac( const string in, double *out ); int wofmac( const string in, string *out ); - bool nonempty(); + bool empty(); // internals, used only in this file: bool initialized=0; @@ -170,9 +170,9 @@ int NRead::wofmac( const string in, string *out ) //! Anything left on input stack? -bool NRead::nonempty() +bool NRead::empty() { - return halfline!=""; + return halfline==""; } diff --git a/src/readln.h b/src/readln.h index e3c3166c6c167af56d2b33d345f2de360c1e026e..5408e4fc47def3061a6627b4e928a9a9f41bbca4 100644 --- a/src/readln.h +++ b/src/readln.h @@ -13,5 +13,5 @@ namespace NRead { int iofmac(const string in, int *out); int dofmac(const string in, double *out); int wofmac(const string in, string *out); - bool nonempty( void ); + bool empty( void ); };