11#ifndef EIGEN_CXX11_TENSOR_TENSOR_RANDOM_H
12#define EIGEN_CXX11_TENSOR_TENSOR_RANDOM_H
17EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint64_t get_random_seed() {
18#if defined(EIGEN_GPU_COMPILE_PHASE)
21 gpu_assert(threadIdx.z == 0);
22 return blockIdx.x * blockDim.x + threadIdx.x
23 + gridDim.x * blockDim.x * (blockIdx.y * blockDim.y + threadIdx.y);
26 return random<uint64_t>();
30EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
unsigned PCG_XSH_RS_generator(uint64_t* state, uint64_t stream) {
32 uint64_t current = *state;
34 *state = current * 6364136223846793005ULL + (stream << 1 | 1);
36 return static_cast<unsigned>((current ^ (current >> 22)) >> (22 + (current >> 61)));
39EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint64_t PCG_XSH_RS_state(uint64_t seed) {
40 seed = seed ? seed : get_random_seed();
41 return seed * 6364136223846793005ULL + 0xda3e39cb94b95bdbULL;
44template <
typename T> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
45T RandomToTypeUniform(uint64_t* state, uint64_t stream) {
46 unsigned rnd = PCG_XSH_RS_generator(state, stream);
47 return static_cast<T
>(rnd);
51template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
52Eigen::half RandomToTypeUniform<Eigen::half>(uint64_t* state, uint64_t stream) {
54 unsigned rnd = PCG_XSH_RS_generator(state, stream);
55 const uint16_t half_bits =
static_cast<uint16_t
>(rnd & 0x3ffu) | (
static_cast<uint16_t
>(15) << 10);
56 Eigen::half result = Eigen::numext::bit_cast<Eigen::half>(half_bits);
58 return result - Eigen::half(1.0f);
61template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
62Eigen::bfloat16 RandomToTypeUniform<Eigen::bfloat16>(uint64_t* state, uint64_t stream) {
65 unsigned rnd = PCG_XSH_RS_generator(state, stream);
66 const uint16_t half_bits =
static_cast<uint16_t
>(rnd & 0x7fu) | (
static_cast<uint16_t
>(127) << 7);
67 Eigen::bfloat16 result = Eigen::numext::bit_cast<Eigen::bfloat16>(half_bits);
69 return result - Eigen::bfloat16(1.0f);
72template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
73float RandomToTypeUniform<float>(uint64_t* state, uint64_t stream) {
80 const unsigned rnd = PCG_XSH_RS_generator(state, stream);
81 result.raw = rnd & 0x7fffffu;
83 result.raw |= (
static_cast<uint32_t
>(127) << 23);
85 return result.fp - 1.0f;
88template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
89double RandomToTypeUniform<double>(uint64_t* state, uint64_t stream) {
98 unsigned rnd1 = PCG_XSH_RS_generator(state, stream) & 0xfffffu;
100 unsigned rnd2 = PCG_XSH_RS_generator(state, stream);
101 result.raw = (
static_cast<uint64_t
>(rnd1) << 32) | rnd2;
103 result.raw |= (
static_cast<uint64_t
>(1023) << 52);
105 return result.dp - 1.0;
108template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
109std::complex<float> RandomToTypeUniform<std::complex<float> >(uint64_t* state, uint64_t stream) {
110 return std::complex<float>(RandomToTypeUniform<float>(state, stream),
111 RandomToTypeUniform<float>(state, stream));
113template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
114std::complex<double> RandomToTypeUniform<std::complex<double> >(uint64_t* state, uint64_t stream) {
115 return std::complex<double>(RandomToTypeUniform<double>(state, stream),
116 RandomToTypeUniform<double>(state, stream));
119template <
typename T>
class UniformRandomGenerator {
121 static const bool PacketAccess =
true;
124 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE UniformRandomGenerator(
126 m_state = PCG_XSH_RS_state(seed);
127 #ifdef EIGEN_USE_SYCL
144 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE UniformRandomGenerator(
145 const UniformRandomGenerator& other) {
146 m_state = other.m_state;
147 #ifdef EIGEN_USE_SYCL
148 m_exec_once =other.m_exec_once;
152 template<
typename Index> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
153 T operator()(
Index i)
const {
154 #ifdef EIGEN_USE_SYCL
158 m_state += (i * 6364136223846793005ULL);
162 T result = RandomToTypeUniform<T>(&m_state, i);
166 template<
typename Packet,
typename Index> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
167 Packet packetOp(
Index i)
const {
168 const int packetSize = internal::unpacket_traits<Packet>::size;
169 EIGEN_ALIGN_MAX T values[packetSize];
170 #ifdef EIGEN_USE_SYCL
173 m_state += (i * 6364136223846793005ULL);
178 for (
int j = 0; j < packetSize; ++j) {
179 values[j] = RandomToTypeUniform<T>(&m_state, i);
181 return internal::pload<Packet>(values);
185 mutable uint64_t m_state;
186 #ifdef EIGEN_USE_SYCL
187 mutable bool m_exec_once;
191template <
typename Scalar>
192struct functor_traits<UniformRandomGenerator<Scalar> > {
195 Cost = 12 * NumTraits<Scalar>::AddCost *
196 ((
sizeof(Scalar) +
sizeof(float) - 1) /
sizeof(float)),
197 PacketAccess = UniformRandomGenerator<Scalar>::PacketAccess
203template <
typename T> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
204T RandomToTypeNormal(uint64_t* state, uint64_t stream) {
210 u = RandomToTypeUniform<T>(state, stream);
211 v = T(1.7156) * (RandomToTypeUniform<T>(state, stream) - T(0.5));
212 const T x = u - T(0.449871);
213 const T y = numext::abs(v) + T(0.386595);
214 q = x*x + y * (T(0.196)*y - T(0.25472)*x);
215 }
while (q > T(0.27597) &&
216 (q > T(0.27846) || v*v > T(-4) * numext::log(u) * u*u));
221template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
222std::complex<float> RandomToTypeNormal<std::complex<float> >(uint64_t* state, uint64_t stream) {
223 return std::complex<float>(RandomToTypeNormal<float>(state, stream),
224 RandomToTypeNormal<float>(state, stream));
226template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
227std::complex<double> RandomToTypeNormal<std::complex<double> >(uint64_t* state, uint64_t stream) {
228 return std::complex<double>(RandomToTypeNormal<double>(state, stream),
229 RandomToTypeNormal<double>(state, stream));
233template <
typename T>
class NormalRandomGenerator {
235 static const bool PacketAccess =
true;
238 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE NormalRandomGenerator(uint64_t seed = 0) {
239 m_state = PCG_XSH_RS_state(seed);
240 #ifdef EIGEN_USE_SYCL
254 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE NormalRandomGenerator(
255 const NormalRandomGenerator& other) {
256 m_state = other.m_state;
258 m_exec_once=other.m_exec_once;
262 template<
typename Index> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
263 T operator()(
Index i)
const {
264 #ifdef EIGEN_USE_SYCL
267 m_state += (i * 6364136223846793005ULL);
271 T result = RandomToTypeNormal<T>(&m_state, i);
275 template<
typename Packet,
typename Index> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
276 Packet packetOp(
Index i)
const {
277 const int packetSize = internal::unpacket_traits<Packet>::size;
278 EIGEN_ALIGN_MAX T values[packetSize];
279 #ifdef EIGEN_USE_SYCL
282 m_state += (i * 6364136223846793005ULL);
287 for (
int j = 0; j < packetSize; ++j) {
288 values[j] = RandomToTypeNormal<T>(&m_state, i);
290 return internal::pload<Packet>(values);
294 mutable uint64_t m_state;
295 #ifdef EIGEN_USE_SYCL
296 mutable bool m_exec_once;
301template <
typename Scalar>
302struct functor_traits<NormalRandomGenerator<Scalar> > {
306 Cost = 3 * functor_traits<UniformRandomGenerator<Scalar> >::Cost +
307 15 * NumTraits<Scalar>::AddCost + 8 * NumTraits<Scalar>::AddCost +
308 3 * functor_traits<scalar_log_op<Scalar> >::Cost / 2,
309 PacketAccess = NormalRandomGenerator<Scalar>::PacketAccess
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index