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.
11 * $Id: uniform_on_sphere.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $
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.
155 void reset() { _normal.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)
165 for(typename Cont::iterator it = _container.begin();
166 it != _container.end();
168 RealType val = _normal(eng);
173 // for all i: result[i] /= sqrt(sqsum)
174 std::transform(_container.begin(), _container.end(), _container.begin(),
175 std::bind2nd(std::divides<RealType>(), sqrt(sqsum)));
180 * Returns a point uniformly distributed over the surface of
181 * a sphere of dimension param.dim().
183 template<class Engine>
184 result_type operator()(Engine& eng, const param_type& parm) const
186 return uniform_on_sphere(parm)(eng);
189 /** Writes the distribution to a @c std::ostream. */
190 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_on_sphere, sd)
196 /** Reads the distribution from a @c std::istream. */
197 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_on_sphere, sd)
200 sd._container.resize(sd._dim);
205 * Returns true if the two distributions will produce identical
206 * sequences of values, given equal generators.
208 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_on_sphere, lhs, rhs)
209 { return lhs._dim == rhs._dim && lhs._normal == rhs._normal; }
212 * Returns true if the two distributions may produce different
213 * sequences of values, given equal generators.
215 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_on_sphere)
218 normal_distribution<RealType> _normal;
219 result_type _container;
223 } // namespace random
225 using random::uniform_on_sphere;
229 #endif // BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP