aboutsummaryrefslogtreecommitdiff
path: root/include/EASTL/random.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/EASTL/random.h')
-rw-r--r--include/EASTL/random.h254
1 files changed, 254 insertions, 0 deletions
diff --git a/include/EASTL/random.h b/include/EASTL/random.h
new file mode 100644
index 0000000..ca3e20b
--- /dev/null
+++ b/include/EASTL/random.h
@@ -0,0 +1,254 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// This file defines random number generation like the std C++ <random> header.
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef EASTL_RANDOM_H
+#define EASTL_RANDOM_H
+
+#if defined(EA_PRAGMA_ONCE_SUPPORTED)
+ #pragma once
+#endif
+
+
+#include <EASTL/internal/config.h>
+#include <EASTL/numeric_limits.h>
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// min/max workaround
+//
+// MSVC++ has #defines for min/max which collide with the min/max algorithm
+// declarations. The following may still not completely resolve some kinds of
+// problems with MSVC++ #defines, though it deals with most cases in production
+// game code.
+//
+#if EASTL_NOMINMAX
+ #ifdef min
+ #undef min
+ #endif
+ #ifdef max
+ #undef max
+ #endif
+#endif
+
+
+namespace eastl
+{
+
+ // Implements a uniform distribution of values generated by a Generator,
+ // where Generator is typically a random or pseudo-random number generator.
+ // Note that the min/max range for this class is inclusive, so if you want
+ // random integers 0, 1, 2, and 3, then you need to init this class with (0, 3)
+ // and not (0, 4).
+ // See the C++11 Standard, section 26.5.1.6
+ template<class IntType = int>
+ class uniform_int_distribution
+ {
+ static_assert(eastl::is_integral<IntType>::value, "uniform_int_distribution: IntType must be integral.");
+
+ public:
+ typedef IntType result_type;
+
+ // For uniform_int_distribution, param_type defines simply the min and max values of
+ // the range returned by operator(). It may mean something else for other distribution types.
+ struct param_type
+ {
+ explicit param_type(IntType a = 0, IntType b = eastl::numeric_limits<IntType>::max());
+
+ result_type a() const;
+ result_type b() const;
+
+ bool operator==(const param_type& x) { return (x.mA == mA) && (x.mB == mB); }
+ bool operator!=(const param_type& x) { return (x.mA != mA) || (x.mB != mB); }
+
+ protected:
+ IntType mA;
+ IntType mB;
+ };
+
+ uniform_int_distribution(IntType a = 0, IntType b = eastl::numeric_limits<IntType>::max());
+ uniform_int_distribution(const param_type& params);
+
+ void reset();
+
+ template<class Generator>
+ result_type operator()(Generator& g);
+
+ template<class Generator>
+ result_type operator()(Generator& g, const param_type& params);
+
+ result_type a() const;
+ result_type b() const;
+
+ param_type param() const;
+ void param(const param_type& params);
+
+ result_type min() const;
+ result_type max() const;
+
+ protected:
+ param_type mParam;
+ };
+
+
+
+ ///////////////////////////////////////////////////////////////////////
+ // uniform_int_distribution
+ ///////////////////////////////////////////////////////////////////////
+
+ template<class IntType>
+ inline uniform_int_distribution<IntType>::param_type::param_type(IntType aValue, IntType bValue)
+ : mA(aValue), mB(bValue)
+ {
+ EASTL_ASSERT(aValue <= bValue);
+ }
+
+ template<class IntType>
+ inline typename uniform_int_distribution<IntType>::result_type
+ uniform_int_distribution<IntType>::param_type::a() const
+ {
+ return mA;
+ }
+
+ template<class IntType>
+ inline typename uniform_int_distribution<IntType>::result_type
+ uniform_int_distribution<IntType>::param_type::b() const
+ {
+ return mB;
+ }
+
+
+
+ template<class IntType>
+ inline uniform_int_distribution<IntType>::uniform_int_distribution(IntType aValue, IntType bValue)
+ : mParam(aValue, bValue)
+ {
+ // Nothing more to do.
+ }
+
+ template<class IntType>
+ inline uniform_int_distribution<IntType>::uniform_int_distribution(const param_type& params)
+ : mParam(params)
+ {
+ // Nothing more to do.
+ }
+
+ template<class IntType>
+ void uniform_int_distribution<IntType>::reset()
+ {
+ // Nothing to do.
+ }
+
+ template<class IntType>
+ template<class Generator>
+ inline typename uniform_int_distribution<IntType>::result_type
+ uniform_int_distribution<IntType>::operator()(Generator& g)
+ {
+ return operator()(g, mParam);
+ }
+
+ template<class IntType>
+ template<class Generator>
+ inline typename uniform_int_distribution<IntType>::result_type
+ uniform_int_distribution<IntType>::operator()(Generator& g, const param_type& params)
+ {
+ // This is a tricky function to implement in a generic way for all integral types.
+ // The solution will involve handling the case of signed types and 64 bit types,
+ // probably in a way that uses template metaprogramming to deal with signed ranges.
+
+ // Temporary solution while we research a full solution. It supports only uint8_t,
+ // uint16_t, and uint32_t uniform_int_distribution types.
+ static_assert(eastl::is_unsigned<result_type>::value && (sizeof(result_type) <= 4), "uniform_int_distribution currently supports only uint8_t, uint16_t, uint32_t.");
+
+ result_type v = g(); // Generates a value in the range of (numeric_limits<result_type>::min(), numeric_limits<result_type>::max()).
+ result_type r = (result_type)((v * (uint64_t)((params.b() - params.a()) + 1)) >> (sizeof(result_type) * 8)); // +1 because ranges are inclusive.
+ return params.a() + r;
+ }
+
+ template<class IntType>
+ inline typename uniform_int_distribution<IntType>::result_type
+ uniform_int_distribution<IntType>::a() const
+ {
+ return mParam.mA;
+ }
+
+ template<class IntType>
+ inline typename uniform_int_distribution<IntType>::result_type
+ uniform_int_distribution<IntType>::b() const
+ {
+ return mParam.mB;
+ }
+
+
+ template<class IntType>
+ inline typename uniform_int_distribution<IntType>::param_type
+ uniform_int_distribution<IntType>::param() const
+ {
+ return mParam;
+ }
+
+ template<class IntType>
+ inline void
+ uniform_int_distribution<IntType>::param(const param_type& params)
+ {
+ mParam = params;
+ }
+
+ template<class IntType>
+ inline typename uniform_int_distribution<IntType>::result_type
+ uniform_int_distribution<IntType>::min() const
+ {
+ return mParam.mA;
+ }
+
+ template<class IntType>
+ inline typename uniform_int_distribution<IntType>::result_type
+ uniform_int_distribution<IntType>::max() const
+ {
+ return mParam.mB;
+ }
+
+
+
+ template<class ResultType>
+ inline bool operator==(const uniform_int_distribution<ResultType>& lhs,
+ const uniform_int_distribution<ResultType>& rhs)
+ {
+ return (lhs.param() == rhs.param());
+ }
+
+ template<class ResultType>
+ inline bool operator!=(const uniform_int_distribution<ResultType>& lhs,
+ const uniform_int_distribution<ResultType>& rhs)
+ {
+ return (lhs.param() != rhs.param());
+ }
+
+
+ // EASTL doesn't currently implement IO stream-related functionality.
+ // It may be useful to forward declare these templates and let the user implement them in the meantime.
+ //
+ // template<class CharT, class Traits, class ResultType>
+ // eastl::basic_ostream<CharT, Traits>& operator<<(eastl::basic_ostream<CharT, Traits>& os, const uniform_int_distribution& uid);
+ //
+ // template<class CharT, class Traits, class ResultType>
+ // eastl::basic_istream<CharT, Traits>& operator>>(eastl::basic_istream<CharT, Traits>& is, uniform_int_distribution& uid);
+
+
+} // namespace eastl
+
+
+#endif // Header include guard
+
+
+
+
+
+
+