diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5f21f52f4aad5bdb8399881a0ffce9fa79578326..ba9954522c587357cc6d86586d7efd2d2e809416 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,6 +14,7 @@ stages: before_script: # Ccache configuration and introspection. + - apt-get update - apt-get install ccache --yes - ccache --set-config=cache_dir="$CI_PROJECT_DIR/.ccache" - ccache --max-size=5G diff --git a/SimoxUtility/CMakeLists.txt b/SimoxUtility/CMakeLists.txt index e08899ec3142885c5045d53a996262d2a69019a1..95bf0823199ea31f5c79e36f8cc97c7eaa80a12d 100644 --- a/SimoxUtility/CMakeLists.txt +++ b/SimoxUtility/CMakeLists.txt @@ -74,6 +74,8 @@ SET(INCLUDES algorithm/string/string_conversion_eigen.h algorithm/ordered_circular_buffer.h + backport/span/gcc_header.h + caching/CacheMap.h color/cmaps/colormaps.h @@ -106,7 +108,6 @@ SET(INCLUDES json/json.h json/util.h - math/mean.h math/sum.h math/SoftMinMax.h @@ -199,7 +200,6 @@ SET(INCLUDES math/statistics/Histogram1D.h math/statistics/measures.h - meta/undefined_t/undefined_t.h meta/undefined_t/is_set.h meta/eigen/enable_if_compile_time_size.h @@ -220,12 +220,9 @@ SET(INCLUDES meta/enum/EnumNames.hpp meta/key_type.h - simox/SimoxPath.h + random/choice.h - xml/rapidxml/rapidxml.hpp - xml/rapidxml/rapidxml_print.hpp - xml/rapidxml/RapidXMLWrapper.h - xml/rapidxml/RapidXMLForwardDecl.h + simox/SimoxPath.h shapes/AxisAlignedBoundingBox.h shapes/OrientedBoxBase.h @@ -233,10 +230,13 @@ SET(INCLUDES shapes/XYConstrainedOrientedBox.h shapes/json_conversions.h - backport/span/gcc_header.h - threads/system_thread_id.h threads/CountingSemaphore.h + + xml/rapidxml/rapidxml.hpp + xml/rapidxml/rapidxml_print.hpp + xml/rapidxml/RapidXMLWrapper.h + xml/rapidxml/RapidXMLForwardDecl.h ) diff --git a/SimoxUtility/random.h b/SimoxUtility/random.h new file mode 100644 index 0000000000000000000000000000000000000000..19a8006aa76d85a0ee1db71f1180a299d9e96f90 --- /dev/null +++ b/SimoxUtility/random.h @@ -0,0 +1,5 @@ +#pragma once + +// This file is generated! + +#include "random/choice.h" diff --git a/SimoxUtility/random/choice.h b/SimoxUtility/random/choice.h new file mode 100644 index 0000000000000000000000000000000000000000..7c7b67adc43b9f68299f97f9bc6d47ed3af05392 --- /dev/null +++ b/SimoxUtility/random/choice.h @@ -0,0 +1,41 @@ +#pragma once + +#include <random> +#include <iterator> + +#include <SimoxUtility/error/SimoxError.h> + + +namespace simox::random +{ + /** + * Return a random element from the non-empty iterable items. + * + * @throw `std::out_of_range` if items is empty. + */ + template <class IterableT, class RandomEngineT> + const typename IterableT::value_type& + choice(const IterableT& items, RandomEngineT& gen) + { + if (items.empty()) + { + throw error::SimoxError("Cannot choose an item from an empty vector."); + } + + std::uniform_int_distribution<size_t> distrib(0, items.size() - 1); + std::size_t index = distrib(gen); + auto it = items.begin(); + std::advance(it, index); + return *it; + } + + + template <class IterableT> + const typename IterableT::value_type& + choice(const IterableT& items) + { + std::default_random_engine gen{std::random_device{}()}; + return choice(items, gen); + } + +} // namespace simox::random diff --git a/SimoxUtility/tests/CMakeLists.txt b/SimoxUtility/tests/CMakeLists.txt index b9a06183286cbbb0171b4fb31bd89420042a8707..5c09ff19f328cb58a736a1c40cd6b9870d297cb8 100644 --- a/SimoxUtility/tests/CMakeLists.txt +++ b/SimoxUtility/tests/CMakeLists.txt @@ -45,6 +45,7 @@ ADD_SUBDIRECTORY(filesystem) ADD_SUBDIRECTORY(json) ADD_SUBDIRECTORY(math) ADD_SUBDIRECTORY(meta) +ADD_SUBDIRECTORY(random) ADD_SUBDIRECTORY(shapes) ADD_SUBDIRECTORY(simox) ADD_SUBDIRECTORY(backport) diff --git a/SimoxUtility/tests/random/CMakeLists.txt b/SimoxUtility/tests/random/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5e4088d67f12c7e6e7f5ee51833f6a9669ee51a9 --- /dev/null +++ b/SimoxUtility/tests/random/CMakeLists.txt @@ -0,0 +1,3 @@ + +ADD_SU_TEST( Choice ) + diff --git a/SimoxUtility/tests/random/Choice.cpp b/SimoxUtility/tests/random/Choice.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fec986df8f5f2a10989f2414adcc2fb1ca1cd9a5 --- /dev/null +++ b/SimoxUtility/tests/random/Choice.cpp @@ -0,0 +1,99 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @package RobotAPI::ArmarXObjects::FrameTracking + * @author Adrian Knobloch ( adrian dot knobloch at student dot kit dot edu ) + * @date 2019 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#define BOOST_TEST_MODULE SimoxUtility/color/ColorMap + +#include <boost/test/included/unit_test.hpp> + +#include <SimoxUtility/random/choice.h> + +#include <iostream> + +#include <set> +#include <vector> + + +namespace ChoiceTest +{ + +struct Fixture +{ + + std::vector<std::string> vector { "a", "b", "c" }; + std::set<std::string> set {vector.begin(), vector.end()}; + + Fixture() + { + } + ~Fixture() + { + } +}; + +} + + +BOOST_FIXTURE_TEST_SUITE(ChoiceTest, ChoiceTest::Fixture) + + +BOOST_AUTO_TEST_CASE(test_choice_vector) +{ + std::set<std::string> allChosen; + for (int i = 0; i < 1e5; ++i) + { + std::string chosen = simox::random::choice(vector); + BOOST_CHECK(std::find(vector.begin(), vector.end(), chosen) != vector.end()); + + allChosen.insert(chosen); + } + + // All items must be hit at least once ... very likely. + BOOST_CHECK_EQUAL(allChosen.size(), 3); +} + + +BOOST_AUTO_TEST_CASE(test_choice_set) +{ + std::set<std::string> allChosen; + for (int i = 0; i < 1e5; ++i) + { + std::string chosen = simox::random::choice(set); + BOOST_CHECK(std::find(set.begin(), set.end(), chosen) != set.end()); + + allChosen.insert(chosen); + } + + // All items must be hit at least once ... very likely. + BOOST_CHECK_EQUAL(allChosen.size(), 3); +} + + +BOOST_AUTO_TEST_CASE(test_choice_empty) +{ + vector.clear(); + set.clear(); + BOOST_CHECK_THROW(simox::random::choice(vector), simox::error::SimoxError); + BOOST_CHECK_THROW(simox::random::choice(set), simox::error::SimoxError); +} + + +BOOST_AUTO_TEST_SUITE_END()