/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #pragma once #include // std::swap() #include // std::numeric_limits #include // std::make_unsigned #include "BaseTypes.h" // uint32, uint64 #include "CompileTimeAssert.h" #include "Cry_Vector2.h" #include "Cry_Vector3.h" #include "Cry_Vector4.h" namespace CryRandom_Internal { template struct BoundedRandomUint { COMPILE_TIME_ASSERT(std::numeric_limits::is_integer); COMPILE_TIME_ASSERT(!std::numeric_limits::is_signed); COMPILE_TIME_ASSERT(sizeof(T) == size); COMPILE_TIME_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 struct BoundedRandomUint { COMPILE_TIME_ASSERT(std::numeric_limits::is_integer); COMPILE_TIME_ASSERT(!std::numeric_limits::is_signed); COMPILE_TIME_ASSERT(sizeof(T) == sizeof(uint64)); inline static T Get(R& randomGenerator, const T maxValue) { const uint64 r = randomGenerator.GenerateUint64(); if (maxValue >= (std::numeric_limits::max)()) { return r; } // Note that the computation below is biased. return (T)(r % ((uint64)maxValue + 1)); } }; ////////////////////////////////////////////////////////////////////////// template ::is_integer> struct BoundedRandom; template struct BoundedRandom { COMPILE_TIME_ASSERT(std::numeric_limits::is_integer); typedef typename std::make_unsigned::type UT; COMPILE_TIME_ASSERT(sizeof(T) == sizeof(UT)); COMPILE_TIME_ASSERT(std::numeric_limits::is_integer); COMPILE_TIME_ASSERT(!std::numeric_limits::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::Get(randomGenerator, (UT)(maxValue - minValue))); } }; template struct BoundedRandom { COMPILE_TIME_ASSERT(!std::numeric_limits::is_integer); inline static T Get(R& randomGenerator, const T minValue, const T maxValue) { return minValue + (maxValue - minValue) * randomGenerator.GenerateFloat(); } }; ////////////////////////////////////////////////////////////////////////// template struct BoundedRandomComponentwise; template struct BoundedRandomComponentwise { inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue) { const T x = BoundedRandom::Get(randomGenerator, minValue.x, maxValue.x); const T y = BoundedRandom::Get(randomGenerator, minValue.y, maxValue.y); return VT(x, y); } }; template struct BoundedRandomComponentwise { inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue) { const T x = BoundedRandom::Get(randomGenerator, minValue.x, maxValue.x); const T y = BoundedRandom::Get(randomGenerator, minValue.y, maxValue.y); const T z = BoundedRandom::Get(randomGenerator, minValue.z, maxValue.z); return VT(x, y, z); } }; template struct BoundedRandomComponentwise { inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue) { const T x = BoundedRandom::Get(randomGenerator, minValue.x, maxValue.x); const T y = BoundedRandom::Get(randomGenerator, minValue.y, maxValue.y); const T z = BoundedRandom::Get(randomGenerator, minValue.z, maxValue.z); const T w = BoundedRandom::Get(randomGenerator, minValue.w, maxValue.w); return VT(x, y, z, w); } }; ////////////////////////////////////////////////////////////////////////// template inline VT GetRandomUnitVector(R& randomGenerator) { typedef typename VT::value_type T; COMPILE_TIME_ASSERT(!std::numeric_limits::is_integer); VT res; T lenSquared; do { res = BoundedRandomComponentwise::Get(randomGenerator, VT(-1), VT(1)); lenSquared = res.GetLengthSquared(); } while (lenSquared > 1); if (lenSquared >= (std::numeric_limits::min)()) { return res * isqrt_tpl(lenSquared); } res = VT(ZERO); res.x = 1; return res; } } // namespace CryRandom_Internal // eof