mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-06-05 11:24:17 +03:00
Foundation Classes - HashUtils NoExcept optimization #473
Refactor hash functions in Standard_HashUtils for improved performanceю Optimized load_bytes functionality. Making all hash function noexcept
This commit is contained in:
parent
81efe3d3ed
commit
638b0bfc40
@ -28,28 +28,29 @@ namespace opencascade
|
|||||||
//! The default value for the seed is optimal for general cases at a certain hash size.
|
//! The default value for the seed is optimal for general cases at a certain hash size.
|
||||||
namespace MurmurHash
|
namespace MurmurHash
|
||||||
{
|
{
|
||||||
uint32_t MurmurHash2A(const void* theKey, int theLen, uint32_t theSeed);
|
uint32_t MurmurHash2A(const void* theKey, int theLen, uint32_t theSeed) noexcept;
|
||||||
uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed);
|
uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed) noexcept;
|
||||||
|
|
||||||
template <typename T1, typename T = size_t>
|
template <typename T1, typename T = size_t>
|
||||||
typename std::enable_if<sizeof(T) == 8, uint64_t>::type hash_combine(
|
typename std::enable_if<sizeof(T) == 8, uint64_t>::type hash_combine(
|
||||||
const T1& theValue,
|
const T1& theValue,
|
||||||
const int theLen = sizeof(T1),
|
const int theLen = sizeof(T1),
|
||||||
const T theSeed = 0xA329F1D3A586ULL)
|
const T theSeed = 0xA329F1D3A586ULL) noexcept
|
||||||
{
|
{
|
||||||
return MurmurHash::MurmurHash64A(&theValue, theLen, theSeed);
|
return MurmurHash::MurmurHash64A(&theValue, theLen, theSeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1, typename T = size_t>
|
template <typename T1, typename T = size_t>
|
||||||
typename std::enable_if<sizeof(T) != 8, T>::type hash_combine(const T1& theValue,
|
typename std::enable_if<sizeof(T) != 8, T>::type hash_combine(
|
||||||
|
const T1& theValue,
|
||||||
const int theLen = sizeof(T1),
|
const int theLen = sizeof(T1),
|
||||||
const T theSeed = 0xc70f6907U)
|
const T theSeed = 0xc70f6907U) noexcept
|
||||||
{
|
{
|
||||||
return static_cast<T>(MurmurHash::MurmurHash2A(&theValue, theLen, theSeed));
|
return static_cast<T>(MurmurHash::MurmurHash2A(&theValue, theLen, theSeed));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T = size_t>
|
template <typename T = size_t>
|
||||||
constexpr T optimalSeed()
|
constexpr T optimalSeed() noexcept
|
||||||
{
|
{
|
||||||
return sizeof(T) == 8 ? static_cast<T>(0xA329F1D3A586ULL) : static_cast<T>(0xc70f6907U);
|
return sizeof(T) == 8 ? static_cast<T>(0xA329F1D3A586ULL) : static_cast<T>(0xc70f6907U);
|
||||||
}
|
}
|
||||||
@ -63,47 +64,48 @@ constexpr T optimalSeed()
|
|||||||
//! The default value for the seed is optimal for general cases at a certain hash size.
|
//! The default value for the seed is optimal for general cases at a certain hash size.
|
||||||
namespace FNVHash
|
namespace FNVHash
|
||||||
{
|
{
|
||||||
uint32_t FNVHash1A(const void* theKey, int theLen, uint32_t theSeed);
|
uint32_t FNVHash1A(const void* theKey, int theLen, uint32_t theSeed) noexcept;
|
||||||
uint64_t FNVHash64A(const void* theKey, int theLen, uint64_t theSeed);
|
uint64_t FNVHash64A(const void* theKey, int theLen, uint64_t theSeed) noexcept;
|
||||||
|
|
||||||
template <typename T1, typename T = size_t>
|
template <typename T1, typename T = size_t>
|
||||||
static typename std::enable_if<sizeof(T) == 8, uint64_t>::type hash_combine(
|
static typename std::enable_if<sizeof(T) == 8, uint64_t>::type hash_combine(
|
||||||
const T1& theValue,
|
const T1& theValue,
|
||||||
const int theLen = sizeof(T1),
|
const int theLen = sizeof(T1),
|
||||||
const T theSeed = 14695981039346656037ULL)
|
const T theSeed = 14695981039346656037ULL) noexcept
|
||||||
{
|
{
|
||||||
return FNVHash::FNVHash64A(&theValue, theLen, theSeed);
|
return FNVHash::FNVHash64A(&theValue, theLen, theSeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1, typename T = size_t>
|
template <typename T1, typename T = size_t>
|
||||||
static typename std::enable_if<sizeof(T) != 8, T>::type hash_combine(const T1& theValue,
|
static typename std::enable_if<sizeof(T) != 8, T>::type hash_combine(
|
||||||
|
const T1& theValue,
|
||||||
const int theLen = sizeof(T1),
|
const int theLen = sizeof(T1),
|
||||||
const T theSeed = 2166136261U)
|
const T theSeed = 2166136261U) noexcept
|
||||||
{
|
{
|
||||||
return static_cast<T>(FNVHash::FNVHash1A(&theValue, theLen, theSeed));
|
return static_cast<T>(FNVHash::FNVHash1A(&theValue, theLen, theSeed));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T = size_t>
|
template <typename T = size_t>
|
||||||
constexpr T optimalSeed()
|
constexpr T optimalSeed() noexcept
|
||||||
{
|
{
|
||||||
return sizeof(T) == 8 ? static_cast<T>(14695981039346656037ULL) : static_cast<T>(2166136261U);
|
return sizeof(T) == 8 ? static_cast<T>(14695981039346656037ULL) : static_cast<T>(2166136261U);
|
||||||
}
|
}
|
||||||
}; // namespace FNVHash
|
}; // namespace FNVHash
|
||||||
|
|
||||||
template <typename T1, typename T = size_t>
|
template <typename T1, typename T = size_t>
|
||||||
T hash(const T1 theValue) noexcept
|
T hash(const T1& theValue) noexcept
|
||||||
{
|
{
|
||||||
return opencascade::MurmurHash::hash_combine<T1, T>(theValue);
|
return opencascade::MurmurHash::hash_combine<T1, T>(theValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1, typename T = size_t>
|
template <typename T1, typename T = size_t>
|
||||||
T hashBytes(const T1* theKey, int theLen)
|
T hashBytes(const T1* theKey, int theLen) noexcept
|
||||||
{
|
{
|
||||||
return opencascade::MurmurHash::hash_combine<T1, T>(*theKey, theLen);
|
return opencascade::MurmurHash::hash_combine<T1, T>(*theKey, theLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T1, typename T = size_t>
|
template <typename T1, typename T = size_t>
|
||||||
T hash_combine(const T1 theValue, const int theLen, const T theSeed)
|
T hash_combine(const T1& theValue, const int theLen, const T theSeed) noexcept
|
||||||
{
|
{
|
||||||
return opencascade::MurmurHash::hash_combine<T1, T>(theValue, theLen, theSeed);
|
return opencascade::MurmurHash::hash_combine<T1, T>(theValue, theLen, theSeed);
|
||||||
}
|
}
|
||||||
|
@ -19,24 +19,50 @@ namespace MurmurHash
|
|||||||
{
|
{
|
||||||
namespace MurmurHashUtils
|
namespace MurmurHashUtils
|
||||||
{
|
{
|
||||||
inline uint64_t shift_mix(uint64_t theV)
|
inline uint64_t shift_mix(uint64_t theV) noexcept
|
||||||
{
|
{
|
||||||
return theV ^ (theV >> 47);
|
return theV ^ (theV >> 47);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads n bytes, where 1 <= n < 8.
|
// Loads n bytes, where 1 <= n < 8
|
||||||
inline uint64_t load_bytes(const char* thePnt, int theNb)
|
inline uint64_t load_bytes(const char* thePnt, int theNb) noexcept
|
||||||
{
|
{
|
||||||
uint64_t aRes = 0;
|
// Initialize result value
|
||||||
--theNb;
|
uint64_t aResult = 0;
|
||||||
do
|
|
||||||
aRes = (aRes << 8) + static_cast<unsigned char>(thePnt[theNb]);
|
// Use switch with fall-through for better performance and branch prediction
|
||||||
while (--theNb >= 0);
|
switch (theNb)
|
||||||
return aRes;
|
{
|
||||||
|
case 7:
|
||||||
|
aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[6])) << 48) | aResult;
|
||||||
|
Standard_FALLTHROUGH
|
||||||
|
case 6:
|
||||||
|
aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[5])) << 40) | aResult;
|
||||||
|
Standard_FALLTHROUGH
|
||||||
|
case 5:
|
||||||
|
aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[4])) << 32) | aResult;
|
||||||
|
Standard_FALLTHROUGH
|
||||||
|
case 4:
|
||||||
|
aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[3])) << 24) | aResult;
|
||||||
|
Standard_FALLTHROUGH
|
||||||
|
case 3:
|
||||||
|
aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[2])) << 16) | aResult;
|
||||||
|
Standard_FALLTHROUGH
|
||||||
|
case 2:
|
||||||
|
aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[1])) << 8) | aResult;
|
||||||
|
Standard_FALLTHROUGH
|
||||||
|
case 1:
|
||||||
|
aResult = static_cast<uint64_t>(static_cast<unsigned char>(thePnt[0])) | aResult;
|
||||||
|
Standard_FALLTHROUGH
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T unaligned_load(const char* thePnt)
|
inline T unaligned_load(const char* thePnt) noexcept
|
||||||
{
|
{
|
||||||
T aRes;
|
T aRes;
|
||||||
memcpy(&aRes, thePnt, sizeof(aRes));
|
memcpy(&aRes, thePnt, sizeof(aRes));
|
||||||
@ -48,7 +74,7 @@ inline T unaligned_load(const char* thePnt)
|
|||||||
// function : MurmurHash64A
|
// function : MurmurHash64A
|
||||||
// purpose :
|
// purpose :
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
inline uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed)
|
inline uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed) noexcept
|
||||||
{
|
{
|
||||||
static constexpr uint64_t aMul = (((uint64_t)0xc6a4a793UL) << 32UL) + (uint64_t)0x5bd1e995UL;
|
static constexpr uint64_t aMul = (((uint64_t)0xc6a4a793UL) << 32UL) + (uint64_t)0x5bd1e995UL;
|
||||||
const char* const aBuf = static_cast<const char*>(theKey);
|
const char* const aBuf = static_cast<const char*>(theKey);
|
||||||
@ -80,9 +106,9 @@ inline uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed)
|
|||||||
// function : MurmurHash2A
|
// function : MurmurHash2A
|
||||||
// purpose :
|
// purpose :
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
inline uint32_t MurmurHash2A(const void* theKey, int theLen, uint32_t theSeed)
|
inline uint32_t MurmurHash2A(const void* theKey, int theLen, uint32_t theSeed) noexcept
|
||||||
{
|
{
|
||||||
const uint32_t aMul = 0x5bd1e995;
|
constexpr uint32_t aMul = 0x5bd1e995;
|
||||||
uint32_t aHash = theSeed ^ theLen;
|
uint32_t aHash = theSeed ^ theLen;
|
||||||
const char* aBuf = static_cast<const char*>(theKey);
|
const char* aBuf = static_cast<const char*>(theKey);
|
||||||
|
|
||||||
@ -131,7 +157,7 @@ namespace FNVHash
|
|||||||
// function : FNVHash1A
|
// function : FNVHash1A
|
||||||
// purpose :
|
// purpose :
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
inline uint32_t FNVHash1A(const void* theKey, int theLen, uint32_t theSeed)
|
inline uint32_t FNVHash1A(const void* theKey, int theLen, uint32_t theSeed) noexcept
|
||||||
{
|
{
|
||||||
const char* cptr = static_cast<const char*>(theKey);
|
const char* cptr = static_cast<const char*>(theKey);
|
||||||
for (; theLen; --theLen)
|
for (; theLen; --theLen)
|
||||||
@ -146,7 +172,7 @@ inline uint32_t FNVHash1A(const void* theKey, int theLen, uint32_t theSeed)
|
|||||||
// function : FNVHash64A
|
// function : FNVHash64A
|
||||||
// purpose :
|
// purpose :
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
inline uint64_t FNVHash64A(const void* theKey, int theLen, uint64_t theSeed)
|
inline uint64_t FNVHash64A(const void* theKey, int theLen, uint64_t theSeed) noexcept
|
||||||
{
|
{
|
||||||
const char* cptr = static_cast<const char*>(theKey);
|
const char* cptr = static_cast<const char*>(theKey);
|
||||||
for (; theLen; --theLen)
|
for (; theLen; --theLen)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user