Back to home page

EIC code displayed by LXR

 
 

    


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) noexcept
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) noexcept
0029 {
0030   // Initialize result value
0031   uint64_t aResult = 0;
0032 
0033   // Use switch with fall-through for better performance and branch prediction
0034   switch (theNb)
0035   {
0036     case 7:
0037       aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[6])) << 48) | aResult;
0038       [[fallthrough]];
0039     case 6:
0040       aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[5])) << 40) | aResult;
0041       [[fallthrough]];
0042     case 5:
0043       aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[4])) << 32) | aResult;
0044       [[fallthrough]];
0045     case 4:
0046       aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[3])) << 24) | aResult;
0047       [[fallthrough]];
0048     case 3:
0049       aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[2])) << 16) | aResult;
0050       [[fallthrough]];
0051     case 2:
0052       aResult = (static_cast<uint64_t>(static_cast<unsigned char>(thePnt[1])) << 8) | aResult;
0053       [[fallthrough]];
0054     case 1:
0055       aResult = static_cast<uint64_t>(static_cast<unsigned char>(thePnt[0])) | aResult;
0056       [[fallthrough]];
0057     default:
0058       break;
0059   }
0060 
0061   return aResult;
0062 }
0063 
0064 template <typename T>
0065 inline T unaligned_load(const char* thePnt) noexcept
0066 {
0067   T aRes;
0068   memcpy(&aRes, thePnt, sizeof(aRes));
0069   return aRes;
0070 }
0071 } // namespace MurmurHashUtils
0072 
0073 //=================================================================================================
0074 
0075 inline uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed) noexcept
0076 {
0077   static constexpr uint64_t aMul = (((uint64_t)0xc6a4a793UL) << 32UL) + (uint64_t)0x5bd1e995UL;
0078   const char* const         aBuf = static_cast<const char*>(theKey);
0079 
0080   // Remove the bytes not divisible by the sizeof(uint64_t).  This
0081   // allows the main loop to process the data as 64-bit integers.
0082   const uint64_t    aLenAligned = theLen & ~(uint64_t)0x7;
0083   const char* const anEnd       = aBuf + aLenAligned;
0084   uint64_t          aHash       = theSeed ^ (theLen * aMul);
0085   for (const char* aPnt = aBuf; aPnt != anEnd; aPnt += 8)
0086   {
0087     const uint64_t aData =
0088       MurmurHashUtils::shift_mix(MurmurHashUtils::unaligned_load<uint64_t>(aPnt) * aMul) * aMul;
0089     aHash ^= aData;
0090     aHash *= aMul;
0091   }
0092   if ((theLen & 0x7) != 0)
0093   {
0094     const uint64_t data = MurmurHashUtils::load_bytes(anEnd, theLen & 0x7);
0095     aHash ^= data;
0096     aHash *= aMul;
0097   }
0098   aHash = MurmurHashUtils::shift_mix(aHash) * aMul;
0099   aHash = MurmurHashUtils::shift_mix(aHash);
0100   return aHash;
0101 }
0102 
0103 //=================================================================================================
0104 
0105 inline uint32_t MurmurHash2A(const void* theKey, int theLen, uint32_t theSeed) noexcept
0106 {
0107   constexpr uint32_t aMul  = 0x5bd1e995;
0108   uint32_t           aHash = theSeed ^ theLen;
0109   const char*        aBuf  = static_cast<const char*>(theKey);
0110 
0111   // Mix 4 bytes at a time into the hash.
0112   while (theLen >= 4)
0113   {
0114     uint32_t aKey = MurmurHashUtils::unaligned_load<uint32_t>(aBuf);
0115     aKey *= aMul;
0116     aKey ^= aKey >> 24;
0117     aKey *= aMul;
0118     aHash *= aMul;
0119     aHash ^= aKey;
0120     aBuf += 4;
0121     theLen -= 4;
0122   }
0123 
0124   uint32_t aKey;
0125   // Handle the last few bytes of the input array.
0126   switch (theLen)
0127   {
0128     case 3:
0129       aKey = static_cast<unsigned char>(aBuf[2]);
0130       aHash ^= aKey << 16;
0131       [[fallthrough]];
0132     case 2:
0133       aKey = static_cast<unsigned char>(aBuf[1]);
0134       aHash ^= aKey << 8;
0135       [[fallthrough]];
0136     case 1:
0137       aKey = static_cast<unsigned char>(aBuf[0]);
0138       aHash ^= aKey;
0139       aHash *= aMul;
0140   };
0141 
0142   // Do a few final mixes of the hash.
0143   aHash ^= aHash >> 13;
0144   aHash *= aMul;
0145   aHash ^= aHash >> 15;
0146   return aHash;
0147 }
0148 } // namespace MurmurHash
0149 
0150 namespace FNVHash
0151 {
0152 //=================================================================================================
0153 
0154 inline uint32_t FNVHash1A(const void* theKey, int theLen, uint32_t theSeed) noexcept
0155 {
0156   const char* cptr = static_cast<const char*>(theKey);
0157   for (; theLen; --theLen)
0158   {
0159     theSeed ^= static_cast<uint32_t>(*cptr++);
0160     theSeed *= static_cast<uint32_t>(16777619UL);
0161   }
0162   return theSeed;
0163 }
0164 
0165 //=================================================================================================
0166 
0167 inline uint64_t FNVHash64A(const void* theKey, int theLen, uint64_t theSeed) noexcept
0168 {
0169   const char* cptr = static_cast<const char*>(theKey);
0170   for (; theLen; --theLen)
0171   {
0172     theSeed ^= static_cast<uint64_t>(*cptr++);
0173     theSeed *= static_cast<uint64_t>(1099511628211ULL);
0174   }
0175   return theSeed;
0176 }
0177 } // namespace FNVHash
0178 } // namespace opencascade