From d8bc9819d9ca357fe35784180985c43643b9f7eb Mon Sep 17 00:00:00 2001
From: Paolo Carlini <pcarlini@suse.de>
Date: Fri, 9 Jun 2006 23:37:28 +0000
Subject: [PATCH] acinclude.m4 ([GLIBCXX_CHECK_RANDOM_TR1]): New, check for the
 availability of "/dev/random" and "/dev/urandom".

2006-06-09  Paolo Carlini  <pcarlini@suse.de>

	* acinclude.m4 ([GLIBCXX_CHECK_RANDOM_TR1]): New, check for
	the availability of "/dev/random" and "/dev/urandom".
	* configure.ac: Use it.
	* include/tr1/random (random_device): Implement, a fall-back for
	systems not providing "/dev/random" and "/dev/urandom" included.
	* testsuite/tr1/5_numerical_facilities/random/random_device/
	cons/default.cc: New.
	* testsuite/tr1/5_numerical_facilities/random/random_device/
	cons/token.cc: Likewise.
	* testsuite/tr1/5_numerical_facilities/random/random_device/
	requirements/typedefs.cc: Likewise.
	* config.h.in: Regenerate.
	* configure: Likewise.

	* testsuite/tr1/5_numerical_facilities/random/mersenne_twister/
	cons/gen1.cc: Minor tweak, add bool test.

From-SVN: r114529
---
 libstdc++-v3/ChangeLog                        | 19 +++++
 libstdc++-v3/acinclude.m4                     | 26 +++++++
 libstdc++-v3/config.h.in                      |  4 ++
 libstdc++-v3/configure                        | 63 +++++++++++++++++
 libstdc++-v3/configure.ac                     |  3 +
 libstdc++-v3/include/tr1/random               | 70 ++++++++++++++++---
 .../random/mersenne_twister/cons/gen1.cc      |  3 +-
 .../random/random_device/cons/default.cc      | 43 ++++++++++++
 .../random/random_device/cons/token.cc        | 47 +++++++++++++
 .../random_device/requirements/typedefs.cc    | 32 +++++++++
 10 files changed, 300 insertions(+), 10 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/cons/default.cc
 create mode 100644 libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/cons/token.cc
 create mode 100644 libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/requirements/typedefs.cc

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 3c7a84b24d52..a2b158edb8f7 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,22 @@
+2006-06-09  Paolo Carlini  <pcarlini@suse.de>
+
+	* acinclude.m4 ([GLIBCXX_CHECK_RANDOM_TR1]): New, check for
+	the availability of "/dev/random" and "/dev/urandom".
+	* configure.ac: Use it.
+	* include/tr1/random (random_device): Implement, a fall-back for
+	systems not providing "/dev/random" and "/dev/urandom" included.
+	* testsuite/tr1/5_numerical_facilities/random/random_device/
+	cons/default.cc: New.
+	* testsuite/tr1/5_numerical_facilities/random/random_device/
+	cons/token.cc: Likewise.
+	* testsuite/tr1/5_numerical_facilities/random/random_device/
+	requirements/typedefs.cc: Likewise.
+	* config.h.in: Regenerate.
+	* configure: Likewise.
+
+	* testsuite/tr1/5_numerical_facilities/random/mersenne_twister/
+	cons/gen1.cc: Minor tweak, add bool test.
+
 2006-06-06  Benjamin Kosnik  <bkoz@redhat.com>
 
 	* testsuite/util: New directory.
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index fcbc9677344b..f58a84fc05a6 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -1268,6 +1268,32 @@ AC_DEFUN([GLIBCXX_CHECK_C99_TR1], [
   AC_LANG_RESTORE
 ])
 
