18#ifndef TRINITY_CONTAINERS_H
19#define TRINITY_CONTAINERS_H
58 throw std::out_of_range(
"index");
66 template <std::ranges::forward_range C>
70 if (elementsToProcess <= requestedSize)
73 auto keepIt = std::ranges::begin(container), curIt = std::ranges::begin(container);
75 while (elementsToProcess)
78 if (
urand(1, elementsToProcess) <= elementsToKeep)
81 *keepIt = std::move(*curIt);
88 container.erase(keepIt, std::ranges::end(container));
91 template <std::ranges::forward_range C, invocable_r<
bool, std::ranges::range_reference_t<C>> Predicate>
92 void RandomResize(C& container, Predicate&& predicate, std::size_t requestedSize)
96 std::ranges::copy_if(container, std::inserter(containerCopy, std::ranges::end(containerCopy)), std::forward<Predicate>(predicate));
101 container = std::move(containerCopy);
109 template <std::ranges::input_range C>
112 auto it = std::ranges::begin(container);
113 std::ranges::advance(it,
urand(0,
uint32(std::ranges::distance(container)) - 1));
126 template <std::ranges::input_range C>
129 auto it = std::ranges::begin(container);
130 std::ranges::advance(it,
urandweighted(weights.size(), weights.data()));
142 template <std::ranges::input_range C, invocable_r<
double, std::ranges::range_reference_t<C>> Fn>
145 std::size_t
size = std::ranges::distance(container);
147 double* weights =
new double[
size];
148 double weightSum = 0.0;
149 for (
auto const& val : container)
151 double weight = weightExtractor(val);
152 weights[i++] = weight;
156 auto it = std::ranges::begin(container);
170 template <std::random_access_iterator Iterator>
183 template <std::ranges::random_access_range C>
186 RandomShuffle(std::ranges::begin(container), std::ranges::end(container));
201 template <std::input_iterator Iterator1, std::sentinel_for<Iterator1> Sentinel1,
202 std::input_iterator Iterator2, std::sentinel_for<Iterator2> Sentinel2>
203 inline constexpr bool Intersects(Iterator1 first1, Sentinel1 last1, Iterator2 first2, Sentinel2 last2)
205 while (first1 != last1 && first2 != last2)
207 if (*first1 < *first2)
209 else if (*first2 < *first1)
231 template <std::input_iterator Iterator1, std::sentinel_for<Iterator1> Sentinel1,
232 std::input_iterator Iterator2, std::sentinel_for<Iterator2> Sentinel2,
233 invocable_r<
bool, std::iter_reference_t<Iterator1>, std::iter_reference_t<Iterator2>> Predicate>
234 inline constexpr bool Intersects(Iterator1 first1, Sentinel1 last1, Iterator2 first2, Sentinel2 last2, Predicate&& equalPred)
236 while (first1 != last1 && first2 != last2)
238 if (*first1 < *first2)
240 else if (*first2 < *first1)
242 else if (!std::invoke(std::forward<Predicate>(equalPred), *first1, *first2))
253 template <
typename Container,
typename Predicate>
256 auto wpos = c.begin();
257 for (
auto rpos = c.begin(), end = c.end(); rpos != end; ++rpos)
262 std::swap(*rpos, *wpos);
266 c.erase(wpos, c.end());
269 template <
typename Container,
typename Predicate>
272 for (
auto it = c.begin(); it != c.end();)
282 template <std::ranges::forward_range Container, invocable_r<
bool, std::ranges::range_reference_t<Container>> Predicate>
283 inline constexpr void EraseIf(Container& c, Predicate p)
requires requires { c.erase(c.begin(), c.end()); }
285 if constexpr (std::is_move_assignable_v<
decltype(*c.begin())>)
298 template <
typename T>
313 template <
typename T>
314 inline constexpr decltype(
auto)
EnsureWritableVectorIndex(std::vector<T>& vec,
typename std::vector<T>::size_type i, T
const& resizeDefault)
317 vec.resize(i + 1, resizeDefault);
uint32 urandweighted(size_t count, double const *chances)
uint32 urand(uint32 min, uint32 max)
static RandomEngine & Instance()
CheckedBufferOutputIterator operator++(int)
CheckedBufferOutputIterator & operator++()
std::ptrdiff_t difference_type
std::output_iterator_tag iterator_category
CheckedBufferOutputIterator(T *buf, size_t n)
constexpr void EraseIfMoveAssignable(Container &c, Predicate &p)
constexpr void EraseIfNotMoveAssignable(Container &c, Predicate &p)
auto SelectRandomWeightedContainerElement(C const &container, std::span< double > const &weights) -> decltype(std::ranges::begin(container))
constexpr void EraseIf(Container &c, Predicate p)
void RandomShuffle(Iterator begin, Iterator end)
Reorder the elements of the iterator range randomly.
auto SelectRandomContainerElement(C const &container) -> std::add_const_t< decltype(*std::ranges::begin(container))> &
constexpr decltype(auto) EnsureWritableVectorIndex(std::vector< T > &vec, typename std::vector< T >::size_type i)
void RandomResize(C &container, std::size_t requestedSize)
constexpr bool Intersects(Iterator1 first1, Sentinel1 last1, Iterator2 first2, Sentinel2 last2)
constexpr std::size_t size()