// Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE /// @file /// Contains misc functions #pragma once #include #include #include #include #include namespace anki { /// @addtogroup util_other /// @{ /// Pick a random number from min to max extern I32 randRange(I32 min, I32 max); /// Pick a random number from min to max extern U32 randRange(U32 min, U32 max); /// Pick a random number from min to max extern F32 randRange(F32 min, F32 max); /// Pick a random number from min to max extern F64 randRange(F64 min, F64 max); extern F32 randFloat(F32 max); /// Get min of two values. template inline T min(T a, T b) { return (a < b) ? a : b; } /// Get max of two values. template inline T max(T a, T b) { return (a > b) ? a : b; } template inline T clamp(T v, T minv, T maxv) { ANKI_ASSERT(minv < maxv); return min(max(minv, v), maxv); } /// Check if a number os a power of 2 template inline Bool isPowerOfTwo(Int x) { return !(x == 0) && !(x & (x - 1)); } /// Get the next power of two number. For example if x is 130 this will return /// 256 template inline Int nextPowerOfTwo(Int x) { return pow(2, ceil(log(x) / log(2))); } /// Get align number /// @param alignment The bytes of alignment /// @param value The value to align template inline Type getAlignedRoundUp(PtrSize alignment, Type value) { ANKI_ASSERT(isPowerOfTwo(alignment)); PtrSize v = (PtrSize)value; v = (v + alignment - 1) & ~(alignment - 1); return (Type)v; } /// Align number /// @param alignment The bytes of alignment /// @param value The value to align template inline void alignRoundUp(PtrSize alignment, Type& value) { value = getAlignedRoundUp(alignment, value); } /// Get align number /// @param alignment The bytes of alignment /// @param value The value to align template inline Type getAlignedRoundDown(PtrSize alignment, Type value) { ANKI_ASSERT(isPowerOfTwo(alignment)); PtrSize v = (PtrSize)value; v &= ~(alignment - 1); return (Type)v; } /// Align number /// @param alignment The bytes of alignment /// @param value The value to align template inline void alignRoundDown(PtrSize alignment, Type& value) { value = getAlignedRoundDown(alignment, value); } /// Check if a number is aligned template inline Bool isAligned(PtrSize alignment, Type value) { return ((PtrSize)value % alignment) == 0; } template inline void swapValues(T& a, T& b) { T tmp = b; b = a; a = tmp; } /// Convert any pointer to a number. template inline PtrSize ptrToNumber(TPtr ptr) { ANKI_ASSERT(ptr); uintptr_t i = reinterpret_cast(ptr); PtrSize size = i; return size; } /// Convert a number to a pointer. template inline TPtr numberToPtr(PtrSize num) { ANKI_ASSERT(num); uintptr_t i = static_cast(num); TPtr ptr = reinterpret_cast(i); return ptr; } /// A simple template trick to remove the pointer from one type /// /// Example: /// @code /// double a = 1234.456; /// RemovePointer::Type b = a; /// @endcode /// The b is of type double template struct RemovePointer; template struct RemovePointer { typedef T Type; }; /// Perform a static cast of a pointer template To staticCastPtr(From from) { #if ANKI_DEBUG == 1 To ptr = dynamic_cast(from); ANKI_ASSERT(ptr != nullptr); return ptr; #else return static_cast(from); #endif } /// Count bits inline U32 countBits(U32 number) { #if defined(__GNUC__) return __builtin_popcount(number); #else #error "Unimplemented" #endif } /// Check if types are the same. template struct TypesAreTheSame { enum { m_value = 0 }; }; template struct TypesAreTheSame { enum { m_value = 1 }; }; /// @} } // end namespace anki