From 645a2abdabf42c1770131bd2e3c4d97e14daad6e Mon Sep 17 00:00:00 2001 From: ArsenP0doba Date: Fri, 8 May 2026 17:34:39 +0200 Subject: [PATCH 1/2] Add flat interpolation --- QuantLib.vcxproj | 1 + QuantLib.vcxproj.filters | 1 + ql/CMakeLists.txt | 1 + ql/math/interpolations/Makefile.am | 1 + ql/math/interpolations/all.hpp | 1 + .../linearthenflatinterpolation.hpp | 117 ++++++++++++++++++ 6 files changed, 122 insertions(+) create mode 100644 ql/math/interpolations/linearthenflatinterpolation.hpp diff --git a/QuantLib.vcxproj b/QuantLib.vcxproj index 1bc4d704e2f..83bc4697671 100644 --- a/QuantLib.vcxproj +++ b/QuantLib.vcxproj @@ -1049,6 +1049,7 @@ + diff --git a/QuantLib.vcxproj.filters b/QuantLib.vcxproj.filters index d8950a45295..bc6199188e6 100644 --- a/QuantLib.vcxproj.filters +++ b/QuantLib.vcxproj.filters @@ -4527,6 +4527,7 @@ pricingengines\vanilla + diff --git a/ql/CMakeLists.txt b/ql/CMakeLists.txt index c616d1d471e..7902ac36388 100644 --- a/ql/CMakeLists.txt +++ b/ql/CMakeLists.txt @@ -1479,6 +1479,7 @@ set(QL_HEADERS math/interpolations/kernelinterpolation2d.hpp math/interpolations/lagrangeinterpolation.hpp math/interpolations/linearinterpolation.hpp + math/interpolations/linearthenflatinterpolation.hpp math/interpolations/loginterpolation.hpp math/interpolations/mixedinterpolation.hpp math/interpolations/multicubicspline.hpp diff --git a/ql/math/interpolations/Makefile.am b/ql/math/interpolations/Makefile.am index d958dd9f038..0a5384c6aef 100644 --- a/ql/math/interpolations/Makefile.am +++ b/ql/math/interpolations/Makefile.am @@ -20,6 +20,7 @@ this_include_HEADERS = \ kernelinterpolation2d.hpp \ lagrangeinterpolation.hpp \ linearinterpolation.hpp \ + linearthenflatinterpolation.hpp \ loginterpolation.hpp \ mixedinterpolation.hpp \ multicubicspline.hpp \ diff --git a/ql/math/interpolations/all.hpp b/ql/math/interpolations/all.hpp index a89b680bd62..7b85e0fa0a7 100644 --- a/ql/math/interpolations/all.hpp +++ b/ql/math/interpolations/all.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/ql/math/interpolations/linearthenflatinterpolation.hpp b/ql/math/interpolations/linearthenflatinterpolation.hpp new file mode 100644 index 00000000000..c87951c2c34 --- /dev/null +++ b/ql/math/interpolations/linearthenflatinterpolation.hpp @@ -0,0 +1,117 @@ +/* + Copyright (C) 2026 SoftSolution + + This file is part of QuantLib, a free-software/open-source library + for financial quantitative analysts and developers - http://quantlib.org/ + + QuantLib is free software: you can redistribute it and/or modify it + under the terms of the QuantLib license. You should have received a + copy of the license along with this program; if not, please email + . The license is also available online at + . + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the license for more details. +*/ + +/*! \file linearthenflatinterpolation.hpp + \brief linear interpolation between discrete points, that after last point becomes flat +*/ + +#ifndef quantlib_linearthenflat_interpolation_hpp +#define quantlib_linearthenflat_interpolation_hpp + +#include +#include + +namespace QuantLib { + + namespace detail { + template class LinearThenFlatInterpolationImpl; + } + + //! %Linear-then-flat interpolation between discrete points + class LinearThenFlatInterpolation : public Interpolation { + public: + /*! \pre the \f$ x \f$ values must be sorted. */ + template + LinearThenFlatInterpolation(const I1& xBegin, + const I1& xEnd, + const I2& yBegin) { + impl_ = ext::shared_ptr(new + detail::LinearThenFlatInterpolationImpl(xBegin, xEnd, yBegin)); + impl_->update(); + } + }; + + //! %Linear-then-flat interpolation factory and traits + class LinearThenFlat { + public: + template + Interpolation interpolate(const I1& xBegin, + const I1& xEnd, + const I2& yBegin) const { + return LinearThenFlatInterpolation(xBegin, xEnd, yBegin); + } + static const bool global = false; + static const Size requiredPoints = 2; + }; + + namespace detail { + + template + class LinearThenFlatInterpolationImpl : public Interpolation::templateImpl { + public: + LinearThenFlatInterpolationImpl(const I1& xBegin, + const I1& xEnd, + const I2& yBegin) + : Interpolation::templateImpl(xBegin, xEnd, yBegin), + primitiveConst_(xEnd-xBegin), s_(xEnd-xBegin), + primitive_(xEnd-xBegin), n_(xEnd-xBegin) {} + void update() override { + primitiveConst_[0] = 0.0; + for (Size i=1; ixEnd_-this->xBegin_); ++i) { + Real dx = this->xBegin_[i]-this->xBegin_[i-1]; + s_[i-1] = (this->yBegin_[i]-this->yBegin_[i-1])/dx; + primitiveConst_[i] = primitiveConst_[i-1] + + dx*(this->yBegin_[i-1] + 0.5*dx*s_[i-1]); + } + } + Real value(Real x) const override { + if (x >= this->xBegin_[n_-1]) + return this->yBegin_[n_-1]; + Size i = this->locate(x); + return this->yBegin_[i] + (x-this->xBegin_[i])*s_[i]; + } + Real primitive(Real x) const override { + // TODO: fix primitive implementation + if (x >= this->xBegin_[n_-1]) { + Size i = this->locate(x); + Real dx = x-this->xBegin_[i]; + return primitive_[i] + dx*this->yBegin_[i]; + } + Size i = this->locate(x); + Real dx = x-this->xBegin_[i]; + return primitiveConst_[i] + dx*(this->yBegin_[i] + 0.5*dx*s_[i]); + } + Real derivative(Real x) const override { + if (x >= this->xBegin_[n_-1]) + return 0.0; + Size i = this->locate(x); + return s_[i]; + } + Real secondDerivative(Real) const override { + return 0.0; + } + private: + std::vector primitiveConst_, s_; + std::vector primitive_; + Size n_; + }; + + } + +} + +#endif \ No newline at end of file From af0263fe785bcbce2d623358626815b282592190 Mon Sep 17 00:00:00 2001 From: ArsenP0doba Date: Fri, 8 May 2026 17:37:46 +0200 Subject: [PATCH 2/2] Add cubic interpolation --- ql/math/interpolations/cubicinterpolation.hpp | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/ql/math/interpolations/cubicinterpolation.hpp b/ql/math/interpolations/cubicinterpolation.hpp index a3938fd3002..e384d26c8f6 100644 --- a/ql/math/interpolations/cubicinterpolation.hpp +++ b/ql/math/interpolations/cubicinterpolation.hpp @@ -818,6 +818,94 @@ namespace QuantLib { } + class Cubic__FritschButland_nonMonotonic : public Cubic { + public: + Cubic__FritschButland_nonMonotonic() + : Cubic(CubicInterpolation::FritschButland, false, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__FritschButland_monotonic : public Cubic { + public: + Cubic__FritschButland_monotonic() + : Cubic(CubicInterpolation::FritschButland, true, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__NaturalSpline : public Cubic { + public: + Cubic__NaturalSpline() + : Cubic(CubicInterpolation::Spline, false, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__Monotonic_NaturalSpline : public Cubic { + public: + Cubic__Monotonic_NaturalSpline() + : Cubic(CubicInterpolation::Spline, true, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__SplineOvershootingMinimization1 : public Cubic { + public: + Cubic__SplineOvershootingMinimization1() + : Cubic(CubicInterpolation::SplineOM1, false, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__SplineOvershootingMinimization2 : public Cubic { + public: + Cubic__SplineOvershootingMinimization2() + : Cubic(CubicInterpolation::SplineOM2, false, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__Akima : public Cubic { + public: + Cubic__Akima() + : Cubic(CubicInterpolation::Akima, false, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__Parabolic : public Cubic { + public: + Cubic__Parabolic() + : Cubic(CubicInterpolation::Parabolic, false, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__MonotonicParabolic : public Cubic { + public: + Cubic__MonotonicParabolic() + : Cubic(CubicInterpolation::Parabolic, true, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__Kruger : public Cubic { + public: + Cubic__Kruger() + : Cubic(CubicInterpolation::Kruger, false, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + + class Cubic__MonotonicKruger : public Cubic { + public: + Cubic__MonotonicKruger() + : Cubic(CubicInterpolation::Kruger, true, + CubicInterpolation::SecondDerivative, 0.0, + CubicInterpolation::SecondDerivative, 0.0) {} + }; + } #endif