diff --git a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.cpp b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.cpp index a314121459a65664806848c7e3356575683985ce..cf984006af5aea892cd6df1f75795d4277955d9d 100644 --- a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.cpp +++ b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.cpp @@ -72,29 +72,44 @@ double PiecewiseLinearInterpolation::getDerivative( auto const& it(std::lower_bound(_supp_pnts.begin(), _supp_pnts.end(), pnt_to_interpolate)); - std::size_t const interval_idx = std::distance(_supp_pnts.begin(), it) - 1; + std::size_t interval_idx = std::distance(_supp_pnts.begin(), it); + + if (pnt_to_interpolate == _supp_pnts.front()) + { + interval_idx = 1; + } - // interval_idx = interval_max - 1 - interval_idx; - if (interval_idx > 1 && interval_idx < _supp_pnts.size() - 2) + if (interval_idx > 2 && interval_idx < _supp_pnts.size() - 1) { double const tangent_right = - (_values_at_supp_pnts[interval_idx] - - _values_at_supp_pnts[interval_idx + 2]) / - (_supp_pnts[interval_idx] - _supp_pnts[interval_idx + 2]); - double const tangent_left = (_values_at_supp_pnts[interval_idx - 1] - _values_at_supp_pnts[interval_idx + 1]) / (_supp_pnts[interval_idx - 1] - _supp_pnts[interval_idx + 1]); + double const tangent_left = + (_values_at_supp_pnts[interval_idx - 2] - + _values_at_supp_pnts[interval_idx]) / + (_supp_pnts[interval_idx - 2] - _supp_pnts[interval_idx]); double const w = - (pnt_to_interpolate - _supp_pnts[interval_idx + 1]) / - (_supp_pnts[interval_idx] - _supp_pnts[interval_idx + 1]); + (pnt_to_interpolate - _supp_pnts[interval_idx]) / + (_supp_pnts[interval_idx - 1] - _supp_pnts[interval_idx]); return (1. - w) * tangent_right + w * tangent_left; } else { return (_values_at_supp_pnts[interval_idx] - - _values_at_supp_pnts[interval_idx + 1]) / - (_supp_pnts[interval_idx] - _supp_pnts[interval_idx + 1]); + _values_at_supp_pnts[interval_idx - 1]) / + (_supp_pnts[interval_idx] - _supp_pnts[interval_idx - 1]); } } + +double PiecewiseLinearInterpolation::getSupportMax() const +{ + assert(!_supp_pnts.empty()); + return _supp_pnts.back(); +} +double PiecewiseLinearInterpolation::getSupportMin() const +{ + assert(!_supp_pnts.empty()); + return _supp_pnts.front(); +} } // end MathLib diff --git a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h index 7a38a80a5af6e9de664cbf08ddcfcd792d480147..1a66e4d7c3a2a27115fb809cd4e47118ecc55538 100644 --- a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h +++ b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h @@ -75,6 +75,8 @@ public: * using linear interpolation. */ double getDerivative(double const pnt_to_interpolate) const; + double getSupportMax() const; + double getSupportMin() const; private: std::vector<double> _supp_pnts; diff --git a/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp b/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp index e29fc0e0fc720aa106ace9f2b6da64f69ee87e0b..914d781e83d617dc8e98bf519117dffcd96058e9 100644 --- a/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp +++ b/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp @@ -131,7 +131,7 @@ TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolationDerivative) for (std::size_t k(0); k < size; ++k) { supp_pnts.push_back(static_cast<double>(k)); - values.push_back(k * k); + values.push_back(static_cast<double>(k * k)); } MathLib::PiecewiseLinearInterpolation interpolation{std::move(supp_pnts), @@ -142,6 +142,11 @@ TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolationDerivative) ASSERT_NEAR(1 + 2 * k, interpolation.getDerivative(k + 0.5), std::numeric_limits<double>::epsilon()); } + // max and min value test + ASSERT_NEAR(1, interpolation.getDerivative(0), + std::numeric_limits<double>::epsilon()); + ASSERT_NEAR(1997, interpolation.getDerivative(999), + std::numeric_limits<double>::epsilon()); // Extrapolation ASSERT_NEAR(0, interpolation.getDerivative(-1),