10#ifndef EIGEN_RANDOM_IMPL_H
11#define EIGEN_RANDOM_IMPL_H
14#include "./InternalHeaderCheck.h"
24template <
typename Scalar,
bool IsComplex,
bool IsInteger>
25struct random_default_impl {};
27template <
typename Scalar>
28struct random_impl : random_default_impl<Scalar, NumTraits<Scalar>::IsComplex, NumTraits<Scalar>::IsInteger> {};
30template <
typename Scalar>
35template <
typename Scalar>
36inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random(
const Scalar& x,
const Scalar& y) {
37 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run(x, y);
40template <
typename Scalar>
41inline EIGEN_MATHFUNC_RETVAL(random, Scalar) random() {
42 return EIGEN_MATHFUNC_IMPL(random, Scalar)::run();
46struct eigen_random_device {
47 using ReturnType = int;
48 static constexpr int Entropy = meta_floor_log2<(
unsigned int)(RAND_MAX) + 1>::value;
49 static constexpr ReturnType Highest = RAND_MAX;
50 static EIGEN_DEVICE_FUNC
inline ReturnType run() {
return std::rand(); }
54template <
typename Scalar>
55struct random_bits_impl {
56 EIGEN_STATIC_ASSERT(std::is_unsigned<Scalar>::value, SCALAR MUST BE A BUILT - IN UNSIGNED INTEGER)
57 using RandomDevice = eigen_random_device;
58 using RandomReturnType =
typename RandomDevice::ReturnType;
59 static constexpr int kEntropy = RandomDevice::Entropy;
60 static constexpr int kTotalBits =
sizeof(Scalar) * CHAR_BIT;
62 static EIGEN_DEVICE_FUNC
inline Scalar run(
int numRandomBits) {
63 eigen_assert((numRandomBits >= 0) && (numRandomBits <= kTotalBits));
64 const Scalar mask = Scalar(-1) >> ((kTotalBits - numRandomBits) & (kTotalBits - 1));
65 Scalar randomBits = 0;
66 for (
int shift = 0; shift < numRandomBits; shift += kEntropy) {
67 RandomReturnType r = RandomDevice::run();
68 randomBits |=
static_cast<Scalar
>(r) << shift;
76template <
typename BitsType>
77EIGEN_DEVICE_FUNC
inline BitsType getRandomBits(
int numRandomBits) {
78 return random_bits_impl<BitsType>::run(numRandomBits);
82template <typename Scalar, bool BuiltIn = std::is_floating_point<Scalar>::value>
83struct random_float_impl {
84 using BitsType =
typename numext::get_integer_by_size<
sizeof(Scalar)>::unsigned_type;
85 static constexpr EIGEN_DEVICE_FUNC
inline int mantissaBits() {
86 const int digits = NumTraits<Scalar>::digits();
89 static EIGEN_DEVICE_FUNC
inline Scalar run(
int numRandomBits) {
90 eigen_assert(numRandomBits >= 0 && numRandomBits <= mantissaBits());
91 BitsType randomBits = getRandomBits<BitsType>(numRandomBits);
93 randomBits <<= (mantissaBits() - numRandomBits);
95 randomBits |= numext::bit_cast<BitsType>(Scalar(2));
97 Scalar result = numext::bit_cast<Scalar>(randomBits) - Scalar(3);
104template <
typename Scalar>
105struct random_float_impl<Scalar, false> {
106 static EIGEN_DEVICE_FUNC
inline int mantissaBits() {
107 const int digits = NumTraits<Scalar>::digits();
108 constexpr int kDoubleDigits = NumTraits<double>::digits();
109 return numext::mini(digits, kDoubleDigits) - 1;
111 static EIGEN_DEVICE_FUNC
inline Scalar run(
int numRandomBits) {
112 eigen_assert(numRandomBits >= 0 && numRandomBits <= mantissaBits());
113 Scalar result =
static_cast<Scalar
>(random_float_impl<double>::run(numRandomBits));
120template <
bool Specialize = (
sizeof(
long double) == 2 *
sizeof(uint64_t)) &&
121 ((std::numeric_limits<long double>::digits != (2 * std::numeric_limits<double>::digits)))>
122struct random_longdouble_impl {
123 static constexpr int Size =
sizeof(
long double);
124 static constexpr EIGEN_DEVICE_FUNC
inline int mantissaBits() {
return NumTraits<long double>::digits() - 1; }
125 static EIGEN_DEVICE_FUNC
inline long double run(
int numRandomBits) {
126 eigen_assert(numRandomBits >= 0 && numRandomBits <= mantissaBits());
127 EIGEN_USING_STD(memcpy);
128 int numLowBits = numext::mini(numRandomBits, 64);
129 int numHighBits = numext::maxi(numRandomBits - 64, 0);
130 uint64_t randomBits[2];
131 long double result = 2.0L;
132 memcpy(&randomBits, &result, Size);
133 randomBits[0] |= getRandomBits<uint64_t>(numLowBits);
134 randomBits[1] |= getRandomBits<uint64_t>(numHighBits);
135 memcpy(&result, &randomBits, Size);
141struct random_longdouble_impl<false> {
142 static constexpr EIGEN_DEVICE_FUNC
inline int mantissaBits() {
return NumTraits<double>::digits() - 1; }
143 static EIGEN_DEVICE_FUNC
inline long double run(
int numRandomBits) {
144 return static_cast<long double>(random_float_impl<double>::run(numRandomBits));
148struct random_float_impl<long double> : random_longdouble_impl<> {};
150template <
typename Scalar>
151struct random_default_impl<Scalar, false, false> {
152 using Impl = random_float_impl<Scalar>;
153 static EIGEN_DEVICE_FUNC
inline Scalar run(
const Scalar& x,
const Scalar& y,
int numRandomBits) {
154 Scalar half_x = Scalar(0.5) * x;
155 Scalar half_y = Scalar(0.5) * y;
156 Scalar result = (half_x + half_y) + (half_y - half_x) * run(numRandomBits);
160 static EIGEN_DEVICE_FUNC
inline Scalar run(
const Scalar& x,
const Scalar& y) {
161 return run(x, y, Impl::mantissaBits());
163 static EIGEN_DEVICE_FUNC
inline Scalar run(
int numRandomBits) {
return Impl::run(numRandomBits); }
164 static EIGEN_DEVICE_FUNC
inline Scalar run() {
return run(Impl::mantissaBits()); }
167template <typename Scalar, bool IsSigned = NumTraits<Scalar>::IsSigned,
bool BuiltIn = std::is_integral<Scalar>::value>
168struct random_int_impl;
171template <
typename Scalar>
172struct random_int_impl<Scalar, false, true> {
173 static constexpr int kTotalBits =
sizeof(Scalar) * CHAR_BIT;
174 static EIGEN_DEVICE_FUNC
inline Scalar run(
const Scalar& x,
const Scalar& y) {
175 if (y <= x)
return x;
176 Scalar range = y - x;
178 if (range == NumTraits<Scalar>::highest())
return run();
179 Scalar count = range + 1;
181 int numRandomBits = log2_ceil(count);
184 randomBits = getRandomBits<Scalar>(numRandomBits);
187 }
while (randomBits >= count);
188 Scalar result = x + randomBits;
191 static EIGEN_DEVICE_FUNC
inline Scalar run() {
return getRandomBits<Scalar>(kTotalBits); }
195template <
typename Scalar>
196struct random_int_impl<Scalar, true, true> {
197 static constexpr int kTotalBits =
sizeof(Scalar) * CHAR_BIT;
198 using BitsType =
typename make_unsigned<Scalar>::type;
199 static EIGEN_DEVICE_FUNC
inline Scalar run(
const Scalar& x,
const Scalar& y) {
200 if (y <= x)
return x;
202 BitsType range =
static_cast<BitsType
>(y) -
static_cast<BitsType
>(x);
203 BitsType randomBits = random_int_impl<BitsType>::run(0, range);
206 Scalar result =
static_cast<Scalar
>(
static_cast<BitsType
>(x) + randomBits);
209 static EIGEN_DEVICE_FUNC
inline Scalar run() {
return static_cast<Scalar
>(getRandomBits<BitsType>(kTotalBits)); }
213template <
typename Scalar,
bool IsSigned>
214struct random_int_impl<Scalar, IsSigned, false> {
215 static EIGEN_DEVICE_FUNC
inline Scalar run(
const Scalar&,
const Scalar&) {
return run(); }
216 static EIGEN_DEVICE_FUNC
inline Scalar run() {
217 eigen_assert(std::false_type::value &&
"RANDOM FOR CUSTOM INTEGERS NOT YET SUPPORTED");
222template <
typename Scalar>
223struct random_default_impl<Scalar, false, true> : random_int_impl<Scalar> {};
226struct random_impl<bool> {
227 static EIGEN_DEVICE_FUNC
inline bool run(
const bool& x,
const bool& y) {
228 if (y <= x)
return x;
231 static EIGEN_DEVICE_FUNC
inline bool run() {
return getRandomBits<unsigned>(1) ? true :
false; }
234template <
typename Scalar>
235struct random_default_impl<Scalar, true, false> {
236 typedef typename NumTraits<Scalar>::Real RealScalar;
237 using Impl = random_impl<RealScalar>;
238 static EIGEN_DEVICE_FUNC
inline Scalar run(
const Scalar& x,
const Scalar& y,
int numRandomBits) {
239 return Scalar(Impl::run(x.real(), y.real(), numRandomBits), Impl::run(x.imag(), y.imag(), numRandomBits));
241 static EIGEN_DEVICE_FUNC
inline Scalar run(
const Scalar& x,
const Scalar& y) {
242 return Scalar(Impl::run(x.real(), y.real()), Impl::run(x.imag(), y.imag()));
244 static EIGEN_DEVICE_FUNC
inline Scalar run(
int numRandomBits) {
245 return Scalar(Impl::run(numRandomBits), Impl::run(numRandomBits));
247 static EIGEN_DEVICE_FUNC
inline Scalar run() {
return Scalar(Impl::run(), Impl::run()); }
Namespace containing all symbols from the Eigen library.
Definition Core:137