Login  Register

RE:Integral of a one-dimensional function as a template function

Posted by RGProlog on Dec 09, 2002; 1:19am
URL: http://quantlib.414.s1.nabble.com/RE-Integral-of-a-one-dimensional-function-as-a-template-function-tp2313.html

           Hi, Quantlib,

The following is a proposal for the templated SegmentIntegral class, which, I hope, is still on the to do list:

template<class Arg, class Res>
class PFunctor : public std::unary_function<Arg, Res>{
typedef result_type (*QL_ATOR_TYP)(argument_type);
  protected:
PFunctor(QL_ATOR_TYP f) : f_(f) {}
QL_ATOR_TYP f_;
};

template<class Arg, class Res>
         class SegmentIntegral : public PFunctor<Arg, Res>{
          public:
SegmentIntegral(QL_ATOR_TYP f) : PFunctor<Arg, Res>(f) {}
              result_type operator()(Size, argument_type, argument_type) const;
        };

template<class Arg, class Res>
SegmentIntegral<Arg, Res>::result_type
SegmentIntegral<Arg, Res>::operator()(Size intervals,
                                                          argument_type a,
                                                          argument_type b) const {
            QL_REQUIRE(intervals > 3,
                "at least 4 intervals needed, given only "+
                 IntegerFormatter::toString(intervals));
            QL_REQUIRE(a < b,
                "to compute an integral on [a,b] it must be a<b; a="+
                 DoubleFormatter::toString(a)+" b="+
                 DoubleFormatter::toString(b));
            argument_type dx = (b - a) / intervals;
            result_type sum = (f_(a + 0.5 * dx) + f_(b - 0.5 * dx)) * dx / 2;
            for(argument_type x = a + 1.5 * dx; x < b - 0.5 * dx; x += dx)
                 sum += f_(x) * dx;
            return sum;
}

Unlike the SegmentIntegral class' nontemplated version, the templated version of the class takes a function pointer as its ctors' only argument, which, I believe, is a natural way to tie a function to its integral over an interval. The number of subintervals of the segment is an argument to the SegmentIntegral::operator()(). The following is an example of the class' usage:

double f(double x) (...)

int main(int argc, char* argv[]) {
..........................................................
SegmentIntegral<double , double> segmentIntegral(f);
for(int i = 4; i < 40; ++i)
     std::cout << segmentIntegral(i, 3, 5) << std::endl;
..........................................................
return 0;
}

Using the present non templated vesion of the SegmentIntegral class one would have to create 37 instances of the class to have the same print-out. I believe the proposed arrangement is natural, efficient, flexible, and user-friendly.

The general design of the templated SegmentIntegral class was done in the spirit of ATL, where inheritance is widwly used
as means of enhancing a class' functionality.with minimal changes to the class itself.
                                       

Roman Gitlin