/src/quantlib/ql/experimental/math/piecewiseintegral.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2015 Peter Caspers |
5 | | |
6 | | This file is part of QuantLib, a free-software/open-source library |
7 | | for financial quantitative analysts and developers - http://quantlib.org/ |
8 | | |
9 | | QuantLib is free software: you can redistribute it and/or modify it |
10 | | under the terms of the QuantLib license. You should have received a |
11 | | copy of the license along with this program; if not, please email |
12 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
13 | | <http://quantlib.org/license.shtml>. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, but WITHOUT |
16 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
17 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
18 | | */ |
19 | | |
20 | | /*! \file piecewiseintegral.hpp |
21 | | \brief Integral of a piecewise well behaved function using |
22 | | a custom integrator for the pieces. It can be forced |
23 | | that the function is integrated only over intervals |
24 | | strictly not containing the critical points |
25 | | */ |
26 | | |
27 | | #ifndef quantlib_piecewise_integral_hpp |
28 | | #define quantlib_piecewise_integral_hpp |
29 | | |
30 | | #include <ql/math/integrals/integral.hpp> |
31 | | #include <ql/math/comparison.hpp> |
32 | | #include <ql/shared_ptr.hpp> |
33 | | #include <algorithm> |
34 | | #include <vector> |
35 | | |
36 | | namespace QuantLib { |
37 | | |
38 | | class PiecewiseIntegral : public Integrator { |
39 | | public: |
40 | | PiecewiseIntegral(ext::shared_ptr<Integrator> integrator, |
41 | | std::vector<Real> criticalPoints, |
42 | | bool avoidCriticalPoints = true); |
43 | | |
44 | | protected: |
45 | | Real integrate(const std::function<Real(Real)>& f, Real a, Real b) const override; |
46 | | |
47 | | private: |
48 | | Real integrate_h(const std::function<Real(Real)> &f, Real a, |
49 | | Real b) const; |
50 | | const ext::shared_ptr<Integrator> integrator_; |
51 | | std::vector<Real> criticalPoints_; |
52 | | const Real eps_; |
53 | | }; |
54 | | |
55 | | // inline |
56 | | |
57 | | inline Real PiecewiseIntegral::integrate_h(const std::function<Real(Real)> &f, |
58 | 0 | Real a, Real b) const { |
59 | |
|
60 | 0 | if (!close_enough(a, b)) |
61 | 0 | return (*integrator_)(f, a, b); |
62 | 0 | else |
63 | 0 | return 0.0; |
64 | 0 | } |
65 | | |
66 | | inline Real PiecewiseIntegral::integrate(const std::function<Real(Real)> &f, |
67 | 0 | Real a, Real b) const { |
68 | |
|
69 | 0 | auto a0 = std::lower_bound(criticalPoints_.begin(), criticalPoints_.end(), a); |
70 | |
|
71 | 0 | auto b0 = std::lower_bound(criticalPoints_.begin(), criticalPoints_.end(), b); |
72 | |
|
73 | 0 | if (a0 == criticalPoints_.end()) { |
74 | 0 | Real tmp = 1.0; |
75 | 0 | if (!criticalPoints_.empty()) { |
76 | 0 | if (close_enough(a, criticalPoints_.back())) { |
77 | 0 | tmp = eps_; |
78 | 0 | } |
79 | 0 | } |
80 | 0 | return integrate_h(f, a * tmp, b); |
81 | 0 | } |
82 | | |
83 | 0 | Real res = 0.0; |
84 | |
|
85 | 0 | if (!close_enough(a, *a0)) { |
86 | 0 | res += integrate_h(f, a, std::min(*a0 / eps_, b)); |
87 | 0 | } |
88 | |
|
89 | 0 | if (b0 == criticalPoints_.end()) { |
90 | 0 | --b0; |
91 | 0 | if (!close_enough(*b0, b)) { |
92 | 0 | res += integrate_h(f, (*b0) * eps_, b); |
93 | 0 | } |
94 | 0 | } |
95 | |
|
96 | 0 | for (auto x = a0; x < b0; ++x) { |
97 | 0 | res += integrate_h(f, (*x) * eps_, std::min(*(x + 1) / eps_, b)); |
98 | 0 | } |
99 | |
|
100 | 0 | return res; |
101 | 0 | } |
102 | | |
103 | | } // namespace QuantLib |
104 | | |
105 | | #endif |