rand: conform to the std generator concept
This commit is contained in:
parent
7746463c5a
commit
8f88569f61
20
rand/lcg.cpp
20
rand/lcg.cpp
@ -3,7 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*
|
*
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lcg.hpp"
|
#include "lcg.hpp"
|
||||||
@ -50,24 +50,6 @@ lcg<T,M,A,C>::operator() (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T, T M, T A, T C>
|
|
||||||
typename lcg<T,M,A,C>::result_type
|
|
||||||
lcg<T,M,A,C>::min (void)
|
|
||||||
{
|
|
||||||
return std::numeric_limits<result_type>::min ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T, T M, T A, T C>
|
|
||||||
typename lcg<T,M,A,C>::result_type
|
|
||||||
lcg<T,M,A,C>::max (void)
|
|
||||||
{
|
|
||||||
return std::numeric_limits<result_type>::max ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T, T M, T A, T C>
|
template <typename T, T M, T A, T C>
|
||||||
void
|
void
|
||||||
|
22
rand/lcg.hpp
22
rand/lcg.hpp
@ -3,14 +3,15 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*
|
*
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_RAND_LCG_HPP
|
#pragma once
|
||||||
#define __UTIL_RAND_LCG_HPP
|
|
||||||
|
#include "../std.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
namespace cruft::rand {
|
namespace cruft::rand {
|
||||||
@ -25,14 +26,13 @@ namespace cruft::rand {
|
|||||||
public:
|
public:
|
||||||
using result_type = T;
|
using result_type = T;
|
||||||
|
|
||||||
static_assert (std::is_unsigned<T>::value,
|
static_assert (std::is_unsigned_v<T>);
|
||||||
"LCG generates integer overflow which is undefined behaviour for signed types");
|
|
||||||
explicit lcg (T seed);
|
explicit lcg (T seed);
|
||||||
|
|
||||||
result_type operator() (void);
|
result_type operator() (void);
|
||||||
|
|
||||||
static result_type min (void);
|
static constexpr auto min (void) { return std::numeric_limits<T>::min (); }
|
||||||
static result_type max (void);
|
static constexpr auto max (void) { return std::numeric_limits<T>::max (); }
|
||||||
|
|
||||||
void discard (unsigned);
|
void discard (unsigned);
|
||||||
|
|
||||||
@ -40,8 +40,6 @@ namespace cruft::rand {
|
|||||||
T m_x;
|
T m_x;
|
||||||
};
|
};
|
||||||
|
|
||||||
// glibc: typedef lcg<uint32_t, pow2(31), 1103515245, 12345> lcg_t;
|
// glibc: typedef lcg<u64, pow2(31), 1103515245, 12345> lcg_t;
|
||||||
using lcg_t = lcg<uint64_t,0u,6364136223846793005ul, 1ul>;
|
using lcg_t = lcg<u64,0u,6364136223846793005ul, 1ul>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -23,7 +23,7 @@ mwc64x::mwc64x (seed_type _seed):
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
mwc64x::value_type
|
mwc64x::result_type
|
||||||
mwc64x::operator() (void)
|
mwc64x::operator() (void)
|
||||||
{
|
{
|
||||||
CHECK_NEZ (m_state);
|
CHECK_NEZ (m_state);
|
||||||
|
@ -3,13 +3,16 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*
|
*
|
||||||
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2016-2019 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_RAND_MWC64X_HPP
|
#pragma once
|
||||||
#define __UTIL_RAND_MWC64X_HPP
|
|
||||||
|
#include "../std.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
namespace cruft::rand {
|
namespace cruft::rand {
|
||||||
// multiply-with-carry style generator suitable for rapid seeking and
|
// multiply-with-carry style generator suitable for rapid seeking and
|
||||||
@ -19,17 +22,17 @@ namespace cruft::rand {
|
|||||||
// don't allow either half of the uint64_t to be zero.
|
// don't allow either half of the uint64_t to be zero.
|
||||||
struct mwc64x {
|
struct mwc64x {
|
||||||
public:
|
public:
|
||||||
using value_type = uint32_t;
|
using result_type = u32;
|
||||||
using seed_type = uint64_t;
|
using seed_type = u64;
|
||||||
|
|
||||||
explicit mwc64x (seed_type);
|
explicit mwc64x (seed_type);
|
||||||
|
|
||||||
value_type operator() (void);
|
result_type operator() (void);
|
||||||
|
|
||||||
|
static constexpr auto max (void) noexcept { return std::numeric_limits<result_type>::max (); }
|
||||||
|
static constexpr auto min (void) noexcept { return std::numeric_limits<result_type>::min (); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t m_state;
|
uint64_t m_state;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*
|
*
|
||||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xorshift.hpp"
|
#include "xorshift.hpp"
|
||||||
@ -63,23 +63,6 @@ xorshift<T>::operator() (void)
|
|||||||
|
|
||||||
CHECK_NEZ (m_state);
|
CHECK_NEZ (m_state);
|
||||||
return m_state;
|
return m_state;
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
typename xorshift<T>::result_type
|
|
||||||
xorshift<T>::min (void)
|
|
||||||
{
|
|
||||||
return 1u;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
typename xorshift<T>::result_type
|
|
||||||
xorshift<T>::max (void)
|
|
||||||
{
|
|
||||||
return std::numeric_limits<T>::max ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,35 +3,33 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*
|
*
|
||||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_RAND_XORSHIFT_HPP
|
#pragma once
|
||||||
#define __UTIL_RAND_XORSHIFT_HPP
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace cruft::rand {
|
namespace cruft::rand {
|
||||||
// implements a naive xorshift random generator.
|
// implements a naive xorshift random generator.
|
||||||
//
|
//
|
||||||
// * does not comply with the c++11 rng class requirements
|
|
||||||
// * users may not rely on identical output across executions or library
|
// * users may not rely on identical output across executions or library
|
||||||
// updates. internal constants may change across releases
|
// updates. internal constants may change across releases
|
||||||
template <typename T>
|
template <typename ValueT>
|
||||||
struct xorshift {
|
struct xorshift {
|
||||||
public:
|
public:
|
||||||
using result_type = T;
|
using result_type = ValueT;
|
||||||
|
|
||||||
explicit xorshift (T seed);
|
explicit xorshift (ValueT seed);
|
||||||
|
|
||||||
result_type operator() (void);
|
result_type operator() (void);
|
||||||
|
|
||||||
static result_type min (void);
|
static constexpr result_type min (void) noexcept { return 1u; }
|
||||||
static result_type max (void);
|
static constexpr auto max (void) noexcept { return std::numeric_limits<result_type>::max (); }
|
||||||
|
|
||||||
void discard (unsigned);
|
void discard (unsigned);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T m_state;
|
ValueT m_state;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
@ -34,15 +34,15 @@ test_buckets (cruft::TAP::logger &tap, Args&& ...args)
|
|||||||
{
|
{
|
||||||
constexpr unsigned BUCKET_BITS = 8u;
|
constexpr unsigned BUCKET_BITS = 8u;
|
||||||
constexpr size_t BUCKET_COUNT = 1u << BUCKET_BITS;
|
constexpr size_t BUCKET_COUNT = 1u << BUCKET_BITS;
|
||||||
constexpr unsigned BUCKET_MASK = BUCKET_COUNT - 1u;
|
|
||||||
constexpr unsigned EXPECTED = 1024u;
|
constexpr unsigned EXPECTED = 1024u;
|
||||||
constexpr unsigned ITERATIONS = BUCKET_COUNT * EXPECTED;
|
constexpr unsigned ITERATIONS = BUCKET_COUNT * EXPECTED;
|
||||||
|
|
||||||
unsigned buckets[BUCKET_COUNT] = {};
|
|
||||||
G gen (std::forward<Args> (args)...);
|
G gen (std::forward<Args> (args)...);
|
||||||
|
std::uniform_int_distribution<int> dist (0, BUCKET_COUNT - 1);
|
||||||
|
|
||||||
|
unsigned buckets[BUCKET_COUNT] = {};
|
||||||
for (unsigned i = 0; i < ITERATIONS; ++i)
|
for (unsigned i = 0; i < ITERATIONS; ++i)
|
||||||
++buckets[gen () & BUCKET_MASK];
|
++buckets[dist (gen)];
|
||||||
|
|
||||||
tap.expect (
|
tap.expect (
|
||||||
std::find_if (std::cbegin (buckets),
|
std::find_if (std::cbegin (buckets),
|
||||||
|
Loading…
Reference in New Issue
Block a user