From 863a2c7ecc08465b437e66e730bb185474552688 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 13 Jul 2014 11:07:44 +0000 Subject: 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/include/ext/random | 203 ++++++++++++++++++++++++++++++++++-- libstdc++-v3/include/ext/random.tcc | 61 ++++++++++- 2 files changed, 257 insertions(+), 7 deletions(-) (limited to 'libstdc++-v3/include/ext') diff --git a/libstdc++-v3/include/ext/random b/libstdc++-v3/include/ext/random index eab3fb8..e6d5ca0 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 ba9ab6d..c836b21 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 -- cgit v1.1