Skip to content

Instantly share code, notes, and snippets.

@greenbagels
Last active February 21, 2017 19:42
Show Gist options
  • Save greenbagels/2efaf612b8540569a86e6c6075502103 to your computer and use it in GitHub Desktop.
Save greenbagels/2efaf612b8540569a86e6c6075502103 to your computer and use it in GitHub Desktop.
#ifndef XORSHIFT_H
#define XORSHIFT_H
#include <cstddef> //std::size_type
#include <limits> //std::numeric_limits
namespace xor
{
namespace detail
{
template <typename UIntType, std::size_t shiftlen, bool = shiftlen < static_cast<std::size_t>(std::numeric_limits<UIntType>::digits)>
struct Shift
{
static const UIntType value = 0;
};
template <typename UIntType, std::size_t shiftlen>
struct Shift<UIntType, shiftlen, true>
{
static const UIntType value = UIntType(1) << shiftlen;
};
}
template <typename UIntType, std::size_t UIntSize, std::size_t shft1, std::size_t shft2, std::size_t shft3>
class xor_engine
{
static_assert(std::is_unsigned<UIntType>::value, "template argument "
"substituting UIntType not an unsigned integral type");
static_assert(1u <= shft1 && shft1 <= std::numeric_limits<UIntType>::digits,
"template argument substituting shft1 out of bounds");
static_assert(1u <= shft2 && shft2 <= std::numeric_limits<UIntType>::digits,
"template argument substituting shft2 out of bounds");
static_assert(1u <= shft3 && shft3 <= std::numeric_limits<UIntType>::digits,
"template argument substituting shft3 out of bounds");
public:
typedef UIntType result_type;
static const result_type default_seed = 4385u; //Value in GCC's lib seems arbitrary, why not ours, too
explicit xor_engine(result_type initial_state = default_seed) : current_state{initial_state}
{
}
void seed(result_type initial_state = default_seed)
{
current_state = initial_state;
}
static constexpr result_type min()
{
return 0; //unsigned min
}
static constexpr result_type max()
{
return detail::Shift<result_type, UIntSize>::value-1;
//Just in case sizeof(UIntType) >= UIntSize/CHAR_BIT
}
void discard(unsigned long long num)
{
for(auto i = 0; i < num; ++i)
{
gen_rand();
}
}
static xor_engine& Instance()
{
static xor_engine engine;
return engine;
}
result_type operator()()
{
return gen_rand();
}
//TODO: Add comparison operator
private:
result_type gen_rand()
{ //TODO: Optimize out the &= if the sizes match
current_state ^= (current_state << shft1);
current_state &= max(); //cut off extra bits if size > UIntSize
current_state ^= (current_state >> shft2);
current_state ^= (current_state << shft3);
current_state &= max(); //cut again
return current_state;
}
result_type current_state;
};
typedef xor_engine<uint_fast32_t, 32, 2, 5, 15> xorshift_32;
typedef xor_engine<uint_fast64_t, 64, 10, 27, 59> xorshift_64;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment