From 863a2c7ecc08465b437e66e730bb185474552688 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 13 Jul 2014 11:07:44 +0000 Subject: [PATCH] random: Add uniform_on_sphere_distribution definition. 2014-07-12 Ulrich Drepper * include/ext/random: Add uniform_on_sphere_distribution definition. * include/ext/random.tcc: Add out-of-band member function definitions for uniform_on_sphere_distribution. * testsuite/ext/random/uniform_on_sphere_distribution/ cons/default.cc: New file. * testsuite/ext/random/uniform_on_sphere_distribution/ operators/equal.cc: New file. * testsuite/ext/random/uniform_on_sphere_distribution/ operators/inequal.cc: New file. * testsuite/ext/random/uniform_on_sphere_distribution/ operators/serialize.cc: New file. From-SVN: r212492 --- libstdc++-v3/ChangeLog | 24 ++- libstdc++-v3/include/ext/random | 203 +++++++++++++++++- libstdc++-v3/include/ext/random.tcc | 61 +++++- .../cons/default.cc | 45 ++++ .../operators/equal.cc | 43 ++++ .../operators/inequal.cc | 43 ++++ .../operators/serialize.cc | 50 +++++ 7 files changed, 457 insertions(+), 12 deletions(-) create mode 100644 libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/cons/default.cc create mode 100644 libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/equal.cc create mode 100644 libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/inequal.cc create mode 100644 libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/serialize.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c8a6a6d95c6..4b798c0f125 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,17 @@ +2014-07-12 Ulrich Drepper + + * include/ext/random: Add uniform_on_sphere_distribution definition. + * include/ext/random.tcc: Add out-of-band member function definitions + for uniform_on_sphere_distribution. + * testsuite/ext/random/uniform_on_sphere_distribution/ + cons/default.cc: New file. + * testsuite/ext/random/uniform_on_sphere_distribution/ + operators/equal.cc: New file. + * testsuite/ext/random/uniform_on_sphere_distribution/ + operators/inequal.cc: New file. + * testsuite/ext/random/uniform_on_sphere_distribution/ + operators/serialize.cc: New file. + 2014-07-11 Edward Smith-Rowland <3dw4rd@verizon.net> Add the logistic_distribution as an extension. @@ -94,7 +108,7 @@ Revert: 2014-06-18 Paolo Carlini - Ramana Radhakrishnan + Ramana Radhakrishnan PR libstdc++/61536 * config/abi/pre/gnu.ver: Adjust for out of line comparisons. @@ -159,7 +173,7 @@ * include/std/chrono (_Checked_integral_constant): Allow zero. * testsuite/20_util/duration/literals/values.cc: Test non-positive values and digit separators. - * include/experimental/any + * include/experimental/any PR libstdc++/61532 * testsuite/20_util/make_signed/requirements/typedefs-1.cc: Do not @@ -541,10 +555,10 @@ 2014-05-20 Cesar Philippidis - * scripts/testsuite_flags.in (cxxflags): Remove @CXXFLAGS@ since + * scripts/testsuite_flags.in (cxxflags): Remove @CXXFLAGS@ since libstdc++.exp imports those flags via getenv. - * testsuite/lib/libstdc++.exp (libstdc++_init): Ensure that - CXXFLAGS contains a '-O' flag. + * testsuite/lib/libstdc++.exp (libstdc++_init): Ensure that + CXXFLAGS contains a '-O' flag. 2014-05-20 Alexey Merzlyakov diff --git a/libstdc++-v3/include/ext/random b/libstdc++-v3/include/ext/random index eab3fb8ef32..e6d5ca0dba4 100644 --- a/libstdc++-v3/include/ext/random +++ b/libstdc++-v3/include/ext/random @@ -36,6 +36,7 @@ #else #include +#include #include #include #ifdef __SSE2__ @@ -2962,7 +2963,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { using _IntType = typename std::make_signed::type; return static_cast(std::max(static_cast<_IntType>(0), - static_cast<_IntType>(this->total_draws() + static_cast<_IntType>(this->total_draws() - this->unsuccessful_size()))); } @@ -3033,7 +3034,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const __gnu_cxx::hypergeometric_distribution<_UIntType1>& - __x); + __x); /** * @brief Extracts a %hypergeometric_distribution random number @@ -3127,7 +3128,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend bool operator==(const param_type& __p1, const param_type& __p2) { return __p1._M_a == __p2._M_a - && __p1._M_b == __p2._M_b; } + && __p1._M_b == __p2._M_b; } private: void _M_initialize(); @@ -3238,10 +3239,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * be generated are equal. */ template - friend bool - operator==(const logistic_distribution<_RealType1>& __d1, + friend bool + operator==(const logistic_distribution<_RealType1>& __d1, const logistic_distribution<_RealType1>& __d2) - { return __d1.param() == __d2.param(); } + { return __d1.param() == __d2.param(); } /** * @brief Inserts a %logistic_distribution random number distribution @@ -3293,6 +3294,196 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const logistic_distribution<_RealType1>& __d2) { return !(__d1 == __d2); } + + /** + * @brief A distribution for random coordinates on a unit sphere. + * + * The method used in the generation function is attributed by Donald Knuth + * to G. W. Brown, Modern Mathematics for the Engineer (1956). + */ + template + class uniform_on_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. */ + typedef std::array<_RealType, _Dimen> result_type; + /** Parameter type. */ + struct param_type + { + explicit + param_type() + { } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return true; } + }; + + /** + * @brief Constructs a uniform on sphere distribution. + */ + explicit + uniform_on_sphere_distribution() + : _M_param(), _M_n(_RealType(0), _RealType(1)) + { } + + explicit + uniform_on_sphere_distribution(const param_type& __p) + : _M_param(__p), _M_n(_RealType(0), _RealType(1)) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @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 + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, this->param()); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + 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_on_sphere_distribution& __d1, + const uniform_on_sphere_distribution& __d2) + { return true; } + + /** + * @brief Inserts a %uniform_on_sphere_distribution random number distribution + * @p __x into the output stream @p __os. + * + * @param __os An output stream. + * @param __x A %uniform_on_sphere_distribution random number distribution. + * + * @returns The output stream with the state of @p __x inserted or in + * an error state. + */ + template + friend std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const __gnu_cxx::uniform_on_sphere_distribution<_Dimen1, + _RealType1>& + __x); + + /** + * @brief Extracts a %uniform_on_sphere_distribution random number distribution + * @p __x from the input stream @p __is. + * + * @param __is An input stream. + * @param __x A %uniform_on_sphere_distribution random number generator engine. + * + * @returns The input stream with @p __x extracted or in an error state. + */ + template + friend std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + __gnu_cxx::uniform_on_sphere_distribution<_Dimen1, + _RealType1>& __x); + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + std::normal_distribution<_RealType> _M_n; + }; + + /** + * @brief Return true if two uniform on sphere distributions are different. + */ + template + inline bool + operator!=(const __gnu_cxx::uniform_on_sphere_distribution<_Dimen, + _RealType>& __d1, + const __gnu_cxx::uniform_on_sphere_distribution<_Dimen, + _RealType>& __d2) + { return false; } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace __gnu_cxx diff --git a/libstdc++-v3/include/ext/random.tcc b/libstdc++-v3/include/ext/random.tcc index ba9ab6dcce2..c836b211cae 100644 --- a/libstdc++-v3/include/ext/random.tcc +++ b/libstdc++-v3/include/ext/random.tcc @@ -1362,7 +1362,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION result_type __b = __param.total_size(); result_type __k = 0; - if (__param.total_draws() < __param.total_size() / 2) + if (__param.total_draws() < __param.total_size() / 2) { for (result_type __i = 0; __i < __param.total_draws(); ++__i) { @@ -1539,6 +1539,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __is; } + + template + template + typename uniform_on_sphere_distribution<_Dimen, _RealType>::result_type + uniform_on_sphere_distribution<_Dimen, _RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + result_type __ret; + _RealType __sum = _RealType(0); + + std::generate(__ret.begin(), __ret.end(), + [&__urng, &__sum, this](){ _RealType __t = _M_n(__urng); + __sum += __t * __t; + return __t; }); + auto __norm = std::sqrt(__sum); + std::transform(__ret.begin(), __ret.end(), __ret.begin(), + [__norm](_RealType __val){ return __val / __norm; }); + + return __ret; + } + + template + template + void + uniform_on_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::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const __gnu_cxx::uniform_on_sphere_distribution<_Dimen, + _RealType>& __x) + { + // The distribution has no state, nothing to save. + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + __gnu_cxx::uniform_on_sphere_distribution<_Dimen, + _RealType>& __x) + { + // The distribution has no state, nothing to restore. + return __is; + } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/cons/default.cc b/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/cons/default.cc new file mode 100644 index 00000000000..fb48fe23ab5 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/cons/default.cc @@ -0,0 +1,45 @@ +// { dg-options "-std=gnu++11" } +// { dg-require-cstdint "" } +// +// 2014-04-15 Ulrich Drepper +// +// 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 +// . + +// 26.4.8.3.* Class template uniform_in_sphere [rand.dist.ext.uniform_on_sphere] +// 26.4.2.4 Concept RandomNumberDistribution [rand.concept.dist] + +#include +#include + +void +test01() +{ + bool test [[gnu::unused]] = true; + + __gnu_cxx::uniform_on_sphere_distribution<2> u2; + __gnu_cxx::uniform_on_sphere_distribution<3> u3; + __gnu_cxx::uniform_on_sphere_distribution<4, double> u4; + __gnu_cxx::uniform_on_sphere_distribution<5, float> u5; +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/equal.cc b/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/equal.cc new file mode 100644 index 00000000000..35a024ee9a5 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/equal.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11" } +// { dg-require-cstdint "" } +// +// 2014-04-15 Ulrich Drepper +// +// 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 +// . + +// 26.5.8.4.5 Class template uniform_on_sphere_distribution [rand.dist.ext.uniform_on_sphere] + +#include +#include + +void +test01() +{ + bool test [[gnu::unused]] = true; + + __gnu_cxx::uniform_on_sphere_distribution<3> u, v; + + VERIFY( u == v ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/inequal.cc b/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/inequal.cc new file mode 100644 index 00000000000..9f8e8c81720 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/inequal.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11" } +// { dg-require-cstdint "" } +// +// 2014-04-15 Ulrich Drepper +// +// 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 +// . + +// 26.5.8.4.5 Class template uniform_on_sphere_distribution [rand.dist.ext.uniform_on_sphere] + +#include +#include + +void +test01() +{ + bool test [[gnu::unused]] = true; + + __gnu_cxx::uniform_on_sphere_distribution<3> u, v; + + VERIFY( !(u != v) ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/serialize.cc b/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/serialize.cc new file mode 100644 index 00000000000..80264ff8294 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/random/uniform_on_sphere_distribution/operators/serialize.cc @@ -0,0 +1,50 @@ +// { dg-options "-std=gnu++11" } +// { dg-require-cstdint "" } +// +// 2014-04-15 Ulrich Drepper +// +// 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 +// . + +// 26.4.8.3.* Class template uniform_on_sphere_distribution [rand.dist.ext.uniform_on_sphere] +// 26.4.2.4 Concept RandomNumberDistribution [rand.concept.dist] + +#include +#include +#include + +void +test01() +{ + bool test [[gnu::unused]] = true; + + std::stringstream str; + __gnu_cxx::uniform_on_sphere_distribution<3> u, v; + std::minstd_rand0 rng; + + u(rng); // advance + str << u; + + str >> v; +} + +int +main() +{ + test01(); + return 0; +}