Jonathan Wakely jwakely@redhat.com
Mon Oct 24 16:53:00 GMT 2016

```On 07/11/14 11:24 -0500, Ed Smith-Rowland wrote:
>On 11/06/2014 02:23 AM, Marc Glisse wrote:
>>On Wed, 5 Nov 2014, Ed Smith-Rowland wrote:
>>
>>>On 11/05/2014 04:25 PM, Marc Glisse wrote:
>>>>On Wed, 5 Nov 2014, Ed Smith-Rowland wrote:
>>>>
>>>>>Like the uniform_on_sphere_distribution which is used inside,
>>>>>the 2-dimensional case uses rejection
>>>>
>>>>Could you point out where in the code you are special-casing
>>>>dimension 2? Somehow I can't see it in the patch.
>>>>
>>>My miscommunication.  Sorry.
>>>
>>>The special casing - and all the hard work - is done by the
>>>contained uniform_on_sphere_distribution.
>>
>>In dimension 2, uniform_on_sphere_distribution generates a uniform
>>random point in the unit disk and projects it to the circle. Using
>>that + one more random number to regenerate a uniform random point
>>in the disk seems wasteful to me.
>>
>OK.
>
>That was a sobering exercise in the difference between asymptotic
>analysis and reality.  I measured transform vs. rejection from Dim=1
>to 9 on a couple boxen.
>Time for rejection is a power law like t = A.2^D and transform was
>linear t = B + C.D.  On the machine with results below A ~ 12, B ~ 20,
>C ~ 880.  Rather different numbers but same results on an older box.
>Basically, the linear coefficient is huge.  I can't blame pow or sqrt
>though by the numbers.  My timer is crude though.  i'll try more
>tools.
>
>LD_LIBRARY_PATH=/home/ed/bin/lib64:\$LD_LIBRARY_PATH ./deathmatch
>100000
>
>  New (Rejection) Distribution - Dim=1
>  Total time per iter = 38 ms
>  Mean time per iter  = 0.00038 ms
>
>  Old (Transform) Distribution - Dim=1
>  Total time per iter = 905 ms
>  Mean time per iter  = 0.00905 ms
>
>  New (Rejection) Distribution - Dim=2
>  Total time per iter = 48 ms
>  Mean time per iter  = 0.00048 ms
>
>  Old (Transform) Distribution - Dim=2
>  Total time per iter = 1776 ms
>  Mean time per iter  = 0.01776 ms
>
>  New (Rejection) Distribution - Dim=3
>  Total time per iter = 104 ms
>  Mean time per iter  = 0.00104 ms
>
>  Old (Transform) Distribution - Dim=3
>  Total time per iter = 2659 ms
>  Mean time per iter  = 0.02659 ms
>
>  New (Rejection) Distribution - Dim=4
>  Total time per iter = 227 ms
>  Mean time per iter  = 0.00227 ms
>
>  Old (Transform) Distribution - Dim=4
>  Total time per iter = 3532 ms
>  Mean time per iter  = 0.03532 ms
>
>  New (Rejection) Distribution - Dim=5
>  Total time per iter = 525 ms
>  Mean time per iter  = 0.00525 ms
>
>  Old (Transform) Distribution - Dim=5
>  Total time per iter = 4402 ms
>  Mean time per iter  = 0.04402 ms
>
>  New (Rejection) Distribution - Dim=6
>  Total time per iter = 1275 ms
>  Mean time per iter  = 0.01275 ms
>
>  Old (Transform) Distribution - Dim=6
>  Total time per iter = 5299 ms
>  Mean time per iter  = 0.05299 ms
>
>  New (Rejection) Distribution - Dim=7
>  Total time per iter = 3269 ms
>  Mean time per iter  = 0.03269 ms
>
>  Old (Transform) Distribution - Dim=7
>  Total time per iter = 6193 ms
>  Mean time per iter  = 0.06193 ms
>
><---  BREAK EVEN  --->
>
>  New (Rejection) Distribution - Dim=8
>  Total time per iter = 8722 ms
>  Mean time per iter  = 0.08722 ms
>
>  Old (Transform) Distribution - Dim=8
>  Total time per iter = 7047 ms
>  Mean time per iter  = 0.07047 ms
>
>  New (Rejection) Distribution - Dim=9
>  Total time per iter = 23814 ms
>  Mean time per iter  = 0.23814 ms
>
>  Old (Transform) Distribution - Dim=9
>  Total time per iter = 7893 ms
>  Mean time per iter  = 0.07893 ms
>
>  Bunch of calls to pow and sqrt
>  Total time per iter = 6 ms
>  Mean time per iter  = 6e-05 ms
>
>  uniform_on_sphere_distribution - Dim=3
>  Total time per iter = 87 ms
>  Mean time per iter  = 0.00087 ms
>
>  default_random_engine - Dim=3
>  Total time per iter = 4 ms
>  Mean time per iter  = 4e-05 ms
>
>The new patch dispatches to rejection for Dim<8, transform otherwise.
>
>I include deathmatch.  You can hack bits from the patch to make the
>
>I have to admit I'm puzzled as to why the transform method is so slow
>relative to rejection.
>
>Ed
>
>

It looks like this was never reviewed properly, and so not committed.

Ed, are you still interested in getting this in?

>2014-09-07  Edward Smith-Rowland  <3dw4rd@verizon.net>
>
>	* include/ext/random.tcc: Out-of-line implementation of
>	uniform_inside_sphere_distribution.
>	* testsuite/ext/random/uniform_inside_sphere_distribution/cons/
>	default.cc: New.
>	* testsuite/ext/random/uniform_inside_sphere_distribution/cons/
>	parms.cc: New.
>	* testsuite/ext/random/uniform_inside_sphere_distribution/operators/
>	equal.cc: New.
>	* testsuite/ext/random/uniform_inside_sphere_distribution/operators/
>	generate.cc: New.
>	* testsuite/ext/random/uniform_inside_sphere_distribution/operators/
>	inequal.cc: New.
>	* testsuite/ext/random/uniform_inside_sphere_distribution/operators/
>	serialize.cc: New.

>Index: include/ext/random
>===================================================================
>--- include/ext/random	(revision 217109)
>+++ include/ext/random	(working copy)
>@@ -3487,6 +3487,218 @@
> 	       _RealType>& __d2)
>     { return !(__d1 == __d2); }
>
>+
>+  /**
>+   * @brief A distribution for random coordinates inside a unit sphere.
>+   */
>+  template<std::size_t _Dimen, typename _RealType = double>
>+    class uniform_inside_sphere_distribution
>+    {
>+      static_assert(std::is_floating_point<_RealType>::value,
>+		    "template argument not a floating point type");
>+      static_assert(_Dimen != 0, "dimension is zero");
>+
>+    public:
>+      /** The type of the range of the distribution. */
>+      using result_type = std::array<_RealType, _Dimen>;
>+
>+      /** Parameter type. */
>+      struct param_type
>+      {
>+	using distribution_type
>+	  = uniform_inside_sphere_distribution<_Dimen, _RealType>;
>+	friend class uniform_inside_sphere_distribution<_Dimen, _RealType>;
>+
>+	explicit
>+	{
>+	}
>+
>+	_RealType
>+
>+	friend bool
>+	operator==(const param_type& __p1, const param_type& __p2)
>+
>+      private:
>+      };
>+
>+      /**
>+       * @brief Constructors.
>+       */
>+      explicit
>+      { }
>+
>+      explicit
>+      uniform_inside_sphere_distribution(const param_type& __p)
>+      : _M_param(__p), _M_uosd()
>+      { }
>+
>+      /**
>+       * @brief Resets the distribution state.
>+       */
>+      void
>+      reset()
>+      { _M_uosd.reset(); }
>+
>+      /**
>+       * @brief Returns the @f\$radius@f\$ of the distribution.
>+       */
>+      _RealType
>+
>+      /**
>+       * @brief Returns the parameter set of the distribution.
>+       */
>+      param_type
>+      param() const
>+      { return _M_param; }
>+
>+      /**
>+       * @brief Sets the parameter set of the distribution.
>+       * @param __param The new parameter set of the distribution.
>+       */
>+      void
>+      param(const param_type& __param)
>+      { _M_param = __param; }
>+
>+      /**
>+       * @brief Returns the greatest lower bound value of the distribution.
>+       * This function makes no sense for this distribution.
>+       */
>+      result_type
>+      min() const
>+      {
>+	result_type __res;
>+	__res.fill(0);
>+	return __res;
>+      }
>+
>+      /**
>+       * @brief Returns the least upper bound value of the distribution.
>+       * This function makes no sense for this distribution.
>+       */
>+      result_type
>+      max() const
>+      {
>+	result_type __res;
>+	__res.fill(0);
>+	return __res;
>+      }
>+
>+      /**
>+       * @brief Generating functions.
>+       */
>+      template<typename _UniformRandomNumberGenerator>
>+	result_type
>+	operator()(_UniformRandomNumberGenerator& __urng)
>+	{ return this->operator()(__urng, _M_param); }
>+
>+      template<typename _UniformRandomNumberGenerator>
>+	result_type
>+	operator()(_UniformRandomNumberGenerator& __urng,
>+		   const param_type& __p);
>+
>+      template<typename _ForwardIterator,
>+	       typename _UniformRandomNumberGenerator>
>+	void
>+	__generate(_ForwardIterator __f, _ForwardIterator __t,
>+		   _UniformRandomNumberGenerator& __urng)
>+	{ this->__generate(__f, __t, __urng, this->param()); }
>+
>+      template<typename _ForwardIterator,
>+	       typename _UniformRandomNumberGenerator>
>+	void
>+	__generate(_ForwardIterator __f, _ForwardIterator __t,
>+		   _UniformRandomNumberGenerator& __urng,
>+		   const param_type& __p)
>+	{ this->__generate_impl(__f, __t, __urng, __p); }
>+
>+      template<typename _UniformRandomNumberGenerator>
>+	void
>+	__generate(result_type* __f, result_type* __t,
>+		   _UniformRandomNumberGenerator& __urng,
>+		   const param_type& __p)
>+	{ this->__generate_impl(__f, __t, __urng, __p); }
>+
>+      /**
>+       * @brief Return true if two uniform on sphere distributions have
>+       *        the same parameters and the sequences that would be
>+       *        generated are equal.
>+       */
>+      friend bool
>+      operator==(const uniform_inside_sphere_distribution& __d1,
>+		 const uniform_inside_sphere_distribution& __d2)
>+      { return __d1._M_param == __d2._M_param && __d1._M_uosd == __d2._M_uosd; }
>+
>+      /**
>+       * @brief Inserts a %uniform_inside_sphere_distribution random number
>+       *        distribution @p __x into the output stream @p __os.
>+       *
>+       * @param __os An output stream.
>+       * @param __x  A %uniform_inside_sphere_distribution random number
>+       *             distribution.
>+       *
>+       * @returns The output stream with the state of @p __x inserted or in
>+       * an error state.
>+       */
>+      template<size_t _Dimen1, typename _RealType1, typename _CharT,
>+	       typename _Traits>
>+	friend std::basic_ostream<_CharT, _Traits>&
>+	operator<<(std::basic_ostream<_CharT, _Traits>& __os,
>+		   const __gnu_cxx::uniform_inside_sphere_distribution<_Dimen1,
>+								   _RealType1>&
>+		   );
>+
>+      /**
>+       * @brief Extracts a %uniform_inside_sphere_distribution random number
>+       *        distribution
>+       * @p __x from the input stream @p __is.
>+       *
>+       * @param __is An input stream.
>+       * @param __x  A %uniform_inside_sphere_distribution random number
>+       *             generator engine.
>+       *
>+       * @returns The input stream with @p __x extracted or in an error state.
>+       */
>+      template<std::size_t _Dimen1, typename _RealType1, typename _CharT,
>+	       typename _Traits>
>+	friend std::basic_istream<_CharT, _Traits>&
>+	operator>>(std::basic_istream<_CharT, _Traits>& __is,
>+		   __gnu_cxx::uniform_inside_sphere_distribution<_Dimen1,
>+								 _RealType1>&);
>+
>+    private:
>+      template<typename _ForwardIterator,
>+	       typename _UniformRandomNumberGenerator>
>+	void
>+	__generate_impl(_ForwardIterator __f, _ForwardIterator __t,
>+			_UniformRandomNumberGenerator& __urng,
>+			const param_type& __p);
>+
>+      param_type _M_param;
>+      uniform_on_sphere_distribution<_Dimen, _RealType> _M_uosd;
>+    };
>+
>+  /**
>+   * @brief Return true if two uniform on sphere distributions are different.
>+   */
>+  template<std::size_t _Dimen, typename _RealType>
>+    inline bool
>+    operator!=(const __gnu_cxx::uniform_inside_sphere_distribution<_Dimen,
>+	       _RealType>& __d1,
>+	       const __gnu_cxx::uniform_inside_sphere_distribution<_Dimen,
>+	       _RealType>& __d2)
>+    { return !(__d1 == __d2); }
>+
> _GLIBCXX_END_NAMESPACE_VERSION
> } // namespace __gnu_cxx
>
>Index: include/ext/random.tcc
>===================================================================
>--- include/ext/random.tcc	(revision 217109)
>+++ include/ext/random.tcc	(working copy)
>@@ -1669,6 +1669,160 @@
>       return __is >> __x._M_nd;
>     }
>
>+
>+  namespace {
>+
>+    // Helper class for the uniform_inside_sphere_distribution generation
>+    // function.
>+    template<std::size_t _Dimen, bool _SmallDimen, typename _RealType>
>+      class uniform_inside_sphere_helper;
>+
>+    template<std::size_t _Dimen, typename _RealType>
>+      class uniform_inside_sphere_helper<_Dimen, false, _RealType>
>+      {
>+	using result_type
>+	  = typename uniform_inside_sphere_distribution<_Dimen, _RealType>::
>+	    result_type;
>+
>+      public:
>+	template<typename _UniformOnSphereDistribution,
>+		 typename _UniformRandomNumberGenerator>
>+	result_type
>+	operator()(_UniformOnSphereDistribution& __uosd,
>+		   _UniformRandomNumberGenerator& __urng,
>+        {
>+				  _RealType> __aurng(__urng);
>+
>+	  _RealType __pow = 1 / _RealType(_Dimen);
>+	  _RealType __urt = __radius * std::pow(__aurng(), __pow);
>+	  result_type __ret = __uosd(__aurng);
>+
>+	  std::transform(__ret.begin(), __ret.end(), __ret.begin(),
>+			 [__urt](_RealType __val)
>+			 { return __val * __urt; });
>+
>+	  return __ret;
>+        }
>+      };
>+
>+    // Helper class for the uniform_inside_sphere_distribution generation
>+    // function specialized for small dimensions.
>+    template<std::size_t _Dimen, typename _RealType>
>+      class uniform_inside_sphere_helper<_Dimen, true, _RealType>
>+      {
>+	using result_type
>+	  = typename uniform_inside_sphere_distribution<_Dimen, _RealType>::
>+	    result_type;
>+
>+      public:
>+	template<typename _UniformOnSphereDistribution,
>+		 typename _UniformRandomNumberGenerator>
>+	result_type
>+	operator()(_UniformOnSphereDistribution&,
>+		   _UniformRandomNumberGenerator& __urng,
>+        {
>+	  result_type __ret;
>+	  _RealType __sq;
>+				  _RealType> __aurng(__urng);
>+
>+	  do
>+	    {
>+	      __sq = _RealType(0);
>+	      for (int i = 0; i < _Dimen; ++i)
>+		{
>+		  __ret[i] = _RealType(2) * __aurng() - _RealType(1);
>+		  __sq += __ret[i] * __ret[i];
>+		}
>+	    }
>+	  while (__sq > _RealType(1));
>+
>+	  for (int i = 0; i < _Dimen; ++i)
>+
>+	  return __ret;
>+        }
>+      };
>+  }
>+
>+
>+  template<std::size_t _Dimen, typename _RealType>
>+    template<typename _UniformRandomNumberGenerator>
>+      typename uniform_inside_sphere_distribution<_Dimen, _RealType>::result_type
>+      uniform_inside_sphere_distribution<_Dimen, _RealType>::
>+      operator()(_UniformRandomNumberGenerator& __urng,
>+		 const param_type& __p)
>+      {
>+        uniform_inside_sphere_helper<_Dimen, _Dimen < 8, _RealType> __helper;
>+      }
>+
>+  template<std::size_t _Dimen, typename _RealType>
>+    template<typename _OutputIterator,
>+	     typename _UniformRandomNumberGenerator>
>+      void
>+      uniform_inside_sphere_distribution<_Dimen, _RealType>::
>+      __generate_impl(_OutputIterator __f, _OutputIterator __t,
>+		      _UniformRandomNumberGenerator& __urng,
>+		      const param_type& __param)
>+      {
>+	__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator>)
>+
>+	while (__f != __t)
>+	  *__f++ = this->operator()(__urng, __param);
>+      }
>+
>+  template<std::size_t _Dimen, typename _RealType, typename _CharT,
>+	   typename _Traits>
>+    std::basic_ostream<_CharT, _Traits>&
>+    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
>+	       const __gnu_cxx::uniform_inside_sphere_distribution<_Dimen,
>+								_RealType>& __x)
>+    {
>+      typedef std::basic_ostream<_CharT, _Traits>  __ostream_type;
>+      typedef typename __ostream_type::ios_base    __ios_base;
>+
>+      const typename __ios_base::fmtflags __flags = __os.flags();
>+      const _CharT __fill = __os.fill();
>+      const std::streamsize __precision = __os.precision();
>+      const _CharT __space = __os.widen(' ');
>+      __os.flags(__ios_base::scientific | __ios_base::left);
>+      __os.fill(__space);
>+      __os.precision(std::numeric_limits<_RealType>::max_digits10);
>+
>+      __os.flags(__flags);
>+      __os.fill(__fill);
>+      __os.precision(__precision);
>+      return __os << __x.radius() << __space << __x._M_uosd;
>+    }
>+
>+  template<std::size_t _Dimen, typename _RealType, typename _CharT,
>+	   typename _Traits>
>+    std::basic_istream<_CharT, _Traits>&
>+    operator>>(std::basic_istream<_CharT, _Traits>& __is,
>+	       __gnu_cxx::uniform_inside_sphere_distribution<_Dimen,
>+							     _RealType>& __x)
>+    {
>+      typedef std::basic_istream<_CharT, _Traits>  __istream_type;
>+      typedef typename __istream_type::ios_base    __ios_base;
>+
>+      const typename __ios_base::fmtflags __flags = __is.flags();
>+      __is.flags(__ios_base::dec | __ios_base::skipws);
>+
>+      __is >> __x._M_uosd;
>+      __x.param(typename uniform_inside_sphere_distribution<_Dimen, _RealType>::
>+
>+      __is.flags(__flags);
>+      return __is;
>+    }
>+
> _GLIBCXX_END_NAMESPACE_VERSION
> } // namespace
>
>Index: testsuite/ext/random/uniform_inside_sphere_distribution/cons/default.cc
>===================================================================
>--- testsuite/ext/random/uniform_inside_sphere_distribution/cons/default.cc	(revision 0)
>+++ testsuite/ext/random/uniform_inside_sphere_distribution/cons/default.cc	(working copy)
>@@ -0,0 +1,43 @@
>+// { dg-options "-std=gnu++11" }
>+// { dg-require-cstdint "" }
>+//
>+// Copyright (C) 2014 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
>+// 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 copy of the GNU General Public License along
>+// with this library; see the file COPYING3.  If not see
>+
>+// Class template uniform_on_sphere
>+// 26.5.1.6 Random number distribution requirements [rand.req.dist]
>+
>+#include <ext/random>
>+#include <testsuite_hooks.h>
>+
>+void
>+test01()
>+{
>+  bool test [[gnu::unused]] = true;
>+
>+  __gnu_cxx::uniform_inside_sphere_distribution<2> u2;
>+  __gnu_cxx::uniform_inside_sphere_distribution<3> u3;
>+  __gnu_cxx::uniform_inside_sphere_distribution<4, double> u4;
>+  __gnu_cxx::uniform_inside_sphere_distribution<5, float> u5;
>+}
>+
>+int
>+main()
>+{
>+  test01();
>+  return 0;
>+}
>Index: testsuite/ext/random/uniform_inside_sphere_distribution/cons/parms.cc
>===================================================================
>--- testsuite/ext/random/uniform_inside_sphere_distribution/cons/parms.cc	(revision 0)
>+++ testsuite/ext/random/uniform_inside_sphere_distribution/cons/parms.cc	(working copy)
>@@ -0,0 +1,44 @@
>+// { dg-options "-std=gnu++11" }
>+// { dg-require-cstdint "" }
>+//
>+// Copyright (C) 2014 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
>+// 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 copy of the GNU General Public License along
>+// with this library; see the file COPYING3.  If not see
>+
>+// Class template logistic_distribution
>+// 26.5.1.6 Random number distribution requirements [rand.req.dist]
>+
>+#include <ext/random>
>+#include <testsuite_hooks.h>
>+
>+void
>+test01()
>+{
>+  bool test [[gnu::unused]] = true;
>+
>+  __gnu_cxx::uniform_inside_sphere_distribution<2> u(1.5);
>+  VERIFY( u.radius() == 1.5 );
>+
>+  __gnu_cxx::uniform_inside_sphere_distribution<3> v(3.0);
>+  VERIFY( v.radius() == 3.0 );
>+}
>+
>+int
>+main()
>+{
>+  test01();
>+  return 0;
>+}
>Index: testsuite/ext/random/uniform_inside_sphere_distribution/operators/equal.cc
>===================================================================
>--- testsuite/ext/random/uniform_inside_sphere_distribution/operators/equal.cc	(revision 0)
>+++ testsuite/ext/random/uniform_inside_sphere_distribution/operators/equal.cc	(working copy)
>@@ -0,0 +1,41 @@
>+// { dg-options "-std=gnu++11" }
>+// { dg-require-cstdint "" }
>+//
>+// Copyright (C) 2014 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
>+// 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 copy of the GNU General Public License along
>+// with this library; see the file COPYING3.  If not see
>+
>+// Class template uniform_inside_sphere_distribution
>+
>+#include <ext/random>
>+#include <testsuite_hooks.h>
>+
>+void
>+test01()
>+{
>+  bool test [[gnu::unused]] = true;
>+
>+  __gnu_cxx::uniform_inside_sphere_distribution<3> u(2.0), v(2.0);
>+
>+  VERIFY( u == v );
>+}
>+
>+int
>+main()
>+{
>+  test01();
>+  return 0;
>+}
>Index: testsuite/ext/random/uniform_inside_sphere_distribution/operators/generate.cc
>===================================================================
>--- testsuite/ext/random/uniform_inside_sphere_distribution/operators/generate.cc	(revision 0)
>+++ testsuite/ext/random/uniform_inside_sphere_distribution/operators/generate.cc	(working copy)
>@@ -0,0 +1,60 @@
>+// { dg-options "-std=gnu++11" }
>+// { dg-require-cstdint "" }
>+//
>+// Copyright (C) 2014 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
>+// 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 copy of the GNU General Public License along
>+// with this library; see the file COPYING3.  If not see
>+
>+// Class template uniform_inside_sphere_distribution
>+// 26.5.1.6 Random number distribution requirements [rand.req.dist]
>+
>+#include <ext/random>
>+#include <sstream>
>+#include <testsuite_hooks.h>
>+
>+void
>+test01()
>+{
>+  bool test [[gnu::unused]] = true;
>+  std::minstd_rand0 rng;
>+
>+  __gnu_cxx::uniform_inside_sphere_distribution<3> u3(2.0);
>+
>+  for (size_t n = 0; n < 1000; ++n)
>+    {
>+      auto r = u3(rng);
>+
>+      VERIFY (std::abs(r[0]) < 2.0
>+           && std::abs(r[1]) < 2.0
>+           && std::abs(r[2]) < 2.0);
>+    }
>+
>+  __gnu_cxx::uniform_inside_sphere_distribution<2> u2(4000.0);
>+
>+  for (size_t n = 0; n < 1000; ++n)
>+    {
>+      auto r = u2(rng);
>+
>+      VERIFY (std::abs(r[0]) < 4000.0 && std::abs(r[1]) < 4000.0);
>+    }
>+}
>+
>+int
>+main()
>+{
>+  test01();
>+  return 0;
>+}
>Index: testsuite/ext/random/uniform_inside_sphere_distribution/operators/inequal.cc
>===================================================================
>--- testsuite/ext/random/uniform_inside_sphere_distribution/operators/inequal.cc	(revision 0)
>+++ testsuite/ext/random/uniform_inside_sphere_distribution/operators/inequal.cc	(working copy)
>@@ -0,0 +1,41 @@
>+// { dg-options "-std=gnu++11" }
>+// { dg-require-cstdint "" }
>+//
>+// Copyright (C) 2014 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
>+// 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 copy of the GNU General Public License along
>+// with this library; see the file COPYING3.  If not see
>+
>+// Class template uniform_inside_sphere_distribution
>+
>+#include <ext/random>
>+#include <testsuite_hooks.h>
>+
>+void
>+test01()
>+{
>+  bool test [[gnu::unused]] = true;
>+
>+  __gnu_cxx::uniform_inside_sphere_distribution<3> u(4.0), v(4.0);
>+
>+  VERIFY( !(u != v) );
>+}
>+
>+int
>+main()
>+{
>+  test01();
>+  return 0;
>+}
>Index: testsuite/ext/random/uniform_inside_sphere_distribution/operators/serialize.cc
>===================================================================
>--- testsuite/ext/random/uniform_inside_sphere_distribution/operators/serialize.cc	(revision 0)
>+++ testsuite/ext/random/uniform_inside_sphere_distribution/operators/serialize.cc	(working copy)
>@@ -0,0 +1,50 @@
>+// { dg-options "-std=gnu++11" }
>+// { dg-require-cstdint "" }
>+//
>+// Copyright (C) 2014 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
>+// 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 copy of the GNU General Public License along
>+// with this library; see the file COPYING3.  If not see
>+
>+// Class template uniform_inside_sphere_distribution
>+// 26.5.1.6 Random number distribution requirements [rand.req.dist]
>+
>+#include <ext/random>
>+#include <sstream>
>+#include <testsuite_hooks.h>
>+
>+void
>+test01()
>+{
>+  bool test [[gnu::unused]] = true;
>+
>+  std::stringstream str;
>+  __gnu_cxx::uniform_inside_sphere_distribution<3> u(8.0), v(8.0);
>+  std::minstd_rand0 rng;
>+
>+  str << u;
>+
>+  str >> v;
>+
>+  VERIFY( u == v );
>+}
>+
>+int
>+main()
>+{
>+  test01();
>+  return 0;
>+}

>// /home/ed/bin/bin/g++ -std=c++1z -o deathmatch deathmatch.cpp
>
>// LD_LIBRARY_PATH=/home/ed/bin/lib64:\$LD_LIBRARY_PATH ./deathmatch 100000
>
>#include "uniform_inside_sphere_distribution.h"
>#include "uniform_inside_sphere_distribution_old.h"
>#include <ext/random>
>#include "timer.h"
>
>#include <iostream>
>
>template <std::size_t _Dim>
>  void
>  test(double radius = 1.0, int num = 1000000)
>  {
>    Timer timer;
>
>    std::default_random_engine re; // the default engine
>
>
>    timer.start();
>    for (int i = 0; i < num; ++i)
>      insphnew(re);
>    timer.stop();
>
>    std::cout << std::endl << "  New (Rejection) Distribution - Dim=" << _Dim;
>    std::cout << std::endl << "  Total time per iter = "
>              << 1.0 * timer.time_elapsed() << " ms";
>    std::cout << std::endl << "  Mean time per iter  = "
>              << 1.0 * timer.time_elapsed() / num << " ms" << std::endl;
>
>
>    timer.start();
>    for (int i = 0; i < num; ++i)
>      insphold(re);
>    timer.stop();
>
>    std::cout << std::endl << "  Old (Transform) Distribution - Dim=" << _Dim;
>    std::cout << std::endl << "  Total time per iter = "
>              << 1.0 * timer.time_elapsed() << " ms";
>    std::cout << std::endl << "  Mean time per iter  = "
>              << 1.0 * timer.time_elapsed() / num << " ms" << std::endl;
>  }
>
>int
>main(int n_app_args, char ** app_arg)
>{
>  int num = 10000;
>  if (n_app_args > 1)
>    num = atoi(app_arg[1]);
>
>  //  Segment
>
>  test<1>(1.0, num);
>
>  //  Circle
>
>  test<2>(2.0, num);
>
>  //  Sphere
>
>  test<3>(3.0, num);
>
>  //  Hypersphere
>
>  test<4>(4.0, num);
>
>  //  Etc...
>
>  test<5>(5.0, num);
>
>  test<6>(6.0, num);
>
>  test<7>(7.0, num);
>
>  test<8>(8.0, num);
>
>  test<9>(9.0, num);
>
>  Timer timer;
>
>  //
>
>  timer.start();
>  double sum = 0.0;
>  for (int i = 0; i < num; ++i)
>  {
>    sum += std::sqrt(i*1.0);
>    sum -= std::pow(i*1.0, 0.333333);
>  }
>  timer.stop();
>  std::cout << std::endl << "  Bunch of calls to pow";
>  std::cout << std::endl << "  Total time per iter = "
>            << 1.0 * timer.time_elapsed() << " ms";
>  std::cout << std::endl << "  Mean time per iter  = "
>            << 1.0 * timer.time_elapsed() / num << " ms" << std::endl;
>
>  //
>
>  std::default_random_engine re; // the default engine
>
>  __gnu_cxx::uniform_on_sphere_distribution<3> onsphnew;
>
>  timer.start();
>  for (int i = 0; i < num; ++i)
>    onsphnew(re);
>  timer.stop();
>
>  std::cout << std::endl << "  uniform_on_sphere_distribution - Dim=" << 3;
>  std::cout << std::endl << "  Total time per iter = "
>            << 1.0 * timer.time_elapsed() << " ms";
>  std::cout << std::endl << "  Mean time per iter  = "
>            << 1.0 * timer.time_elapsed() / num << " ms" << std::endl;
>
>  //
>
>  timer.start();
>  for (int i = 0; i < num * 3; ++i)
>    re();
>  timer.stop();
>
>  std::cout << std::endl << "  default_random_engine - Dim=" << 3;
>  std::cout << std::endl << "  Total time per iter = "
>            << 1.0 * timer.time_elapsed() << " ms";
>  std::cout << std::endl << "  Mean time per iter  = "
>            << 1.0 * timer.time_elapsed() / num << " ms" << std::endl;
>}

```