CryRandomInternal.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <algorithm> // std::swap()
  10. #include <limits> // std::numeric_limits
  11. #include <type_traits> // std::make_unsigned
  12. #include "BaseTypes.h" // uint32, uint64
  13. #include "Cry_Vector2.h"
  14. #include "Cry_Vector3.h"
  15. #include "Cry_Vector4.h"
  16. namespace CryRandom_Internal
  17. {
  18. template <class R, class T, size_t size>
  19. struct BoundedRandomUint
  20. {
  21. static_assert(std::numeric_limits<T>::is_integer);
  22. static_assert(!std::numeric_limits<T>::is_signed);
  23. static_assert(sizeof(T) == size);
  24. static_assert(sizeof(T) <= sizeof(uint32));
  25. inline static T Get(R& randomGenerator, const T maxValue)
  26. {
  27. const uint32 r = randomGenerator.GenerateUint32();
  28. // Note that the computation below is biased. An alternative computation
  29. // (also biased): uint32((uint64)r * ((uint64)maxValue + 1)) >> 32)
  30. return (T)((uint64)r % ((uint64)maxValue + 1));
  31. }
  32. };
  33. template <class R, class T>
  34. struct BoundedRandomUint<R, T, 8>
  35. {
  36. static_assert(std::numeric_limits<T>::is_integer);
  37. static_assert(!std::numeric_limits<T>::is_signed);
  38. static_assert(sizeof(T) == sizeof(uint64));
  39. inline static T Get(R& randomGenerator, const T maxValue)
  40. {
  41. const uint64 r = randomGenerator.GenerateUint64();
  42. if (maxValue >= (std::numeric_limits<uint64>::max)())
  43. {
  44. return r;
  45. }
  46. // Note that the computation below is biased.
  47. return (T)(r % ((uint64)maxValue + 1));
  48. }
  49. };
  50. //////////////////////////////////////////////////////////////////////////
  51. template <class R, class T, bool bInteger = std::numeric_limits<T>::is_integer>
  52. struct BoundedRandom;
  53. template <class R, class T>
  54. struct BoundedRandom<R, T, true>
  55. {
  56. static_assert(std::numeric_limits<T>::is_integer);
  57. typedef typename std::make_unsigned<T>::type UT;
  58. static_assert(sizeof(T) == sizeof(UT));
  59. static_assert(std::numeric_limits<UT>::is_integer);
  60. static_assert(!std::numeric_limits<UT>::is_signed);
  61. inline static T Get(R& randomGenerator, T minValue, T maxValue)
  62. {
  63. if (minValue > maxValue)
  64. {
  65. std::swap(minValue, maxValue);
  66. }
  67. return (T)((UT)minValue + (UT)BoundedRandomUint<R, UT, sizeof(UT)>::Get(randomGenerator, (UT)(maxValue - minValue)));
  68. }
  69. };
  70. template <class R, class T>
  71. struct BoundedRandom<R, T, false>
  72. {
  73. static_assert(!std::numeric_limits<T>::is_integer);
  74. inline static T Get(R& randomGenerator, const T minValue, const T maxValue)
  75. {
  76. return minValue + (maxValue - minValue) * randomGenerator.GenerateFloat();
  77. }
  78. };
  79. //////////////////////////////////////////////////////////////////////////
  80. template <class R, class VT, class T = typename VT::value_type, size_t componentCount = VT::component_count>
  81. struct BoundedRandomComponentwise;
  82. template <class R, class VT, class T>
  83. struct BoundedRandomComponentwise<R, VT, T, 2>
  84. {
  85. inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
  86. {
  87. const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
  88. const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
  89. return VT(x, y);
  90. }
  91. };
  92. template <class R, class VT, class T>
  93. struct BoundedRandomComponentwise<R, VT, T, 3>
  94. {
  95. inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
  96. {
  97. const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
  98. const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
  99. const T z = BoundedRandom<R, T>::Get(randomGenerator, minValue.z, maxValue.z);
  100. return VT(x, y, z);
  101. }
  102. };
  103. template <class R, class VT, class T>
  104. struct BoundedRandomComponentwise<R, VT, T, 4>
  105. {
  106. inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
  107. {
  108. const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
  109. const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
  110. const T z = BoundedRandom<R, T>::Get(randomGenerator, minValue.z, maxValue.z);
  111. const T w = BoundedRandom<R, T>::Get(randomGenerator, minValue.w, maxValue.w);
  112. return VT(x, y, z, w);
  113. }
  114. };
  115. //////////////////////////////////////////////////////////////////////////
  116. template <class R, class VT>
  117. inline VT GetRandomUnitVector(R& randomGenerator)
  118. {
  119. typedef typename VT::value_type T;
  120. static_assert(!std::numeric_limits<T>::is_integer);
  121. VT res;
  122. T lenSquared;
  123. do
  124. {
  125. res = BoundedRandomComponentwise<R, VT>::Get(randomGenerator, VT(-1), VT(1));
  126. lenSquared = res.GetLengthSquared();
  127. } while (lenSquared > 1);
  128. if (lenSquared >= (std::numeric_limits<T>::min)())
  129. {
  130. return res * isqrt_tpl(lenSquared);
  131. }
  132. res = VT(ZERO);
  133. res.x = 1;
  134. return res;
  135. }
  136. } // namespace CryRandom_Internal
  137. // eof