// Copyright (c) 2023 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include namespace opencascade { namespace MurmurHash { namespace MurmurHashUtils { inline uint64_t shift_mix(uint64_t theV) { return theV ^ (theV >> 47); } // Loads n bytes, where 1 <= n < 8. inline uint64_t load_bytes(const char* thePnt, int theNb) { uint64_t aRes = 0; --theNb; do aRes = (aRes << 8) + static_cast(thePnt[theNb]); while (--theNb >= 0); return aRes; } template inline T unaligned_load(const char* thePnt) { T aRes; memcpy(&aRes, thePnt, sizeof(aRes)); return aRes; } } // namespace MurmurHashUtils //======================================================================= // function : MurmurHash64A // purpose : //======================================================================= inline uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed) { static constexpr uint64_t aMul = (((uint64_t)0xc6a4a793UL) << 32UL) + (uint64_t)0x5bd1e995UL; const char* const aBuf = static_cast(theKey); // Remove the bytes not divisible by the sizeof(uint64_t). This // allows the main loop to process the data as 64-bit integers. const uint64_t aLenAligned = theLen & ~(uint64_t)0x7; const char* const anEnd = aBuf + aLenAligned; uint64_t aHash = theSeed ^ (theLen * aMul); for (const char* aPnt = aBuf; aPnt != anEnd; aPnt += 8) { const uint64_t aData = MurmurHashUtils::shift_mix(MurmurHashUtils::unaligned_load(aPnt) * aMul) * aMul; aHash ^= aData; aHash *= aMul; } if ((theLen & 0x7) != 0) { const uint64_t data = MurmurHashUtils::load_bytes(anEnd, theLen & 0x7); aHash ^= data; aHash *= aMul; } aHash = MurmurHashUtils::shift_mix(aHash) * aMul; aHash = MurmurHashUtils::shift_mix(aHash); return aHash; } //======================================================================= // function : MurmurHash2A // purpose : //======================================================================= inline uint32_t MurmurHash2A(const void* theKey, int theLen, uint32_t theSeed) { const uint32_t aMul = 0x5bd1e995; uint32_t aHash = theSeed ^ theLen; const char* aBuf = static_cast(theKey); // Mix 4 bytes at a time into the hash. while (theLen >= 4) { uint32_t aKey = MurmurHashUtils::unaligned_load(aBuf); aKey *= aMul; aKey ^= aKey >> 24; aKey *= aMul; aHash *= aMul; aHash ^= aKey; aBuf += 4; theLen -= 4; } uint32_t aKey; // Handle the last few bytes of the input array. switch (theLen) { case 3: aKey = static_cast(aBuf[2]); aHash ^= aKey << 16; Standard_FALLTHROUGH case 2: aKey = static_cast(aBuf[1]); aHash ^= aKey << 8; Standard_FALLTHROUGH case 1: aKey = static_cast(aBuf[0]); aHash ^= aKey; aHash *= aMul; }; // Do a few final mixes of the hash. aHash ^= aHash >> 13; aHash *= aMul; aHash ^= aHash >> 15; return aHash; } } // namespace MurmurHash namespace FNVHash { //======================================================================= // function : FNVHash1A // purpose : //======================================================================= inline uint32_t FNVHash1A(const void* theKey, int theLen, uint32_t theSeed) { const char* cptr = static_cast(theKey); for (; theLen; --theLen) { theSeed ^= static_cast(*cptr++); theSeed *= static_cast(16777619UL); } return theSeed; } //======================================================================= // function : FNVHash64A // purpose : //======================================================================= inline uint64_t FNVHash64A(const void* theKey, int theLen, uint64_t theSeed) { const char* cptr = static_cast(theKey); for (; theLen; --theLen) { theSeed ^= static_cast(*cptr++); theSeed *= static_cast(1099511628211ULL); } return theSeed; } } // namespace FNVHash } // namespace opencascade