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)
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