+dnl
+dnl Check whether "dev/random" and "dev/urandom" are available for the
+dnl random_device of "TR1" (Chapter 5.1, "Random number generation").
+dnl
+AC_DEFUN([GLIBCXX_CHECK_RANDOM_TR1], [
+
+  AC_MSG_CHECKING([for "dev/random" and "dev/urandom" for TR1 random_device])
+  AC_CACHE_VAL(ac_random_tr1, [
+  AC_TRY_RUN([#include <stdio.h>
+	      int main()
+	      {
+                return !(fopen("/dev/random", "r")
+                         && fopen("/dev/urandom", "r"));
+	      }	      
+	     ],
+             [ac_random_tr1=yes], [ac_random_tr1=no],
+	     [ac_random_tr1=no])
+  ])
+  AC_MSG_RESULT($ac_random_tr1)
+  if test x"$ac_random_tr1" = x"yes"; then
+    AC_DEFINE(_GLIBCXX_USE_RANDOM_TR1, 1,
+              [Define if dev/random and dev/urandom are available for
+	       the random_device of TR1 (Chapter 5.1).])
+  fi
+
+])
 
 dnl
 dnl Check for what type of C headers to use.
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index a75af3835d07..ba53014434dd 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -744,6 +744,10 @@
 /* Define if NLS translations are to be used. */
 #undef _GLIBCXX_USE_NLS
 
+/* Define if dev/random and dev/urandom are available for the random_device of
+   TR1 (Chapter 5.1). */
+#undef _GLIBCXX_USE_RANDOM_TR1
+
 /* Define if code specialized for wchar_t should be used. */
 #undef _GLIBCXX_USE_WCHAR_T
 
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 68e2f6c0d371..1c2698d35242 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -31113,6 +31113,69 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+  # For dev/random and dev/urandom for TR1.
+
+
+  echo "$as_me:$LINENO: checking for \"dev/random\" and \"dev/urandom\" for TR1 random_device" >&5
+echo $ECHO_N "checking for \"dev/random\" and \"dev/urandom\" for TR1 random_device... $ECHO_C" >&6
+  if test "${ac_random_tr1+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+  if test "$cross_compiling" = yes; then
+  ac_random_tr1=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdio.h>
+	      int main()
+	      {
+                return !(fopen("/dev/random", "r")
+                         && fopen("/dev/urandom", "r"));
+	      }
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_random_tr1=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_random_tr1=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+
+  echo "$as_me:$LINENO: result: $ac_random_tr1" >&5
+echo "${ECHO_T}$ac_random_tr1" >&6
+  if test x"$ac_random_tr1" = x"yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define _GLIBCXX_USE_RANDOM_TR1 1
+_ACEOF
+
+  fi
+
+
+
   # For TLS support.
 
    # Check whether --enable-tls or --disable-tls was given.
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index 45dd410ae0cf..88018c3d57b5 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -160,6 +160,9 @@ if $GLIBCXX_IS_NATIVE; then
   # For C99 support to TR1.
   GLIBCXX_CHECK_C99_TR1
 
+  # For dev/random and dev/urandom for TR1.
+  GLIBCXX_CHECK_RANDOM_TR1
+
   # For TLS support.
   GCC_CHECK_TLS
 
diff --git a/libstdc++-v3/include/tr1/random b/libstdc++-v3/include/tr1/random
index 7bdf8e6be07b..4a797c116290 100644
--- a/libstdc++-v3/include/tr1/random
+++ b/libstdc++-v3/include/tr1/random
@@ -44,6 +44,8 @@
 #include <iosfwd>
 #include <limits>
 #include <tr1/type_traits>
