diff --git a/brent.cpp b/brent.cpp index 0852777..fc3bb24 100644 --- a/brent.cpp +++ b/brent.cpp @@ -7,10 +7,12 @@ using namespace std; # include "brent.hpp" +namespace brent{ + //****************************************************************************80 double glomin ( double a, double b, double c, double m, double e, double t, - double f ( double x ), double &x ) + func_base& f, double &x ) //****************************************************************************80 // @@ -59,8 +61,9 @@ double glomin ( double a, double b, double c, double m, double e, double t, // // Input, double T, a positive error tolerance. // -// Input, double F ( double x ), the name of a user-supplied -// function whose global minimum is being sought. +// Input, func_base& F, a user-supplied c++ functor whose +// global minimum is being sought. The input and output +// of F() are of type double. // // Output, double &X, the estimated value of the abscissa // for which F attains its global minimum value in [A,B]. @@ -290,7 +293,7 @@ double glomin ( double a, double b, double c, double m, double e, double t, } //****************************************************************************80 -double local_min ( double a, double b, double t, double f ( double x ), +double local_min ( double a, double b, double t, func_base& f, double &x ) //****************************************************************************80 @@ -346,8 +349,9 @@ double local_min ( double a, double b, double t, double f ( double x ), // // Input, double T, a positive absolute error tolerance. // -// Input, double F ( double x ), the name of a user-supplied -// function whose local minimum is being sought. +// Input, func_base& F, a user-supplied c++ functor whose +// local minimum is being sought. The input and output +// of F() are of type double. // // Output, double &X, the estimated value of an abscissa // for which F attains a local minimum value in [A,B]. @@ -1043,7 +1047,7 @@ void timestamp ( ) } //****************************************************************************80 -double zero ( double a, double b, double t, double f ( double x ) ) +double zero ( double a, double b, double t, func_base& f ) //****************************************************************************80 // @@ -1088,8 +1092,9 @@ double zero ( double a, double b, double t, double f ( double x ) ) // // Input, double T, a positive error tolerance. // -// Input, double F ( double X ), the name of a user-supplied function -// which evaluates the function whose zero is being sought. +// Input, func_base& F, the name of a user-supplied c++ functor +// whose zero is being sought. The input and output +// of F() are of type double. // // Output, double ZERO, the estimated value of a zero of // the function F. @@ -1445,3 +1450,62 @@ void zero_rc ( double a, double b, double t, double &arg, int &status, return; } + +// ====================================================================== +// === Simple wrapper functions +// === for convenience and/or compatibility. +// +// === The three functions are the same as above, +// === except that they take a plain function F +// === instead of a c++ functor. In all cases, the +// === input and output of F() are of type double. + +typedef double DoubleOfDouble (double); + +class func_wrapper : public func_base { + DoubleOfDouble* func; +public: + func_wrapper(DoubleOfDouble* f) { + func = f; + } + virtual double operator() (double x){ + return func(x); + } +}; + +//****************************************************************************80 + +double glomin ( double a, double b, double c, double m, double e, + double t, double f ( double x ), double &x ){ + func_wrapper foo(f); + return glomin(a, b, c, m, e, t, foo, x); +} + +//****************************************************************************80 + +double local_min ( double a, double b, double t, double f ( double x ), + double &x ){ + func_wrapper foo(f); + return local_min(a, b, t, foo, x); +} + +//****************************************************************************80 + +double zero ( double a, double b, double t, double f ( double x ) ){ + func_wrapper foo(f); + return zero(a, b, t, foo); +} + +// ====================================================================== +// Generally useful functor to evaluate a polynomial. +// For details, see class definition in brent.hpp + +double poly::operator()(double x){ + double rslt(1); + for (int ii = coeff.size()-1; ii >= 0; ii--){ + rslt *= x; + rslt += coeff[ii]; + } +} + +} // end namespace brent diff --git a/brent.hpp b/brent.hpp index aa00a88..5f2f219 100644 --- a/brent.hpp +++ b/brent.hpp @@ -1,6 +1,25 @@ +#include +namespace brent { + +class func_base{ +public: + virtual double operator() (double) = 0; +}; + +class poly : public brent::func_base { +public: + std::vector coeff; + virtual double operator() (double x); +// constructors: + poly(const std::vector& v) + : coeff(v) {} + poly(const double* c, size_t degree) + : coeff(std::vector(c, c+degree)) {} +}; + double glomin ( double a, double b, double c, double m, double e, double t, - double f ( double x ), double &x ); -double local_min ( double a, double b, double t, double f ( double x ), + func_base& f, double &x ); +double local_min ( double a, double b, double t, func_base& f, double &x ); double local_min_rc ( double &a, double &b, int &status, double value ); double r8_abs ( double x ); @@ -8,6 +27,16 @@ double r8_epsilon ( ); double r8_max ( double x, double y ); double r8_sign ( double x ); void timestamp ( ); -double zero ( double a, double b, double t, double f ( double x ) ); +double zero ( double a, double b, double t, func_base& f ); void zero_rc ( double a, double b, double t, double &arg, int &status, double value ); + +// === simple wrapper functions +// === for convenience and/or compatibility +double glomin ( double a, double b, double c, double m, double e, double t, + double f ( double x ), double &x ); +double local_min ( double a, double b, double t, double f ( double x ), + double &x ); +double zero ( double a, double b, double t, double f ( double x ) ); + +} diff --git a/brent_prb.cpp b/brent_prb.cpp index e67bf64..e5d1ca3 100644 --- a/brent_prb.cpp +++ b/brent_prb.cpp @@ -4,10 +4,10 @@ # include # include # include +# include "brent.hpp" using namespace std; - -# include "brent.hpp" +using namespace brent; int main ( ); @@ -21,7 +21,8 @@ void test_zero_one ( double a, double b, double t, double f ( double x ), string title ); void test_zero_rc_one ( double a, double b, double t, double f ( double x ), string title ); -void test_local_min_one ( double a, double b, double t, double f ( double x ), +template +void test_local_min_one ( double a, double b, double t, T f, string title ); void test_local_min_rc_one ( double a, double b, double t, double f ( double x ), string title ); @@ -277,7 +278,12 @@ void test_local_min_all ( ) a = -2.0; b = 2.0; - test_local_min_one ( a, b, t, g_03, +// coefficients in ascending order, starting with scalar term: + const int degree(4); + double coefflist[degree] = {3, 1, 2, 0}; + poly quartic(coefflist, degree); + + test_local_min_one ( a, b, t, quartic, "g_03(x) = x^4 + 2x^2 + x + 3" ); a = 0.0001; @@ -609,7 +615,8 @@ void test_zero_rc_one ( double a, double b, double t, double f ( double x ), } //****************************************************************************80 -void test_local_min_one ( double a, double b, double t, double f ( double x ), +template +void test_local_min_one ( double a, double b, double t, T f, string title ) //****************************************************************************80