Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:33:45

0001 #ifndef BOOST_HASH2_XXHASH_HPP_INCLUDED
0002 #define BOOST_HASH2_XXHASH_HPP_INCLUDED
0003 
0004 // Copyright 2017, 2018 Peter Dimov.
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // https://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // xxHash, https://cyan4973.github.io/xxHash/
0009 
0010 #include <boost/hash2/detail/read.hpp>
0011 #include <boost/hash2/detail/rot.hpp>
0012 #include <boost/hash2/detail/memset.hpp>
0013 #include <boost/hash2/detail/memcpy.hpp>
0014 #include <boost/assert.hpp>
0015 #include <boost/config.hpp>
0016 #include <cstdint>
0017 #include <cstring>
0018 #include <cstddef>
0019 
0020 #if defined(BOOST_MSVC) && BOOST_MSVC < 1920
0021 # pragma warning(push)
0022 # pragma warning(disable: 4307) // '+': integral constant overflow
0023 #endif
0024 
0025 namespace boost
0026 {
0027 namespace hash2
0028 {
0029 
0030 class xxhash_32
0031 {
0032 private:
0033 
0034     static constexpr std::uint32_t P1 = 2654435761U;
0035     static constexpr std::uint32_t P2 = 2246822519U;
0036     static constexpr std::uint32_t P3 = 3266489917U;
0037     static constexpr std::uint32_t P4 =  668265263U;
0038     static constexpr std::uint32_t P5 =  374761393U;
0039 
0040 private:
0041 
0042     std::uint32_t v1_ = P1 + P2;
0043     std::uint32_t v2_ = P2;
0044     std::uint32_t v3_ = 0;
0045     std::uint32_t v4_ = static_cast<std::uint32_t>( 0 ) - P1;
0046 
0047     unsigned char buffer_[ 16 ] = {};
0048     std::size_t m_ = 0; // == n_ % 16
0049 
0050     std::size_t n_ = 0;
0051 
0052 private:
0053 
0054     BOOST_CXX14_CONSTEXPR void init( std::uint32_t seed )
0055     {
0056         v1_ = seed + P1 + P2;
0057         v2_ = seed + P2;
0058         v3_ = seed;
0059         v4_ = seed - P1;
0060     }
0061 
0062     BOOST_CXX14_CONSTEXPR static std::uint32_t round( std::uint32_t seed, std::uint32_t input )
0063     {
0064         seed += input * P2;
0065         seed = detail::rotl( seed, 13 );
0066         seed *= P1;
0067         return seed;
0068     }
0069 
0070     BOOST_CXX14_CONSTEXPR void update_( unsigned char const * p, std::size_t k )
0071     {
0072         std::uint32_t v1 = v1_;
0073         std::uint32_t v2 = v2_;
0074         std::uint32_t v3 = v3_;
0075         std::uint32_t v4 = v4_;
0076 
0077         for( std::size_t i = 0; i < k; ++i, p += 16 )
0078         {
0079             v1 = round( v1, detail::read32le( p +  0 ) );
0080             v2 = round( v2, detail::read32le( p +  4 ) );
0081             v3 = round( v3, detail::read32le( p +  8 ) );
0082             v4 = round( v4, detail::read32le( p + 12 ) );
0083         }
0084 
0085         v1_ = v1; 
0086         v2_ = v2; 
0087         v3_ = v3; 
0088         v4_ = v4; 
0089     }
0090 
0091 public:
0092 
0093     using result_type = std::uint32_t;
0094 
0095     xxhash_32() = default;
0096 
0097     BOOST_CXX14_CONSTEXPR explicit xxhash_32( std::uint64_t seed )
0098     {
0099         std::uint32_t s0 = static_cast<std::uint32_t>( seed );
0100         std::uint32_t s1 = static_cast<std::uint32_t>( seed >> 32 );
0101 
0102         init( s0 );
0103 
0104         if( s1 != 0 )
0105         {
0106             v1_ = round( v1_, s1 );
0107             v2_ = round( v2_, s1 );
0108             v3_ = round( v3_, s1 );
0109             v4_ = round( v4_, s1 );
0110         }
0111     }
0112 
0113     BOOST_CXX14_CONSTEXPR xxhash_32( unsigned char const * p, std::size_t n )
0114     {
0115         if( n != 0 )
0116         {
0117             update( p, n );
0118             result();
0119         }
0120     }
0121 
0122     xxhash_32( void const * p, std::size_t n ): xxhash_32( static_cast<unsigned char const*>( p ), n )
0123     {
0124     }
0125 
0126     BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0127     {
0128         BOOST_ASSERT( m_ == n_ % 16 );
0129 
0130         if( n == 0 ) return;
0131 
0132         n_ += n;
0133 
0134         if( m_ > 0 )
0135         {
0136             std::size_t k = 16 - m_;
0137 
0138             if( n < k )
0139             {
0140                 k = n;
0141             }
0142 
0143             detail::memcpy( buffer_ + m_, p, k );
0144 
0145             p += k;
0146             n -= k;
0147             m_ += k;
0148 
0149             if( m_ < 16 ) return;
0150 
0151             BOOST_ASSERT( m_ == 16 );
0152 
0153             update_( buffer_, 1 );
0154             m_ = 0;
0155         }
0156 
0157         BOOST_ASSERT( m_ == 0 );
0158 
0159         {
0160             std::size_t k = n / 16;
0161 
0162             update_( p, k );
0163 
0164             p += 16 * k;
0165             n -= 16 * k;
0166         }
0167 
0168         BOOST_ASSERT( n < 16 );
0169 
0170         if( n > 0 )
0171         {
0172             detail::memcpy( buffer_, p, n );
0173             m_ = n;
0174         }
0175 
0176         BOOST_ASSERT( m_ == n_ % 16 );
0177     }
0178 
0179     void update( void const* pv, std::size_t n )
0180     {
0181         unsigned char const* p = static_cast<unsigned char const*>( pv );
0182         update( p, n );
0183     }
0184 
0185     BOOST_CXX14_CONSTEXPR std::uint32_t result()
0186     {
0187         BOOST_ASSERT( m_ == n_ % 16 );
0188 
0189         std::uint32_t h = 0;
0190 
0191         if( n_ >= 16 )
0192         {
0193             h = detail::rotl( v1_, 1 ) + detail::rotl( v2_, 7 ) + detail::rotl( v3_, 12 ) + detail::rotl( v4_, 18 );
0194         }
0195         else
0196         {
0197             h = v3_ + P5;
0198         }
0199 
0200         h += static_cast<std::uint32_t>( n_ );
0201 
0202         unsigned char const * p = buffer_;
0203 
0204         std::size_t m = m_;
0205 
0206         while( m >= 4 )
0207         {
0208             h += detail::read32le( p ) * P3;
0209             h = detail::rotl( h, 17 ) * P4;
0210 
0211             p += 4;
0212             m -= 4;
0213         }
0214 
0215         while( m > 0 )
0216         {
0217             h += p[0] * P5;
0218             h = detail::rotl( h, 11 ) * P1;
0219 
0220             ++p;
0221             --m;
0222         }
0223 
0224         n_ += 16 - m_;
0225         m_ = 0;
0226 
0227         // clear buffered plaintext
0228         detail::memset( buffer_, 0, 16 );
0229 
0230         // perturb state
0231         v1_ += h;
0232         v2_ += h;
0233         v3_ -= h;
0234         v4_ -= h;
0235 
0236         // apply final mix
0237         h ^= h >> 15;
0238         h *= P2;
0239         h ^= h >> 13;
0240         h *= P3;
0241         h ^= h >> 16;
0242 
0243         return h;
0244     }
0245 };
0246 
0247 class xxhash_64
0248 {
0249 private:
0250 
0251     static constexpr std::uint64_t P1 = 11400714785074694791ULL;
0252     static constexpr std::uint64_t P2 = 14029467366897019727ULL;
0253     static constexpr std::uint64_t P3 =  1609587929392839161ULL;
0254     static constexpr std::uint64_t P4 =  9650029242287828579ULL;
0255     static constexpr std::uint64_t P5 =  2870177450012600261ULL;
0256 
0257 private:
0258 
0259     std::uint64_t v1_ = P1 + P2;
0260     std::uint64_t v2_ = P2;
0261     std::uint64_t v3_ = 0;
0262     std::uint64_t v4_ = static_cast<std::uint64_t>( 0 ) - P1;
0263 
0264     unsigned char buffer_[ 32 ] = {};
0265     std::size_t m_ = 0; // == n_ % 32
0266 
0267     std::uint64_t n_ = 0;
0268 
0269 private:
0270 
0271     BOOST_CXX14_CONSTEXPR void init( std::uint64_t seed )
0272     {
0273         v1_ = seed + P1 + P2;
0274         v2_ = seed + P2;
0275         v3_ = seed;
0276         v4_ = seed - P1;
0277     }
0278 
0279     BOOST_CXX14_CONSTEXPR static std::uint64_t round( std::uint64_t seed, std::uint64_t input )
0280     {
0281         seed += input * P2;
0282         seed = detail::rotl( seed, 31 );
0283         seed *= P1;
0284         return seed;
0285     }
0286 
0287     BOOST_CXX14_CONSTEXPR static std::uint64_t merge_round( std::uint64_t acc, std::uint64_t val )
0288     {
0289         val = round( 0, val );
0290         acc ^= val;
0291         acc = acc * P1 + P4;
0292         return acc;
0293     }
0294 
0295     BOOST_CXX14_CONSTEXPR void update_( unsigned char const * p, std::size_t k )
0296     {
0297         std::uint64_t v1 = v1_;
0298         std::uint64_t v2 = v2_;
0299         std::uint64_t v3 = v3_;
0300         std::uint64_t v4 = v4_;
0301 
0302         for( std::size_t i = 0; i < k; ++i, p += 32 )
0303         {
0304             v1 = round( v1, detail::read64le( p +  0 ) );
0305             v2 = round( v2, detail::read64le( p +  8 ) );
0306             v3 = round( v3, detail::read64le( p + 16 ) );
0307             v4 = round( v4, detail::read64le( p + 24 ) );
0308         }
0309 
0310         v1_ = v1; 
0311         v2_ = v2; 
0312         v3_ = v3; 
0313         v4_ = v4; 
0314     }
0315 
0316 public:
0317 
0318     typedef std::uint64_t result_type;
0319 
0320     xxhash_64() = default;
0321 
0322     BOOST_CXX14_CONSTEXPR explicit xxhash_64( std::uint64_t seed )
0323     {
0324         init( seed );
0325     }
0326 
0327     BOOST_CXX14_CONSTEXPR xxhash_64( unsigned char const * p, std::size_t n )
0328     {
0329         if( n != 0 )
0330         {
0331             update( p, n );
0332             result();
0333         }
0334     }
0335 
0336     xxhash_64( void const * p, std::size_t n ): xxhash_64( static_cast<unsigned char const*>( p ), n )
0337     {
0338     }
0339 
0340     BOOST_CXX14_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0341     {
0342         BOOST_ASSERT( m_ == n_ % 32 );
0343 
0344         if( n == 0 ) return;
0345 
0346         n_ += n;
0347 
0348         if( m_ > 0 )
0349         {
0350             std::size_t k = 32 - m_;
0351 
0352             if( n < k )
0353             {
0354                 k = n;
0355             }
0356 
0357             detail::memcpy( buffer_ + m_, p, k );
0358 
0359             p += k;
0360             n -= k;
0361             m_ += k;
0362 
0363             if( m_ < 32 ) return;
0364 
0365             BOOST_ASSERT( m_ == 32 );
0366 
0367             update_( buffer_, 1 );
0368             m_ = 0;
0369         }
0370 
0371         BOOST_ASSERT( m_ == 0 );
0372 
0373         {
0374             std::size_t k = n / 32;
0375 
0376             update_( p, k );
0377 
0378             p += 32 * k;
0379             n -= 32 * k;
0380         }
0381 
0382         BOOST_ASSERT( n < 32 );
0383 
0384         if( n > 0 )
0385         {
0386             detail::memcpy( buffer_, p, n );
0387             m_ = n;
0388         }
0389 
0390         BOOST_ASSERT( m_ == n_ % 32 );
0391     }
0392 
0393     void update( void const* pv, std::size_t n )
0394     {
0395         unsigned char const* p = static_cast<unsigned char const*>( pv );
0396         update( p, n );
0397     }
0398 
0399     BOOST_CXX14_CONSTEXPR std::uint64_t result()
0400     {
0401         BOOST_ASSERT( m_ == n_ % 32 );
0402 
0403         std::uint64_t h = 0;
0404 
0405         if( n_ >= 32 )
0406         {
0407             h = detail::rotl( v1_, 1 ) + detail::rotl( v2_, 7 ) + detail::rotl( v3_, 12 ) + detail::rotl( v4_, 18 );
0408 
0409             h = merge_round( h, v1_ );
0410             h = merge_round( h, v2_ );
0411             h = merge_round( h, v3_ );
0412             h = merge_round( h, v4_ );
0413         }
0414         else
0415         {
0416             h = v3_ + P5;
0417         }
0418 
0419         h += n_;
0420 
0421         unsigned char const * p = buffer_;
0422 
0423         std::size_t m = m_;
0424 
0425         while( m >= 8 )
0426         {
0427             std::uint64_t k1 = round( 0, detail::read64le( p ) );
0428 
0429             h ^= k1;
0430             h = detail::rotl( h, 27 ) * P1 + P4;
0431 
0432             p += 8;
0433             m -= 8;
0434         }
0435 
0436         while( m >= 4 )
0437         {
0438             h ^= static_cast<std::uint64_t>( detail::read32le( p ) ) * P1;
0439             h = detail::rotl( h, 23 ) * P2 + P3;
0440 
0441             p += 4;
0442             m -= 4;
0443         }
0444 
0445         while( m > 0 )
0446         {
0447             h ^= p[0] * P5;
0448             h = detail::rotl( h, 11 ) * P1;
0449 
0450             ++p;
0451             --m;
0452         }
0453 
0454         n_ += 32 - m_;
0455         m_ = 0;
0456 
0457         // clear buffered plaintext
0458         detail::memset( buffer_, 0, 32 );
0459 
0460         // perturb state
0461         v1_ += h;
0462         v2_ += h;
0463         v3_ -= h;
0464         v4_ -= h;
0465 
0466         // apply final mix
0467         h ^= h >> 33;
0468         h *= P2;
0469         h ^= h >> 29;
0470         h *= P3;
0471         h ^= h >> 32;
0472 
0473         return h;
0474     }
0475 };
0476 
0477 } // namespace hash2
0478 } // namespace boost
0479 
0480 #if defined(BOOST_MSVC) && BOOST_MSVC < 1920
0481 # pragma warning(pop)
0482 #endif
0483 
0484 #endif // #ifndef BOOST_HASH2_XXHASH_HPP_INCLUDED