From 4cf23e770b966a286daf9b9c3d63f26dfa471634 Mon Sep 17 00:00:00 2001 From: Wenqing Wang <wenqing.wang@ufz.de> Date: Fri, 4 Nov 2016 16:04:52 +0100 Subject: [PATCH] [Alg] Added a function to get inverse value from curve --- .../PiecewiseLinearInterpolation.h | 28 ++++++++++++++++++- .../TestPiecewiseLinearInterpolation.cpp | 27 ++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h index 643c87061c1..03f134c69c7 100644 --- a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h +++ b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h @@ -58,7 +58,26 @@ public: * this interval are set to \f$x_{\min}\f$ or \f$x_{\max}\f$. * @return The interpolated value. */ - double getValue(double pnt_to_interpolate) const; + double getValue(double const pnt_to_interpolate) const; + + /** + * \brief Calculates the interpolation of the variable by a known + * value of the piece wise linear curve. The curve must be + * monotonically increase or decrease. The monotonicity can be + * checked after create an instance of this class. + * + * @param value The variable for a point should be located within the range + * \f$[f(x_{\min}), f(x_{\max})]\f$, where \f$x_{\min} = \min_{1 \le j \le n} + * x_j\f$ and + * \f$x_{\max} = \max_{1 \le j \le n} x_j\f$. Points outside of this + * interval are + * set to f(x_{\min}) or f(x_{\max}). + * @return The interpolated value, \f$x\f$. + * + * \attention Check the monotonicity of the data beforehand if this function + * is used. + */ + double getInverseValue(double const value) const; /** * \brief Calculates derivative using quadratic interpolation @@ -76,9 +95,16 @@ public: double getSupportMax() const; double getSupportMin() const; + bool isMonotonic() const; + private: std::vector<double> _supp_pnts; std::vector<double> _values_at_supp_pnts; + + double interpolate(std::vector<double> const& supp_pnts, + std::vector<double> const& values_at_supp_pnts, + std::size_t const interval_idx, + double const pnt_to_interpolate) const; }; } // end namespace MathLib diff --git a/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp b/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp index 7a0517a368b..6d241be594d 100644 --- a/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp +++ b/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp @@ -156,3 +156,30 @@ TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolationDerivative) ASSERT_NEAR(0, interpolation.getDerivative(1001), std::numeric_limits<double>::epsilon()); } + +TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolationGetInverseValue) +{ + const std::size_t size = 1000; + std::vector<double> variables, values; + for (std::size_t k=0; k < size; ++k) + { + variables.push_back(static_cast<double>(k)); + values.push_back(static_cast<double>(2*k)); + } + + std::vector<double> variables_cpy = variables; + std::vector<double> values_cpy = values; + + MathLib::PiecewiseLinearInterpolation + interpolation{std::move(variables_cpy), + std::move(values_cpy)}; + + ASSERT_EQ(true, interpolation.isMonotonic()); + + // Get inverse values and compare them + for (std::size_t k=0; k < size; ++k) + { + ASSERT_NEAR(variables[k], interpolation.getInverseValue(values[k]), + std::numeric_limits<double>::epsilon()); + } +} -- GitLab