Add uniform_inside_sphere_distribution
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.
>
>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;
>}
More information about the Libstdc++
mailing list