24#ifndef quantlib_convex_monotone_interpolation_hpp
25#define quantlib_convex_monotone_interpolation_hpp
33 template<
class I1,
class I2>
class ConvexMonotoneImpl;
53 template <
class I1,
class I2>
55 typedef std::map<Real, ext::shared_ptr<detail::SectionHelper> >
59 const I2& yBegin,
Real quadraticity,
60 Real monotonicity,
bool forcePositive,
61 bool flatFinalPeriod =
false,
64 impl_ = ext::shared_ptr<Interpolation::Impl>(
79 std::map<Real, ext::shared_ptr<detail::SectionHelper> >
81 ext::shared_ptr<detail::ConvexMonotoneImpl<I1,I2> > derived =
82 ext::dynamic_pointer_cast<detail::ConvexMonotoneImpl<I1,I2>,
84 return derived->getExistingHelpers();
97 Real monotonicity = 0.7,
98 bool forcePositive =
true)
102 template <
class I1,
class I2>
104 const I2& yBegin)
const {
112 template <
class I1,
class I2>
114 const I2& yBegin,
Size localisation,
116 Size finalSize)
const {
117 Size length = std::distance(xBegin, xEnd);
118 if (length - localisation == 1) {
120 if (length == finalSize) {
138 if (length == finalSize) {
140 xBegin, xEnd, yBegin,
148 xBegin, xEnd, yBegin,
173 template <
class I1,
class I2>
175 typedef std::map<Real, ext::shared_ptr<SectionHelper> >
191 bool constantLastPeriod,
202 "Monotonicity must lie between 0 and 1");
204 "Quadraticity must lie between 0 and 1");
206 "Single point provided, not supported by convex "
207 "monotone method as first point is ignored");
209 "Too many existing helpers have been supplied");
217 QL_FAIL(
"Convex-monotone spline derivative not implemented");
220 QL_FAIL(
"Convex-monotone spline second derivative "
227 retArray.erase(*(this->
xEnd_-1));
244 ext::shared_ptr<SectionHelper>& convMonoHelper,
249 QL_REQUIRE(quadraticity < 1.0 && quadraticity > 0.0,
250 "Quadratic value must lie between 0 and 1"); }
430 }
else if (x <
x3_) {
433 xVal = 1.0 - (1.0 - xVal) /
xRatio_;
447 }
else if (x <=
x3_) {
451 xVal = 1.0 - (1.0-xVal)/
xRatio_;
498 return(
a_*xVal*xVal +
b_*xVal +
c_ );
528 Real dAv = bAv*bAv - 4.0*aAv*cAv;
531 Real avRoot = (-bAv - std::sqrt(dAv))/(2*aAv);
553 }
else if (x <
x3_) {
556 xVal = 1.0 - (1.0 - xVal) /
xRatio_;
560 return c_ +
b_*xVal +
a_*xVal*xVal;
568 }
else if (x <
x3_) {
571 xVal = 1.0 - (1.0 - xVal) /
xRatio_;
587 template <
class I1,
class I2>
589 sectionHelpers_.clear();
591 ext::shared_ptr<SectionHelper> singleHelper(
595 sectionHelpers_[this->xBegin_[1]] = singleHelper;
596 extrapolationHelper_ = singleHelper;
600 std::vector<Real>
f(length_);
601 sectionHelpers_ = preSectionHelpers_;
602 Size startPoint = sectionHelpers_.size()+1;
605 for (
Size i=startPoint; i<length_-1; ++i) {
606 Real dxPrev = this->xBegin_[i] - this->xBegin_[i-1];
607 Real dx = this->xBegin_[i+1] - this->xBegin_[i];
608 f[i] = dx/(dx+dxPrev) * this->yBegin_[i]
609 + dxPrev/(dx+dxPrev) * this->yBegin_[i+1];
613 f[startPoint-1] = preSectionHelpers_.rbegin()->second->fNext();
615 f[0] = 1.5 * this->yBegin_[1] - 0.5 *
f[1];
617 f[length_-1] = 1.5 * this->yBegin_[length_-1] - 0.5 *
f[length_-2];
619 if (forcePositive_) {
622 if (
f[length_-1] < 0.0)
626 Real primitive = 0.0;
627 for (
Size i = 0; i < startPoint-1; ++i)
629 this->yBegin_[i+1] * (this->xBegin_[i+1]-this->xBegin_[i]);
631 Size endPoint = length_;
633 if (constantLastPeriod_)
634 endPoint = endPoint-1;
636 for (
Size i=startPoint; i< endPoint; ++i) {
637 Real gPrev =
f[i-1] - this->yBegin_[i];
638 Real gNext =
f[i] - this->yBegin_[i];
640 if ( std::fabs(gPrev) < 1.0E-14
641 && std::fabs(gNext) < 1.0E-14 ) {
642 ext::shared_ptr<SectionHelper> singleHelper(
647 sectionHelpers_[this->xBegin_[i]] = singleHelper;
649 Real quadraticity = quadraticity_;
650 ext::shared_ptr<SectionHelper> quadraticHelper;
651 ext::shared_ptr<SectionHelper> convMonotoneHelper;
652 if (quadraticity_ > 0.0) {
653 if (gPrev >= -2.0*gNext && gPrev > -0.5*gNext && forcePositive_) {
655 ext::shared_ptr<SectionHelper>(
663 ext::shared_ptr<SectionHelper>(
671 if (quadraticity_ < 1.0) {
673 if ((gPrev > 0.0 && -0.5*gPrev >= gNext && gNext >= -2.0*gPrev) ||
674 (gPrev < 0.0 && -0.5*gPrev <= gNext && gNext <= -2.0*gPrev)) {
676 if (quadraticity_ == 0) {
677 if (forcePositive_) {
679 ext::shared_ptr<SectionHelper>(
688 ext::shared_ptr<SectionHelper>(
698 else if ( (gPrev < 0.0 && gNext > -2.0*gPrev) ||
699 (gPrev > 0.0 && gNext < -2.0*gPrev)) {
701 Real eta = (gNext + 2.0*gPrev)/(gNext - gPrev);
702 Real b2 = (1.0 + monotonicity_)/2.0;
705 ext::shared_ptr<SectionHelper>(
713 if (forcePositive_) {
715 ext::shared_ptr<SectionHelper>(
724 ext::shared_ptr<SectionHelper>(
734 else if ( (gPrev > 0.0 && gNext < 0.0 && gNext > -0.5*gPrev) ||
735 (gPrev < 0.0 && gNext > 0.0 && gNext < -0.5*gPrev) ) {
736 Real eta = gNext/(gNext-gPrev) * 3.0;
737 Real b3 = (1.0 - monotonicity_)/2.0;
740 ext::shared_ptr<SectionHelper>(
748 if (forcePositive_) {
750 ext::shared_ptr<SectionHelper>(
759 ext::shared_ptr<SectionHelper>(
769 Real eta = gNext/(gPrev + gNext);
770 Real b2 = (1.0 + monotonicity_)/2.0;
771 Real b3 = (1.0 - monotonicity_)/2.0;
776 if (forcePositive_) {
778 ext::shared_ptr<SectionHelper>(
787 ext::shared_ptr<SectionHelper>(
798 if (quadraticity == 1.0) {
799 sectionHelpers_[this->xBegin_[i]] = quadraticHelper;
800 }
else if (quadraticity == 0.0) {
801 sectionHelpers_[this->xBegin_[i]] = convMonotoneHelper;
803 sectionHelpers_[this->xBegin_[i]] =
804 ext::shared_ptr<SectionHelper>(
812 this->yBegin_[i] * (this->xBegin_[i]-this->xBegin_[i-1]);
815 if (constantLastPeriod_) {
816 sectionHelpers_[this->xBegin_[length_-1]] =
817 ext::shared_ptr<SectionHelper>(
820 this->xBegin_[length_-2]));
821 extrapolationHelper_ = sectionHelpers_[this->xBegin_[length_-1]];
823 extrapolationHelper_ =
824 ext::shared_ptr<SectionHelper>(
826 (sectionHelpers_.rbegin())->second->value(*(this->xEnd_-1)),
832 template <
class I1,
class I2>
834 if (x >= *(this->xEnd_-1)) {
835 return extrapolationHelper_->value(x);
838 return sectionHelpers_.upper_bound(x)->second->value(x);
841 template <
class I1,
class I2>
843 if (x >= *(this->xEnd_-1)) {
844 return extrapolationHelper_->primitive(x);
847 return sectionHelpers_.upper_bound(x)->second->primitive(x);
Convex-monotone interpolation factory and traits.
static const Size dataSizeAdjustment
Interpolation localInterpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, Size localisation, Interpolation &prevInterpolation, Size finalSize) const
static const Size requiredPoints
Interpolation interpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
ConvexMonotone(Real quadraticity=0.3, Real monotonicity=0.7, bool forcePositive=true)
Convex monotone yield-curve interpolation method.
std::map< Real, ext::shared_ptr< detail::SectionHelper > > getExistingHelpers()
std::map< Real, ext::shared_ptr< detail::SectionHelper > > helper_map
ConvexMonotoneInterpolation(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, Real quadraticity, Real monotonicity, bool forcePositive, bool flatFinalPeriod=false, const helper_map &preExistingHelpers=helper_map())
ConvexMonotoneInterpolation(Interpolation &interp)
abstract base class for interpolation implementations
basic template implementation
templateImpl(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, const int requiredPoints=2)
base class for 1-D interpolations.
ext::shared_ptr< Impl > impl_
Real fNext() const override
Real value(Real x) const override
ext::shared_ptr< SectionHelper > convMonoHelper_
ext::shared_ptr< SectionHelper > quadraticHelper_
Real primitive(Real x) const override
ComboHelper(ext::shared_ptr< SectionHelper > &quadraticHelper, ext::shared_ptr< SectionHelper > &convMonoHelper, Real quadraticity)
ConstantGradHelper(Real fPrev, Real prevPrimitive, Real xPrev, Real xNext, Real fNext)
Real fNext() const override
Real value(Real x) const override
Real primitive(Real x) const override
Real fNext() const override
Real value(Real x) const override
Real primitive(Real x) const override
ConvexMonotone2Helper(Real xPrev, Real xNext, Real gPrev, Real gNext, Real fAverage, Real eta2, Real prevPrimitive)
Real fNext() const override
Real value(Real x) const override
Real primitive(Real x) const override
ConvexMonotone3Helper(Real xPrev, Real xNext, Real gPrev, Real gNext, Real fAverage, Real eta3, Real prevPrimitive)
Real fNext() const override
ConvexMonotone4Helper(Real xPrev, Real xNext, Real gPrev, Real gNext, Real fAverage, Real eta4, Real prevPrimitive)
Real value(Real x) const override
Real primitive(Real x) const override
Real value(Real x) const override
Real primitive(Real x) const override
ConvexMonotone4MinHelper(Real xPrev, Real xNext, Real gPrev, Real gNext, Real fAverage, Real eta4, Real prevPrimitive)
helper_map preSectionHelpers_
Real value(Real x) const override
Real derivative(Real) const override
Real secondDerivative(Real) const override
ConvexMonotoneImpl(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, Real quadraticity, Real monotonicity, bool forcePositive, bool constantLastPeriod, const helper_map &preExistingHelpers)
helper_map sectionHelpers_
ext::shared_ptr< SectionHelper > extrapolationHelper_
Real primitive(Real x) const override
std::map< Real, ext::shared_ptr< SectionHelper > > helper_map
helper_map getExistingHelpers()
Real fNext() const override
Real value(Real) const override
Real primitive(Real x) const override
EverywhereConstantHelper(Real value, Real prevPrimitive, Real xPrev)
QuadraticHelper(Real xPrev, Real xNext, Real fPrev, Real fNext, Real fAverage, Real prevPrimitive)
Real fNext() const override
Real value(Real x) const override
Real primitive(Real x) const override
Real fNext() const override
Real value(Real x) const override
QuadraticMinHelper(Real xPrev, Real xNext, Real fPrev, Real fNext, Real fAverage, Real prevPrimitive)
Real primitive(Real x) const override
virtual Real primitive(Real x) const =0
virtual Real fNext() const =0
virtual ~SectionHelper()=default
virtual Real value(Real x) const =0
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
#define QL_FAIL(message)
throw an error (possibly with file and line information)
std::size_t Size
size of a container
base class for 1-D interpolations