Warning, /include/opencascade/Standard_HashUtils.lxx is written in an unsupported language. File is not indexed.
0001 // Copyright (c) 2023 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement.
0013
0014 #include <cstring>
0015
0016 namespace opencascade
0017 {
0018 namespace MurmurHash
0019 {
0020 namespace MurmurHashUtils
0021 {
0022 inline uint64_t shift_mix(uint64_t theV)
0023 {
0024 return theV ^ (theV >> 47);
0025 }
0026
0027 // Loads n bytes, where 1 <= n < 8.
0028 inline uint64_t load_bytes(const char* thePnt, int theNb)
0029 {
0030 uint64_t aRes = 0;
0031 --theNb;
0032 do
0033 aRes = (aRes << 8) + static_cast<unsigned char>(thePnt[theNb]);
0034 while (--theNb >= 0);
0035 return aRes;
0036 }
0037 template <typename T>
0038 inline T unaligned_load(const char* thePnt)
0039 {
0040 T aRes;
0041 memcpy(&aRes, thePnt, sizeof(aRes));
0042 return aRes;
0043 }
0044 }
0045
0046 //=======================================================================
0047 //function : MurmurHash64A
0048 //purpose :
0049 //=======================================================================
0050 inline uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed)
0051 {
0052 static constexpr uint64_t aMul = (((uint64_t)0xc6a4a793UL) << 32UL)
0053 + (uint64_t)0x5bd1e995UL;
0054 const char* const aBuf = static_cast<const char*>(theKey);
0055
0056 // Remove the bytes not divisible by the sizeof(uint64_t). This
0057 // allows the main loop to process the data as 64-bit integers.
0058 const uint64_t aLenAligned = theLen & ~(uint64_t)0x7;
0059 const char* const anEnd = aBuf + aLenAligned;
0060 uint64_t aHash = theSeed ^ (theLen * aMul);
0061 for (const char* aPnt = aBuf; aPnt != anEnd; aPnt += 8)
0062 {
0063 const uint64_t aData = MurmurHashUtils::shift_mix(MurmurHashUtils::unaligned_load<uint64_t>(aPnt) * aMul) * aMul;
0064 aHash ^= aData;
0065 aHash *= aMul;
0066 }
0067 if ((theLen & 0x7) != 0)
0068 {
0069 const uint64_t data = MurmurHashUtils::load_bytes(anEnd, theLen & 0x7);
0070 aHash ^= data;
0071 aHash *= aMul;
0072 }
0073 aHash = MurmurHashUtils::shift_mix(aHash) * aMul;
0074 aHash = MurmurHashUtils::shift_mix(aHash);
0075 return aHash;
0076 }
0077
0078 //=======================================================================
0079 //function : MurmurHash2A
0080 //purpose :
0081 //=======================================================================
0082 inline uint32_t MurmurHash2A(const void* theKey, int theLen, uint32_t theSeed)
0083 {
0084 const uint32_t aMul = 0x5bd1e995;
0085 uint32_t aHash = theSeed ^ theLen;
0086 const char* aBuf = static_cast<const char*>(theKey);
0087
0088 // Mix 4 bytes at a time into the hash.
0089 while (theLen >= 4)
0090 {
0091 uint32_t aKey = MurmurHashUtils::unaligned_load<uint32_t>(aBuf);
0092 aKey *= aMul;
0093 aKey ^= aKey >> 24;
0094 aKey *= aMul;
0095 aHash *= aMul;
0096 aHash ^= aKey;
0097 aBuf += 4;
0098 theLen -= 4;
0099 }
0100
0101 uint32_t aKey;
0102 // Handle the last few bytes of the input array.
0103 switch (theLen)
0104 {
0105 case 3:
0106 aKey = static_cast<unsigned char>(aBuf[2]);
0107 aHash ^= aKey << 16;
0108 Standard_FALLTHROUGH
0109 case 2:
0110 aKey = static_cast<unsigned char>(aBuf[1]);
0111 aHash ^= aKey << 8;
0112 Standard_FALLTHROUGH
0113 case 1:
0114 aKey = static_cast<unsigned char>(aBuf[0]);
0115 aHash ^= aKey;
0116 aHash *= aMul;
0117 };
0118
0119 // Do a few final mixes of the hash.
0120 aHash ^= aHash >> 13;
0121 aHash *= aMul;
0122 aHash ^= aHash >> 15;
0123 return aHash;
0124 }
0125 } // MurmurHash
0126
0127 namespace FNVHash
0128 {
0129 //=======================================================================
0130 //function : FNVHash1A
0131 //purpose :
0132 //=======================================================================
0133 inline uint32_t FNVHash1A(const void* theKey, int theLen, uint32_t theSeed)
0134 {
0135 const char* cptr = static_cast<const char*>(theKey);
0136 for (; theLen; --theLen)
0137 {
0138 theSeed ^= static_cast<uint32_t>(*cptr++);
0139 theSeed *= static_cast<uint32_t>(16777619UL);
0140 }
0141 return theSeed;
0142 }
0143
0144 //=======================================================================
0145 //function : FNVHash64A
0146 //purpose :
0147 //=======================================================================
0148 inline uint64_t FNVHash64A(const void* theKey, int theLen, uint64_t theSeed)
0149 {
0150 const char* cptr = static_cast<const char*>(theKey);
0151 for (; theLen; --theLen)
0152 {
0153 theSeed ^= static_cast<uint64_t>(*cptr++);
0154 theSeed *= static_cast<uint64_t>(1099511628211ULL);
0155 }
0156 return theSeed;
0157 }
0158 } // FNVHash
0159 } // opencascade