diff options
author | drepper <drepper@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-08-09 17:56:57 +0000 |
---|---|---|
committer | drepper <drepper@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-08-09 17:56:57 +0000 |
commit | 434a8652bcfca85cc7943f40edcb446d3836df0e (patch) | |
tree | fe2db3e1f114899d237246f8880766ed03556483 /libstdc++-v3/include | |
parent | 995b79b1898d03059f21226e9ac483d01cd95f71 (diff) | |
download | gcc-434a8652bcfca85cc7943f40edcb446d3836df0e.tar.gz |
* include/ext/random.tcc (uniform_on_sphere_helper): Define.
(uniform_on_sphere_distribution::operator()): Use the new helper
class for the implementation.
* testsuite/ext/random/uniform_on_sphere_distribution/operators/
equal.cc: Remove bogus part of comment.
* testsuite/ext/random/uniform_on_sphere_distribution/operators/
inequal.cc: Likewise.
* testsuite/ext/random/uniform_on_sphere_distribution/operators/
serialize.cc: Add check to verify result of serialzation and
deserialization.
* testsuite/ext/random/uniform_on_sphere_distribution/operators/
generate.cc: New file.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@213779 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/ext/random.tcc | 91 |
1 files changed, 79 insertions, 12 deletions
diff --git a/libstdc++-v3/include/ext/random.tcc b/libstdc++-v3/include/ext/random.tcc index 05361d8f491..997c204ffe2 100644 --- a/libstdc++-v3/include/ext/random.tcc +++ b/libstdc++-v3/include/ext/random.tcc @@ -1540,6 +1540,83 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } + namespace { + + // Helper class for the uniform_on_sphere_distribution generation + // function. + template<std::size_t _Dimen, typename _RealType> + class uniform_on_sphere_helper + { + typedef typename uniform_on_sphere_distribution<_Dimen, _RealType>::result_type result_type; + + public: + template<typename _NormalDistribution, typename _UniformRandomNumberGenerator> + result_type operator()(_NormalDistribution& __nd, + _UniformRandomNumberGenerator& __urng) + { + result_type __ret; + typename result_type::value_type __norm; + + do + { + auto __sum = _RealType(0); + + std::generate(__ret.begin(), __ret.end(), + [&__nd, &__urng, &__sum](){ + _RealType __t = __nd(__urng); + __sum += __t * __t; + return __t; }); + __norm = std::sqrt(__sum); + } + while (__norm == _RealType(0) || ! std::isfinite(__norm)); + + std::transform(__ret.begin(), __ret.end(), __ret.begin(), + [__norm](_RealType __val){ return __val / __norm; }); + + return __ret; + } + }; + + + template<typename _RealType> + class uniform_on_sphere_helper<2, _RealType> + { + typedef typename uniform_on_sphere_distribution<2, _RealType>:: + result_type result_type; + + public: + template<typename _NormalDistribution, + typename _UniformRandomNumberGenerator> + result_type operator()(_NormalDistribution&, + _UniformRandomNumberGenerator& __urng) + { + result_type __ret; + _RealType __sq; + std::__detail::_Adaptor<_UniformRandomNumberGenerator, + _RealType> __aurng(__urng); + + do + { + __ret[0] = _RealType(2) * __aurng() - _RealType(1); + __ret[1] = _RealType(2) * __aurng() - _RealType(1); + + __sq = __ret[0] * __ret[0] + __ret[1] * __ret[1]; + } + while (__sq == _RealType(0) || __sq > _RealType(1)); + + // Yes, we do not just use sqrt(__sq) because hypot() is more + // accurate. + auto __norm = std::hypot(__ret[0], __ret[1]); + __ret[0] /= __norm; + __ret[1] /= __norm; + + return __ret; + } + }; + + } + + template<std::size_t _Dimen, typename _RealType> template<typename _UniformRandomNumberGenerator> typename uniform_on_sphere_distribution<_Dimen, _RealType>::result_type @@ -1547,18 +1624,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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_nd(__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; + uniform_on_sphere_helper<_Dimen, _RealType> __helper; + return __helper(_M_nd, __urng); } template<std::size_t _Dimen, typename _RealType> |