diff mbox

Define std::experimental::randint etc.

Message ID 20151113164949.GW2937@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Nov. 13, 2015, 4:49 p.m. UTC
Another piece of the Library Fundamentals v2 TS, as specified by
https://rawgit.com/cplusplus/fundamentals-ts/v2/fundamentals-ts.html#rand.util.randint

Tested powerpc64le-linux, committed to trunk.
diff mbox

Patch

commit 3a59dc1453e5d273e6943a0928fc7722488ae654
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Nov 13 16:26:34 2015 +0000

    Define std::experimental::randint etc.
    
    	* include/Makefile.am: Add new header.
    	* include/Makefile.in: Regenerate.
    	* include/experimental/random: New.
    	* testsuite/experimental/random/randint.cc: New.

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 4e2ae18..5560b9e 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -660,6 +660,7 @@  experimental_headers = \
 	${experimental_srcdir}/numeric \
 	${experimental_srcdir}/optional \
 	${experimental_srcdir}/propagate_const \
+	${experimental_srcdir}/random \
 	${experimental_srcdir}/ratio \
 	${experimental_srcdir}/regex \
 	${experimental_srcdir}/set \
diff --git a/libstdc++-v3/include/experimental/random b/libstdc++-v3/include/experimental/random
new file mode 100644
index 0000000..9be1d31
--- /dev/null
+++ b/libstdc++-v3/include/experimental/random
@@ -0,0 +1,77 @@ 
+// <experimental/random> -*- C++ -*-
+
+// Copyright (C) 2015 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 3, 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file experimental/random
+ *  This is a TS C++ Library header.
+ */
+
+#ifndef _GLIBCXX_EXPERIMENTAL_RANDOM
+#define _GLIBCXX_EXPERIMENTAL_RANDOM 1
+
+#include <random>
+
+namespace std {
+namespace experimental {
+inline namespace fundamentals_v2 {
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#define __cpp_lib_experimental_randint 201511
+
+  inline std::default_random_engine&
+  _S_randint_engine()
+  {
+    static thread_local default_random_engine __eng{random_device{}()};
+    return __eng;
+  }
+
+  // 13.2.2.1, Function template randint
+  template<typename _IntType>
+    inline _IntType
+    randint(_IntType __a, _IntType __b)
+    {
+      static_assert(is_integral<_IntType>::value && sizeof(_IntType) > 1,
+		    "argument must be an integer type");
+      using _Dist = std::uniform_int_distribution<_IntType>;
+      static thread_local _Dist __dist;
+      return __dist(_S_randint_engine(), typename _Dist::param_type{__a, __b});
+    }
+
+  inline void
+  reseed()
+  {
+    _S_randint_engine().seed(random_device{}());
+  }
+
+  inline void
+  reseed(default_random_engine::result_type __value)
+  {
+    _S_randint_engine().seed(__value);
+  }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace fundamentals_v2
+} // namespace experimental
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/testsuite/experimental/random/randint.cc b/libstdc++-v3/testsuite/experimental/random/randint.cc
new file mode 100644
index 0000000..d523836
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/random/randint.cc
@@ -0,0 +1,84 @@ 
+// { dg-options "-std=gnu++14" }
+// { dg-require-effective-target tls_runtime }
+
+// Copyright (C) 2015 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 3, 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 moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/random>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  for (int i = 0; i < 100; ++i)
+  {
+    const int n = std::experimental::randint(-10, i);
+    VERIFY( -10 <= n && n <= i );
+  }
+
+  std::experimental::reseed(99u);
+  const long n1[] = {
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100)
+  };
+  std::experimental::reseed(99u);
+  const long n2[] = {
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100)
+  };
+  for (int i = 0; i < 5; ++i)
+    VERIFY( n1[i] == n2[i] );
+
+  std::experimental::reseed();
+  const long n3[] = {
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100),
+    std::experimental::randint(0, 100)
+  };
+  VERIFY( !(n3[0] == n1[0] && n3[1] == n1[1] && n3[2] == n1[2]) );
+}
+
+void
+test02()
+{
+  auto check = [](auto v) {
+    auto n = std::experimental::randint(decltype(v)(0), v);
+    static_assert(std::is_same<decltype(n), decltype(v)>::value,
+        "return type is correct");
+    VERIFY(0 <= n && n <= v);
+  };
+  check( (short)10 );
+  check( 100 );
+  check( 1000L );
+  check( 10000LL );
+  check( (unsigned short)10 );
+  check( 100U );
+  check( 1000UL );
+  check( 10000ULL );
+}
+
+int main()
+{
+  test01();
+  test02();
+}