diff --git a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.cpp b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.cpp
index 79c8c0cd939bbbbbb8d5f605e171644f6b269a7c..a314121459a65664806848c7e3356575683985ce 100644
--- a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.cpp
+++ b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.cpp
@@ -15,9 +15,8 @@
 #include <limits>
 #include <utility>
 
-#include "PiecewiseLinearInterpolation.h"
-
 #include "BaseLib/quicksort.h"
+#include "PiecewiseLinearInterpolation.h"
 
 namespace MathLib
 {
@@ -28,31 +27,74 @@ PiecewiseLinearInterpolation::PiecewiseLinearInterpolation(
     : _supp_pnts(std::move(supporting_points)),
       _values_at_supp_pnts(std::move(values_at_supp_pnts))
 {
-    if (!supp_pnts_sorted) {
-        BaseLib::quicksort<double, double>(_supp_pnts, static_cast<std::size_t> (0),
-                                           _supp_pnts.size(), _values_at_supp_pnts);
+    if (!supp_pnts_sorted)
+    {
+        BaseLib::quicksort<double, double>(
+            _supp_pnts, static_cast<std::size_t>(0), _supp_pnts.size(),
+            _values_at_supp_pnts);
     }
 }
 
 double PiecewiseLinearInterpolation::getValue(double pnt_to_interpolate) const
 {
     // search interval that has the point inside
-    std::size_t interval_idx(std::numeric_limits<std::size_t>::max());
-    if (pnt_to_interpolate <= _supp_pnts.front()) {
-        interval_idx = 0;
-    } else {
-        if (_supp_pnts.back() <= pnt_to_interpolate) {
-            interval_idx = _supp_pnts.size() - 2;
-        } else {
-            auto const& it(std::lower_bound(_supp_pnts.begin(), _supp_pnts.end(), pnt_to_interpolate));
-            interval_idx = std::distance(_supp_pnts.begin(), it) - 1;
-        }
+    if (pnt_to_interpolate <= _supp_pnts.front())
+    {
+        return _values_at_supp_pnts[0];
     }
 
+    if (_supp_pnts.back() <= pnt_to_interpolate)
+    {
+        return _values_at_supp_pnts[_supp_pnts.size() - 1];
+    }
+
+    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;
+
     // compute linear interpolation polynom: y = m * (x - support[i]) + value[i]
-    const double m((_values_at_supp_pnts[interval_idx + 1] - _values_at_supp_pnts[interval_idx])
-                    / (_supp_pnts[interval_idx + 1] - _supp_pnts[interval_idx]));
+    const double m((_values_at_supp_pnts[interval_idx + 1] -
+                    _values_at_supp_pnts[interval_idx]) /
+                   (_supp_pnts[interval_idx + 1] - _supp_pnts[interval_idx]));
+
+    return m * (pnt_to_interpolate - _supp_pnts[interval_idx]) +
+           _values_at_supp_pnts[interval_idx];
+}
+
+double PiecewiseLinearInterpolation::getDerivative(
+    double const pnt_to_interpolate) const
+{
+    if (pnt_to_interpolate < _supp_pnts.front() ||
+        _supp_pnts.back() < pnt_to_interpolate)
+    {
+        return 0;
+    }
 
-    return m * (pnt_to_interpolate - _supp_pnts[interval_idx]) + _values_at_supp_pnts[interval_idx];
+    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;
+
+    // interval_idx = interval_max - 1 - interval_idx;
+    if (interval_idx > 1 && interval_idx < _supp_pnts.size() - 2)
+    {
+        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 w =
+            (pnt_to_interpolate - _supp_pnts[interval_idx + 1]) /
+            (_supp_pnts[interval_idx] - _supp_pnts[interval_idx + 1]);
+        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]);
+    }
 }
-} // end MathLib
+}  // end MathLib
diff --git a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h
index f0bdbb08568e9ce8dc9c00959b1e6c4d826c6b08..7a38a80a5af6e9de664cbf08ddcfcd792d480147 100644
--- a/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h
+++ b/MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h
@@ -20,7 +20,8 @@
 namespace MathLib
 {
 /**
- * This class implements a one dimensional piecewise linear interpolation algorithm.
+ * This class implements a one dimensional piecewise linear interpolation
+ * algorithm.
  */
 class PiecewiseLinearInterpolation final
 {
@@ -41,7 +42,8 @@ public:
      * time.
      * @param supporting_points vector of supporting points
      * @param values_at_supp_pnts vector of values at the supporting points
-     * @param supp_pnts_sorted false (default), if it is sure the supporting points are sorted
+     * @param supp_pnts_sorted false (default), if it is sure the supporting
+     * points are sorted
      * one can set the switch to true
      */
     PiecewiseLinearInterpolation(std::vector<double>&& supporting_points,
@@ -51,17 +53,33 @@ public:
     /**
      * \brief Calculates the interpolation value.
      * @param pnt_to_interpolate The point should be located within the range
-     * \f$[x_{\min}, 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
-     * extrapolated.
+     * \f$[x_{\min}, 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 x_{\min} or x_{\max}.
      * @return The interpolated value.
      */
     double getValue(double pnt_to_interpolate) const;
 
+    /**
+     * \brief Calculates derivative using quadratic interpolation
+     * and central difference quotient.
+     * @param pnt_to_interpolate The point should be located within the range
+     * \f$[x_{\min}, 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$. when points are located
+     * outside of this interval, the derivative is set to 0.
+     * \attention if a point is located between the first and second points
+     * (or last and second to last point), the derivative is calculated
+     * using linear interpolation.
+     */
+    double getDerivative(double const pnt_to_interpolate) const;
+
 private:
     std::vector<double> _supp_pnts;
     std::vector<double> _values_at_supp_pnts;
 };
-} // end namespace MathLib
+}  // end namespace MathLib
 
 #endif /* PIECEWISELINEARINTERPOLATION_H_ */
