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 <http://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
35namespace 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 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 /*! \deprecated Use `auto` or `decltype` instead.
75 Deprecated in version 1.29.
76 */
77 QL_DEPRECATED
78 typedef Real argument_type;
79
80 /*! \deprecated Use `auto` or `decltype` instead.
81 Deprecated in version 1.29.
82 */
83 QL_DEPRECATED
84 typedef Real result_type;
85
86 //! basic template implementation
87 template <class I1, class I2>
88 class templateImpl : public Impl {
89 public:
90 templateImpl(const I1& xBegin, const I1& xEnd, const I2& yBegin,
91 const int requiredPoints = 2)
92 : xBegin_(xBegin), xEnd_(xEnd), yBegin_(yBegin) {
93 QL_REQUIRE(static_cast<int>(xEnd_-xBegin_) >= requiredPoints,
94 "not enough points to interpolate: at least " <<
95 requiredPoints <<
96 " required, " << static_cast<int>(xEnd_-xBegin_)<< " provided");
97 }
98 Real xMin() const override { return *xBegin_; }
99 Real xMax() const override { return *(xEnd_ - 1); }
100 std::vector<Real> xValues() const override { return std::vector<Real>(xBegin_, xEnd_); }
101 std::vector<Real> yValues() const override {
102 return std::vector<Real>(yBegin_,yBegin_+(xEnd_-xBegin_));
103 }
104 bool isInRange(Real x) const override {
105#if defined(QL_EXTRA_SAFETY_CHECKS)
106 for (I1 i=xBegin_, j=xBegin_+1; j!=xEnd_; ++i, ++j)
107 QL_REQUIRE(*j > *i, "unsorted x values");
108 #endif
109 Real x1 = xMin(), x2 = xMax();
110 return (x >= x1 && x <= x2) || close(x,y: x1) || close(x,y: x2);
111 }
112
113 protected:
114 Size locate(Real x) const {
115 #if defined(QL_EXTRA_SAFETY_CHECKS)
116 for (I1 i=xBegin_, j=xBegin_+1; j!=xEnd_; ++i, ++j)
117 QL_REQUIRE(*j > *i, "unsorted x values");
118 #endif
119 if (x < *xBegin_)
120 return 0;
121 else if (x > *(xEnd_-1))
122 return xEnd_-xBegin_-2;
123 else
124 return std::upper_bound(xBegin_,xEnd_-1,x)-xBegin_-1;
125 }
126 I1 xBegin_, xEnd_;
127 I2 yBegin_;
128 };
129
130 Interpolation() = default;
131 ~Interpolation() override = default;
132 bool empty() const { return !impl_; }
133 Real operator()(Real x, bool allowExtrapolation = false) const {
134 checkRange(x,extrapolate: allowExtrapolation);
135 return impl_->value(x);
136 }
137 Real primitive(Real x, bool allowExtrapolation = false) const {
138 checkRange(x,extrapolate: allowExtrapolation);
139 return impl_->primitive(x);
140 }
141 Real derivative(Real x, bool allowExtrapolation = false) const {
142 checkRange(x,extrapolate: allowExtrapolation);
143 return impl_->derivative(x);
144 }
145 Real secondDerivative(Real x, bool allowExtrapolation = false) const {
146 checkRange(x,extrapolate: allowExtrapolation);
147 return impl_->secondDerivative(x);
148 }
149 Real xMin() const {
150 return impl_->xMin();
151 }
152 Real xMax() const {
153 return impl_->xMax();
154 }
155 bool isInRange(Real x) const {
156 return impl_->isInRange(x);
157 }
158 void update() {
159 impl_->update();
160 }
161 protected:
162 void checkRange(Real x, bool extrapolate) const {
163 QL_REQUIRE(extrapolate || allowsExtrapolation() ||
164 impl_->isInRange(x),
165 "interpolation range is ["
166 << impl_->xMin() << ", " << impl_->xMax()
167 << "]: extrapolation at " << x << " not allowed");
168 }
169 };
170
171}
172
173#endif
174

source code of quantlib/ql/math/interpolation.hpp