From 3979788911bb937f9ed5da53a630e8956dc217f4 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de> Date: Sun, 28 Jun 2020 14:30:20 +0200 Subject: [PATCH] provide generic functions min_value, max_value --- Core/Basics/Algorithms.h | 65 +++++++++++++++++++ .../UnitTests/Core/Basics/MinMaxValueTest.cpp | 32 +++++++++ 2 files changed, 97 insertions(+) create mode 100644 Core/Basics/Algorithms.h create mode 100644 Tests/UnitTests/Core/Basics/MinMaxValueTest.cpp diff --git a/Core/Basics/Algorithms.h b/Core/Basics/Algorithms.h new file mode 100644 index 00000000000..39c2f1480b3 --- /dev/null +++ b/Core/Basics/Algorithms.h @@ -0,0 +1,65 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file Core/Basics/Algorithms +//! @brief Defines and implements namespace algo with some algorithms +//! +//! @homepage http://www.bornagainproject.org +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2018 +//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS) +// +// ************************************************************************** // + +#ifndef ALGORITHMS_H +#define ALGORITHMS_H + +#include <algorithm> +#include <functional> +#include <vector> +#include <cassert> + +//! Some additions to standard library algorithms. + +namespace algo { + +//! Returns the minimum value of function evaluate as applied to the elements of an iterator range. +template<typename Evaluator, typename Iterator> +double min_value(const Iterator& begin, const Iterator& end, const Evaluator& evaluate); + +//! Returns the maximum value of function evaluate as applied to the elements of an iterator range. +template<typename Evaluator, typename Iterator> +double max_value(const Iterator& begin, const Iterator& end, const Evaluator& evaluate); + +} // namespace algo + + +// ************************************************************************** // +// Implementation +// ************************************************************************** // + +template<typename Evaluator, typename Iterator> +double algo::min_value(const Iterator& begin, const Iterator& end, const Evaluator& evaluate) +{ + assert(begin != end); + double ret = evaluate(*begin); + Iterator it = begin; + while (++it != end) + ret = std::min(ret, evaluate(*it)); + return ret; +} + +template<typename Evaluator, typename Iterator> +double algo::max_value(const Iterator& begin, const Iterator& end, const Evaluator& evaluate) +{ + assert(begin != end); + double ret = evaluate(*begin); + Iterator it = begin; + while (++it != end) + ret = std::max(ret, evaluate(*it)); + return ret; +} + + +#endif // ALGORITHMS_H diff --git a/Tests/UnitTests/Core/Basics/MinMaxValueTest.cpp b/Tests/UnitTests/Core/Basics/MinMaxValueTest.cpp new file mode 100644 index 00000000000..4cc4591e8d7 --- /dev/null +++ b/Tests/UnitTests/Core/Basics/MinMaxValueTest.cpp @@ -0,0 +1,32 @@ +#include "Algorithms.h" +#include "google_test.h" +#include <cmath> + +class MinMaxValueTest : public ::testing::Test +{ +}; + +TEST_F(MinMaxValueTest, MinMaxValueAlmostEq) +{ + double val; + std::vector<double> A{0.}; + std::vector<int> C {1, 2, 3}; + + val = algo::min_value(A.begin(), A.end(), [](const double& x)->double { return x; }); + EXPECT_EQ(val, 0.); + val = algo::max_value(A.begin(), A.end(), [](const double& x)->double { return 2+x; }); + EXPECT_NEAR(val, 2., 1e-15); + + val = algo::min_value(C.begin(), C.end(), [](const int& i)->double { return i; }); + EXPECT_EQ(val, 1); + val = algo::min_value(C.begin(), C.end(), [](const int& i)->double { return -i; }); + EXPECT_EQ(val, -3); + val = algo::min_value(C.begin(), C.end(), [](const int& i)->double { return pow(i-2.1,2); }); + EXPECT_NEAR(val, 0.01, 1e-13); + val = algo::max_value(C.begin(), C.end(), [](const int& i)->double { return i; }); + EXPECT_EQ(val, 3); + val = algo::max_value(C.begin(), C.end(), [](const int& i)->double { return -i; }); + EXPECT_EQ(val, -1); + val = algo::max_value(C.begin(), C.end(), [](const int& i)->double { return -pow(i-2.1,2); }); + EXPECT_NEAR(val, -0.01, 1e-13); +} -- GitLab