diff --git a/Tests/GeoLib/TestLineSegmentIntersect2d.cpp b/Tests/GeoLib/TestLineSegmentIntersect2d.cpp
index 819ffc4fa097f8dba52bd9250d998f33a8e76bb7..62d7a5d3c0cc8505ee86f0e9687a9ac9352fd0b7 100644
--- a/Tests/GeoLib/TestLineSegmentIntersect2d.cpp
+++ b/Tests/GeoLib/TestLineSegmentIntersect2d.cpp
@@ -50,7 +50,7 @@ public:
     ac::gtest_reporter gtest_reporter;
 };
 
-#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+#if !defined(_MSC_VER) || (_MSC_VER >= 2000)
 // Compilers of MVS below 2015 do not support unrestricted unions. The
 // unrestricted union is used by autocheck to handle test data. The autocheck
 // workaround for MVS compilers (below version 2015) contains a bug and in the
diff --git a/Tests/GeoLib/TestSortSegments.cpp b/Tests/GeoLib/TestSortSegments.cpp
index 247dab95dfc7a731e6715faa9f9e37bf19162aa8..1b2c6c76ef8ea55d1510338e865c7589f64d28f1 100644
--- a/Tests/GeoLib/TestSortSegments.cpp
+++ b/Tests/GeoLib/TestSortSegments.cpp
@@ -8,7 +8,7 @@
  */
 
 #include <gtest/gtest.h>
-
+#include <numeric>
 #include "Tests/GeoLib/AutoCheckGenerators.h"
 
 #include "GeoLib/AnalyticalGeometry.h"
@@ -30,7 +30,7 @@ public:
     ac::gtest_reporter gtest_reporter;
 };
 
-#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
+#if !defined(_MSC_VER) || (_MSC_VER >= 2000)
 // Compilers of MVS below 2015 do not support unrestricted unions. The
 // unrestricted union is used by autocheck to handle test data. The autocheck
 // workaround for MVS compilers (below version 2015) contains a bug and in the
