Index: trunk/tests/test_ContOrthoPoly1D.cc =================================================================== --- trunk/tests/test_ContOrthoPoly1D.cc (revision 864) +++ trunk/tests/test_ContOrthoPoly1D.cc (revision 865) @@ -1,406 +1,406 @@ #include "UnitTest++.h" #include "test_utils.hh" #include "npstat/nm/ContOrthoPoly1D.hh" #include "npstat/nm/ClassicalOrthoPolys1D.hh" #include "npstat/nm/FejerQuadrature.hh" #include "npstat/nm/StorablePolySeries1D.hh" #include "npstat/rng/MersenneTwister.hh" #include "npstat/stat/Distributions1D.hh" using namespace npstat; using namespace std; inline static int kdelta(const unsigned i, const unsigned j) { return i == j ? 1 : 0; } namespace { TEST(ContOrthoPoly1D_orthonormalization) { const double eps = 1.0e-15; const OrthoPolyMethod method[] = {OPOLY_STIELTJES, OPOLY_LANCZOS}; const unsigned nMethods = sizeof(method)/sizeof(method[0]); const unsigned npoints = 64; const unsigned maxdeg = 10; const unsigned ntries = 10; std::vector points(2U*npoints); std::vector measure; measure.reserve(npoints); std::vector coeffs(maxdeg + 1); MersenneTwister rng; for (unsigned imeth=0; imeth(kdelta(i, j)), d, eps); } measure.clear(); for (unsigned i=0; i(kdelta(i, 0)), coeffs[i], eps); } } #ifdef USE_LAPACK_QUAD TEST(ContOrthoPoly1D_orthonormalization_quad_STIELTJES) { const lapack_double eps = FLT128_EPSILON*100.0; const OrthoPolyMethod method = OPOLY_STIELTJES; const unsigned npoints = 64; const unsigned maxdeg = 10; const unsigned ntries = 5; const double xmin = -1.0; const double xmax = 1.0; const double range = xmax - xmin; std::vector points(2U*npoints); std::vector measure; measure.reserve(npoints); MersenneTwister rng; for (unsigned itry=0; itry(kdelta(i, j)), d, eps); } } } TEST(ContOrthoPoly1D_orthonormalization_quad_LANCZOS) { const lapack_double eps = FLT128_EPSILON*100.0; const OrthoPolyMethod method = OPOLY_LANCZOS; const unsigned npoints = 64; const unsigned maxdeg = 10; const unsigned ntries = 5; const double xmin = -1.0; const double xmax = 1.0; const double range = xmax - xmin; std::vector points(2U*npoints); std::vector measure; measure.reserve(npoints); MersenneTwister rng; for (unsigned itry=0; itry(kdelta(i, j)), d, eps); } } } #endif TEST(ContOrthoPoly1D_weightCoeffs) { const double eps = 1.0e-7; const unsigned maxdeg = 10; const unsigned ntries = 10; const unsigned npoints = maxdeg + 1U; std::vector points(2U*npoints); std::vector measure; measure.reserve(npoints); std::vector coeffs(maxdeg + 1); MersenneTwister rng; for (unsigned itry=0; itry poly2( poly.makeStorablePolySeries(xmin, xmax)); for (unsigned deg=0; deg<=maxdeg; ++deg) for (unsigned ipow=0; ipow<4; ++ipow) { const double i1 = poly.integratePoly(deg, ipow, xmin, xmax); const double i2 = poly2->integratePoly(deg, ipow); if (fabs(i2) > 1.0e-10) CHECK_CLOSE(1.0, i1/i2, 1.0e-10); } for (unsigned i=0; iseries(&coeffs[0], maxdeg, x); CHECK_CLOSE(w, fvalue, 1000*eps); - CHECK_CLOSE(fvalue, f2, 20*eps); + CHECK_CLOSE(fvalue, f2, 50*eps); } } } TEST(ContOrthoPoly1D_cov8) { const double eps = 1.0e-12; MersenneTwister rng; const unsigned npoints = 64; const unsigned maxdeg = 6; const unsigned ntries = 5; const unsigned degtries = 100; std::vector points(npoints); for (unsigned itry=0; itry points(npoints); std::vector aves(maxdeg + 1); Beta1D beta(0.0, 1.0, 2.0, 2.0); GaussLegendreQuadrature glq(nInteg); for (unsigned itry=0; itry& mat = poly.extWeightProductAverages( df, glq, maxdeg, 0.0, 1.0); poly.extWeightAverages(df, glq, maxdeg, 0.0, 1.0, &aves[0]); for (unsigned i=0; i<=maxdeg; ++i) for (unsigned j=0; j<=maxdeg; ++j) { const double integ = poly.integrateEWPolyProduct( DensityFunctor1D(beta), i, j, 0.0, 1.0, nInteg); CHECK_CLOSE(integ, mat[i][j], eps); } for (unsigned j=0; j<=maxdeg; ++j) CHECK_CLOSE(aves[j], mat[0][j], eps); } } TEST(ContOrthoPoly1D_epsCovariance) { const double eps = 1.0e-15; const unsigned npoints = 64; const unsigned maxdeg = 6; const unsigned ntries = 5; MersenneTwister rng; std::vector points(npoints); for (unsigned itry=0; itry r(nrandom); for (unsigned i=0; i result(maxdeg + 1); poly.sampleAverages(&r[0], r.size(), &result[0], maxdeg); Matrix mat(maxdeg + 1, maxdeg + 1, 0); std::vector acc(maxdeg + 1, 0.0L); std::vector tmp(maxdeg + 1); for (unsigned i=0; i(acc[deg]), result[deg], eps); } // Test "pairwiseSampleAverages" method mat /= nrandom; Matrix averages = poly.sampleProductAverages( &r[0], r.size(), maxdeg); Matrix refmat(mat); CHECK((averages - refmat).maxAbsValue() < eps); } TEST(ContOrthoPoly1D_jacobi_2) { typedef ContOrthoPoly1D::PreciseQuadrature Quadrature; const double eps = 1.0e-13; const unsigned alpha = 3; const unsigned beta = 4; const unsigned maxdeg = 5; const unsigned npoints = 64; JacobiOrthoPoly1D jac(alpha, beta); OrthoPoly1DWeight weight(jac); const unsigned npt = Quadrature::minimalExactRule(2*maxdeg+alpha+beta); Quadrature glq(npt); ContOrthoPoly1D poly(maxdeg, glq.weightedIntegrationPoints(weight, -1.0, 1.0), OPOLY_LANCZOS); for (unsigned i=0; i #include #include #include #include // The following include is needed for std::sqrt(lapack_double) #include "npstat/nm/lapack_double.h" namespace npstat { /** Base class for a functor that takes no arguments */ template struct Functor0 { typedef Result result_type; inline virtual ~Functor0() {} virtual Result operator()() const = 0; }; /** Copyable reference to Functor0 */ template class Functor0RefHelper : public Functor0 { public: inline Functor0RefHelper(const Functor0& ref) : ref_(ref) {} inline virtual ~Functor0RefHelper() {} inline virtual Result operator()() const {return ref_();} private: const Functor0& ref_; }; /** Convenience function for creating Functor0RefHelper instances */ template inline Functor0RefHelper Functor0Ref(const Functor0& ref) { return Functor0RefHelper(ref); } /** Base class for a functor that takes a single argument */ template struct Functor1 { typedef Result result_type; typedef Arg1 first_argument_type; inline virtual ~Functor1() {} virtual Result operator()(const Arg1&) const = 0; }; /** Copyable reference to Functor1 */ template class Functor1RefHelper : public Functor1 { public: inline Functor1RefHelper(const Functor1& ref) : ref_(ref) {} inline virtual ~Functor1RefHelper() {} inline virtual Result operator()(const Arg1& x1) const {return ref_(x1);} private: const Functor1& ref_; }; /** Convenience function for creating Functor1RefHelper instances */ template inline Functor1RefHelper Functor1Ref(const Functor1& ref) { return Functor1RefHelper(ref); } /** Base class for a functor that takes two arguments */ template struct Functor2 { typedef Result result_type; typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; inline virtual ~Functor2() {} virtual Result operator()(const Arg1&, const Arg2&) const = 0; }; /** Copyable reference to Functor2 */ template class Functor2RefHelper : public Functor2 { public: inline Functor2RefHelper(const Functor2& ref) : ref_(ref) {} inline virtual ~Functor2RefHelper() {} inline virtual Result operator()(const Arg1& x1, const Arg2& x2) const {return ref_(x1, x2);} private: const Functor2& ref_; }; /** Convenience function for creating Functor2RefHelper instances */ template inline Functor2RefHelper Functor2Ref( const Functor2& ref) { return Functor2RefHelper(ref); } /** Base class for a functor that takes three arguments */ template struct Functor3 { typedef Result result_type; typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Arg3 third_argument_type; inline virtual ~Functor3() {} virtual Result operator()(const Arg1&,const Arg2&,const Arg3&) const=0; }; /** Copyable reference to Functor3 */ template class Functor3RefHelper : public Functor3 { public: inline Functor3RefHelper(const Functor3& ref) : ref_(ref) {} inline virtual ~Functor3RefHelper() {} inline virtual Result operator()(const Arg1& x1, const Arg2& x2, const Arg3& x3) const {return ref_(x1, x2, x3);} private: const Functor3& ref_; }; /** Convenience function for creating Functor3RefHelper instances */ template inline Functor3RefHelper Functor3Ref( const Functor3& ref) { return Functor3RefHelper(ref); } /** Base class for a functor that returns a pair */ template struct PairFunctor { typedef std::pair result_type; typedef Numeric first_argument_type; inline virtual ~PairFunctor() {} virtual std::pair operator()(const Numeric&) const=0; }; /** Copyable reference to PairFunctor */ template class PairFunctorRefHelper : public PairFunctor { public: inline PairFunctorRefHelper(const PairFunctor& ref) : ref_(ref) {} inline virtual ~PairFunctorRefHelper() {} inline virtual std::pair operator()(const Numeric& c) const {return ref_(c);} private: const PairFunctor& ref_; }; /** Convenience function for creating PairFunctorRefHelper instances */ template inline PairFunctorRefHelper PairFunctorRef( const PairFunctor& ref) { return PairFunctorRefHelper(ref); } /** A simple functor which returns a copy of its argument */ template struct Same : public Functor1 { inline virtual ~Same() {} inline Result operator()(const Result& a) const {return a;} inline bool operator==(const Same&) const {return true;} inline bool operator!=(const Same&) const {return false;} }; /** A simple functor which adds a constant to its argument */ template class Shift : public Functor1 { public: inline Shift(const Result& v) : value_(v) {} inline virtual ~Shift() {} inline Result operator()(const Result& a) const {return a + value_;} inline bool operator==(const Shift& r) const {return value_ == r.value_;} inline bool operator!=(const Shift& r) const {return !(*this == r);} private: Shift(); Result value_; }; /** A simple functor which returns a reference to its argument */ template struct SameRef : public Functor1 { inline virtual ~SameRef() {} inline const Result& operator()(const Result& a) const {return a;} inline bool operator==(const SameRef&) const {return true;} inline bool operator!=(const SameRef&) const {return false;} }; /** // Simple functor which ignores is arguments and instead // builds the result using the default constructor of the result type */ template struct DefaultConstructor0 : public Functor0 { inline virtual ~DefaultConstructor0() {} inline Result operator()() const {return Result();} inline bool operator==(const DefaultConstructor0&) const {return true;} inline bool operator!=(const DefaultConstructor0&) const {return false;} }; /** // Simple functor which ignores is arguments and instead // builds the result using the default constructor of the result type */ template struct DefaultConstructor1 : public Functor1 { inline virtual ~DefaultConstructor1() {} inline Result operator()(const Arg1&) const {return Result();} inline bool operator==(const DefaultConstructor1&) const {return true;} inline bool operator!=(const DefaultConstructor1&) const {return false;} }; /** // Simple functor which ignores is arguments and instead // builds the result using the default constructor of the result type */ template struct DefaultConstructor2 : public Functor2 { inline virtual ~DefaultConstructor2() {} inline Result operator()(const Arg1&, const Arg2&) const {return Result();} inline bool operator==(const DefaultConstructor2&) const {return true;} inline bool operator!=(const DefaultConstructor2&) const {return false;} }; /** // Simple functor which ignores is arguments and instead // builds the result using the default constructor of the result type */ template struct DefaultConstructor3 : public Functor3 { inline virtual ~DefaultConstructor3() {} inline Result operator()(const Arg1&, const Arg2&, const Arg3&) const {return Result();} inline bool operator==(const DefaultConstructor3&) const {return true;} inline bool operator!=(const DefaultConstructor3&) const {return false;} }; /** Simple functor which returns a constant */ template class ConstValue0 : public Functor0 { public: inline ConstValue0(const Result& v) : value_(v) {} inline virtual ~ConstValue0() {} inline Result operator()() const {return value_;} inline bool operator==(const ConstValue0& r) const {return value_ == r.value_;} inline bool operator!=(const ConstValue0& r) const {return !(*this == r);} private: ConstValue0(); Result value_; }; /** Simple functor which returns a constant */ template class ConstValue1 : public Functor1 { public: inline ConstValue1(const Result& v) : value_(v) {} inline virtual ~ConstValue1() {} inline Result operator()(const Arg1&) const {return value_;} inline bool operator==(const ConstValue1& r) const {return value_ == r.value_;} inline bool operator!=(const ConstValue1& r) const {return !(*this == r);} private: ConstValue1(); Result value_; }; /** Simple functor which returns a constant */ template class ConstValue2 : public Functor2 { public: inline ConstValue2(const Result& v) : value_(v) {} inline virtual ~ConstValue2() {} inline Result operator()(const Arg1&, const Arg2&) const {return value_;} inline bool operator==(const ConstValue2& r) const {return value_ == r.value_;} inline bool operator!=(const ConstValue2& r) const {return !(*this == r);} private: ConstValue2(); Result value_; }; /** Simple functor which returns a constant */ template class ConstValue3 : public Functor3 { public: inline ConstValue3(const Result& v) : value_(v) {} inline virtual ~ConstValue3() {} inline Result operator()(const Arg1&, const Arg2&, const Arg3&) const {return value_;} inline bool operator==(const ConstValue3& r) const {return value_ == r.value_;} inline bool operator!=(const ConstValue3& r) const {return !(*this == r);} private: ConstValue3(); Result value_; }; /** // Sometimes it becomes necessary to perform an explicit cast for proper // overload resolution of a converting copy constructor */ template struct CastingCopyConstructor : public Functor1 { inline virtual ~CastingCopyConstructor() {} inline Result operator()(const Arg1& a) const {return Result(static_cast(a));} inline bool operator==(const CastingCopyConstructor&) const {return true;} inline bool operator!=(const CastingCopyConstructor&) const {return false;} }; /** // Adaptation for using functors without arguments with simple // cmath-style functions */ template struct FcnFunctor0 : public Functor0 { inline explicit FcnFunctor0(Result (*fcn)()) : fcn_(fcn) {} inline virtual ~FcnFunctor0() {} inline Result operator()() const {return fcn_();} inline bool operator==(const FcnFunctor0& r) const {return fcn_ == r.fcn_;} inline bool operator!=(const FcnFunctor0& r) const {return !(*this == r);} private: FcnFunctor0(); Result (*fcn_)(); }; /** // Adaptation for using single-argument functors with simple // cmath-style functions */ template struct FcnFunctor1 : public Functor1 { inline explicit FcnFunctor1(Result (*fcn)(Arg1)) : fcn_(fcn) {} inline virtual ~FcnFunctor1() {} inline Result operator()(const Arg1& a) const {return fcn_(a);} inline bool operator==(const FcnFunctor1& r) const {return fcn_ == r.fcn_;} inline bool operator!=(const FcnFunctor1& r) const {return !(*this == r);} private: FcnFunctor1(); Result (*fcn_)(Arg1); }; /** // Adaptation for using two-argument functors with simple // cmath-style functions */ template struct FcnFunctor2 : public Functor2 { inline explicit FcnFunctor2(Result (*fcn)(Arg1, Arg2)) : fcn_(fcn) {} inline virtual ~FcnFunctor2() {} inline Result operator()(const Arg1& x, const Arg2& y) const {return fcn_(x, y);} inline bool operator==(const FcnFunctor2& r) const {return fcn_ == r.fcn_;} inline bool operator!=(const FcnFunctor2& r) const {return !(*this == r);} private: FcnFunctor2(); Result (*fcn_)(Arg1, Arg2); }; /** // Adaptation for using three-argument functors with simple // cmath-style functions */ template struct FcnFunctor3 : public Functor3 { inline explicit FcnFunctor3(Result (*fcn)(Arg1,Arg2,Arg3)):fcn_(fcn) {} inline virtual ~FcnFunctor3() {} inline Result operator()(const Arg1&x,const Arg2&y,const Arg3&z) const {return fcn_(x, y, z);} inline bool operator==(const FcnFunctor3& r) const {return fcn_ == r.fcn_;} inline bool operator!=(const FcnFunctor3& r) const {return !(*this == r);} private: FcnFunctor3(); Result (*fcn_)(Arg1, Arg2, Arg3); }; template < typename Result1, typename Arg1, typename Result2, typename Arg2, class Operator > struct ComboFunctor1Helper : public Functor1 { inline ComboFunctor1Helper(const Functor1& f1, const Functor1& f2, const Operator& op) : f1_(f1), f2_(f2), op_(op) {} inline virtual ~ComboFunctor1Helper() {} inline virtual Result1 operator()(const Arg1& x) const { return op_(f1_(x), static_cast(f2_(static_cast(x)))); } private: const Functor1& f1_; const Functor1& f2_; const Operator op_; }; /** // Create a functor which operates on the results produced // by two other functors. Note that only references to f1 // and f2 are stored. Lifetimes of f1 and f2 must be longer // than the lifetime of this functor. The combo functor will // have the result type and the argument type of f1. */ template < typename Result1, typename Arg1, typename Result2, typename Arg2, template class Operator > inline ComboFunctor1Helper > ComboFunctor1(const Functor1& f1, const Functor1& f2, const Operator& op) { return ComboFunctor1Helper >(f1, f2, op); } /** // Functor which extracts a given element from a random access linear // container without bounds checking */ template struct Element1D : public Functor1 { inline explicit Element1D(const unsigned long index) : idx(index) {} inline virtual ~Element1D() {} inline Result operator()(const Container& c) const {return c[idx];} inline bool operator==(const Element1D& r) const {return idx == r.idx;} inline bool operator!=(const Element1D& r) const {return !(*this == r);} private: Element1D(); unsigned long idx; }; /** // Functor which extracts a given element from a random access linear // container with bounds checking */ template struct Element1DAt : public Functor1 { inline explicit Element1DAt(const unsigned long index) : idx(index) {} inline virtual ~Element1DAt() {} inline Result operator()(const Container& c) const {return c.at(idx);} inline bool operator==(const Element1DAt& r) const {return idx == r.idx;} inline bool operator!=(const Element1DAt& r) const {return !(*this == r);} private: Element1DAt(); unsigned long idx; }; /** // Left assignment functor. Works just like normal binary // assignment operator in places where functor is needed. */ template struct assign_left { inline T1& operator()(T1& left, const T2& right) const {return left = right;} }; /** // Right assignment functor. Reverses the assignment direction // in comparison with the normal binary assignment operator. */ template struct assign_right { inline T2& operator()(const T1& left, T2& right) const {return right = left;} }; /** In-place addition on the left side */ template struct pluseq_left { inline T1& operator()(T1& left, const T2& right) const {return left += right;} }; /** In-place addition on the right side */ template struct pluseq_right { inline T2& operator()(const T1& left, T2& right) const {return right += left;} }; /** // In-place addition on the left side preceded by // multiplication of the right argument by a double */ template struct addmul_left { inline explicit addmul_left(const double weight) : w_(weight) {} inline T1& operator()(T1& left, const T2& right) const {return left += w_*right;} private: addmul_left(); double w_; }; /** // In-place addition on the right side preceded by // multiplication of the left argument by a double */ template struct addmul_right { inline explicit addmul_right(const double weight) : w_(weight) {} inline T1& operator()(T1& left, const T2& right) const {return right += w_*left;} private: addmul_right(); double w_; }; /** In-place subtraction on the left side */ template struct minuseq_left { inline T1& operator()(T1& left, const T2& right) const {return left -= right;} }; /** In-place subtraction on the right side */ template struct minuseq_right { inline T2& operator()(const T1& left, T2& right) const {return right -= left;} }; /** In-place multiplication on the left side */ template struct multeq_left { inline T1& operator()(T1& left, const T2& right) const {return left *= right;} }; /** In-place multiplication on the right side */ template struct multeq_right { inline T2& operator()(const T1& left, T2& right) const {return right *= left;} }; /** In-place division on the left side without checking for division by 0 */ template struct diveq_left { inline T1& operator()(T1& left, const T2& right) const {return left /= right;} }; /** In-place division on the right side without checking for division by 0 */ template struct diveq_right { inline T2& operator()(const T1& left, T2& right) const {return right /= left;} }; /** In-place division on the left side. Allow 0/0 = const. */ template struct diveq_left_0by0isC { inline diveq_left_0by0isC() : C(T1()), leftZero(T1()), rightZero(T2()) {} inline explicit diveq_left_0by0isC(const T1& value) : C(value), leftZero(T1()), rightZero(T2()) {} inline T1& operator()(T1& left, const T2& right) const { if (right == rightZero) if (left == leftZero) { left = C; return left; } return left /= right; } private: T1 C; T1 leftZero; T2 rightZero; }; /** In-place division on the right side. Allow 0/0 = const. */ template struct diveq_right_0by0isC { inline diveq_right_0by0isC() : C(T2()), leftZero(T1()), rightZero(T2()) {} inline explicit diveq_right_0by0isC(const T2& value) : C(value), leftZero(T1()), rightZero(T2()) {} inline T2& operator()(const T1& left, T2& right) const { if (left == leftZero) if (right == rightZero) { right = C; return right; } return right /= left; } private: T2 C; T1 leftZero; T2 rightZero; }; /** Left assignment functor preceded by a static cast */ template struct scast_assign_left { inline T1& operator()(T1& left, const T2& right) const {return left = static_cast(right);} }; /** Right assignment functor preceded by a static cast */ template struct scast_assign_right { inline T2& operator()(const T1& left, T2& right) const {return right = static_cast(left);} }; /** In-place addition on the left side preceded by a static cast */ template struct scast_pluseq_left { inline T1& operator()(T1& left, const T2& right) const {return left += static_cast(right);} }; /** In-place addition on the right side preceded by a static cast */ template struct scast_pluseq_right { inline T2& operator()(const T1& left, T2& right) const {return right += static_cast(left);} }; /** In-place subtraction on the left side preceded by a static cast */ template struct scast_minuseq_left { inline T1& operator()(T1& left, const T2& right) const {return left -= static_cast(right);} }; /** In-place subtraction on the right side preceded by a static cast */ template struct scast_minuseq_right { inline T2& operator()(const T1& left, T2& right) const {return right -= static_cast(left);} }; /** Square root functor */ template struct SquareRoot : public Functor1 { inline virtual ~SquareRoot() {} inline virtual T1 operator()(const T1& x) const { static const T1 zero = static_cast(0); if (!(x >= zero)) throw std::domain_error( "In npstat::SquareRoot::operator(): " "argument must be non-negative"); return std::sqrt(x); } }; /** Inverse square root functor */ template struct InverseSquareRoot : public Functor1 { inline virtual ~InverseSquareRoot() {} inline virtual T1 operator()(const T1& x) const { static const T1 zero = static_cast(0); static const T1 one = static_cast(1); if (!(x > zero)) throw std::domain_error( "In npstat::InverseSquareRoot::operator(): " "argument must be positive"); return one/std::sqrt(x); } }; + /** Useful functor for calculating ISE between two densities */ + template + class DeltaSquaredFcnHelper : public Functor1 + { + public: + inline DeltaSquaredFcnHelper(const F1& f1, const F2& f2) + : f1_(f1), f2_(f2) {} + + inline virtual ~DeltaSquaredFcnHelper() {} + + inline virtual double operator()(const double& x) const + { + const double delta = f1_(x) - f2_(x); + return delta*delta; + } + + private: + const F1& f1_; + const F2& f2_; + }; + + template + inline DeltaSquaredFcnHelper + DeltaSquaredFcn(const F1& f1, const F2& f2) + { + return DeltaSquaredFcnHelper(f1, f2); + } + /** // Useful functor for calculating ISE between a function and // a polynomial series */ template class DeltaSquaredSerFcn : public Functor1 { public: // Note that the series coefficients are not copied inline DeltaSquaredSerFcn( const Poly& poly, const Functor& fcn, const double* coeffs, const unsigned maxdeg) : poly_(poly), fcn_(fcn), coeffs_(coeffs), maxdeg_(maxdeg) {} inline virtual ~DeltaSquaredSerFcn() {} - inline double operator()(const double& x) const + inline virtual double operator()(const double& x) const { const double delta = poly_.series(coeffs_, maxdeg_, x) - fcn_(x); return delta*delta; } private: const Poly& poly_; const Functor& fcn_; const double* coeffs_; unsigned maxdeg_; }; /** // Useful functor for calculating powers of another functor or // a cmath-style function. Does not make a copy of the argument // functor, using only a reference. */ template class FunctorPowerFcnHelper : public Functor1 { public: inline FunctorPowerFcnHelper(const Functor& fcn, const double power) : fcn_(fcn), power_(power) {} inline virtual ~FunctorPowerFcnHelper() {} - inline double operator()(const double& x) const + inline virtual double operator()(const double& x) const { if (power_) { const double tmp = fcn_(x); if (power_ == 1.0) return tmp; else if (power_ == 2.0) return tmp*tmp; else if (power_ == -1.0) { assert(tmp); return 1.0/tmp; } else { if (power_ < 0.0) assert(tmp); return std::pow(tmp, power_); } } else return 1.0; } private: const Functor& fcn_; double power_; }; /** Utility function for making FunctorPowerFcnHelper objects */ template inline FunctorPowerFcnHelper FunctorPowerFcn( const Functor& fcn, const double power) { return FunctorPowerFcnHelper(fcn, power); } /** // Useful functor for calculating powers of another functor or // a cmath-style function. Makes a copy of the argument functor. */ template class FunctorPowerFcnCpHelper : public Functor1 { public: inline FunctorPowerFcnCpHelper(const Functor& fcn, const double power) : fcn_(fcn), power_(power) {} inline virtual ~FunctorPowerFcnCpHelper() {} - inline double operator()(const double& x) const + inline virtual double operator()(const double& x) const {return FunctorPowerFcnHelper(fcn_, power_)(x);} private: Functor fcn_; double power_; }; /** Utility function for making FunctorPowerFcnCpHelper objects */ template inline FunctorPowerFcnCpHelper FunctorPowerFcnCp( const Functor& fcn, const double power) { return FunctorPowerFcnCpHelper(fcn, power); } /** Functor for multiplying the result of another functor by a constant */ template class MultiplyByConstHelper : public Functor1 { public: inline MultiplyByConstHelper(const Functor1& fcn, const Result& factor) : fcn_(fcn), factor_(factor) {} inline virtual ~MultiplyByConstHelper() {} - inline double operator()(const Arg1& x) const + inline virtual double operator()(const Arg1& x) const {return factor_*fcn_(x);} private: const Functor1& fcn_; Result factor_; }; /** Utility function for making MultiplyByConstHelper objects */ template inline MultiplyByConstHelper MultiplyByConst( const Functor1& fcn, const Numeric& factor) { return MultiplyByConstHelper(fcn, static_cast(factor)); } } #endif // NPSTAT_SIMPLEFUNCTORS_HH_