flatten 20260225
This commit is contained in:
236
tjp/core/random/Random.h
Executable file
236
tjp/core/random/Random.h
Executable file
@@ -0,0 +1,236 @@
|
||||
// TJP COPYRIGHT HEADER
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tjp/core/types/Types.h>
|
||||
#include <algorithm>
|
||||
#include <tjp/core/algorithm/numeric_limits.hpp>
|
||||
#include <tjp/core/system/System.h>
|
||||
|
||||
#define HAS_CPP_11
|
||||
#ifdef HAS_CPP_11
|
||||
|
||||
#include <random>
|
||||
|
||||
#else
|
||||
|
||||
#include <stdlib.h>
|
||||
namespace std {
|
||||
|
||||
class default_random_engine {
|
||||
|
||||
public:
|
||||
char operator ()() {
|
||||
return random();
|
||||
}
|
||||
|
||||
void seed(int seed=0) {}
|
||||
} ;
|
||||
|
||||
typedef default_random_engine random_device;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace tjp {
|
||||
namespace core {
|
||||
|
||||
namespace random_detail {
|
||||
|
||||
template<typename T>
|
||||
T abs_(T t) { return std::abs(t); }
|
||||
|
||||
template<>
|
||||
inline
|
||||
s128 abs_(s128 t) { return t > 0 ? t : -t; }
|
||||
|
||||
template<>
|
||||
inline
|
||||
constexpr u64 abs_(u64 t) { return t; }
|
||||
|
||||
template<>
|
||||
inline
|
||||
constexpr u32 abs_(u32 t) { return t; }
|
||||
|
||||
template<>
|
||||
inline
|
||||
constexpr u16 abs_(u16 t) { return t; }
|
||||
|
||||
template<>
|
||||
inline
|
||||
constexpr u8 abs_(u8 t) { return t; }
|
||||
|
||||
#if defined(SYS_APPLE) || defined(SYS_IOS)
|
||||
template<>
|
||||
inline
|
||||
constexpr size_t abs_(size_t t) { return t; }
|
||||
#endif
|
||||
|
||||
|
||||
} //
|
||||
|
||||
template<typename G>
|
||||
class Random {
|
||||
|
||||
public:
|
||||
using Generator = G;
|
||||
Generator generator;
|
||||
|
||||
template<typename T>
|
||||
T next () {
|
||||
T t;
|
||||
char *begin = (char *)&t;
|
||||
char *end = begin + sizeof(T);
|
||||
|
||||
fill(begin, end);
|
||||
return t;
|
||||
}
|
||||
|
||||
public:
|
||||
Random() {};
|
||||
|
||||
Random(Generator &&generator_) :
|
||||
generator(generator_)
|
||||
{
|
||||
}
|
||||
|
||||
auto generate()
|
||||
{
|
||||
return generator();
|
||||
}
|
||||
|
||||
char nextChar ()
|
||||
{
|
||||
return next<char>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T nextIndex (T r)
|
||||
{
|
||||
return nextInt<T>() % r;
|
||||
}
|
||||
|
||||
template<typename T=int>
|
||||
T nextInt ()
|
||||
{
|
||||
return random_detail::abs_(next<T>());
|
||||
}
|
||||
|
||||
template<typename T=int>
|
||||
T nextInt (T l, T r)
|
||||
{
|
||||
auto d = r - l + 1;
|
||||
return (random_detail::abs_(next<T>()) % d) + l;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T nextReal (T min=0, T max=1)
|
||||
{
|
||||
auto d = max - min;
|
||||
|
||||
constexpr auto random_max = numeric_limits_ext<T>::random_max;
|
||||
auto l = T(nextInt<u64>(0, random_max));
|
||||
auto r = T(random_max);
|
||||
auto v = l/r * d + min;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename T=int>
|
||||
T nextPositiveBits (size_t numBits)
|
||||
{
|
||||
auto v = next<T>();
|
||||
auto zeroBits = sizeof(v) * 8 - numBits;
|
||||
v = (v << zeroBits) >> zeroBits;
|
||||
return random_detail::abs_(v);
|
||||
}
|
||||
|
||||
template<typename T=int>
|
||||
T nextBits (size_t numBits)
|
||||
{
|
||||
auto v = next<T>();
|
||||
auto zeroBits = sizeof(v) * 8 - numBits;
|
||||
v = (v << zeroBits) >> zeroBits;
|
||||
return v;
|
||||
}
|
||||
|
||||
void fill (char *begin, char *end)
|
||||
{
|
||||
if (begin == end)
|
||||
return;
|
||||
|
||||
auto *i = begin;
|
||||
while (true)
|
||||
{
|
||||
auto v = generate();
|
||||
for (auto j=0; j<sizeof(v); ++j)
|
||||
{
|
||||
*i++ = (u8)v;
|
||||
v = v >> 8;
|
||||
|
||||
if (i == end)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RandomGeneratorSeeded
|
||||
{
|
||||
public:
|
||||
using Generator = T;
|
||||
Generator random;
|
||||
|
||||
public:
|
||||
RandomGeneratorSeeded () :
|
||||
random(std::random_device()())
|
||||
{
|
||||
}
|
||||
|
||||
RandomGeneratorSeeded(int seed) :
|
||||
random(seed)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
auto operator()()
|
||||
{
|
||||
return random();
|
||||
}
|
||||
} ;
|
||||
|
||||
using ReliableRandom = Random<RandomGeneratorSeeded<std::mt19937>>;
|
||||
using RealRandom = ReliableRandom;
|
||||
|
||||
using FastRandom = Random<RandomGeneratorSeeded<std::default_random_engine>>;
|
||||
|
||||
using StandardRandomAdapter = FastRandom;
|
||||
|
||||
extern StandardRandomAdapter StandardRandom;
|
||||
extern RealRandom StandardRealRandom;
|
||||
|
||||
#if 1
|
||||
template <class _RandomAccessIterator>
|
||||
void random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 g(rd());
|
||||
|
||||
std::shuffle(__first, __last, g);
|
||||
}
|
||||
#else
|
||||
template <class _RandomAccessIterator>
|
||||
void random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{
|
||||
std::random_shuffle(__first, __last);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#ifdef TJP_CORE_HEADER_ONLY_SINGLE_FILE
|
||||
#include "Random.cpp"
|
||||
#endif
|
||||
Reference in New Issue
Block a user