diff --git a/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp b/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp
index 149d7338fbd7837d01db101c947acfba004e7b09..e29fc0e0fc720aa106ace9f2b6da64f69ee87e0b 100644
--- a/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp
+++ b/Tests/MathLib/TestPiecewiseLinearInterpolation.cpp
@@ -23,11 +23,15 @@ TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolation)
 {
     const std::size_t size(1000);
     std::vector<double> supp_pnts, values;
-    for (std::size_t k(0); k<size; ++k) {
+    for (std::size_t k(0); k < size; ++k)
+    {
         supp_pnts.push_back(static_cast<double>(k));
-        if (k % 2 == 0) {
+        if (k % 2 == 0)
+        {
             values.push_back(0.0);
-        } else {
+        }
+        else
+        {
             values.push_back(1.0);
         }
     }
@@ -35,35 +39,52 @@ TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolation)
     MathLib::PiecewiseLinearInterpolation interpolation{std::move(supp_pnts),
                                                         std::move(values)};
     // Interpolation
-    for (std::size_t k(0); k<size-1; ++k) {
-        ASSERT_NEAR(0.5, interpolation.getValue(k+0.5), std::numeric_limits<double>::epsilon());
+    for (std::size_t k(0); k < size - 1; ++k)
+    {
+        ASSERT_NEAR(0.5, interpolation.getValue(k + 0.5),
+                    std::numeric_limits<double>::epsilon());
     }
 
-    for (std::size_t k(0); k<size-1; ++k) {
-        if (k % 2 == 0) {
-            ASSERT_NEAR(0.25, interpolation.getValue(k+0.25), std::numeric_limits<double>::epsilon());
-            ASSERT_NEAR(0.75, interpolation.getValue(k+0.75), std::numeric_limits<double>::epsilon());
-        } else {
-            ASSERT_NEAR(0.75, interpolation.getValue(k+0.25), std::numeric_limits<double>::epsilon());
-            ASSERT_NEAR(0.25, interpolation.getValue(k+0.75), std::numeric_limits<double>::epsilon());
+    for (std::size_t k(0); k < size - 1; ++k)
+    {
+        if (k % 2 == 0)
+        {
+            ASSERT_NEAR(0.25, interpolation.getValue(k + 0.25),
+                        std::numeric_limits<double>::epsilon());
+            ASSERT_NEAR(0.75, interpolation.getValue(k + 0.75),
+                        std::numeric_limits<double>::epsilon());
+        }
+        else
+        {
+            ASSERT_NEAR(0.75, interpolation.getValue(k + 0.25),
+                        std::numeric_limits<double>::epsilon());
+            ASSERT_NEAR(0.25, interpolation.getValue(k + 0.75),
+                        std::numeric_limits<double>::epsilon());
         }
     }
 
     // Extrapolation
-    ASSERT_NEAR(-0.5, interpolation.getValue(-0.5), std::numeric_limits<double>::epsilon());
+    ASSERT_NEAR(0.0, interpolation.getValue(-0.5),
+                std::numeric_limits<double>::epsilon());
     // Extrapolation
-    ASSERT_NEAR(1.5, interpolation.getValue(size-0.5), std::numeric_limits<double>::epsilon());
+    ASSERT_NEAR(1.0, interpolation.getValue(size - 0.5),
+                std::numeric_limits<double>::epsilon());
 }
 
-TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolationSupportPntsInReverseOrder)
+TEST(MathLibInterpolationAlgorithms,
+     PiecewiseLinearInterpolationSupportPntsInReverseOrder)
 {
     const std::size_t size(1000);
     std::vector<double> supp_pnts, values;
-    for (std::size_t k(0); k<size; ++k) {
-        supp_pnts.push_back(static_cast<double>(size-1-k));
-        if (k % 2 == 0) {
+    for (std::size_t k(0); k < size; ++k)
+    {
+        supp_pnts.push_back(static_cast<double>(size - 1 - k));
+        if (k % 2 == 0)
+        {
             values.push_back(1.0);
-        } else {
+        }
+        else
+        {
             values.push_back(0.0);
         }
     }
@@ -71,22 +92,61 @@ TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolationSupportPntsInRe
     MathLib::PiecewiseLinearInterpolation interpolation{std::move(supp_pnts),
                                                         std::move(values)};
     // Interpolation
-    for (std::size_t k(0); k<size-1; ++k) {
-        ASSERT_NEAR(0.5, interpolation.getValue(k+0.5), std::numeric_limits<double>::epsilon());
+    for (std::size_t k(0); k < size - 1; ++k)
+    {
+        ASSERT_NEAR(0.5, interpolation.getValue(k + 0.5),
+                    std::numeric_limits<double>::epsilon());
     }
 
-    for (std::size_t k(0); k<size-1; ++k) {
-        if (k % 2 == 0) {
-            ASSERT_NEAR(0.25, interpolation.getValue(k+0.25), std::numeric_limits<double>::epsilon());
-            ASSERT_NEAR(0.75, interpolation.getValue(k+0.75), std::numeric_limits<double>::epsilon());
-        } else {
-            ASSERT_NEAR(0.75, interpolation.getValue(k+0.25), std::numeric_limits<double>::epsilon());
-            ASSERT_NEAR(0.25, interpolation.getValue(k+0.75), std::numeric_limits<double>::epsilon());
+    for (std::size_t k(0); k < size - 1; ++k)
+    {
+        if (k % 2 == 0)
+        {
+            ASSERT_NEAR(0.25, interpolation.getValue(k + 0.25),
+                        std::numeric_limits<double>::epsilon());
+            ASSERT_NEAR(0.75, interpolation.getValue(k + 0.75),
+                        std::numeric_limits<double>::epsilon());
         }
+        else
+        {
+            ASSERT_NEAR(0.75, interpolation.getValue(k + 0.25),
+                        std::numeric_limits<double>::epsilon());
+            ASSERT_NEAR(0.25, interpolation.getValue(k + 0.75),
+                        std::numeric_limits<double>::epsilon());
+        }
+    }
+
+    // Extrapolation
+    ASSERT_NEAR(0.0, interpolation.getValue(-0.5),
+                std::numeric_limits<double>::epsilon());
+    // Extrapolation
+    ASSERT_NEAR(1.0, interpolation.getValue(size - 0.5),
+                std::numeric_limits<double>::epsilon());
+}
+
+TEST(MathLibInterpolationAlgorithms, PiecewiseLinearInterpolationDerivative)
+{
+    const std::size_t size(1000);
+    std::vector<double> supp_pnts, values;
+    for (std::size_t k(0); k < size; ++k)
+    {
+        supp_pnts.push_back(static_cast<double>(k));
+        values.push_back(k * k);
+    }
+
+    MathLib::PiecewiseLinearInterpolation interpolation{std::move(supp_pnts),
+                                                        std::move(values)};
+    // Interpolation
+    for (std::size_t k(0); k < size - 1; ++k)
+    {
+        ASSERT_NEAR(1 + 2 * k, interpolation.getDerivative(k + 0.5),
+                    std::numeric_limits<double>::epsilon());
     }
 
     // Extrapolation
-    ASSERT_NEAR(-0.5, interpolation.getValue(-0.5), std::numeric_limits<double>::epsilon());
+    ASSERT_NEAR(0, interpolation.getDerivative(-1),
+                std::numeric_limits<double>::epsilon());
     // Extrapolation
-    ASSERT_NEAR(1.5, interpolation.getValue(size-0.5), std::numeric_limits<double>::epsilon());
+    ASSERT_NEAR(0, interpolation.getDerivative(1001),
+                std::numeric_limits<double>::epsilon());
 }