LeviLamina
Loading...
Searching...
No Matches
RandomUtils.h
1#pragma once
2
3#include <cfloat>
4#include <concepts>
5#include <cstdint>
6#include <limits>
7#include <random>
8
9#include "pcg_cpp/pcg_extras.hpp"
10#include "pcg_cpp/pcg_random.hpp"
11
12#include "ll/api/base/StdInt.h"
13
14namespace ll::inline utils::random_utils {
15
16template <std::integral T>
17inline T rand(T upBound = 0) {
18 static pcg64 random{pcg_extras::seed_seq_from<std::random_device>{}};
19
20 constexpr auto digits = std::numeric_limits<T>::digits;
21 if (upBound != 0) {
22 return static_cast<T>(random(upBound));
23 } else if constexpr (digits != 64) {
24 static auto u = (uintmax_t)std::pow<ldouble>(2ull, digits);
25 return static_cast<T>(random(u));
26 } else {
27 return static_cast<T>(random());
28 }
29}
30template <std::floating_point T>
31inline T rand() {
32 union {
33 uintmax_t u;
34 T f;
35 } x;
36 auto r = rand<uintmax_t>();
37 x.f = std::numeric_limits<T>::max();
38 r &= x.u;
39 x.f = std::numeric_limits<T>::infinity();
40 r &= ~x.u;
41 x.f = static_cast<T>(1);
42 x.u |= r;
43 /* Trick from MTGP: generate a uniformly distributed
44 float number in [1,2) and subtract 1. */
45 return x.f - static_cast<T>(1);
46}
47template <std::floating_point T>
48inline T rand(T max) {
49 return rand<T>() * max;
50}
51template <class T>
52inline T rand(T min, T max) {
53 return min + rand<T>(max - min);
54}
55template <class T>
56inline T openIntervalRand(T min = 0, T max = 1) {
57 return rand<T>(std::nexttoward(min, std::numeric_limits<long double>::max()), max);
58}
59template <class T>
60inline T closeIntervalRand(T min = 0, T max = 1) {
61 return rand<T>(min, std::nexttoward(max, std::numeric_limits<long double>::max()));
62}
63template <class T>
64inline T rightCloseIntervalRand(T min = 0, T max = 1) {
65 return rand<T>(
66 std::nexttoward(min, std::numeric_limits<long double>::max()),
67 std::nexttoward(max, std::numeric_limits<long double>::max())
68 );
69}
70template <class T>
71inline T leftCloseIntervalRand(T min = 0, T max = 1) {
72 return rand<T>(min, max);
73}
74
75} // namespace ll::inline utils::random_utils