rand: conform to the std generator concept

This commit is contained in:
Danny Robson 2019-02-21 20:53:07 +11:00
parent 7746463c5a
commit 8f88569f61
7 changed files with 39 additions and 75 deletions

View File

@ -3,7 +3,7 @@
* 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/.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
*/
#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>
void

View File

@ -3,14 +3,15 @@
* 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/.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_RAND_LCG_HPP
#define __UTIL_RAND_LCG_HPP
#pragma once
#include "../std.hpp"
#include <cstdint>
#include <type_traits>
#include <limits>
namespace cruft::rand {
@ -25,14 +26,13 @@ namespace cruft::rand {
public:
using result_type = T;
static_assert (std::is_unsigned<T>::value,
"LCG generates integer overflow which is undefined behaviour for signed types");
static_assert (std::is_unsigned_v<T>);
explicit lcg (T seed);
result_type operator() (void);
static result_type min (void);
static result_type max (void);
static constexpr auto min (void) { return std::numeric_limits<T>::min (); }
static constexpr auto max (void) { return std::numeric_limits<T>::max (); }
void discard (unsigned);
@ -40,8 +40,6 @@ namespace cruft::rand {
T m_x;
};
// glibc: typedef lcg<uint32_t, pow2(31), 1103515245, 12345> lcg_t;
using lcg_t = lcg<uint64_t,0u,6364136223846793005ul, 1ul>;
// glibc: typedef lcg<u64, pow2(31), 1103515245, 12345> lcg_t;
using lcg_t = lcg<u64,0u,6364136223846793005ul, 1ul>;
}
#endif

View File

@ -23,7 +23,7 @@ mwc64x::mwc64x (seed_type _seed):
///////////////////////////////////////////////////////////////////////////////
mwc64x::value_type
mwc64x::result_type
mwc64x::operator() (void)
{
CHECK_NEZ (m_state);

View File

@ -3,13 +3,16 @@
* 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/.
*
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
* Copyright 2016-2019 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_RAND_MWC64X_HPP
#define __UTIL_RAND_MWC64X_HPP
#pragma once
#include "../std.hpp"
#include <cstdint>
#include <limits>
namespace cruft::rand {
// 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.
struct mwc64x {
public:
using value_type = uint32_t;
using seed_type = uint64_t;
using result_type = u32;
using seed_type = u64;
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:
uint64_t m_state;
};
}
#endif

View File

@ -3,7 +3,7 @@
* 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/.
*
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
*/
#include "xorshift.hpp"
@ -63,23 +63,6 @@ xorshift<T>::operator() (void)
CHECK_NEZ (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 ();
}

View File

@ -3,35 +3,33 @@
* 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/.
*
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
* Copyright 2015-2019 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_RAND_XORSHIFT_HPP
#define __UTIL_RAND_XORSHIFT_HPP
#pragma once
#include <limits>
namespace cruft::rand {
// 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
// updates. internal constants may change across releases
template <typename T>
template <typename ValueT>
struct xorshift {
public:
using result_type = T;
using result_type = ValueT;
explicit xorshift (T seed);
explicit xorshift (ValueT seed);
result_type operator() (void);
static result_type min (void);
static result_type max (void);
static constexpr result_type min (void) noexcept { return 1u; }
static constexpr auto max (void) noexcept { return std::numeric_limits<result_type>::max (); }
void discard (unsigned);
private:
T m_state;
ValueT m_state;
};
}
#endif

View File

@ -34,15 +34,15 @@ test_buckets (cruft::TAP::logger &tap, Args&& ...args)
{
constexpr unsigned BUCKET_BITS = 8u;
constexpr size_t BUCKET_COUNT = 1u << BUCKET_BITS;
constexpr unsigned BUCKET_MASK = BUCKET_COUNT - 1u;
constexpr unsigned EXPECTED = 1024u;
constexpr unsigned ITERATIONS = BUCKET_COUNT * EXPECTED;
unsigned buckets[BUCKET_COUNT] = {};
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)
++buckets[gen () & BUCKET_MASK];
++buckets[dist (gen)];
tap.expect (
std::find_if (std::cbegin (buckets),