DART  6.7.3
Random-impl.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2019, The DART development contributors
3  * All rights reserved.
4  *
5  * The list of contributors can be found at:
6  * https://github.com/dartsim/dart/blob/master/LICENSE
7  *
8  * This file is provided under the following "BSD-style" License:
9  * Redistribution and use in source and binary forms, with or
10  * without modification, are permitted provided that the following
11  * conditions are met:
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "dart/math/Random.hpp"
34 
35 //==============================================================================
36 // This workaround is necessary for old Eigen (< 3.3). See the details here:
37 // http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1286
38 #if !EIGEN_VERSION_AT_LEAST(3, 3, 0)
39 
40 namespace dart {
41 namespace math {
42 namespace detail {
43 
44 template <typename Derived>
46 {
47  using S = typename Derived::Scalar;
48 
50  const Eigen::MatrixBase<Derived>& min,
51  const Eigen::MatrixBase<Derived>& max)
52  : mMin(min), mMax(max)
53  {
54  // Do nothing
55  }
56 
57  S operator()(int i, int j) const
58  {
59  return Random::uniform<S>(mMin(i, j), mMax(i, j));
60  }
61 
62  const Eigen::MatrixBase<Derived>& mMin;
63  const Eigen::MatrixBase<Derived>& mMax;
64 };
65 
66 template <typename Derived>
68 {
69  using S = typename Derived::Scalar;
70 
72  const Eigen::MatrixBase<Derived>& min,
73  const Eigen::MatrixBase<Derived>& max)
74  : mMin(min), mMax(max)
75  {
76  // Do nothing
77  }
78 
79  S operator()(int i) const
80  {
81  return Random::uniform<S>(mMin[i], mMax[i]);
82  }
83 
84  const Eigen::MatrixBase<Derived>& mMin;
85  const Eigen::MatrixBase<Derived>& mMax;
86 };
87 
88 } // namespace detail
89 } // namespace math
90 } // namespace dart
91 
92 namespace Eigen {
93 namespace internal {
94 
95 template <typename T>
96 struct functor_has_linear_access<dart::math::detail::
97  UniformScalarFromMatrixFunctor<T>>
98 {
99  enum
100  {
101  ret = false
102  };
103 };
104 
105 template <typename T>
106 struct functor_has_linear_access<dart::math::detail::
107  UniformScalarFromVectorFunctor<T>>
108 {
109  enum
110  {
111  ret = true
112  };
113 };
114 
115 } // namespace internal
116 } // namespace Eigen
117 
118 #endif // !EIGEN_VERSION_AT_LEAST(3,3,0)
119 
120 namespace dart {
121 namespace math {
122 
123 namespace {
124 
125 //==============================================================================
126 template <template <typename...> class C, typename... Ts>
127 std::true_type is_base_of_template_impl(const C<Ts...>*);
128 
129 template <template <typename...> class C>
130 std::false_type is_base_of_template_impl(...);
131 
132 template <template <typename...> class C, typename T>
133 using is_base_of_template
134  = decltype(is_base_of_template_impl<C>(std::declval<T*>()));
135 
136 template <typename T>
137 using is_base_of_matrix = is_base_of_template<Eigen::MatrixBase, T>;
138 
139 //==============================================================================
143 template <typename T, typename Enable = void>
144 struct is_compatible_to_uniform_int_distribution : std::false_type
145 {
146  // Define nothing
147 };
148 
149 // clang-format off
150 
151 template <typename T>
152 struct is_compatible_to_uniform_int_distribution<
153  T, typename std::enable_if<
154  std::is_same<typename std::remove_cv<T>::type, short>::value
155  || std::is_same<typename std::remove_cv<T>::type, int>::value
156  || std::is_same<typename std::remove_cv<T>::type, long>::value
157  || std::is_same<typename std::remove_cv<T>::type, long long>::value
158  || std::is_same<typename std::remove_cv<T>::type, unsigned short>::value
159  || std::is_same<typename std::remove_cv<T>::type, unsigned int>::value
160  || std::is_same<typename std::remove_cv<T>::type, unsigned long>::value
161  || std::is_same<typename std::remove_cv<T>::type, unsigned long long>::value
162  >::type
163  > : std::true_type
164 {
165  // Define nothing
166 };
167 
168 // clang-format on
169 
170 //==============================================================================
171 template <typename S, typename Enable = void>
172 struct UniformScalarImpl
173 {
174  // Define nothing
175 };
176 
177 //==============================================================================
178 // Floating-point case
179 template <typename S>
180 struct UniformScalarImpl<S,
181  typename std::
182  enable_if<std::is_floating_point<S>::value>::type>
183 {
184  static S run(S min, S max)
185  {
186  // Distribution objects are lightweight so we simply construct a new
187  // distribution for each random number generation.
188  Random::UniformRealDist<S> d(min, max);
189  return d(Random::getGenerator());
190  }
191 };
192 
193 //==============================================================================
194 // Floating-point case
195 template <typename S>
196 struct
197  UniformScalarImpl<S,
198  typename std::
199  enable_if<is_compatible_to_uniform_int_distribution<S>::
200  value>::type>
201 {
202  static S run(S min, S max)
203  {
204  // Distribution objects are lightweight so we simply construct a new
205  // distribution for each random number generation.
206  Random::UniformIntDist<S> d(min, max);
207  return d(Random::getGenerator());
208  }
209 };
210 
211 //==============================================================================
212 template <typename Derived, typename Enable = void>
213 struct UniformMatrixImpl
214 {
215  // Define nothing
216 };
217 
218 //==============================================================================
219 // Dynamic matrix case
220 template <typename Derived>
221 struct UniformMatrixImpl<Derived,
222  typename std::enable_if<!Derived::IsVectorAtCompileTime
223  && Derived::SizeAtCompileTime
224  == Eigen::Dynamic>::
225  type>
226 {
227  static typename Derived::PlainObject run(
228  const Eigen::MatrixBase<Derived>& min,
229  const Eigen::MatrixBase<Derived>& max)
230  {
231 #if EIGEN_VERSION_AT_LEAST(3, 3, 0)
232  const auto uniformFunc = [&](int i, int j) {
233  return Random::uniform<typename Derived::Scalar>(min(i, j), max(i, j));
234  };
235  return Derived::PlainObject::NullaryExpr(
236  min.rows(), min.cols(), uniformFunc);
237 #else
238  return Derived::PlainObject::NullaryExpr(
239  min.rows(),
240  min.cols(),
241  detail::UniformScalarFromMatrixFunctor<Derived>(min, max));
242 #endif
243  }
244 };
245 
246 //==============================================================================
247 // Dynamic vector case
248 template <typename Derived>
249 struct UniformMatrixImpl<Derived,
250  typename std::enable_if<Derived::IsVectorAtCompileTime
251  && Derived::SizeAtCompileTime
252  == Eigen::Dynamic>::
253  type>
254 {
255  static typename Derived::PlainObject run(
256  const Eigen::MatrixBase<Derived>& min,
257  const Eigen::MatrixBase<Derived>& max)
258  {
259 #if EIGEN_VERSION_AT_LEAST(3, 3, 0)
260  const auto uniformFunc = [&](int i) {
261  return Random::uniform<typename Derived::Scalar>(min[i], max[i]);
262  };
263  return Derived::PlainObject::NullaryExpr(min.size(), uniformFunc);
264 #else
265  return Derived::PlainObject::NullaryExpr(
266  min.size(), detail::UniformScalarFromVectorFunctor<Derived>(min, max));
267 #endif
268  }
269 };
270 
271 //==============================================================================
272 // Fixed matrix case
273 template <typename Derived>
274 struct UniformMatrixImpl<Derived,
275  typename std::enable_if<!Derived::IsVectorAtCompileTime
276  && Derived::SizeAtCompileTime
277  != Eigen::Dynamic>::
278  type>
279 {
280  static typename Derived::PlainObject run(
281  const Eigen::MatrixBase<Derived>& min,
282  const Eigen::MatrixBase<Derived>& max)
283  {
284 #if EIGEN_VERSION_AT_LEAST(3, 3, 0)
285  const auto uniformFunc = [&](int i, int j) {
286  return Random::uniform<typename Derived::Scalar>(min(i, j), max(i, j));
287  };
288  return Derived::PlainObject::NullaryExpr(uniformFunc);
289 #else
290  return Derived::PlainObject::NullaryExpr(
291  detail::UniformScalarFromMatrixFunctor<Derived>(min, max));
292 #endif
293  }
294 };
295 
296 //==============================================================================
297 // Fixed vector case
298 template <typename Derived>
299 struct UniformMatrixImpl<Derived,
300  typename std::enable_if<Derived::IsVectorAtCompileTime
301  && Derived::SizeAtCompileTime
302  != Eigen::Dynamic>::
303  type>
304 {
305  static typename Derived::PlainObject run(
306  const Eigen::MatrixBase<Derived>& min,
307  const Eigen::MatrixBase<Derived>& max)
308  {
309 #if EIGEN_VERSION_AT_LEAST(3, 3, 0)
310  const auto uniformFunc = [&](int i) {
311  return Random::uniform<typename Derived::Scalar>(min[i], max[i]);
312  };
313  return Derived::PlainObject::NullaryExpr(uniformFunc);
314 #else
315  return Derived::PlainObject::NullaryExpr(
316  detail::UniformScalarFromVectorFunctor<Derived>(min, max));
317 #endif
318  }
319 };
320 
321 //==============================================================================
322 template <typename T, typename Enable = void>
323 struct UniformImpl
324 {
325  // Define nothing
326 };
327 
328 //==============================================================================
329 template <typename T>
330 struct UniformImpl<T,
331  typename std::enable_if<std::is_arithmetic<T>::value>::type>
332 {
333  static T run(T min, T max)
334  {
335  return UniformScalarImpl<T>::run(min, max);
336  }
337 };
338 
339 //==============================================================================
340 template <typename T>
341 struct UniformImpl<T,
342  typename std::enable_if<is_base_of_matrix<T>::value>::type>
343 {
344  static T run(const Eigen::MatrixBase<T>& min, const Eigen::MatrixBase<T>& max)
345  {
346  return UniformMatrixImpl<T>::run(min, max);
347  }
348 };
349 
350 //==============================================================================
351 template <typename S, typename Enable = void>
352 struct NormalScalarImpl
353 {
354  // Define nothing
355 };
356 
357 //==============================================================================
358 // Floating-point case
359 template <typename S>
360 struct NormalScalarImpl<S,
361  typename std::
362  enable_if<std::is_floating_point<S>::value>::type>
363 {
364  static S run(S mean, S sigma)
365  {
366  Random::NormalRealDist<S> d(mean, sigma);
367  return d(Random::getGenerator());
368  }
369 };
370 
371 //==============================================================================
372 // Floating-point case
373 template <typename S>
374 struct
375  NormalScalarImpl<S,
376  typename std::
377  enable_if<is_compatible_to_uniform_int_distribution<S>::
378  value>::type>
379 {
380  static S run(S mean, S sigma)
381  {
382  using DefaultFloatType = float;
383  const DefaultFloatType realNormal = Random::normal(
384  static_cast<DefaultFloatType>(mean),
385  static_cast<DefaultFloatType>(sigma));
386  return static_cast<S>(std::round(realNormal));
387  }
388 };
389 
390 //==============================================================================
391 template <typename T, typename Enable = void>
392 struct NormalImpl
393 {
394  // Define nothing
395 };
396 
397 //==============================================================================
398 template <typename T>
399 struct NormalImpl<T,
400  typename std::enable_if<std::is_arithmetic<T>::value>::type>
401 {
402  static T run(T min, T max)
403  {
404  return NormalScalarImpl<T>::run(min, max);
405  }
406 };
407 
408 } // (anonymous) namespace
409 
410 //==============================================================================
411 template <typename S>
412 S Random::uniform(S min, S max)
413 {
414  return UniformImpl<S>::run(min, max);
415 }
416 
417 //==============================================================================
418 template <typename FixedSizeT>
419 FixedSizeT Random::uniform(
420  typename FixedSizeT::Scalar min, typename FixedSizeT::Scalar max)
421 {
422  return uniform<FixedSizeT>(
423  FixedSizeT::Constant(min), FixedSizeT::Constant(max));
424 }
425 
426 //==============================================================================
427 template <typename DynamicSizeVectorT>
428 DynamicSizeVectorT Random::uniform(
429  int size,
430  typename DynamicSizeVectorT::Scalar min,
431  typename DynamicSizeVectorT::Scalar max)
432 {
433  return uniform<DynamicSizeVectorT>(
434  DynamicSizeVectorT::Constant(size, min),
435  DynamicSizeVectorT::Constant(size, max));
436 }
437 
438 //==============================================================================
439 template <typename DynamicSizeMatrixT>
440 DynamicSizeMatrixT Random::uniform(
441  int rows,
442  int cols,
443  typename DynamicSizeMatrixT::Scalar min,
444  typename DynamicSizeMatrixT::Scalar max)
445 {
446  return uniform<DynamicSizeMatrixT>(
447  DynamicSizeMatrixT::Constant(rows, cols, min),
448  DynamicSizeMatrixT::Constant(rows, cols, max));
449 }
450 
451 //==============================================================================
452 template <typename S>
453 S Random::normal(S min, S max)
454 {
455  return NormalImpl<S>::run(min, max);
456 }
457 
458 } // namespace math
459 } // namespace dart
std::string type
Definition: SdfParser.cpp:82
static S normal(S mean, S sigma)
Returns a random number from a normal distribution.
Definition: Random-impl.hpp:453
static GeneratorType & getGenerator()
Returns a mutable reference to the random generator.
Definition: Random.cpp:39
static S uniform(S min, S max)
Returns a random number from an uniform distribution.
Definition: Random-impl.hpp:412
Definition: Random-impl.hpp:92
double round(double _x)
Definition: Helpers.hpp:134
Definition: BulletCollisionDetector.cpp:63
Definition: SharedLibraryManager.hpp:43
typename Derived::Scalar S
Definition: Random-impl.hpp:47
const Eigen::MatrixBase< Derived > & mMin
Definition: Random-impl.hpp:62
UniformScalarFromMatrixFunctor(const Eigen::MatrixBase< Derived > &min, const Eigen::MatrixBase< Derived > &max)
Definition: Random-impl.hpp:49
const Eigen::MatrixBase< Derived > & mMax
Definition: Random-impl.hpp:63
S operator()(int i, int j) const
Definition: Random-impl.hpp:57
UniformScalarFromVectorFunctor(const Eigen::MatrixBase< Derived > &min, const Eigen::MatrixBase< Derived > &max)
Definition: Random-impl.hpp:71
S operator()(int i) const
Definition: Random-impl.hpp:79
const Eigen::MatrixBase< Derived > & mMin
Definition: Random-impl.hpp:84
typename Derived::Scalar S
Definition: Random-impl.hpp:69
const Eigen::MatrixBase< Derived > & mMax
Definition: Random-impl.hpp:85