+#include <sstream>
+#include <fstream>
 
 namespace std
 {
@@ -1157,10 +1159,6 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
   /**
    * A standard interface to a platform-specific non-deterministic random number
    * generator (if any are available).
-   *
-   * @todo The underlying interface is system-specific and needs to be factored
-   * into the generated configury mechs.  For example, the use of "/dev/random"
-   * under a Linux OS would be appropriate.
    */
   class random_device
   {
@@ -1169,15 +1167,69 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
     typedef unsigned int result_type;
     
     // constructors, destructors and member functions
-    explicit random_device(const std::string& __token = "unimplemented");
-    result_type min() const;
-    result_type max() const;
-    double entropy() const;
-    result_type operator()();
+
+#ifdef _GLIBCXX_USE_RANDOM_TR1
+    explicit
+    random_device(const std::string& __token = "/dev/urandom")
+    {
+      if ((__token != "/dev/urandom" && __token != "/dev/random")
+	  || !_M_filebuf.open(__token.c_str(), std::ios_base::in))
+	std::__throw_runtime_error(__N("random_device::"
+				       "random_device(const std::string&)"));
+    }
+
+    ~random_device()
+    { _M_filebuf.close(); }
+
+#else
+    explicit
+    random_device(const std::string& __token = "rand")
+    {
+      if (__token != "rand")
+	{
+	  std::stringstream __ss(__token);
+	  unsigned int __seed;
+	  __ss >> __seed;
+	  if (__ss.fail())
+	    std::__throw_runtime_error(__N("random_device::random_device"
+					   "(const std::string&)"));
+	  else
+	    std::srand(__seed);
+	}
+    }
+#endif
+
+    result_type
+    min() const
+    { return std::numeric_limits<result_type>::min(); }
+
+    result_type
+    max() const
+    { return std::numeric_limits<result_type>::max(); }
+
+    double
+    entropy() const
+    { return 0.0; }
+
+    result_type
+    operator()()
+    {
+#ifdef _GLIBCXX_USE_RANDOM_TR1
+      result_type __ret;
+      _M_filebuf.sgetn(reinterpret_cast<char*>(&__ret), sizeof(result_type));
+      return __ret;
+#else
+      return max() * (std::rand() / double(RAND_MAX));
+#endif
+    }
 
   private:
     random_device(const random_device&);
     void operator=(const random_device&);
+
+#ifdef _GLIBCXX_USE_RANDOM_TR1
+    std::filebuf _M_filebuf;
+#endif    
   };
 
   /* @} */ // group tr1_random_generators
diff --git a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/mersenne_twister/cons/gen1.cc b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/mersenne_twister/cons/gen1.cc
index 0321bea067fd..7861954a13ff 100644
--- a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/mersenne_twister/cons/gen1.cc
+++ b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/mersenne_twister/cons/gen1.cc
@@ -34,7 +34,8 @@ gen()
 
 void
 test01() 
-{ 
+{
+  bool test __attribute__((unused)) = true;
   using namespace std::tr1;
 
   mersenne_twister<
diff --git a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/cons/default.cc b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/cons/default.cc
new file mode 100644
index 000000000000..5150c5e494f1
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/cons/default.cc
@@ -0,0 +1,43 @@
+// 2006-06-09  Paolo Carlini  <pcarlini@suse.de>
+//
+// Copyright (C) 2006 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 5.1.6 class random_device [tr.rand.device]
+// 5.1.1 Table 15 default ctor
+
+#include <tr1/random>
+#include <testsuite_hooks.h>
+
+void
+test01() 
+{
+  bool test __attribute__((unused)) = true;
+
+  using namespace std::tr1;
+  random_device x;
+  
+  VERIFY( x.min() == std::numeric_limits<random_device::result_type>::min() );
+  VERIFY( x.max() == std::numeric_limits<random_device::result_type>::max() );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/cons/token.cc
new file mode 100644
index 000000000000..9a6686bbedc8
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/cons/token.cc
@@ -0,0 +1,47 @@
+// 2006-06-09  Paolo Carlini  <pcarlini@suse.de>
+//
+// Copyright (C) 2006 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 5.1.6 class random_device [tr.rand.device]
+// 5.1.6, p3
+
+#include <tr1/random>
+#include <testsuite_hooks.h>
+
+void
+test01() 
+{
+  bool test __attribute__((unused)) = true;
+  using namespace std::tr1;
+
+#ifdef _GLIBCXX_USE_RANDOM_TR1
+  random_device x("/dev/random");
+#else
+  random_device x("0");
+#endif
+
+  VERIFY( x.min() == std::numeric_limits<random_device::result_type>::min() );
+  VERIFY( x.max() == std::numeric_limits<random_device::result_type>::max() );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/requirements/typedefs.cc
new file mode 100644
index 000000000000..28363cbcdc45
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/random_device/requirements/typedefs.cc
@@ -0,0 +1,32 @@
+// { dg-do compile }
+//
+// 2006-06-09  Paolo Carlini  <pcarlini@suse.de>
+//
+// Copyright (C) 2006 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 5.1.6 class random_device [tr.rand.device]
+
+#include <tr1/random>
+
+void
+test01() 
+{ 
+  typedef std::tr1::random_device test_type;
+  typedef test_type::result_type result_type;
+}
-- 
GitLab