aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2011-03-20 16:19:41 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2011-03-20 16:20:42 +0000
commitc4455dd4491879bf64122e863ad4fd8ff9b6dfa5 (patch)
treecacc73e5ba81819ad9362a3f7d69468add2c64ba
parent1ea7c642bc74df0d42e0b214c1a13ce7cc7b97e8 (diff)
downloadpaludis-c4455dd4491879bf64122e863ad4fd8ff9b6dfa5.tar.gz
paludis-c4455dd4491879bf64122e863ad4fd8ff9b6dfa5.tar.xz
Use std::random
-rw-r--r--configure.ac37
-rw-r--r--paludis/repositories/e/e_repository.cc20
-rw-r--r--paludis/util/files.m41
-rw-r--r--paludis/util/random.cc37
-rw-r--r--paludis/util/random.hh82
-rw-r--r--paludis/util/random_TEST.cc119
6 files changed, 54 insertions, 242 deletions
diff --git a/configure.ac b/configure.ac
index 74dcb8f..4696731 100644
--- a/configure.ac
+++ b/configure.ac
@@ -783,6 +783,43 @@ int main(int, char **)
])
dnl }}}
+dnl {{{ std::random
+random_is_tr1=
+AC_MSG_CHECKING([for c++0x-compliant <random>])
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#include <random>
+#include <ctime>
+int main(int, char **)
+{
+ std::mt19937 rand(std::time(0));
+ std::uniform_int_distribution<int> dist(0, 9);
+ return dist(rand);
+}
+])],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_CHECKING([for tr1-compliant <random>])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#include <random>
+#include <ctime>
+int main(int, char **)
+{
+ std::mt19937 rand(std::time(0));
+ std::uniform_int<int> dist(0, 9);
+ return dist(rand);
+}
+ ])],
+ [AC_MSG_RESULT([yes])
+ random_is_tr1=yes],
+ [AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Your compiler does not support <random>])])
+ ])
+
+if test x$random_is_tr1 = xyes ; then
+ PALUDIS_CXXFLAGS="${PALUDIS_CXXFLAGS} -DPALUDIS_RANDOM_IS_TR1=1"
+fi
+dnl }}}
+
dnl {{{ c++0x default and deleted functions
AC_MSG_CHECKING([for c++0x default and deleted functions])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
diff --git a/paludis/repositories/e/e_repository.cc b/paludis/repositories/e/e_repository.cc
index e233508..0c9f436 100644
--- a/paludis/repositories/e/e_repository.cc
+++ b/paludis/repositories/e/e_repository.cc
@@ -82,7 +82,6 @@
#include <paludis/util/options.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/process.hh>
-#include <paludis/util/random.hh>
#include <paludis/util/rmd160.hh>
#include <paludis/util/safe_ifstream.hh>
#include <paludis/util/safe_ofstream.hh>
@@ -98,6 +97,7 @@
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/wrapped_output_iterator.hh>
+#include <random>
#include <functional>
#include <unordered_map>
#include <map>
@@ -105,6 +105,7 @@
#include <algorithm>
#include <vector>
#include <list>
+#include <ctime>
#include <strings.h>
#include <ctype.h>
@@ -644,6 +645,19 @@ ERepository::arch_flags() const
return _imp->arch_flags;
}
+namespace
+{
+ struct Randomator
+ {
+ std::mt19937 & rand;
+
+ int operator() (int n)
+ {
+ return rand() % n;
+ }
+ };
+}
+
void
ERepository::need_mirrors() const
{
@@ -666,8 +680,8 @@ ERepository::need_mirrors() const
if (! ee.empty())
{
/* pick up to five random mirrors only */
- static Random r;
- std::random_shuffle(next(ee.begin()), ee.end(), r);
+ std::mt19937 random(std::time(0));
+ std::random_shuffle(next(ee.begin()), ee.end(), Randomator{random});
if (ee.size() > 6)
ee.resize(6);
diff --git a/paludis/util/files.m4 b/paludis/util/files.m4
index d98aae3..d475e8f 100644
--- a/paludis/util/files.m4
+++ b/paludis/util/files.m4
@@ -64,7 +64,6 @@ add(`pool', `hh', `cc', `impl', `test')
add(`pretty_print', `hh', `cc', `test')
add(`process', `hh', `cc', `fwd', `gtest', `testscript')
add(`pty', `hh', `cc', `gtest')
-add(`random', `hh', `cc', `test')
add(`realpath', `hh', `cc', `gtest', `testscript')
add(`remove_shared_ptr', `hh')
add(`return_literal_function', `hh', `cc', `fwd', `gtest')
diff --git a/paludis/util/random.cc b/paludis/util/random.cc
deleted file mode 100644
index 74bf2d4..0000000
--- a/paludis/util/random.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2006, 2007 Ciaran McCreesh
- *
- * This file is part of the Paludis package manager. Paludis is free software;
- * you can redistribute it and/or modify it under the terms of the GNU General
- * Public License version 2, as published by the Free Software Foundation.
- *
- * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "random.hh"
-#include <time.h>
-
-using namespace paludis;
-
-uint32_t Random::global_seed(0xdeadbeef ^ ::time(0));
-
-Random::Random(uint32_t seed) :
- local_seed(seed)
-{
-}
-
-Random::Random() :
- local_seed(global_seed ^ ((::time(0) >> 16) | (::time(0) << 16)))
-{
- global_seed += local_seed;
-}
-
diff --git a/paludis/util/random.hh b/paludis/util/random.hh
deleted file mode 100644
index a5d391f..0000000
--- a/paludis/util/random.hh
+++ /dev/null
@@ -1,82 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh
- *
- * This file is part of the Paludis package manager. Paludis is free software;
- * you can redistribute it and/or modify it under the terms of the GNU General
- * Public License version 2, as published by the Free Software Foundation.
- *
- * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef PALUDIS_GUARD_PALUDIS_UTIL_RANDOM_HH
-#define PALUDIS_GUARD_PALUDIS_UTIL_RANDOM_HH 1
-
-#include <cstdlib>
-#include <inttypes.h>
-#include <paludis/util/attributes.hh>
-
-/** \file
- * Declarations for the Random class.
- *
- * \ingroup g_utils
- *
- * \section Examples
- *
- * - None at this time.
- */
-
-namespace paludis
-{
- /**
- * A basic random number generator class, which is not suitable for
- * cryptography but is fast and reasonably pseudorandom.
- *
- * See \ref TCppPL 22.7 for justification. See \ref TaoCP2 3.2.1 for the
- * basic algorithm and \ref AppCrypt 16.1 for the choice of numbers.
- *
- * \ingroup g_utils
- * \nosubgrouping
- */
- class PALUDIS_VISIBLE Random
- {
- private:
- static uint32_t global_seed;
- uint32_t local_seed;
-
- static const uint32_t _a = 2416;
- static const uint32_t _b = 374441;
- static const uint32_t _m = 1771875;
-
- public:
- ///\name Basic operations
- ///\{
-
- /// Constructor, with a seed.
- Random(uint32_t seed);
-
- /// Constructor, with a magic random seed.
- Random();
-
- ///\}
-
- /// Fetch a random number in (0, max]
- template <typename DiffType_>
- DiffType_ operator() (DiffType_ max)
- {
- local_seed = (_a * local_seed + _b) % _m;
- double t(static_cast<double>(local_seed) / static_cast<double>(_m));
- return static_cast<DiffType_>(t * max);
- }
- };
-}
-
-#endif
diff --git a/paludis/util/random_TEST.cc b/paludis/util/random_TEST.cc
deleted file mode 100644
index 87bcadd..0000000
--- a/paludis/util/random_TEST.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2006 Ciaran McCreesh
- *
- * This file is part of the Paludis package manager. Paludis is free software;
- * you can redistribute it and/or modify it under the terms of the GNU General
- * Public License version 2, as published by the Free Software Foundation.
- *
- * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "random.hh"
-#include <test/test_framework.hh>
-#include <test/test_runner.hh>
-#include <vector>
-#include <algorithm>
-
-/** \file
- * Test cases for paludis::Random.
- *
- */
-
-using namespace paludis;
-using namespace test;
-
-namespace
-{
- struct RandomUpTo
- {
- Random random;
- unsigned max;
-
- RandomUpTo(const Random & r, const unsigned m) :
- random(r),
- max(m)
- {
- }
-
- int operator() ()
- {
- return random(max);
- }
- };
-
- inline double square(double v)
- {
- return v * v;
- }
-}
-
-namespace test_cases
-{
- /**
- * \test Test Random distibutions using counts.
- *
- */
- struct RandomDistributionCountsTest : TestCase
- {
- RandomDistributionCountsTest() : TestCase("distribution (counts)") { }
-
- void run()
- {
- std::vector<int> v;
- v.reserve(10000);
- std::generate_n(std::back_inserter(v), 10000, RandomUpTo(Random(), 10));
-
- TEST_CHECK_EQUAL(0, *std::min_element(v.begin(), v.end()));
- TEST_CHECK_EQUAL(9, *std::max_element(v.begin(), v.end()));
- for (int i(0) ; i < 10 ; ++i)
- {
- TEST_CHECK(std::count(v.begin(), v.end(), i) > 1);
- TEST_CHECK(std::count(v.begin(), v.end(), i) < 3000);
- }
- }
- } test_random_counts;
-
- /**
- * \test Test Random distibutions using chi square.
- *
- * This is a chi square test, so it could theoretically fail
- * occasionally. See \ref TaoCP2 3.3.1 for details.
- */
- struct RandomDistributionChiSquaredTest : TestCase
- {
- RandomDistributionChiSquaredTest() : TestCase("distribution (chi square)") { }
-
- void run()
- {
- int failures(0);
-
- for (int attempts(0) ; attempts < 3 ; ++ attempts)
- {
- std::vector<int> v;
- v.reserve(10000);
- std::generate_n(std::back_inserter(v), 10000, RandomUpTo(Random(), 10));
-
- double a(0);
- for (int i(0) ; i <= 9 ; ++i)
- a += (square(std::count(v.begin(), v.end(), i) - (10000 / 10)) / (10000 / 10));
-
- TestMessageSuffix suffix("a=" + stringify(a), true);
- TEST_CHECK(true);
- if ((a < 2.088) || (a > 21.67))
- ++failures;
- }
-
- TEST_CHECK(failures <= 1);
- }
- } test_random_chi_square;
-}
-