random: remove typed randomisers without generators

This commit is contained in:
Danny Robson 2016-11-17 18:25:46 +11:00
parent 9a6a406fa2
commit 246357e279
8 changed files with 27 additions and 214 deletions

View File

@ -216,7 +216,6 @@ UTIL_FILES = \
rand/mwc64x.hpp \ rand/mwc64x.hpp \
random.cpp \ random.cpp \
random.hpp \ random.hpp \
random.ipp \
range.cpp \ range.cpp \
range.hpp \ range.hpp \
range.ipp \ range.ipp \
@ -435,7 +434,6 @@ TEST_BIN = \
test/pool \ test/pool \
test/quaternion \ test/quaternion \
test/rand/buckets \ test/rand/buckets \
test/random \
test/range \ test/range \
test/rational \ test/rational \
test/region \ test/region \

View File

@ -18,7 +18,6 @@
#include "./debug.hpp" #include "./debug.hpp"
#include "./range.hpp" #include "./range.hpp"
#include "./random.hpp"
#include <array> #include <array>
#include <map> #include <map>
@ -361,24 +360,6 @@ namespace json { namespace tree {
} } } }
//-----------------------------------------------------------------------------
namespace util {
template<>
colour4f
random (void) {
return colour4f ({ range<float>::UNIT.random (),
range<float>::UNIT.random (),
range<float>::UNIT.random (),
range<float>::UNIT.random () });
}
template <>
colour4f&
randomise (colour4f &c)
{ return c = random<colour4f> (); }
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t S, typename T>
std::ostream& std::ostream&

View File

@ -47,9 +47,9 @@ tmpname (std::string &str, size_t length)
"0123456789"; "0123456789";
str.resize (length); str.resize (length);
std::generate_n (str.begin (), std::generate_n (str.begin (), length, [&] (void) {
length, return util::rand::choose (alphanum);
[&] (void) { return util::choose (alphanum); }); });
} }

View File

@ -11,49 +11,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* Copyright 2010 Danny Robson <danny@nerdcruft.net> * Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/ */
#include "random.hpp" #include "random.hpp"
#include "range.hpp"
#include <type_traits>
using namespace util;
namespace util {
template <typename T>
T
random (void) {
static_assert (std::is_integral<T>::value, "random should only operate on integral types");
return range<T>::UNLIMITED.random ();
}
template <>
double
random (void)
{ return range<double>::UNIT.random (); }
template <>
float
random (void)
{ return range<float>::UNIT.random (); }
template <>
bool
random (void)
{ return rand () & 0x01; }
template <typename T>
T&
randomise (T &val)
{ return val = util::random<T> (); }
}
template double util::random (void);
template float util::random (void);
template uint64_t util::random (void);
template uint32_t util::random (void);
template uint16_t util::random (void);

View File

@ -11,50 +11,40 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* Copyright 2010 Danny Robson <danny@nerdcruft.net> * Copyright 2016 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef __UTIL_RANDOM_HPP #ifndef __UTIL_RANDOM_HPP
#define __UTIL_RANDOM_HPP #define __UTIL_RANDOM_HPP
#include <iterator> #include <random>
namespace util {
template <typename T>
T& randomise (T &);
template <typename T, size_t N> ///////////////////////////////////////////////////////////////////////////////
T* randomise (T(&)[N]); namespace util::rand {
//-------------------------------------------------------------------------
using default_generator = std::minstd_rand;
template <typename T>
T random (void);
template <typename T> //-------------------------------------------------------------------------
typename T::value_type& template <typename Generator = default_generator>
choose (T &container) { Generator&
typename T::iterator cursor = container.begin (); thread_engine (void)
typename T::size_type size = container.size (); {
typename T::size_type offset = random<typename T::size_type> () % size; std::random_device rd;
thread_local Generator gen (rd ());
std::advance (cursor, offset); return gen;
return *cursor;
} }
template <typename T, size_t N>
//-------------------------------------------------------------------------
template <typename Generator = default_generator, typename T, size_t N>
T& T&
choose (T (&v)[N]) { choose (T (&t)[N], Generator gen = thread_engine<Generator> ())
return v[static_cast<size_t> (random<float> () * N)]; {
} std::uniform_int_distribution<size_t> dist (0, N-1);
return t[dist (gen)];
template <typename T>
typename T::value_type&
choose (T begin, T end) {
typename T::difference_type size = std::distance (begin, end);
std::advance (begin, random<T::size_type> () % size);
return *begin;
} }
} }
#include "random.ipp"
#endif #endif

View File

@ -1,33 +0,0 @@
/*
* 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 2010 Danny Robson <danny@nerdcruft.net>
*/
#ifdef __UTIL_RANDOM_IPP
#error Double inclusion of util/random.ipp
#endif
#define __UTIL_RANDOM_IPP
//-----------------------------------------------------------------------------
namespace util {
template <typename T, size_t N>
T* randomise (T (&array)[N]) {
for (auto &i: array)
i = random<T> ();
return array;
}
}

View File

@ -1,69 +0,0 @@
#include "random.hpp"
#include "debug.hpp"
#include "tap.hpp"
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
///////////////////////////////////////////////////////////////////////////////
// TODO: Use a more robust test like Chi-Square
void
test_bool (util::TAP::logger &tap)
{
static const unsigned ITERATIONS = 8192;
static const unsigned THRESHOLD = ITERATIONS / 10;
unsigned counts[2] = { 0, 0 };
for (unsigned i = 0; i < ITERATIONS; ++i)
++counts[util::random<bool> () ? 0 : 1];
unsigned diff = counts[0] > counts[1] ?
counts[0] - counts[1] :
counts[1] - counts[0];
tap.expect_lt (diff, THRESHOLD, "approximately even bool distribution");
}
///////////////////////////////////////////////////////////////////////////////
// TODO: Use a more robust test like Kolmogorov-Smirnov
void
test_float (util::TAP::logger &tap)
{
static const unsigned BUCKETS = 8;
static const unsigned ITERATIONS = 8912;
static const unsigned EXPECTED = ITERATIONS / BUCKETS;
static const float THRESHOLD = EXPECTED / 10;
unsigned counts[BUCKETS] = { 0 };
for (unsigned i = 0; i < ITERATIONS; ++i)
++counts[unsigned (util::random<float> () * BUCKETS)];
bool success = true;
for (unsigned c: counts) {
unsigned diff = EXPECTED > c ?
EXPECTED - c :
c - EXPECTED;
success = success && diff < THRESHOLD;
}
tap.expect (success, "approximately equal float buckets");
}
///////////////////////////////////////////////////////////////////////////////
int
main (int, char **) {
util::TAP::logger tap;
srand (0u);
test_bool (tap);
test_float (tap);
return tap.status ();
}

View File

@ -17,7 +17,6 @@
#include "vector.hpp" #include "vector.hpp"
#include "debug.hpp" #include "debug.hpp"
#include "random.hpp"
#include "json/tree.hpp" #include "json/tree.hpp"
@ -177,17 +176,5 @@ INSTANTIATE(double)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
namespace util { template vector<2,float> util::polar_to_cartesian (util::vector<2,float>);
template vector<2,float> polar_to_cartesian (util::vector<2,float>); template vector<2,float> util::cartesian_to_polar (util::vector<2,float>);
template vector<2,float> cartesian_to_polar (util::vector<2,float>);
template <> vector<1,float> random (void) { util::vector<1,float> out; randomise (out.data); return out; }
template <> vector<2,float> random (void) { util::vector<2,float> out; randomise (out.data); return out; }
template <> vector<3,float> random (void) { util::vector<3,float> out; randomise (out.data); return out; }
template <> vector<4,float> random (void) { util::vector<4,float> out; randomise (out.data); return out; }
template <> vector<1,double> random (void) { util::vector<1,double> out; randomise (out.data); return out; }
template <> vector<2,double> random (void) { util::vector<2,double> out; randomise (out.data); return out; }
template <> vector<3,double> random (void) { util::vector<3,double> out; randomise (out.data); return out; }
template <> vector<4,double> random (void) { util::vector<4,double> out; randomise (out.data); return out; }
}