File indexing completed on 2025-01-18 09:51:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP
0018 #define BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP
0019
0020 #include <vector>
0021 #include <algorithm> // std::transform
0022 #include <functional> // std::bind2nd, std::divides
0023 #include <boost/assert.hpp>
0024 #include <boost/random/detail/config.hpp>
0025 #include <boost/random/detail/operators.hpp>
0026 #include <boost/random/normal_distribution.hpp>
0027
0028 namespace boost {
0029 namespace random {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 template<class RealType = double, class Cont = std::vector<RealType> >
0040 class uniform_on_sphere
0041 {
0042 public:
0043 typedef RealType input_type;
0044 typedef Cont result_type;
0045
0046 class param_type
0047 {
0048 public:
0049
0050 typedef uniform_on_sphere distribution_type;
0051
0052
0053
0054
0055
0056 explicit param_type(int dim_arg = 2) : _dim(dim_arg)
0057 {
0058 BOOST_ASSERT(_dim >= 0);
0059 }
0060
0061
0062 int dim() const { return _dim; }
0063
0064
0065 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
0066 {
0067 os << parm._dim;
0068 return os;
0069 }
0070
0071
0072 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
0073 {
0074 is >> parm._dim;
0075 return is;
0076 }
0077
0078
0079 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
0080 { return lhs._dim == rhs._dim; }
0081
0082
0083 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
0084
0085 private:
0086 int _dim;
0087 };
0088
0089
0090
0091
0092
0093
0094
0095 explicit uniform_on_sphere(int dim_arg = 2)
0096 : _container(dim_arg), _dim(dim_arg) { }
0097
0098
0099
0100
0101 explicit uniform_on_sphere(const param_type& parm)
0102 : _container(parm.dim()), _dim(parm.dim()) { }
0103
0104
0105
0106
0107 int dim() const { return _dim; }
0108
0109
0110 param_type param() const { return param_type(_dim); }
0111
0112 void param(const param_type& parm)
0113 {
0114 _dim = parm.dim();
0115 _container.resize(_dim);
0116 }
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
0127 {
0128 result_type result(_dim);
0129 if(_dim != 0) {
0130 result.front() = RealType(-1.0);
0131 }
0132 return result;
0133 }
0134
0135
0136
0137
0138
0139
0140
0141
0142 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
0143 {
0144 result_type result(_dim);
0145 if(_dim != 0) {
0146 result.front() = RealType(1.0);
0147 }
0148 return result;
0149 }
0150
0151
0152
0153
0154
0155 void reset() {}
0156
0157
0158
0159
0160
0161 template<class Engine>
0162 const result_type & operator()(Engine& eng)
0163 {
0164 using std::sqrt;
0165 switch(_dim)
0166 {
0167 case 0: break;
0168 case 1:
0169 {
0170 if(uniform_01<RealType>()(eng) < 0.5) {
0171 *_container.begin() = -1;
0172 } else {
0173 *_container.begin() = 1;
0174 }
0175 break;
0176 }
0177 case 2:
0178 {
0179 uniform_01<RealType> uniform;
0180 RealType sqsum;
0181 RealType x, y;
0182 do {
0183 x = uniform(eng) * 2 - 1;
0184 y = uniform(eng) * 2 - 1;
0185 sqsum = x*x + y*y;
0186 } while(sqsum == 0 || sqsum > 1);
0187 RealType mult = 1/sqrt(sqsum);
0188 typename Cont::iterator iter = _container.begin();
0189 *iter = x * mult;
0190 iter++;
0191 *iter = y * mult;
0192 break;
0193 }
0194 case 3:
0195 {
0196 uniform_01<RealType> uniform;
0197 RealType sqsum;
0198 RealType x, y;
0199 do {
0200 x = uniform(eng) * 2 - 1;
0201 y = uniform(eng) * 2 - 1;
0202 sqsum = x*x + y*y;
0203 } while(sqsum > 1);
0204 RealType mult = 2 * sqrt(1 - sqsum);
0205 typename Cont::iterator iter = _container.begin();
0206 *iter = x * mult;
0207 ++iter;
0208 *iter = y * mult;
0209 ++iter;
0210 *iter = 2 * sqsum - 1;
0211 break;
0212 }
0213 default:
0214 {
0215 detail::unit_normal_distribution<RealType> normal;
0216 RealType sqsum;
0217 do {
0218 sqsum = 0;
0219 for(typename Cont::iterator it = _container.begin();
0220 it != _container.end();
0221 ++it) {
0222 RealType val = normal(eng);
0223 *it = val;
0224 sqsum += val * val;
0225 }
0226 } while(sqsum == 0);
0227
0228 RealType inverse_distance = 1 / sqrt(sqsum);
0229 for(typename Cont::iterator it = _container.begin();
0230 it != _container.end();
0231 ++it) {
0232 *it *= inverse_distance;
0233 }
0234 }
0235 }
0236 return _container;
0237 }
0238
0239
0240
0241
0242
0243 template<class Engine>
0244 result_type operator()(Engine& eng, const param_type& parm) const
0245 {
0246 return uniform_on_sphere(parm)(eng);
0247 }
0248
0249
0250 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_on_sphere, sd)
0251 {
0252 os << sd._dim;
0253 return os;
0254 }
0255
0256
0257 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_on_sphere, sd)
0258 {
0259 is >> sd._dim;
0260 sd._container.resize(sd._dim);
0261 return is;
0262 }
0263
0264
0265
0266
0267
0268 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_on_sphere, lhs, rhs)
0269 { return lhs._dim == rhs._dim; }
0270
0271
0272
0273
0274
0275 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_on_sphere)
0276
0277 private:
0278 result_type _container;
0279 int _dim;
0280 };
0281
0282 }
0283
0284 using random::uniform_on_sphere;
0285
0286 }
0287
0288 #endif