1 /* boost random/uniform_on_sphere.hpp header file
3 * Copyright Jens Maurer 2000-2001
4 * Copyright Steven Watanabe 2011
5 * Distributed under the Boost Software License, Version 1.0. (See
6 * accompanying file LICENSE_1_0.txt or copy at
7 * http://www.boost.org/LICENSE_1_0.txt)
9 * See http://www.boost.org for most recent version including documentation.
14 * 2001-02-18 moved to individual header files
17 #ifndef BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP
18 #define BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP
21 #include <algorithm> // std::transform
22 #include <functional> // std::bind2nd, std::divides
23 #include <boost/assert.hpp>
24 #include <boost/random/detail/config.hpp>
25 #include <boost/random/detail/operators.hpp>
26 #include <boost/random/normal_distribution.hpp>
32 * Instantiations of class template uniform_on_sphere model a
33 * \random_distribution. Such a distribution produces random
34 * numbers uniformly distributed on the unit sphere of arbitrary
35 * dimension @c dim. The @c Cont template parameter must be a STL-like
36 * container type with begin and end operations returning non-const
37 * ForwardIterators of type @c Cont::iterator.
39 template<class RealType = double, class Cont = std::vector<RealType> >
40 class uniform_on_sphere
43 typedef RealType input_type;
44 typedef Cont result_type;
50 typedef uniform_on_sphere distribution_type;
53 * Constructs the parameters of a uniform_on_sphere
54 * distribution, given the dimension of the sphere.
56 explicit param_type(int dim_arg = 2) : _dim(dim_arg)
58 BOOST_ASSERT(_dim >= 0);
61 /** Returns the dimension of the sphere. */
62 int dim() const { return _dim; }
64 /** Writes the parameters to a @c std::ostream. */
65 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
71 /** Reads the parameters from a @c std::istream. */
72 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
78 /** Returns true if the two sets of parameters are equal. */
79 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
80 { return lhs._dim == rhs._dim; }
82 /** Returns true if the two sets of parameters are different. */
83 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
90 * Constructs a @c uniform_on_sphere distribution.
91 * @c dim is the dimension of the sphere.
95 explicit uniform_on_sphere(int dim_arg = 2)
96 : _container(dim_arg), _dim(dim_arg) { }
99 * Constructs a @c uniform_on_sphere distribution from its parameters.
101 explicit uniform_on_sphere(const param_type& parm)
102 : _container(parm.dim()), _dim(parm.dim()) { }
104 // compiler-generated copy ctor and assignment operator are fine
106 /** Returns the dimension of the sphere. */
107 int dim() const { return _dim; }
109 /** Returns the parameters of the distribution. */
110 param_type param() const { return param_type(_dim); }
111 /** Sets the parameters of the distribution. */
112 void param(const param_type& parm)
115 _container.resize(_dim);
119 * Returns the smallest value that the distribution can produce.
120 * Note that this is required to approximate the standard library's
121 * requirements. The behavior is defined according to lexicographical
122 * comparison so that for a container type of std::vector,
123 * dist.min() <= x <= dist.max() where x is any value produced
124 * by the distribution.
126 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
128 result_type result(_dim);
130 result.front() = RealType(-1.0);
135 * Returns the largest value that the distribution can produce.
136 * Note that this is required to approximate the standard library's
137 * requirements. The behavior is defined according to lexicographical
138 * comparison so that for a container type of std::vector,
139 * dist.min() <= x <= dist.max() where x is any value produced
140 * by the distribution.
142 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
144 result_type result(_dim);
146 result.front() = RealType(1.0);
152 * Effects: Subsequent uses of the distribution do not depend
153 * on values produced by any engine prior to invoking reset.
158 * Returns a point uniformly distributed over the surface of
159 * a sphere of dimension dim().
161 template<class Engine>
162 const result_type & operator()(Engine& eng)
170 if(uniform_01<RealType>()(eng) < 0.5) {
171 *_container.begin() = -1;
173 *_container.begin() = 1;
179 uniform_01<RealType> uniform;
183 x = uniform(eng) * 2 - 1;
184 y = uniform(eng) * 2 - 1;
186 } while(sqsum == 0 || sqsum > 1);
187 RealType mult = 1/sqrt(sqsum);
188 typename Cont::iterator iter = _container.begin();
196 uniform_01<RealType> uniform;
200 x = uniform(eng) * 2 - 1;
201 y = uniform(eng) * 2 - 1;
204 RealType mult = 2 * sqrt(1 - sqsum);
205 typename Cont::iterator iter = _container.begin();
210 *iter = 2 * sqsum - 1;
215 detail::unit_normal_distribution<RealType> normal;
219 for(typename Cont::iterator it = _container.begin();
220 it != _container.end();
222 RealType val = normal(eng);
227 // for all i: result[i] /= sqrt(sqsum)
228 std::transform(_container.begin(), _container.end(), _container.begin(),
229 std::bind2nd(std::multiplies<RealType>(), 1/sqrt(sqsum)));
236 * Returns a point uniformly distributed over the surface of
237 * a sphere of dimension param.dim().
239 template<class Engine>
240 result_type operator()(Engine& eng, const param_type& parm) const
242 return uniform_on_sphere(parm)(eng);
245 /** Writes the distribution to a @c std::ostream. */
246 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_on_sphere, sd)
252 /** Reads the distribution from a @c std::istream. */
253 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_on_sphere, sd)
256 sd._container.resize(sd._dim);
261 * Returns true if the two distributions will produce identical
262 * sequences of values, given equal generators.
264 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_on_sphere, lhs, rhs)
265 { return lhs._dim == rhs._dim; }
268 * Returns true if the two distributions may produce different
269 * sequences of values, given equal generators.
271 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_on_sphere)
274 result_type _container;
278 } // namespace random
280 using random::uniform_on_sphere;
284 #endif // BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP