diff --git a/Makefile.am b/Makefile.am index a443ef24..020110e5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -216,7 +216,6 @@ UTIL_FILES = \ rand/mwc64x.hpp \ random.cpp \ random.hpp \ - random.ipp \ range.cpp \ range.hpp \ range.ipp \ @@ -435,7 +434,6 @@ TEST_BIN = \ test/pool \ test/quaternion \ test/rand/buckets \ - test/random \ test/range \ test/rational \ test/region \ diff --git a/colour.cpp b/colour.cpp index 2e6afee7..70a514e7 100644 --- a/colour.cpp +++ b/colour.cpp @@ -18,7 +18,6 @@ #include "./debug.hpp" #include "./range.hpp" -#include "./random.hpp" #include #include @@ -361,24 +360,6 @@ namespace json { namespace tree { } } -//----------------------------------------------------------------------------- -namespace util { - template<> - colour4f - random (void) { - return colour4f ({ range::UNIT.random (), - range::UNIT.random (), - range::UNIT.random (), - range::UNIT.random () }); - } - - template <> - colour4f& - randomise (colour4f &c) - { return c = random (); } -} - - /////////////////////////////////////////////////////////////////////////////// template std::ostream& diff --git a/memory/buffer/circular.cpp b/memory/buffer/circular.cpp index 2f8a5948..457db4fe 100644 --- a/memory/buffer/circular.cpp +++ b/memory/buffer/circular.cpp @@ -47,9 +47,9 @@ tmpname (std::string &str, size_t length) "0123456789"; str.resize (length); - std::generate_n (str.begin (), - length, - [&] (void) { return util::choose (alphanum); }); + std::generate_n (str.begin (), length, [&] (void) { + return util::rand::choose (alphanum); + }); } diff --git a/random.cpp b/random.cpp index d182aa8d..451e2124 100644 --- a/random.cpp +++ b/random.cpp @@ -11,49 +11,8 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2010 Danny Robson + * Copyright 2016 Danny Robson */ - #include "random.hpp" -#include "range.hpp" - -#include - -using namespace util; - -namespace util { - template - T - random (void) { - static_assert (std::is_integral::value, "random should only operate on integral types"); - return range::UNLIMITED.random (); - } - - template <> - double - random (void) - { return range::UNIT.random (); } - - template <> - float - random (void) - { return range::UNIT.random (); } - - template <> - bool - random (void) - { return rand () & 0x01; } - - template - T& - randomise (T &val) - { return val = util::random (); } -} - -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); diff --git a/random.hpp b/random.hpp index 1a6fda47..b2bbe4a5 100644 --- a/random.hpp +++ b/random.hpp @@ -11,50 +11,40 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2010 Danny Robson + * Copyright 2016 Danny Robson */ #ifndef __UTIL_RANDOM_HPP #define __UTIL_RANDOM_HPP -#include +#include -namespace util { - template - T& randomise (T &); - template - T* randomise (T(&)[N]); +/////////////////////////////////////////////////////////////////////////////// +namespace util::rand { + //------------------------------------------------------------------------- + using default_generator = std::minstd_rand; - template - T random (void); - template - typename T::value_type& - choose (T &container) { - typename T::iterator cursor = container.begin (); - typename T::size_type size = container.size (); - typename T::size_type offset = random () % size; - - std::advance (cursor, offset); - return *cursor; + //------------------------------------------------------------------------- + template + Generator& + thread_engine (void) + { + std::random_device rd; + thread_local Generator gen (rd ()); + return gen; } - template + + //------------------------------------------------------------------------- + template T& - choose (T (&v)[N]) { - return v[static_cast (random () * N)]; - } - - template - typename T::value_type& - choose (T begin, T end) { - typename T::difference_type size = std::distance (begin, end); - std::advance (begin, random () % size); - return *begin; + choose (T (&t)[N], Generator gen = thread_engine ()) + { + std::uniform_int_distribution dist (0, N-1); + return t[dist (gen)]; } } -#include "random.ipp" - #endif diff --git a/random.ipp b/random.ipp deleted file mode 100644 index 95ffadf7..00000000 --- a/random.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_RANDOM_IPP -#error Double inclusion of util/random.ipp -#endif - -#define __UTIL_RANDOM_IPP - - -//----------------------------------------------------------------------------- -namespace util { - template - T* randomise (T (&array)[N]) { - for (auto &i: array) - i = random (); - return array; - } -} - diff --git a/test/random.cpp b/test/random.cpp deleted file mode 100644 index 7bb7dafd..00000000 --- a/test/random.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "random.hpp" -#include "debug.hpp" -#include "tap.hpp" - -#include -#include -#include -#include - - -/////////////////////////////////////////////////////////////////////////////// -// 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 () ? 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 () * 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 (); -} diff --git a/vector.cpp b/vector.cpp index c913d483..8ee61a3d 100644 --- a/vector.cpp +++ b/vector.cpp @@ -17,7 +17,6 @@ #include "vector.hpp" #include "debug.hpp" -#include "random.hpp" #include "json/tree.hpp" @@ -177,17 +176,5 @@ INSTANTIATE(double) //----------------------------------------------------------------------------- -namespace util { - template vector<2,float> polar_to_cartesian (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; } -} +template vector<2,float> util::polar_to_cartesian (util::vector<2,float>); +template vector<2,float> util::cartesian_to_polar (util::vector<2,float>);