sandbox
Loading...
Searching...
No Matches
random.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_MATH_RANDOM_HPP_
3#define LIBSBX_MATH_RANDOM_HPP_
4
5#include <random>
6#include <ranges>
7#include <concepts>
8#include <limits>
9
11#include <libsbx/math/vector2.hpp>
12#include <libsbx/math/vector3.hpp>
13#include <libsbx/math/color.hpp>
15
16namespace sbx::math {
17
18class random {
19
20public:
21
22 using generator_type = std::mt19937;
23
24 random() = delete;
25
26 template<numeric Type>
27 static auto next(Type min = std::numeric_limits<Type>::min(), Type max = std::numeric_limits<Type>::max()) -> Type {
28 using distribution_type = std::conditional_t<std::floating_point<Type>, std::uniform_real_distribution<Type>, std::uniform_int_distribution<Type>>;
29
30 auto distribution = distribution_type{min, max};
31
32 return distribution(_generator());
33 }
34
35 template<integral Seed>
36 static auto seed(const Seed seed) -> void {
37 _generator().seed(static_cast<generator_type::result_type>(seed));
38 }
39
40private:
41
42 static auto _generator() -> generator_type& {
43 static auto device = std::random_device{};
44 static auto generator = generator_type{device()};
45
46 return generator;
47 }
48
49}; // struct random
50
51template<std::ranges::random_access_range Range>
52auto shuffle_range(Range& range) -> void {
53 for (auto i = std::ranges::size(range); i > 1u; --i) {
54 const auto j = sbx::math::random::next<std::size_t>(0u, i - 1u);
55
56 std::swap(range[i - 1u], range[j]);
57 }
58}
59
60template<std::ranges::sized_range Range>
61auto random_element(const Range& range) -> std::ranges::range_value_t<Range> {
62 const auto size = static_cast<std::ranges::range_difference_t<Range>>(std::ranges::size(range));
63 const auto index = random::next<std::ranges::range_difference_t<Range>>(0, size - 1);
64
65 return *std::next(std::begin(range), index);
66}
67
68template<scalar Type>
69auto random_point_in_circle(const basic_vector2<Type>& center, const Type radius) -> basic_vector2<Type> {
70 const auto r = radius * std::sqrt(random::next<Type>(Type{0}, Type{1}));
71 const auto theta = random::next<Type>(Type{0}, Type{2} * std::numbers::pi_v<Type>);
72
73 return center + basic_vector2<Type>{r * std::cos(theta), r * std::sin(theta)};
74}
75
76template<scalar Type>
77auto random_point_on_circle(const basic_vector2<Type>& center, const Type radius) -> basic_vector2<Type> {
78 const auto theta = random::next<Type>(Type{0}, Type{2} * std::numbers::pi_v<Type>);
79
80 return center + basic_vector2<Type>{radius * std::cos(theta), radius * std::sin(theta)};
81}
82
83template<scalar Type>
84auto random_point_in_sphere(const basic_vector3<Type>& center, const Type radius) -> basic_vector3<Type> {
85 const auto r = radius * std::cbrt(random::next<Type>(Type{0}, Type{1}));
86 const auto theta = random::next<Type>(Type{0}, Type{2} * std::numbers::pi_v<Type>);
87 const auto phi = random::next<Type>(Type{0}, std::numbers::pi_v<Type>);
88
89 const auto x = r * std::sin(phi) * std::cos(theta);
90 const auto y = r * std::sin(phi) * std::sin(theta);
91 const auto z = r * std::cos(phi);
92
93 return center + basic_vector3<Type>{x, y, z};
94}
95
96auto random_color(const std::float_t alpha = 1.0f) -> color;
97
98} // namespace sbx::math
99
100#endif // LIBSBX_MATH_RANDOM_HPP_
Definition: random.hpp:18
RGBA color representation and utilities.
Core numeric concepts and type traits.