LiteLoaderBDS-1.16.40/LiteLoader/Header/Utils/RNG.h
2023-02-04 01:03:36 +08:00

135 lines
3.7 KiB
C++

/**
* @file RNG.h
* @author OEOTYAN (https://github.com/OEOTYAN)
* @brief Random Number Generator
*
* @copyright Created by OEOTYAN on 2022/09/03.
*
*/
#pragma once
#include "Global.h"
#include <pcg/pcg_random.hpp>
namespace RNG {
template <class T>
inline T rand() {
static pcg64 rng(pcg_extras::seed_seq_from<std::random_device>{});
return static_cast<T>(rng());
}
template <class T>
inline T rand(T min, T max) {
static pcg64 rng(pcg_extras::seed_seq_from<std::random_device>{});
return min + static_cast<T>(rng(max - min + 1));
}
template <>
inline bool rand() {
static pcg32 rng(pcg_extras::seed_seq_from<std::random_device>{});
return static_cast<bool>(rng(2));
}
template <>
inline uint32_t rand() {
static pcg32 rng(pcg_extras::seed_seq_from<std::random_device>{});
return rng();
}
template <>
inline uint32_t rand(uint32_t min, uint32_t max) {
static pcg32 rng(pcg_extras::seed_seq_from<std::random_device>{});
return min + rng(max - min + 1);
}
template <>
inline int32_t rand() {
static pcg32 rng(pcg_extras::seed_seq_from<std::random_device>{});
return static_cast<int32_t>(rng());
}
template <>
inline int32_t rand(int32_t min, int32_t max) {
static pcg32 rng(pcg_extras::seed_seq_from<std::random_device>{});
return (static_cast<int64_t>(min) + rng(static_cast<uint32_t>(static_cast<int64_t>(max) - min + 1)));
}
template <>
inline int64_t rand() {
static pcg64 rng(pcg_extras::seed_seq_from<std::random_device>{});
return static_cast<int64_t>(rng());
}
template <>
inline int64_t rand(int64_t min, int64_t max) {
static pcg64 rng(pcg_extras::seed_seq_from<std::random_device>{});
return min + static_cast<int64_t>(rng(static_cast<uint64_t>(max - min + 1)));
}
template <>
inline uint64_t rand() {
static pcg64 rng(pcg_extras::seed_seq_from<std::random_device>{});
return rng();
}
template <>
inline uint64_t rand(uint64_t min, uint64_t max) {
static pcg64 rng(pcg_extras::seed_seq_from<std::random_device>{});
return min + rng(max - min + 1);
}
template <>
inline float rand() {
union {
uint32_t u;
float f;
} x;
x.u = (rand<uint32_t>() >> 9u) | 0x3f800000u;
/* Trick from MTGP: generate an uniformly distributed
single precision number in [1,2) and subtract 1. */
return x.f - 1.0f;
}
template <>
inline float rand(float min, float max) {
return min + rand<float>() * (max - min);
}
template <>
inline double rand() {
union {
uint64_t u;
double f;
} x;
x.u = (rand<uint64_t>() >> 12ull) | 0x3ff0000000000000ull;
/* Trick from MTGP: generate an uniformly distributed
single precision number in [1,2) and subtract 1. */
return x.f - 1.0;
}
template <>
inline double rand(double min, double max) {
return min + rand<double>() * (max - min);
}
template <class T>
inline T openIntervalRand(T min = 0, T max = 1) {
return rand<T>(std::nexttoward(min, LDBL_MAX), max);
}
template <class T>
inline T closeIntervalRand(T min = 0, T max = 1) {
return rand<T>(min, std::nexttoward(max, LDBL_MAX));
}
template <class T>
inline T rightCloseIntervalRand(T min = 0, T max = 1) {
return rand<T>(std::nexttoward(min, LDBL_MAX), std::nexttoward(max, LDBL_MAX));
}
template <class T>
inline T leftCloseIntervalRand(T min = 0, T max = 1) {
return rand<T>(min, max);
}
} // namespace RNG