/src/quantlib/ql/math/interpolations/bicubicsplineinterpolation.hpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2003 Ferdinando Ametrano |
5 | | Copyright (C) 2004 StatPro Italia srl |
6 | | |
7 | | This file is part of QuantLib, a free-software/open-source library |
8 | | for financial quantitative analysts and developers - http://quantlib.org/ |
9 | | |
10 | | QuantLib is free software: you can redistribute it and/or modify it |
11 | | under the terms of the QuantLib license. You should have received a |
12 | | copy of the license along with this program; if not, please email |
13 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
14 | | <https://www.quantlib.org/license.shtml>. |
15 | | |
16 | | This program is distributed in the hope that it will be useful, but WITHOUT |
17 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
18 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
19 | | */ |
20 | | |
21 | | /*! \file bicubicsplineinterpolation.hpp |
22 | | \brief bicubic spline interpolation between discrete points |
23 | | */ |
24 | | |
25 | | #ifndef quantlib_bicubic_spline_interpolation_hpp |
26 | | #define quantlib_bicubic_spline_interpolation_hpp |
27 | | |
28 | | #include <ql/math/interpolations/interpolation2d.hpp> |
29 | | #include <ql/math/interpolations/cubicinterpolation.hpp> |
30 | | |
31 | | namespace QuantLib { |
32 | | |
33 | | namespace detail { |
34 | | |
35 | | class BicubicSplineDerivatives { |
36 | | public: |
37 | 0 | virtual ~BicubicSplineDerivatives() = default; |
38 | | virtual Real derivativeX(Real x, Real y) const = 0; |
39 | | virtual Real derivativeY(Real x, Real y) const = 0; |
40 | | virtual Real derivativeXY(Real x, Real y) const = 0; |
41 | | virtual Real secondDerivativeX(Real x, Real y) const = 0; |
42 | | virtual Real secondDerivativeY(Real x, Real y) const = 0; |
43 | | }; |
44 | | |
45 | | template <class I1, class I2, class M> |
46 | | class BicubicSplineImpl |
47 | | : public Interpolation2D::templateImpl<I1,I2,M>, |
48 | | public BicubicSplineDerivatives { |
49 | | public: |
50 | | BicubicSplineImpl(const I1& xBegin, const I1& xEnd, |
51 | | const I2& yBegin, const I2& yEnd, |
52 | | const M& zData) |
53 | 0 | : Interpolation2D::templateImpl<I1,I2,M>(xBegin,xEnd, |
54 | 0 | yBegin,yEnd, |
55 | 0 | zData) { |
56 | 0 | BicubicSplineImpl::calculate(); |
57 | 0 | } Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>::BicubicSplineImpl(std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, QuantLib::Matrix const&) Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>::BicubicSplineImpl(std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, QuantLib::Matrix const&) |
58 | 0 | void calculate() override { |
59 | 0 | splines_.resize(this->zData_.rows()); |
60 | 0 | for (Size i=0; i<(this->zData_.rows()); ++i) |
61 | 0 | splines_[i] = CubicInterpolation( |
62 | 0 | this->xBegin_, this->xEnd_, |
63 | 0 | this->zData_.row_begin(i), |
64 | 0 | CubicInterpolation::Spline, false, |
65 | 0 | CubicInterpolation::SecondDerivative, 0.0, |
66 | 0 | CubicInterpolation::SecondDerivative, 0.0); |
67 | 0 | } Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>::calculate() Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>::calculate() |
68 | 0 | Real value(Real x, Real y) const override { |
69 | 0 | std::vector<Real> section(splines_.size()); |
70 | 0 | for (Size i=0; i<splines_.size(); i++) |
71 | 0 | section[i]=splines_[i](x,true); |
72 | |
|
73 | 0 | CubicInterpolation spline(this->yBegin_, this->yEnd_, |
74 | 0 | section.begin(), |
75 | 0 | CubicInterpolation::Spline, false, |
76 | 0 | CubicInterpolation::SecondDerivative, 0.0, |
77 | 0 | CubicInterpolation::SecondDerivative, 0.0); |
78 | 0 | return spline(y,true); |
79 | 0 | } Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>::value(double, double) const Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>::value(double, double) const |
80 | | |
81 | 0 | Real derivativeX(Real x, Real y) const override { |
82 | 0 | std::vector<Real> section(this->zData_.columns()); |
83 | 0 | for (Size i=0; i < section.size(); ++i) { |
84 | 0 | section[i] = value(this->xBegin_[i], y); |
85 | 0 | } |
86 | | |
87 | 0 | return CubicInterpolation( |
88 | 0 | this->xBegin_, this->xEnd_, |
89 | 0 | section.begin(), |
90 | 0 | CubicInterpolation::Spline, false, |
91 | 0 | CubicInterpolation::SecondDerivative, 0.0, |
92 | 0 | CubicInterpolation::SecondDerivative, 0.0).derivative(x); |
93 | 0 | } Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>::derivativeX(double, double) const Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>::derivativeX(double, double) const |
94 | | |
95 | 0 | Real secondDerivativeX(Real x, Real y) const override { |
96 | 0 | std::vector<Real> section(this->zData_.columns()); |
97 | 0 | for (Size i=0; i < section.size(); ++i) { |
98 | 0 | section[i] = value(this->xBegin_[i], y); |
99 | 0 | } |
100 | | |
101 | 0 | return CubicInterpolation( |
102 | 0 | this->xBegin_, this->xEnd_, |
103 | 0 | section.begin(), |
104 | 0 | CubicInterpolation::Spline, false, |
105 | 0 | CubicInterpolation::SecondDerivative, 0.0, |
106 | 0 | CubicInterpolation::SecondDerivative, 0.0) |
107 | 0 | .secondDerivative(x); |
108 | 0 | } Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>::secondDerivativeX(double, double) const Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>::secondDerivativeX(double, double) const |
109 | | |
110 | 0 | Real derivativeY(Real x, Real y) const override { |
111 | 0 | std::vector<Real> section(splines_.size()); |
112 | 0 | for (Size i=0; i<splines_.size(); i++) |
113 | 0 | section[i]=splines_[i](x,true); |
114 | |
|
115 | 0 | return CubicInterpolation( |
116 | 0 | this->yBegin_, this->yEnd_, |
117 | 0 | section.begin(), |
118 | 0 | CubicInterpolation::Spline, false, |
119 | 0 | CubicInterpolation::SecondDerivative, 0.0, |
120 | 0 | CubicInterpolation::SecondDerivative, 0.0).derivative(y); |
121 | 0 | } Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>::derivativeY(double, double) const Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>::derivativeY(double, double) const |
122 | | |
123 | 0 | Real secondDerivativeY(Real x, Real y) const override { |
124 | 0 | std::vector<Real> section(splines_.size()); |
125 | 0 | for (Size i=0; i<splines_.size(); i++) |
126 | 0 | section[i]=splines_[i](x,true); |
127 | |
|
128 | 0 | return CubicInterpolation( |
129 | 0 | this->yBegin_, this->yEnd_, |
130 | 0 | section.begin(), |
131 | 0 | CubicInterpolation::Spline, false, |
132 | 0 | CubicInterpolation::SecondDerivative, 0.0, |
133 | 0 | CubicInterpolation::SecondDerivative, 0.0) |
134 | 0 | .secondDerivative(y); |
135 | 0 | } Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>::secondDerivativeY(double, double) const Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>::secondDerivativeY(double, double) const |
136 | | |
137 | 0 | Real derivativeXY(Real x, Real y) const override { |
138 | 0 | std::vector<Real> section(this->zData_.columns()); |
139 | 0 | for (Size i=0; i < section.size(); ++i) { |
140 | 0 | section[i] = derivativeY(this->xBegin_[i], y); |
141 | 0 | } |
142 | | |
143 | 0 | return CubicInterpolation( |
144 | 0 | this->xBegin_, this->xEnd_, |
145 | 0 | section.begin(), |
146 | 0 | CubicInterpolation::Spline, false, |
147 | 0 | CubicInterpolation::SecondDerivative, 0.0, |
148 | 0 | CubicInterpolation::SecondDerivative, 0.0).derivative(x); |
149 | 0 | } Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>::derivativeXY(double, double) const Unexecuted instantiation: QuantLib::detail::BicubicSplineImpl<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>::derivativeXY(double, double) const |
150 | | |
151 | | private: |
152 | | std::vector<Interpolation> splines_; |
153 | | }; |
154 | | |
155 | | } |
156 | | |
157 | | //! bicubic-spline interpolation between discrete points |
158 | | /*! \ingroup interpolations |
159 | | \todo revise end conditions |
160 | | \warning See the Interpolation class for information about the |
161 | | required lifetime of the underlying data. |
162 | | */ |
163 | | class BicubicSpline : public Interpolation2D { |
164 | | public: |
165 | | /*! \pre the \f$ x \f$ and \f$ y \f$ values must be sorted. */ |
166 | | template <class I1, class I2, class M> |
167 | | BicubicSpline(const I1& xBegin, const I1& xEnd, |
168 | | const I2& yBegin, const I2& yEnd, |
169 | 0 | const M& zData) { |
170 | 0 | impl_ = ext::shared_ptr<Interpolation2D::Impl>( |
171 | 0 | new detail::BicubicSplineImpl<I1,I2,M>(xBegin, xEnd, |
172 | 0 | yBegin, yEnd, zData)); |
173 | 0 | } Unexecuted instantiation: QuantLib::BicubicSpline::BicubicSpline<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<double*>, QuantLib::Matrix>(std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, std::__1::__wrap_iter<double*> const&, QuantLib::Matrix const&) Unexecuted instantiation: QuantLib::BicubicSpline::BicubicSpline<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>, QuantLib::Matrix>(std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, QuantLib::Matrix const&) |
174 | | |
175 | 0 | Real derivativeX(Real x, Real y) const { |
176 | 0 | return ext::dynamic_pointer_cast<detail::BicubicSplineDerivatives> |
177 | 0 | (impl_)->derivativeX(x, y); |
178 | 0 | } |
179 | 0 | Real derivativeY(Real x, Real y) const { |
180 | 0 | return ext::dynamic_pointer_cast<detail::BicubicSplineDerivatives> |
181 | 0 | (impl_)->derivativeY(x, y); |
182 | 0 | } |
183 | 0 | Real secondDerivativeX(Real x, Real y) const { |
184 | 0 | return ext::dynamic_pointer_cast<detail::BicubicSplineDerivatives> |
185 | 0 | (impl_)->secondDerivativeX(x, y); |
186 | 0 | } |
187 | 0 | Real secondDerivativeY(Real x, Real y) const { |
188 | 0 | return ext::dynamic_pointer_cast<detail::BicubicSplineDerivatives> |
189 | 0 | (impl_)->secondDerivativeY(x, y); |
190 | 0 | } |
191 | | |
192 | 0 | Real derivativeXY(Real x, Real y) const { |
193 | 0 | return ext::dynamic_pointer_cast<detail::BicubicSplineDerivatives> |
194 | 0 | (impl_)->derivativeXY(x, y); |
195 | 0 | } |
196 | | }; |
197 | | |
198 | | //! bicubic-spline-interpolation factory |
199 | | class Bicubic { |
200 | | public: |
201 | | template <class I1, class I2, class M> |
202 | | Interpolation2D interpolate(const I1& xBegin, const I1& xEnd, |
203 | | const I2& yBegin, const I2& yEnd, |
204 | | const M& z) const { |
205 | | return BicubicSpline(xBegin,xEnd,yBegin,yEnd,z); |
206 | | } |
207 | | }; |
208 | | |
209 | | } |
210 | | |
211 | | #endif |