/* boost random/uniform_on_sphere.hpp header file | |
* | |
* Copyright Jens Maurer 2000-2001 | |
* Distributed under the Boost Software License, Version 1.0. (See | |
* accompanying file LICENSE_1_0.txt or copy at | |
* http://www.boost.org/LICENSE_1_0.txt) | |
* | |
* See http://www.boost.org for most recent version including documentation. | |
* | |
* $Id: uniform_on_sphere.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ | |
* | |
* Revision history | |
* 2001-02-18 moved to individual header files | |
*/ | |
#ifndef BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP | |
#define BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP | |
#include <vector> | |
#include <algorithm> // std::transform | |
#include <functional> // std::bind2nd, std::divides | |
#include <boost/random/detail/config.hpp> | |
#include <boost/random/normal_distribution.hpp> | |
namespace boost { | |
/** | |
* Instantiations of class template uniform_on_sphere model a | |
* \random_distribution. Such a distribution produces random | |
* numbers uniformly distributed on the unit sphere of arbitrary | |
* dimension @c dim. The @c Cont template parameter must be a STL-like | |
* container type with begin and end operations returning non-const | |
* ForwardIterators of type @c Cont::iterator. Each invocation of the | |
* @c UniformRandomNumberGenerator shall result in a floating-point | |
* value in the range [0,1). | |
*/ | |
template<class RealType = double, class Cont = std::vector<RealType> > | |
class uniform_on_sphere | |
{ | |
public: | |
typedef RealType input_type; | |
typedef Cont result_type; | |
/** | |
* Constructs a @c uniform_on_sphere distribution. | |
* @c dim is the dimension of the sphere. | |
*/ | |
explicit uniform_on_sphere(int dim = 2) : _container(dim), _dim(dim) { } | |
// compiler-generated copy ctor and assignment operator are fine | |
void reset() { _normal.reset(); } | |
template<class Engine> | |
const result_type & operator()(Engine& eng) | |
{ | |
RealType sqsum = 0; | |
for(typename Cont::iterator it = _container.begin(); | |
it != _container.end(); | |
++it) { | |
RealType val = _normal(eng); | |
*it = val; | |
sqsum += val * val; | |
} | |
#ifndef BOOST_NO_STDC_NAMESPACE | |
using std::sqrt; | |
#endif | |
// for all i: result[i] /= sqrt(sqsum) | |
std::transform(_container.begin(), _container.end(), _container.begin(), | |
std::bind2nd(std::divides<RealType>(), sqrt(sqsum))); | |
return _container; | |
} | |
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS | |
template<class CharT, class Traits> | |
friend std::basic_ostream<CharT,Traits>& | |
operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_on_sphere& sd) | |
{ | |
os << sd._dim; | |
return os; | |
} | |
template<class CharT, class Traits> | |
friend std::basic_istream<CharT,Traits>& | |
operator>>(std::basic_istream<CharT,Traits>& is, uniform_on_sphere& sd) | |
{ | |
is >> std::ws >> sd._dim; | |
sd._container.resize(sd._dim); | |
return is; | |
} | |
#endif | |
private: | |
normal_distribution<RealType> _normal; | |
result_type _container; | |
int _dim; | |
}; | |
} // namespace boost | |
#endif // BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP |