p7zip-rar/CPP/7zip/Compress/Lzham/lzhamdecomp/lzham_math.h
2017-10-11 12:40:22 +02:00

143 lines
3.2 KiB
C++

// File: lzham_math.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#if defined(LZHAM_USE_MSVC_INTRINSICS) && !defined(__MINGW32__)
#include <intrin.h>
#if defined(_MSC_VER)
#pragma intrinsic(_BitScanReverse)
#endif
#endif
namespace lzham
{
namespace math
{
// Yes I know these should probably be pass by ref, not val:
// http://www.stepanovpapers.com/notes.pdf
// Just don't use them on non-simple (non built-in) types!
template<typename T> inline T minimum(T a, T b) { return (a < b) ? a : b; }
template<typename T> inline T minimum(T a, T b, T c) { return minimum(minimum(a, b), c); }
template<typename T> inline T maximum(T a, T b) { return (a > b) ? a : b; }
template<typename T> inline T maximum(T a, T b, T c) { return maximum(maximum(a, b), c); }
template<typename T> inline T clamp(T value, T low, T high) { return (value < low) ? low : ((value > high) ? high : value); }
inline bool is_power_of_2(uint32 x) { return x && ((x & (x - 1U)) == 0U); }
inline bool is_power_of_2(uint64 x) { return x && ((x & (x - 1U)) == 0U); }
template<typename T> inline T align_up_pointer(T p, uint alignment)
{
LZHAM_ASSERT(is_power_of_2(alignment));
ptr_bits_t q = reinterpret_cast<ptr_bits_t>(p);
q = (q + alignment - 1) & (~((uint_ptr)alignment - 1));
return reinterpret_cast<T>(q);
}
// From "Hackers Delight"
// val remains unchanged if it is already a power of 2.
inline uint32 next_pow2(uint32 val)
{
val--;
val |= val >> 16;
val |= val >> 8;
val |= val >> 4;
val |= val >> 2;
val |= val >> 1;
return val + 1;
}
// val remains unchanged if it is already a power of 2.
inline uint64 next_pow2(uint64 val)
{
val--;
val |= val >> 32;
val |= val >> 16;
val |= val >> 8;
val |= val >> 4;
val |= val >> 2;
val |= val >> 1;
return val + 1;
}
inline uint floor_log2i(uint v)
{
uint l = 0;
while (v > 1U)
{
v >>= 1;
l++;
}
return l;
}
inline uint ceil_log2i(uint v)
{
uint l = floor_log2i(v);
if ((l != cIntBits) && (v > (1U << l)))
l++;
return l;
}
// Returns the total number of bits needed to encode v.
inline uint total_bits(uint v)
{
unsigned long l = 0;
#if defined(__MINGW32__)
if (v)
{
l = 32 -__builtin_clz(v);
}
#elif defined(LZHAM_USE_MSVC_INTRINSICS)
if (_BitScanReverse(&l, v))
{
l++;
}
else
{
l = 0;
}
#else
while (v > 0U)
{
v >>= 1;
l++;
}
#endif
return static_cast<uint>(l);
}
inline uint compute_mask_size(uint x)
{
uint l = 0;
while (x)
{
x &= (x - 1);
l++;
}
return l;
}
inline uint compute_mask_shift(uint x)
{
if (!x)
return 0;
uint l = 0;
while ((x & 1) == 0)
{
x >>= 1;
l++;
}
return l;
}
}
} // namespace lzham