random.h - エンジンの C API リファレンス

random.h
  1. #pragma once
  2. #include "platform.h"
  3. #include "math.h"
  4. namespace stingray_plugin_foundation {
  5. // A fast LCG random number generator. The numbers it produces are not completely
  6. // random but it is faster and more random than vanilla C rand(). It should be good
  7. // enough for most purposes.
  8. class Random
  9. {
  10. // This variable should NOT need to be volatile, but there is a bug in VC++. If
  11. // this variable is not volatile Vector3(random(), random(), random()) sets all
  12. // components to the same value.
  13. volatile unsigned _state;
  14. public:
  15. static const unsigned A = 1664525 , B = 1013904223;
  16. __forceinline Random() : _state(0) {}
  17. __forceinline Random(unsigned s) : _state(s) {}
  18. __forceinline unsigned seed() const {return _state;}
  19. __forceinline void set_seed(unsigned s) {_state = s;}
  20. __forceinline void next() {_state = A * _state + B;}
  21. __forceinline unsigned rand_u32() {next(); return _state;}
  22. __forceinline double rand_double() {return double(rand_u32()) * (0.5 / 0x80000000);}
  23. __forceinline float rand_float() {return float(rand_u32()) * (0.5f / 0x80000000);}
  24. __forceinline double operator()(double max) {return max * rand_double();}
  25. __forceinline double operator()(double min, double max) {return min + (max - min)*rand_double();}
  26. __forceinline float operator()() {return rand_float();}
  27. __forceinline float operator()(float max) {return max * rand_float();}
  28. __forceinline float operator()(float min, float max) {return min + (max - min)*rand_float();}
  29. __forceinline int operator()(int max_plus_1) {return (int)floor(max_plus_1*rand_double());}
  30. __forceinline int operator()(int min, int max) {return (int)floor(min + (max - min + 1)*rand_double());}
  31. __forceinline unsigned operator()(unsigned max_plus_1) {return unsigned(max_plus_1*rand_double());}
  32. __forceinline unsigned operator()(unsigned min, unsigned max) {return unsigned(min + (max - min + 1)*rand_double());}
  33. // Convenience methods -- coin toss
  34. __forceinline bool heads() {return rand_float() < 0.5f;}
  35. __forceinline bool tails() {return rand_float() > 0.5f;}
  36. // Convenience methods -- random picking
  37. template <class T> __forceinline T &pick(T &t1, T &t2) {return rand_float() < 0.5f ? t1 : t2;}
  38. template <class T> __forceinline const T &pick(const T &t1, const T &t2) {return rand_float() < 0.5f ? t1 : t2;}
  39. template <class T> __forceinline T &pick( T &v ) {return v[ (*this)(v.size()) ];}
  40. template <class T> __forceinline const T &pick( const T &v ) {return v[ (*this)(v.size()) ];}
  41. // Random pick with weight. T must have "weight" field.
  42. template <class T> __forceinline T &pick_weighted( T &v ) {
  43. float sum = 0;
  44. typename T::iterator it, begin = v.begin(), end = v.end();
  45. for (it=begin; it<end; ++it)
  46. sum += it->weight;
  47. float pick = (*this)(sum);
  48. float acc = 0;
  49. for (it=begin; it<end; ++it) {
  50. acc += it->weight;
  51. if (pick < acc) return *it;
  52. }
  53. return v.back();
  54. }
  55. template <class T> __forceinline const T &pick_weighted( T &v ) {
  56. float sum = 0;
  57. typename T::const_iterator it, begin = v.begin(), end = v.end();
  58. for (it=begin; it<end; ++it)
  59. sum += it->weight;
  60. float pick = (*this)(sum);
  61. float acc = 0;
  62. for (it=begin; it<end; ++it) {
  63. acc += it->weight;
  64. if (pick < acc) return *it;
  65. }
  66. return v.back();
  67. }
  68. };
  69. }