rand: add mwc64x generator

This commit is contained in:
Danny Robson 2016-06-30 18:15:05 +10:00
parent 3b82757e5c
commit 2e700e6444
4 changed files with 100 additions and 7 deletions

View File

@ -210,6 +210,8 @@ UTIL_FILES = \
rand/lcg.hpp \
rand/xorshift.cpp \
rand/xorshift.hpp \
rand/mwc64x.cpp \
rand/mwc64x.hpp \
random.cpp \
random.hpp \
random.ipp \

45
rand/mwc64x.cpp Normal file
View File

@ -0,0 +1,45 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/
#include "./mwc64x.hpp"
#include "../debug.hpp"
using util::rand::mwc64x;
///////////////////////////////////////////////////////////////////////////////
mwc64x::mwc64x (seed_type _seed):
m_state (_seed)
{
CHECK_NEZ (m_state);
}
///////////////////////////////////////////////////////////////////////////////
mwc64x::value_type
mwc64x::operator() (void)
{
CHECK_NEZ (m_state);
uint32_t c = m_state >> 32u;
uint32_t x = m_state & 0xFFFFFFFFu;
m_state = x * 4294883355ULL + c;
return x ^ c;
}

43
rand/mwc64x.hpp Normal file
View File

@ -0,0 +1,43 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __UTIL_RAND_MWC64X_HPP
#define __UTIL_RAND_MWC64X_HPP
#include <cstdint>
namespace util { namespace rand {
// multiply-with-carry style generator suitable for rapid seeking and
// GPU generation.
//
// as with all such style generators, the seed value is very important.
// 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;
mwc64x (seed_type);
value_type operator() (void);
private:
uint64_t m_state;
};
} }
#endif

View File

@ -1,5 +1,6 @@
#include "rand/xorshift.hpp"
#include "rand/lcg.hpp"
#include "rand/mwc64x.hpp"
#include "tap.hpp"
#include "maths.hpp"
@ -15,9 +16,9 @@ template <>
std::string
type_to_string<util::rand::xorshift<uint64_t>> (void) { return "xorshift<uint64_t>"; }
template <>
std::string
type_to_string<util::rand::lcg_t> (void) { return "lcg_t"; }
template <> std::string type_to_string<util::rand::lcg_t> (void) { return "lcg_t"; }
template <> std::string type_to_string<util::rand::mwc64x> (void) { return "mwc64x"; }
///////////////////////////////////////////////////////////////////////////////
@ -43,10 +44,11 @@ test_buckets (util::TAP::logger &tap, Args&& ...args)
for (unsigned i = 0; i < ITERATIONS; ++i)
++buckets[gen () & BUCKET_MASK];
tap.expect (std::find_if (std::cbegin (buckets),
std::cend (buckets),
[] (auto v) { return v < EXPECTED * 3 / 4; }) == std::cend (buckets),
"bucket counts for %s", type_to_string<G> ());
tap.expect (
std::find_if (std::cbegin (buckets),
std::cend (buckets),
[] (auto v) { return v < EXPECTED * 7 / 8; }) == std::cend (buckets),
"bucket counts for %s", type_to_string<G> ());
}
@ -59,6 +61,7 @@ main (int,char**)
test_buckets<util::rand::xorshift<uint32_t>> (tap, 0x1234u);
test_buckets<util::rand::xorshift<uint64_t>> (tap, 0x1234u);
test_buckets<util::rand::lcg_t> (tap, 0x1234u);
test_buckets<util::rand::mwc64x> (tap, 0x1234u);
return tap.status ();
}