/src/quantlib/ql/math/interpolation.hpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2002, 2003 Ferdinando Ametrano |
5 | | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl |
6 | | Copyright (C) 2003, 2004, 2005, 2006 StatPro Italia srl |
7 | | |
8 | | This file is part of QuantLib, a free-software/open-source library |
9 | | for financial quantitative analysts and developers - http://quantlib.org/ |
10 | | |
11 | | QuantLib is free software: you can redistribute it and/or modify it |
12 | | under the terms of the QuantLib license. You should have received a |
13 | | copy of the license along with this program; if not, please email |
14 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
15 | | <https://www.quantlib.org/license.shtml>. |
16 | | |
17 | | This program is distributed in the hope that it will be useful, but WITHOUT |
18 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
19 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
20 | | */ |
21 | | |
22 | | /*! \file interpolation.hpp |
23 | | \brief base class for 1-D interpolations |
24 | | */ |
25 | | |
26 | | #ifndef quantlib_interpolation_hpp |
27 | | #define quantlib_interpolation_hpp |
28 | | |
29 | | #include <ql/math/interpolations/extrapolation.hpp> |
30 | | #include <ql/math/comparison.hpp> |
31 | | #include <ql/errors.hpp> |
32 | | #include <vector> |
33 | | #include <algorithm> |
34 | | |
35 | | namespace QuantLib { |
36 | | |
37 | | //! base class for 1-D interpolations. |
38 | | /*! Classes derived from this class will provide interpolated |
39 | | values from two sequences of equal length, representing |
40 | | discretized values of a variable and a function of the former, |
41 | | respectively. |
42 | | |
43 | | \warning Interpolations don't copy their underlying data; |
44 | | instead, they store iterators through which they |
45 | | access them. This allow them to see changes in the |
46 | | underlying data without having to propagate them |
47 | | manually, but adds the requirement that the lifetime |
48 | | of the underlying data exceeds or equals the lifetime |
49 | | of the interpolation. It is up to the user to ensure |
50 | | this: usually, a class will store as data members |
51 | | both the data and the interpolation (see, e.g., the |
52 | | InterpolatedCurve class) and call the update() method |
53 | | on the latter when the data change. |
54 | | */ |
55 | | class Interpolation : public Extrapolator { |
56 | | protected: |
57 | | //! abstract base class for interpolation implementations |
58 | | class Impl { |
59 | | public: |
60 | 0 | virtual ~Impl() = default; |
61 | | virtual void update() = 0; |
62 | | virtual Real xMin() const = 0; |
63 | | virtual Real xMax() const = 0; |
64 | | virtual std::vector<Real> xValues() const = 0; |
65 | | virtual std::vector<Real> yValues() const = 0; |
66 | | virtual bool isInRange(Real) const = 0; |
67 | | virtual Real value(Real) const = 0; |
68 | | virtual Real primitive(Real) const = 0; |
69 | | virtual Real derivative(Real) const = 0; |
70 | | virtual Real secondDerivative(Real) const = 0; |
71 | | }; |
72 | | ext::shared_ptr<Impl> impl_; |
73 | | public: |
74 | | //! basic template implementation |
75 | | template <class I1, class I2> |
76 | | class templateImpl : public Impl { |
77 | | public: |
78 | | templateImpl(const I1& xBegin, const I1& xEnd, const I2& yBegin, |
79 | | const int requiredPoints = 2) |
80 | 0 | : xBegin_(xBegin), xEnd_(xEnd), yBegin_(yBegin) { |
81 | 0 | QL_REQUIRE(static_cast<std::ptrdiff_t>(xEnd_-xBegin_) >= requiredPoints, |
82 | 0 | "not enough points to interpolate: at least " << |
83 | 0 | requiredPoints << |
84 | 0 | " required, " << static_cast<std::ptrdiff_t>(xEnd_-xBegin_)<< " provided"); |
85 | 0 | } Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >::templateImpl(std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, double const*>::templateImpl(std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, double const* const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double*>::templateImpl(std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, double* const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double const*> >::templateImpl(std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double const*> const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double*> >::templateImpl(std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double*> const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >::templateImpl(std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double const*>::templateImpl(std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, double const* const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, QuantLib::step_iterator<double*> >::templateImpl(std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, QuantLib::step_iterator<double*> const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double const*>::templateImpl(double const* const&, double const* const&, double const* const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double*>::templateImpl(double* const&, double* const&, double* const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double*>::templateImpl(double const* const&, double const* const&, double* const&, int) Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double const*>::templateImpl(double* const&, double* const&, double const* const&, int) |
86 | 0 | Real xMin() const override { return *xBegin_; }Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, double const*>::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double*>::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double const*>::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double*>::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double const*> >::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double*> >::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double const*>::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double*>::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, QuantLib::step_iterator<double*> >::xMin() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double const*>::xMin() const |
87 | 0 | Real xMax() const override { return *(xEnd_ - 1); }Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, double const*>::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double*>::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double const*>::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double*>::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double const*> >::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double*> >::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double const*>::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double*>::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, QuantLib::step_iterator<double*> >::xMax() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double const*>::xMax() const |
88 | 0 | std::vector<Real> xValues() const override { return std::vector<Real>(xBegin_, xEnd_); }Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, double const*>::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double*>::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double const*>::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double*>::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double const*> >::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double*> >::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double const*>::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double*>::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, QuantLib::step_iterator<double*> >::xValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double const*>::xValues() const |
89 | 0 | std::vector<Real> yValues() const override { |
90 | 0 | return std::vector<Real>(yBegin_,yBegin_+(xEnd_-xBegin_)); |
91 | 0 | } Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, double const*>::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double*>::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double const*>::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double*>::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double const*> >::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double*> >::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double const*>::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double*>::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, QuantLib::step_iterator<double*> >::yValues() const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double const*>::yValues() const |
92 | 0 | bool isInRange(Real x) const override { |
93 | | #if defined(QL_EXTRA_SAFETY_CHECKS) |
94 | | for (I1 i=xBegin_, j=xBegin_+1; j!=xEnd_; ++i, ++j) |
95 | | QL_REQUIRE(*j > *i, "unsorted x values"); |
96 | | #endif |
97 | 0 | Real x1 = xMin(), x2 = xMax(); |
98 | 0 | return (x >= x1 && x <= x2) || close(x,x1) || close(x,x2); |
99 | 0 | } Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, double const*>::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double*>::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double const*>::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double*>::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double const*> >::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double*> >::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double const*>::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double*>::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, QuantLib::step_iterator<double*> >::isInRange(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double const*>::isInRange(double) const |
100 | | |
101 | | protected: |
102 | 0 | Size locate(Real x) const { |
103 | | #if defined(QL_EXTRA_SAFETY_CHECKS) |
104 | | for (I1 i=xBegin_, j=xBegin_+1; j!=xEnd_; ++i, ++j) |
105 | | QL_REQUIRE(*j > *i, "unsorted x values"); |
106 | | #endif |
107 | 0 | if (x < *xBegin_) |
108 | 0 | return 0; |
109 | 0 | else if (x > *(xEnd_-1)) |
110 | 0 | return xEnd_-xBegin_-2; |
111 | 0 | else |
112 | 0 | return std::upper_bound(xBegin_,xEnd_-1,x)-xBegin_-1; |
113 | 0 | } Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*> >::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, double const*>::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double*>::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double const*> >::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double*> >::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double*>::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*> >::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double const*>, double const*>::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double*>::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<std::__1::__wrap_iter<double*>, QuantLib::step_iterator<double*> >::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double const*, double const*>::locate(double) const Unexecuted instantiation: QuantLib::Interpolation::templateImpl<double*, double const*>::locate(double) const |
114 | | I1 xBegin_, xEnd_; |
115 | | I2 yBegin_; |
116 | | }; |
117 | | |
118 | 0 | Interpolation() = default; |
119 | 0 | bool empty() const { return !impl_; } |
120 | 0 | Real operator()(Real x, bool allowExtrapolation = false) const { |
121 | 0 | checkRange(x,allowExtrapolation); |
122 | 0 | return impl_->value(x); |
123 | 0 | } |
124 | 0 | Real primitive(Real x, bool allowExtrapolation = false) const { |
125 | 0 | checkRange(x,allowExtrapolation); |
126 | 0 | return impl_->primitive(x); |
127 | 0 | } |
128 | 0 | Real derivative(Real x, bool allowExtrapolation = false) const { |
129 | 0 | checkRange(x,allowExtrapolation); |
130 | 0 | return impl_->derivative(x); |
131 | 0 | } |
132 | 0 | Real secondDerivative(Real x, bool allowExtrapolation = false) const { |
133 | 0 | checkRange(x,allowExtrapolation); |
134 | 0 | return impl_->secondDerivative(x); |
135 | 0 | } |
136 | 0 | Real xMin() const { |
137 | 0 | return impl_->xMin(); |
138 | 0 | } |
139 | 0 | Real xMax() const { |
140 | 0 | return impl_->xMax(); |
141 | 0 | } |
142 | 0 | bool isInRange(Real x) const { |
143 | 0 | return impl_->isInRange(x); |
144 | 0 | } |
145 | 0 | void update() { |
146 | 0 | impl_->update(); |
147 | 0 | } |
148 | | protected: |
149 | 0 | void checkRange(Real x, bool extrapolate) const { |
150 | | QL_REQUIRE(extrapolate || allowsExtrapolation() || |
151 | 0 | impl_->isInRange(x), |
152 | 0 | "interpolation range is [" |
153 | 0 | << impl_->xMin() << ", " << impl_->xMax() |
154 | 0 | << "]: extrapolation at " << x << " not allowed"); |
155 | 0 | } |
156 | | friend class MixedLinearCubicInterpolation; |
157 | | }; |
158 | | |
159 | | } |
160 | | |
161 | | #endif |