Skip to content

Commit

Permalink
Move util_random.hpp > util/random.hpp
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoinePrv committed Jan 15, 2024
1 parent 8ab10ef commit 2ba4665
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 107 deletions.
3 changes: 2 additions & 1 deletion libmamba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ set(
${LIBMAMBA_SOURCE_DIR}/util/os_win.cpp
${LIBMAMBA_SOURCE_DIR}/util/parsers.cpp
${LIBMAMBA_SOURCE_DIR}/util/path_manip.cpp
${LIBMAMBA_SOURCE_DIR}/util/random.cpp
${LIBMAMBA_SOURCE_DIR}/util/string.cpp
${LIBMAMBA_SOURCE_DIR}/util/url.cpp
${LIBMAMBA_SOURCE_DIR}/util/url_manip.cpp
Expand Down Expand Up @@ -278,6 +279,7 @@ set(
${LIBMAMBA_INCLUDE_DIR}/mamba/util/os_win.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/parsers.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/path_manip.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/random.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/string.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/tuple_hash.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/type_traits.hpp
Expand Down Expand Up @@ -342,7 +344,6 @@ set(
${LIBMAMBA_INCLUDE_DIR}/mamba/core/util.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/fsutil.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/util_os.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/util_random.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/util_scope.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/virtual_packages.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/core/env_lockfile.hpp
Expand Down
60 changes: 0 additions & 60 deletions libmamba/include/mamba/core/util_random.hpp

This file was deleted.

84 changes: 84 additions & 0 deletions libmamba/include/mamba/util/random.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) 2019, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifndef MAMBA_UTIL_RANDOM_HPP
#define MAMBA_UTIL_RANDOM_HPP

#include <algorithm>
#include <array>
#include <cstring>
#include <limits>
#include <random>
#include <string>
#include <string_view>

namespace mamba::util
{
using default_random_generator = std::mt19937;

template <typename Generator>
[[nodiscard]] auto random_generator() -> Generator;

[[nodiscard]] auto random_generator() -> default_random_generator;

template <typename Generator>
auto local_random_generator() -> Generator&;

auto local_random_generator() -> default_random_generator&;

template <typename T = int, typename Generator = default_random_generator>
auto random_int(T min, T max, Generator& generator = local_random_generator()) -> T;

template <typename Generator>
auto generate_random_alphanumeric_string(std::size_t len, Generator& generator) -> std::string;

auto generate_random_alphanumeric_string(std::size_t len) -> std::string;

/********************
* Implementation *
********************/

template <typename Generator>
auto random_generator() -> Generator
{
using std::begin;
using std::end;
constexpr auto seed_bits = sizeof(typename Generator::result_type) * Generator::state_size;
constexpr auto seed_len = seed_bits / std::numeric_limits<std::seed_seq::result_type>::digits;
auto seed = std::array<std::seed_seq::result_type, seed_len>{};
auto dev = std::random_device{};
std::generate_n(begin(seed), seed_len, std::ref(dev));
auto seed_seq = std::seed_seq(begin(seed), end(seed));
return Generator{ seed_seq };
}

template <typename Generator>
auto local_random_generator() -> Generator&
{
thread_local auto rng = random_generator<Generator>();
return rng;
}

template <typename T, typename Generator>
auto random_int(T min, T max, Generator& generator) -> T
{
return std::uniform_int_distribution<T>{ min, max }(generator);
}

template <typename Generator>
auto generate_random_alphanumeric_string(std::size_t len, Generator& generator) -> std::string
{
static constexpr auto chars = std::string_view{
"0123456789"
"abcdefghijklmnopqrstuvwxyz",
};
auto dist = std::uniform_int_distribution{ {}, chars.size() - 1 };
auto result = std::string(len, '\0');
std::generate_n(begin(result), len, [&]() { return chars[dist(generator)]; });
return result;
}
}
#endif
25 changes: 25 additions & 0 deletions libmamba/src/util/random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) 2019, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#include "mamba/util/random.hpp"

namespace mamba ::util
{
auto random_generator() -> default_random_generator
{
return random_generator<default_random_generator>();
}

auto local_random_generator() -> default_random_generator&
{
return local_random_generator<default_random_generator>();
}

auto generate_random_alphanumeric_string(std::size_t len) -> std::string
{
return generate_random_alphanumeric_string(len, local_random_generator());
}
}
1 change: 1 addition & 0 deletions libmamba/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ set(
src/util/test_os_win.cpp
src/util/test_path_manip.cpp
src/util/test_parsers.cpp
src/util/test_random.cpp
src/util/test_string.cpp
src/util/test_tuple_hash.cpp
src/util/test_type_traits.cpp
Expand Down
46 changes: 0 additions & 46 deletions libmamba/tests/src/core/test_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include "mamba/core/context.hpp"
#include "mamba/core/fsutil.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/util_random.hpp"
#include "mamba/core/util_scope.hpp"
#include "mamba/fs/filesystem.hpp"
#include "mamba/util/path_manip.hpp"
Expand All @@ -18,51 +17,6 @@

namespace mamba
{
TEST_SUITE("local_random_generator")
{
TEST_CASE("one_rng_per_thread_and_type")
{
auto same_thread_checks = []
{
auto& a = local_random_generator();
auto& b = local_random_generator();
CHECK_EQ(&a, &b);

auto& c = local_random_generator<std::mt19937>();
CHECK_EQ(&a, &c);

auto& d = local_random_generator<std::mt19937_64>();
CHECK_NE(static_cast<void*>(&a), static_cast<void*>(&d));

return &a;
};
void* pointer_to_this_thread_rng = same_thread_checks();

void* pointer_to_another_thread_rng = nullptr;
std::thread another_thread{ [&]
{ pointer_to_another_thread_rng = same_thread_checks(); } };
another_thread.join();

CHECK_NE(pointer_to_this_thread_rng, pointer_to_another_thread_rng);
}
}

TEST_SUITE("random_int")
{
TEST_CASE("value_in_range")
{
constexpr int arbitrary_min = -20;
constexpr int arbitrary_max = 20;
constexpr int attempts = 2000;
for (int i = 0; i < attempts; ++i)
{
const int value = random_int(arbitrary_min, arbitrary_max);
REQUIRE_GE(value, arbitrary_min);
REQUIRE_LE(value, arbitrary_max);
}
}
}

TEST_SUITE("on_scope_exit")
{
TEST_CASE("basics")
Expand Down
70 changes: 70 additions & 0 deletions libmamba/tests/src/util/test_random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#include <thread>

#include <doctest/doctest.h>

#include "mamba/util/random.hpp"
#include "mamba/util/string.hpp"

using namespace mamba::util;

TEST_SUITE("util::random")
{
TEST_CASE("local_random_generator")
{
auto same_thread_checks = []
{
auto& a = local_random_generator();
auto& b = local_random_generator();
CHECK_EQ(&a, &b);

auto& c = local_random_generator<std::mt19937>();
CHECK_EQ(&a, &c);

auto& d = local_random_generator<std::mt19937_64>();
CHECK_NE(static_cast<void*>(&a), static_cast<void*>(&d));

return &a;
};
void* pointer_to_this_thread_rng = same_thread_checks();

void* pointer_to_another_thread_rng = nullptr;
std::thread another_thread{ [&] { pointer_to_another_thread_rng = same_thread_checks(); } };
another_thread.join();

CHECK_NE(pointer_to_this_thread_rng, pointer_to_another_thread_rng);
}

TEST_CASE("value_in_range")
{
constexpr int arbitrary_min = -20;
constexpr int arbitrary_max = 20;
constexpr std::size_t attempts = 2000;
for (std::size_t i = 0; i < attempts; ++i)
{
const int value = random_int(arbitrary_min, arbitrary_max);
CHECK_GE(value, arbitrary_min);
CHECK_LE(value, arbitrary_max);
}
}

TEST_CASE("random_alphanumeric_string")
{
constexpr std::size_t attempts = 200;
for (std::size_t i = 0; i < attempts; ++i)
{
const auto value = generate_random_alphanumeric_string(i);
CHECK_EQ(value.size(), i);
CHECK(std::all_of(
value.cbegin(),
value.cend(),
[](char c) { return is_digit(c) || is_alpha(c); }
));
}
}
}

0 comments on commit 2ba4665

Please sign in to comment.