123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #pragma once
- #include <algorithm> // std::swap()
- #include <limits> // std::numeric_limits
- #include <type_traits> // std::make_unsigned
- #include "BaseTypes.h" // uint32, uint64
- #include "Cry_Vector2.h"
- #include "Cry_Vector3.h"
- #include "Cry_Vector4.h"
- namespace CryRandom_Internal
- {
- template <class R, class T, size_t size>
- struct BoundedRandomUint
- {
- static_assert(std::numeric_limits<T>::is_integer);
- static_assert(!std::numeric_limits<T>::is_signed);
- static_assert(sizeof(T) == size);
- static_assert(sizeof(T) <= sizeof(uint32));
- inline static T Get(R& randomGenerator, const T maxValue)
- {
- const uint32 r = randomGenerator.GenerateUint32();
- // Note that the computation below is biased. An alternative computation
- // (also biased): uint32((uint64)r * ((uint64)maxValue + 1)) >> 32)
- return (T)((uint64)r % ((uint64)maxValue + 1));
- }
- };
- template <class R, class T>
- struct BoundedRandomUint<R, T, 8>
- {
- static_assert(std::numeric_limits<T>::is_integer);
- static_assert(!std::numeric_limits<T>::is_signed);
- static_assert(sizeof(T) == sizeof(uint64));
- inline static T Get(R& randomGenerator, const T maxValue)
- {
- const uint64 r = randomGenerator.GenerateUint64();
- if (maxValue >= (std::numeric_limits<uint64>::max)())
- {
- return r;
- }
- // Note that the computation below is biased.
- return (T)(r % ((uint64)maxValue + 1));
- }
- };
- //////////////////////////////////////////////////////////////////////////
- template <class R, class T, bool bInteger = std::numeric_limits<T>::is_integer>
- struct BoundedRandom;
- template <class R, class T>
- struct BoundedRandom<R, T, true>
- {
- static_assert(std::numeric_limits<T>::is_integer);
- typedef typename std::make_unsigned<T>::type UT;
- static_assert(sizeof(T) == sizeof(UT));
- static_assert(std::numeric_limits<UT>::is_integer);
- static_assert(!std::numeric_limits<UT>::is_signed);
- inline static T Get(R& randomGenerator, T minValue, T maxValue)
- {
- if (minValue > maxValue)
- {
- std::swap(minValue, maxValue);
- }
- return (T)((UT)minValue + (UT)BoundedRandomUint<R, UT, sizeof(UT)>::Get(randomGenerator, (UT)(maxValue - minValue)));
- }
- };
- template <class R, class T>
- struct BoundedRandom<R, T, false>
- {
- static_assert(!std::numeric_limits<T>::is_integer);
- inline static T Get(R& randomGenerator, const T minValue, const T maxValue)
- {
- return minValue + (maxValue - minValue) * randomGenerator.GenerateFloat();
- }
- };
- //////////////////////////////////////////////////////////////////////////
- template <class R, class VT, class T = typename VT::value_type, size_t componentCount = VT::component_count>
- struct BoundedRandomComponentwise;
- template <class R, class VT, class T>
- struct BoundedRandomComponentwise<R, VT, T, 2>
- {
- inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
- {
- const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
- const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
- return VT(x, y);
- }
- };
- template <class R, class VT, class T>
- struct BoundedRandomComponentwise<R, VT, T, 3>
- {
- inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
- {
- const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
- const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
- const T z = BoundedRandom<R, T>::Get(randomGenerator, minValue.z, maxValue.z);
- return VT(x, y, z);
- }
- };
- template <class R, class VT, class T>
- struct BoundedRandomComponentwise<R, VT, T, 4>
- {
- inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
- {
- const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
- const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
- const T z = BoundedRandom<R, T>::Get(randomGenerator, minValue.z, maxValue.z);
- const T w = BoundedRandom<R, T>::Get(randomGenerator, minValue.w, maxValue.w);
- return VT(x, y, z, w);
- }
- };
- //////////////////////////////////////////////////////////////////////////
- template <class R, class VT>
- inline VT GetRandomUnitVector(R& randomGenerator)
- {
- typedef typename VT::value_type T;
- static_assert(!std::numeric_limits<T>::is_integer);
- VT res;
- T lenSquared;
- do
- {
- res = BoundedRandomComponentwise<R, VT>::Get(randomGenerator, VT(-1), VT(1));
- lenSquared = res.GetLengthSquared();
- } while (lenSquared > 1);
- if (lenSquared >= (std::numeric_limits<T>::min)())
- {
- return res * isqrt_tpl(lenSquared);
- }
- res = VT(ZERO);
- res.x = 1;
- return res;
- }
- } // namespace CryRandom_Internal
- // eof
|