void testMonotonic(const Spline &sp, const double *x, const double *y) { // test the common properties of splines testCommon(sp, x, y); size_t n = sp.numSamples(); for (size_t i = 0; i < n - 1; ++ i) { // make sure that the spline is monotonic for each interval // between sampling points if (!sp.monotonic(x[i], x[i + 1])) OPM_THROW(std::runtime_error, "Spline says it is not monotonic in interval " << i << " where it should be"); // test the intersection methods double d = (y[i] + y[i+1])/2; double interX = sp.template intersectInterval<double>(x[i], x[i+1], /*a=*/0, /*b=*/0, /*c=*/0, d); double interY = sp.eval(interX); if (std::abs(interY - d) > 1e-5) OPM_THROW(std::runtime_error, "Spline::intersectInterval() seems to be broken: " << sp.eval(interX) << " - " << d << " = " << sp.eval(interX) - d << "!"); } // make sure the spline says to be monotonic on the (extrapolated) // left and right sides if (!sp.monotonic(x[0] - 1.0, (x[0] + x[1])/2, /*extrapolate=*/true)) OPM_THROW(std::runtime_error, "Spline says it is not monotonic on left side where it should be"); if (!sp.monotonic((x[n - 2]+ x[n - 1])/2, x[n-1] + 1.0, /*extrapolate=*/true)) OPM_THROW(std::runtime_error, "Spline says it is not monotonic on right side where it should be"); for (size_t i = 0; i < n - 2; ++ i) { // make sure that the spline says that it is non-monotonic for // if extrema are within the queried interval if (sp.monotonic((x[i] + x[i + 1])/2, (x[i + 1] + x[i + 2])/2)) OPM_THROW(std::runtime_error, "Spline says it is monotonic in interval " << i << " where it should not be"); } }