diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/common/mptBaseUtils.h | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/common/mptBaseUtils.h')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/common/mptBaseUtils.h | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/common/mptBaseUtils.h b/Src/external_dependencies/openmpt-trunk/common/mptBaseUtils.h new file mode 100644 index 00000000..2f440995 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/common/mptBaseUtils.h @@ -0,0 +1,177 @@ +/* + * mptBaseUtils.h + * -------------- + * Purpose: Various useful utility functions. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + +#include "openmpt/all/BuildSettings.hpp" + + +#include "mpt/base/algorithm.hpp" +#include "mpt/base/arithmetic_shift.hpp" +#include "mpt/base/array.hpp" +#include "mpt/base/bit.hpp" +#include "mpt/base/constexpr_throw.hpp" +#include "mpt/base/math.hpp" +#include "mpt/base/memory.hpp" +#include "mpt/base/numeric.hpp" +#include "mpt/base/saturate_cast.hpp" +#include "mpt/base/saturate_round.hpp" +#include "mpt/base/utility.hpp" +#include "mpt/base/wrapping_divide.hpp" + +#include "mptBaseMacros.h" +#include "mptBaseTypes.h" + +#include <algorithm> +#include <limits> +#include <numeric> +#include <utility> + +#include <cmath> +#include <cstdlib> + +#include <math.h> +#include <stdlib.h> + +#if MPT_COMPILER_MSVC +#include <intrin.h> +#endif + + + +OPENMPT_NAMESPACE_BEGIN + + + +template <typename T> +inline void Clear(T& x) +{ + static_assert(!std::is_pointer<T>::value); + mpt::reset(x); +} + + +// Memset given object to zero. +template <class T> +inline void MemsetZero(T& a) +{ + static_assert(std::is_pointer<T>::value == false, "Won't memset pointers."); + mpt::memclear(a); +} + + + +// Limits 'val' to given range. If 'val' is less than 'lowerLimit', 'val' is set to value 'lowerLimit'. +// Similarly if 'val' is greater than 'upperLimit', 'val' is set to value 'upperLimit'. +// If 'lowerLimit' > 'upperLimit', 'val' won't be modified. +template<class T, class C> +inline void Limit(T& val, const C lowerLimit, const C upperLimit) +{ + if(lowerLimit > upperLimit) return; + if(val < lowerLimit) val = lowerLimit; + else if(val > upperLimit) val = upperLimit; +} + + +// Like Limit, but returns value +template<class T, class C> +inline T Clamp(T val, const C lowerLimit, const C upperLimit) +{ + if(val < lowerLimit) return lowerLimit; + else if(val > upperLimit) return upperLimit; + else return val; +} + +// Like Limit, but with upperlimit only. +template<class T, class C> +inline void LimitMax(T& val, const C upperLimit) +{ + if(val > upperLimit) + val = upperLimit; +} + + + +namespace Util +{ + + // Returns maximum value of given integer type. + template <class T> constexpr T MaxValueOfType(const T&) {static_assert(std::numeric_limits<T>::is_integer == true, "Only integer types are allowed."); return (std::numeric_limits<T>::max)();} + +} // namespace Util + + + +namespace Util { + + // Multiply two 32-bit integers, receive 64-bit result. + // MSVC generates unnecessarily complicated code for the unoptimized variant using _allmul. + MPT_CONSTEXPR20_FUN int64 mul32to64(int32 a, int32 b) + { + #if MPT_COMPILER_MSVC && (defined(_M_IX86) || defined(_M_X64)) + MPT_MAYBE_CONSTANT_IF(MPT_IS_CONSTANT_EVALUATED20()) + { + return static_cast<int64>(a) * b; + } else + { + return __emul(a, b); + } + #else + return static_cast<int64>(a) * b; + #endif + } + + MPT_CONSTEXPR20_FUN uint64 mul32to64_unsigned(uint32 a, uint32 b) + { + #if MPT_COMPILER_MSVC && (defined(_M_IX86) || defined(_M_X64)) + MPT_MAYBE_CONSTANT_IF(MPT_IS_CONSTANT_EVALUATED20()) + { + return static_cast<uint64>(a) * b; + } else + { + return __emulu(a, b); + } + #else + return static_cast<uint64>(a) * b; + #endif + } + + MPT_CONSTEXPR20_FUN int32 muldiv(int32 a, int32 b, int32 c) + { + return mpt::saturate_cast<int32>( mul32to64( a, b ) / c ); + } + + MPT_CONSTEXPR20_FUN int32 muldivr(int32 a, int32 b, int32 c) + { + return mpt::saturate_cast<int32>( ( mul32to64( a, b ) + ( c / 2 ) ) / c ); + } + + // Do not use overloading because catching unsigned version by accident results in slower X86 code. + MPT_CONSTEXPR20_FUN uint32 muldiv_unsigned(uint32 a, uint32 b, uint32 c) + { + return mpt::saturate_cast<uint32>( mul32to64_unsigned( a, b ) / c ); + } + MPT_CONSTEXPR20_FUN uint32 muldivr_unsigned(uint32 a, uint32 b, uint32 c) + { + return mpt::saturate_cast<uint32>( ( mul32to64_unsigned( a, b ) + ( c / 2u ) ) / c ); + } + + constexpr MPT_FORCEINLINE int32 muldivrfloor(int64 a, uint32 b, uint32 c) + { + a *= b; + a += c / 2u; + return (a >= 0) ? mpt::saturate_cast<int32>(a / c) : mpt::saturate_cast<int32>((a - (c - 1)) / c); + } + +} // namespace Util + + + +OPENMPT_NAMESPACE_END |