This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Add uniform_inside_sphere_distribution


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.

ed@bad-horse:~/tr2$ 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 old and new headers.

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: Add uniform_inside_sphere_distribution.
	* 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
+	param_type(_RealType __radius = _RealType(1))
+	: _M_radius(__radius)
+	{
+	  _GLIBCXX_DEBUG_ASSERT(_M_radius > _RealType(0));
+	}
+
+	_RealType
+	radius() const
+	{ return _M_radius; }
+
+	friend bool
+	operator==(const param_type& __p1, const param_type& __p2)
+	{ return __p1._M_radius == __p2._M_radius; }
+
+      private:
+	_RealType _M_radius;
+      };
+
+      /**
+       * @brief Constructors.
+       */
+      explicit
+      uniform_inside_sphere_distribution(_RealType __radius = _RealType(1))
+      : _M_param(__radius), _M_uosd()
+      { }
+
+      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
+      radius() const
+      { return _M_param.radius(); }
+
+      /**
+       * @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 __radius)
+        {
+	  std::__detail::_Adaptor<_UniformRandomNumberGenerator,
+				  _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,
+		   _RealType __radius)
+        {
+	  result_type __ret;
+	  _RealType __sq;
+	  _RealType __radsq = __radius * __radius;
+	  std::__detail::_Adaptor<_UniformRandomNumberGenerator,
+				  _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)
+            __ret[i] *= __radius;
+
+	  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;
+        return __helper(_M_uosd, __urng, __p.radius());
+      }
+
+  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);
+
+      _RealType __radius_val;
+      __is >> __radius_val;
+      __is >> __x._M_uosd;
+      __x.param(typename uniform_inside_sphere_distribution<_Dimen, _RealType>::
+		param_type(__radius_val));
+
+      __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
+// 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 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
+// 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 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
+// 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 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
+// 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 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
+// 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 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
+// 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 copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 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;
+
+  u(rng); // advance
+  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

   __gnu_cxx::uniform_inside_sphere_distribution<_Dim> insphnew(radius);

   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;

   __old::uniform_inside_sphere_distribution<_Dim> insphold(radius);

   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;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]