11#ifndef EIGEN_CXX11_TENSOR_TENSOR_RANDOM_H
12#define EIGEN_CXX11_TENSOR_TENSOR_RANDOM_H
15#include "./InternalHeaderCheck.h"
20EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint64_t get_random_seed() {
21#if defined(EIGEN_GPU_COMPILE_PHASE)
24 gpu_assert(threadIdx.z == 0);
25 return blockIdx.x * blockDim.x + threadIdx.x + gridDim.x * blockDim.x * (blockIdx.y * blockDim.y + threadIdx.y);
28 return random<uint64_t>();
32EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
unsigned PCG_XSH_RS_generator(uint64_t* state, uint64_t stream) {
34 uint64_t current = *state;
36 *state = current * 6364136223846793005ULL + (stream << 1 | 1);
38 return static_cast<unsigned>((current ^ (current >> 22)) >> (22 + (current >> 61)));
41EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint64_t PCG_XSH_RS_state(uint64_t seed) {
42 seed = seed ? seed : get_random_seed();
43 return seed * 6364136223846793005ULL + 0xda3e39cb94b95bdbULL;
47EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T RandomToTypeUniform(uint64_t* state, uint64_t stream) {
48 unsigned rnd = PCG_XSH_RS_generator(state, stream);
49 return static_cast<T
>(rnd);
53EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool RandomToTypeUniform<bool>(uint64_t* state, uint64_t stream) {
54 unsigned rnd = PCG_XSH_RS_generator(state, stream);
55 return (rnd & 0x1) != 0;
59EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::half RandomToTypeUniform<Eigen::half>(uint64_t* state, uint64_t stream) {
61 unsigned rnd = PCG_XSH_RS_generator(state, stream);
62 const uint16_t half_bits =
static_cast<uint16_t
>(rnd & 0x3ffu) | (
static_cast<uint16_t
>(15) << 10);
63 Eigen::half result = Eigen::numext::bit_cast<Eigen::half>(half_bits);
65 return result - Eigen::half(1.0f);
69EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Eigen::bfloat16 RandomToTypeUniform<Eigen::bfloat16>(uint64_t* state,
72 unsigned rnd = PCG_XSH_RS_generator(state, stream);
73 const uint16_t half_bits =
static_cast<uint16_t
>(rnd & 0x7fu) | (
static_cast<uint16_t
>(127) << 7);
74 Eigen::bfloat16 result = Eigen::numext::bit_cast<Eigen::bfloat16>(half_bits);
76 return result - Eigen::bfloat16(1.0f);
80EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
float RandomToTypeUniform<float>(uint64_t* state, uint64_t stream) {
87 const unsigned rnd = PCG_XSH_RS_generator(state, stream);
88 result.raw = rnd & 0x7fffffu;
90 result.raw |= (
static_cast<uint32_t
>(127) << 23);
92 return result.fp - 1.0f;
96EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
double RandomToTypeUniform<double>(uint64_t* state, uint64_t stream) {
105 unsigned rnd1 = PCG_XSH_RS_generator(state, stream) & 0xfffffu;
107 unsigned rnd2 = PCG_XSH_RS_generator(state, stream);
108 result.raw = (
static_cast<uint64_t
>(rnd1) << 32) | rnd2;
110 result.raw |= (
static_cast<uint64_t
>(1023) << 52);
112 return result.dp - 1.0;
116EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex<float> RandomToTypeUniform<std::complex<float> >(uint64_t* state,
118 return std::complex<float>(RandomToTypeUniform<float>(state, stream), RandomToTypeUniform<float>(state, stream));
121EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex<double> RandomToTypeUniform<std::complex<double> >(uint64_t* state,
123 return std::complex<double>(RandomToTypeUniform<double>(state, stream), RandomToTypeUniform<double>(state, stream));
127class UniformRandomGenerator {
129 static constexpr bool PacketAccess =
true;
132 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE UniformRandomGenerator(uint64_t seed = 0) {
133 m_state = PCG_XSH_RS_state(seed);
151 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE UniformRandomGenerator(
const UniformRandomGenerator& other) {
152 m_state = other.m_state;
154 m_exec_once = other.m_exec_once;
158 template <
typename Index>
159 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(
Index i)
const {
164 m_state += (i * 6364136223846793005ULL);
168 T result = RandomToTypeUniform<T>(&m_state, i);
172 template <
typename Packet,
typename Index>
173 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(
Index i)
const {
174 const int packetSize = internal::unpacket_traits<Packet>::size;
175 EIGEN_ALIGN_MAX T values[packetSize];
179 m_state += (i * 6364136223846793005ULL);
184 for (
int j = 0; j < packetSize; ++j) {
185 values[j] = RandomToTypeUniform<T>(&m_state, i);
187 return internal::pload<Packet>(values);
191 mutable uint64_t m_state;
193 mutable bool m_exec_once;
197template <
typename Scalar>
198struct functor_traits<UniformRandomGenerator<Scalar> > {
201 Cost = 12 * NumTraits<Scalar>::AddCost * ((
sizeof(Scalar) +
sizeof(float) - 1) /
sizeof(float)),
202 PacketAccess = UniformRandomGenerator<Scalar>::PacketAccess
207EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T RandomToTypeNormal(uint64_t* state, uint64_t stream) {
213 u = RandomToTypeUniform<T>(state, stream);
214 v = T(1.7156) * (RandomToTypeUniform<T>(state, stream) - T(0.5));
215 const T x = u - T(0.449871);
216 const T y = numext::abs(v) + T(0.386595);
217 q = x * x + y * (T(0.196) * y - T(0.25472) * x);
218 }
while (q > T(0.27597) && (q > T(0.27846) || v * v > T(-4) * numext::log(u) * u * u));
224EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex<float> RandomToTypeNormal<std::complex<float> >(uint64_t* state,
226 return std::complex<float>(RandomToTypeNormal<float>(state, stream), RandomToTypeNormal<float>(state, stream));
229EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::complex<double> RandomToTypeNormal<std::complex<double> >(uint64_t* state,
231 return std::complex<double>(RandomToTypeNormal<double>(state, stream), RandomToTypeNormal<double>(state, stream));
235class NormalRandomGenerator {
237 static constexpr bool PacketAccess =
true;
240 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE NormalRandomGenerator(uint64_t seed = 0) {
241 m_state = PCG_XSH_RS_state(seed);
256 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE NormalRandomGenerator(
const NormalRandomGenerator& other) {
257 m_state = other.m_state;
259 m_exec_once = other.m_exec_once;
263 template <
typename Index>
264 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(
Index i)
const {
268 m_state += (i * 6364136223846793005ULL);
272 T result = RandomToTypeNormal<T>(&m_state, i);
276 template <
typename Packet,
typename Index>
277 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(
Index i)
const {
278 const int packetSize = internal::unpacket_traits<Packet>::size;
279 EIGEN_ALIGN_MAX T values[packetSize];
283 m_state += (i * 6364136223846793005ULL);
288 for (
int j = 0; j < packetSize; ++j) {
289 values[j] = RandomToTypeNormal<T>(&m_state, i);
291 return internal::pload<Packet>(values);
295 mutable uint64_t m_state;
297 mutable bool m_exec_once;
301template <
typename Scalar>
302struct functor_traits<NormalRandomGenerator<Scalar> > {
306 Cost = 3 * functor_traits<UniformRandomGenerator<Scalar> >::Cost + 15 * NumTraits<Scalar>::AddCost +
307 8 * NumTraits<Scalar>::AddCost + 3 * functor_traits<scalar_log_op<Scalar> >::Cost / 2,
308 PacketAccess = NormalRandomGenerator<Scalar>::PacketAccess
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index