LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
LSSTDataManagementBasePackage
Random.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008-2016 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
25 
32 #include <cstdlib>
33 
34 #include "boost/format.hpp"
35 
36 #include "gsl/gsl_errno.h"
37 #include "gsl/gsl_randist.h"
38 
39 #include "lsst/pex/exceptions.h"
40 
41 #include "lsst/afw/math/Random.h"
42 
44 
45 namespace ex = lsst::pex::exceptions;
46 namespace math = lsst::afw::math;
47 
48 
49 // -- Static data --------
50 
51 ::gsl_rng_type const * const math::Random::_gslRngTypes[math::Random::NUM_ALGORITHMS] = {
52  ::gsl_rng_mt19937,
53  ::gsl_rng_ranlxs0,
54  ::gsl_rng_ranlxs1,
55  ::gsl_rng_ranlxs2,
56  ::gsl_rng_ranlxd1,
57  ::gsl_rng_ranlxd2,
58  ::gsl_rng_ranlux,
59  ::gsl_rng_ranlux389,
60  ::gsl_rng_cmrg,
61  ::gsl_rng_mrg,
62  ::gsl_rng_taus,
63  ::gsl_rng_taus2,
64  ::gsl_rng_gfsr4
65 };
66 
68  "MT19937",
69  "RANLXS0",
70  "RANLXS1",
71  "RANLXS2",
72  "RANLXD1",
73  "RANLXD2",
74  "RANLUX",
75  "RANLUX389",
76  "CMRG",
77  "MRG",
78  "TAUS",
79  "TAUS2",
80  "GFSR4"
81 };
82 
83 char const * const math::Random::_algorithmEnvVarName = "LSST_RNG_ALGORITHM";
84 char const * const math::Random::_seedEnvVarName = "LSST_RNG_SEED";
85 
86 
87 // -- Private helper functions --------
88 
96  if (_seed == 0) {
97  throw LSST_EXCEPT(ex::InvalidParameterError,
98  (boost::format("Invalid RNG seed: %lu") % _seed).str());
99  }
100  ::gsl_rng * rng = ::gsl_rng_alloc(_gslRngTypes[_algorithm]);
101  if (rng == 0) {
102  throw LSST_EXCEPT(ex::MemoryError, "gsl_rng_alloc() failed");
103  }
104  ::gsl_rng_set(rng, _seed);
105  _rng.reset(rng, ::gsl_rng_free);
106 }
107 
118 void math::Random::initialize(std::string const & algorithm) {
119  // linear search (the number of algorithms is small)
120  for (int i = 0; i < NUM_ALGORITHMS; ++i) {
121  if (_algorithmNames[i] == algorithm) {
122  _algorithm = static_cast<Algorithm>(i);
123  initialize();
124  return;
125  }
126  }
127  throw LSST_EXCEPT(ex::InvalidParameterError, "RNG algorithm " +
128  algorithm + " is not supported");
129 }
130 
131 
132 // -- Constructor --------
133 
150 math::Random::Random(Algorithm const algorithm, unsigned long seed)
151  : _rng(), _seed(seed), _algorithm(algorithm)
152 {
153  if (_algorithm < 0 || _algorithm >= NUM_ALGORITHMS) {
154  throw LSST_EXCEPT(ex::InvalidParameterError, "Invalid RNG algorithm");
155  }
156  initialize();
157 }
158 
159 
174 math::Random::Random(std::string const & algorithm, unsigned long seed)
175  : _rng(), _seed(seed)
176 {
177  initialize(algorithm);
178 }
179 
180 
200  : _rng(), _seed()
201 {
202  std::string const seed(policy->getString("rngSeed"));
203  try {
204  _seed = std::stoul(seed);
205  } catch(std::invalid_argument &) {
206  throw LSST_EXCEPT(ex::RuntimeError,
207  (boost::format("Invalid argument in \"rngSeed\" policy value: \"%1%\"") % seed).str());
208  } catch(std::out_of_range &) {
209  throw LSST_EXCEPT(ex::RuntimeError,
210  (boost::format("Out of range in \"rngSeed\" policy value: \"%1%\"") % seed).str());
211  }
212  initialize(policy->getString("rngAlgorithm"));
213 }
214 
215 
226  Random rng = *this;
227  rng._rng.reset(::gsl_rng_clone(_rng.get()), ::gsl_rng_free);
228  if (!rng._rng) {
229  throw LSST_EXCEPT(ex::MemoryError, "gsl_rng_clone() failed");
230  }
231  return rng;
232 }
233 
235  return State(static_cast<char*>(::gsl_rng_state(_rng.get())), getStateSize());
236 }
237 
238 void math::Random::setState(State const & state) {
239  if (state.size() != getStateSize()) {
240  throw LSST_EXCEPT(
241  pex::exceptions::LengthError,
242  (boost::format("Size of given state vector (%d) does not match expected size (%d)")
243  % state.size() % getStateSize()).str()
244  );
245  }
246  std::copy(state.begin(), state.end(), static_cast<char*>(::gsl_rng_state(_rng.get())));
247 }
248 
249 std::size_t math::Random::getStateSize() const {
250  return ::gsl_rng_size(_rng.get());
251 }
252 
253 // -- Accessors --------
254 
259  return _algorithm;
260 }
261 
265 std::string math::Random::getAlgorithmName() const {
266  return std::string(_algorithmNames[_algorithm]);
267 }
268 
272 std::vector<std::string> const & math::Random::getAlgorithmNames() {
273  static std::vector<std::string> names;
274  if (names.size() == 0) {
275  for (int i = 0; i < NUM_ALGORITHMS; ++i) {
276  names.push_back(_algorithmNames[i]);
277  }
278  }
279  return names;
280 }
281 
287 unsigned long math::Random::getSeed() const {
288  return _seed;
289 }
290 
291 
292 // -- Mutators: generating random numbers --------
293 
307  return ::gsl_rng_uniform(_rng.get());
308 }
309 
322  return ::gsl_rng_uniform_pos(_rng.get());
323 }
324 
343 unsigned long math::Random::uniformInt(unsigned long n) {
344  if (n > ::gsl_rng_max(_rng.get()) - ::gsl_rng_min(_rng.get())) {
345  throw LSST_EXCEPT(ex::RangeError,
346  "Desired random number range exceeds generator range");
347  }
348  return ::gsl_rng_uniform_int(_rng.get(), n);
349 }
350 
351 // -- Mutators: computing random variates for various distributions --------
352 
360 double math::Random::flat(double const a, double const b) {
361  return ::gsl_ran_flat(_rng.get(), a, b);
362 }
363 
373  return ::gsl_ran_gaussian_ziggurat(_rng.get(), 1.0);
374 }
375 
382 double math::Random::chisq(double nu) {
383  return ::gsl_ran_chisq(_rng.get(), nu);
384 }
385 
386 
392 double math::Random::poisson(double mu
393  ) {
394  return ::gsl_ran_poisson(_rng.get(), mu);
395 }
396 
std::string State
Definition: Random.h:116
Random(Algorithm algorithm=MT19937, unsigned long seed=1)
Definition: Random.cc:150
double poisson(double const nu)
Definition: Random.cc:392
Algorithm _algorithm
Definition: Random.h:142
a container for holding hierarchical configuration data in memory.
Definition: Policy.h:169
std::shared_ptr< Policy > Ptr
Definition: Policy.h:172
unsigned long _seed
Definition: Random.h:141
unsigned long uniformInt(unsigned long n)
Definition: Random.cc:343
unsigned long getSeed() const
Definition: Random.cc:287
static char const *const _seedEnvVarName
Definition: Random.h:147
std::size_t getStateSize() const
Definition: Random.cc:249
static char const *const _algorithmEnvVarName
Definition: Random.h:146
void setState(State const &state)
Definition: Random.cc:238
Algorithm getAlgorithm() const
Definition: Random.cc:258
double chisq(double const nu)
Definition: Random.cc:382
std::string getAlgorithmName() const
Definition: Random.cc:265
double flat(double const a, double const b)
Definition: Random.cc:360
static char const *const _algorithmNames[NUM_ALGORITHMS]
Definition: Random.h:145
std::shared_ptr< ::gsl_rng > _rng
Definition: Random.h:140
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
Random number generator class.
afw::table::Key< double > b
Include files required for standard LSST Exception handling.
Random deepCopy() const
Definition: Random.cc:225
State getState() const
Definition: Random.cc:234
::gsl_rng_type const *const _gslRngTypes[NUM_ALGORITHMS]
Definition: Random.h:144
static std::vector< std::string > const & getAlgorithmNames()
Definition: Random.cc:272