/** * @file RandUtils.h * @author bab2min (bab2min@gmail.com) * @brief * @version 0.4.1 * @date 2022-08-13 * * @copyright Copyright (c) 2020-2021 * */ #ifndef EIGENRAND_RAND_UTILS_H #define EIGENRAND_RAND_UTILS_H #include "MorePacketMath.h" #include "PacketFilter.h" #include "PacketRandomEngine.h" namespace Eigen { namespace internal { template::type::result_type, Rand::RandomEngineType reType = Rand::GetRandomEngineType< typename std::remove_reference::type >::value> struct RawbitsMaker; template struct UniformRealUtils; template struct RandUtils : public UniformRealUtils { EIGEN_STRONG_INLINE PacketType balanced(Rng& rng) { return psub(pmul(this->zero_to_one(rng), pset1(2)), pset1(1)); } template EIGEN_STRONG_INLINE PacketType balanced(Rng& rng, Scalar slope, Scalar bias) { return padd(pmul(this->zero_to_one(rng), pset1(slope)), pset1(bias)); } EIGEN_STRONG_INLINE PacketType nonzero_uniform_real(Rng& rng) { constexpr auto epsilon = std::numeric_limits::type>::epsilon() / 8; return padd(this->uniform_real(rng), pset1(epsilon)); } }; template struct scalar_rng_adaptor { static_assert( Rand::IsScalarFullBitRandomEngine< typename std::remove_reference::type >::value || Rand::IsPacketRandomEngine< typename std::remove_reference::type >::value, "Rng must satisfy RandomNumberEngine" ); Gen gen; Rng rng; scalar_rng_adaptor(const Rng& _rng) : rng{ _rng } { } template scalar_rng_adaptor(const Rng& _rng, _Gen&& _gen) : gen{ _gen }, rng{ _rng } { } scalar_rng_adaptor(const scalar_rng_adaptor& o) = default; scalar_rng_adaptor(scalar_rng_adaptor&& o) = default; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const _Scalar operator() () const { return gen(rng); } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const { return gen.template packetOp(rng); } }; template struct scalar_rng_adaptor { static_assert( Rand::IsScalarFullBitRandomEngine< typename std::remove_reference::type >::value || Rand::IsPacketRandomEngine< typename std::remove_reference::type >::value, "Rng must satisfy RandomNumberEngine" ); mutable Gen gen; Rng rng; scalar_rng_adaptor(const Rng& _rng) : rng{ _rng } { } template scalar_rng_adaptor(const Rng& _rng, _Gen&& _gen) : gen{ _gen }, rng{ _rng } { } scalar_rng_adaptor(const scalar_rng_adaptor& o) = default; scalar_rng_adaptor(scalar_rng_adaptor&& o) = default; EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const _Scalar operator() () const { return gen(rng); } template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp() const { return gen.template packetOp(rng); } }; template struct functor_traits > { enum { Cost = HugeCost, PacketAccess = packet_traits<_Scalar>::Vectorizable, IsRepeatable = false }; }; } } #ifdef EIGEN_VECTORIZE_AVX #include "arch/AVX/RandUtils.h" #endif #ifdef EIGEN_VECTORIZE_SSE2 #include "arch/SSE/RandUtils.h" #endif #ifdef EIGEN_VECTORIZE_NEON #include "arch/NEON/RandUtils.h" #endif namespace Eigen { namespace internal { EIGEN_STRONG_INLINE uint32_t collect_upper8bits(uint32_t a, uint32_t b, uint32_t c) { return ((a & 0xFF000000) >> 24) | ((b & 0xFF000000) >> 16) | ((c & 0xFF000000) >> 8); } } } #if defined(DEBUG) || defined(_DEBUG) #define EIGENRAND_CHECK_INFINITY_LOOP() do { assert(_i < 100); } while(0) #else #define EIGENRAND_CHECK_INFINITY_LOOP() #endif #endif