Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 08:39:06

0001 /* Copyright 2025 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See https://www.boost.org/libs/bloom for library home page.
0007  */
0008 
0009 #ifndef BOOST_BLOOM_DETAIL_FAST_MULTIBLOCK32_SSE2_HPP
0010 #define BOOST_BLOOM_DETAIL_FAST_MULTIBLOCK32_SSE2_HPP
0011 
0012 #include <boost/bloom/detail/multiblock_fpr_base.hpp>
0013 #include <boost/bloom/detail/mulx64.hpp>
0014 #include <boost/bloom/detail/sse2.hpp>
0015 #include <boost/config.hpp>
0016 #include <boost/config/workaround.hpp>
0017 #include <cstddef>
0018 #include <cstdint>
0019 
0020 #ifdef __SSE4_1__
0021 #include <smmintrin.h>
0022 #endif
0023 
0024 namespace boost{
0025 namespace bloom{
0026 
0027 #if defined(BOOST_MSVC)
0028 #pragma warning(push)
0029 #pragma warning(disable:4714) /* marked as __forceinline not inlined */
0030 #endif
0031 
0032 namespace detail{
0033 
0034 struct m128ix2
0035 {
0036   __m128i lo,hi;
0037 };
0038 
0039 /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
0040 static inline int mm_testc_si128(__m128i x,__m128i y)
0041 {
0042 #ifdef __SSE4_1__
0043   return _mm_testc_si128(x,y);
0044 #else
0045   return _mm_movemask_epi8(_mm_cmpeq_epi32(_mm_and_si128(x,y),y))==0xFFFF;
0046 #endif
0047 }
0048 
0049 } /* namespace detail */
0050 
0051 template<std::size_t K>
0052 struct fast_multiblock32:detail::multiblock_fpr_base<K>
0053 {
0054   static constexpr std::size_t k=K;
0055   using value_type=detail::m128ix2[(k+7)/8];
0056   static constexpr std::size_t used_value_size=sizeof(std::uint32_t)*k;
0057 
0058   static BOOST_FORCEINLINE void mark(value_type& x,std::uint64_t hash)
0059   {
0060     for(std::size_t i=0;i<k/8;++i){
0061       mark_m128ix2(x[i],hash,8);
0062       hash=detail::mulx64(hash);
0063     }
0064     if(k%8){
0065       mark_m128ix2(x[k/8],hash,k%8);
0066     }
0067   }
0068 
0069   static BOOST_FORCEINLINE bool check(const value_type& x,std::uint64_t hash)
0070   {
0071     bool res=true;
0072     for(std::size_t i=0;i<k/8;++i){
0073       res&=check_m128ix2(x[i],hash,8);
0074       hash=detail::mulx64(hash);
0075     }
0076     if(k%8){
0077       res&=check_m128ix2(x[k/8],hash,k%8);
0078     }
0079     return res;
0080   }
0081 
0082 private:
0083   static BOOST_FORCEINLINE detail::m128ix2 make_m128ix2(
0084     std::uint64_t hash,std::size_t kp)
0085   {
0086     const std::uint32_t mask=std::uint32_t(31)<<23,
0087                           exp=std::uint32_t(127)<<23;
0088     const __m128i exps[4]={
0089       _mm_set_epi32( 0 , 0 , 0 ,exp),
0090       _mm_set_epi32( 0 , 0 ,exp,exp),
0091       _mm_set_epi32( 0 ,exp,exp,exp),
0092       _mm_set_epi32(exp,exp,exp,exp),
0093     };
0094 
0095     if(kp<=4){
0096       __m128i h_lo=_mm_set_epi64x(hash<<5,hash);
0097       h_lo=_mm_and_si128(h_lo,_mm_set1_epi32(mask));
0098       h_lo=_mm_add_epi32(h_lo,exps[kp-1]);
0099       return {
0100         _mm_cvttps_epi32(*(__m128*)&h_lo),
0101         _mm_set1_epi32(0)
0102       };
0103     }
0104     else{
0105       __m128i h_lo=_mm_set_epi64x(hash<<5,hash),
0106               h_hi=_mm_slli_si128(h_lo,2);
0107       h_lo=_mm_and_si128(h_lo,_mm_set1_epi32(mask));
0108       h_hi=_mm_and_si128(h_hi,_mm_set1_epi32(mask));
0109       h_lo=_mm_add_epi32(h_lo,_mm_set1_epi32(exp));
0110       h_hi=_mm_add_epi32(h_hi,exps[kp-5]);
0111       return {
0112         _mm_cvttps_epi32(*(__m128*)&h_lo),
0113         _mm_cvttps_epi32(*(__m128*)&h_hi)
0114       };
0115     }
0116   }
0117 
0118   static BOOST_FORCEINLINE void mark_m128ix2(
0119     detail::m128ix2& x,std::uint64_t hash,std::size_t kp)
0120   {
0121     detail::m128ix2 h=make_m128ix2(hash,kp);
0122     x.lo=_mm_or_si128(x.lo,h.lo);
0123     if(kp>4)x.hi=_mm_or_si128(x.hi,h.hi);
0124   }
0125 
0126 #if BOOST_WORKAROUND(BOOST_MSVC,<=1900)
0127 /* 'int': forcing value to bool 'true' or 'false' */
0128 #pragma warning(push)
0129 #pragma warning(disable:4800)
0130 #endif
0131 
0132   static BOOST_FORCEINLINE bool check_m128ix2(
0133     const detail::m128ix2& x,std::uint64_t hash,std::size_t kp)
0134   {
0135     detail::m128ix2 h=make_m128ix2(hash,kp);
0136     auto res=detail::mm_testc_si128(x.lo,h.lo);
0137     if(kp>4)res&=detail::mm_testc_si128(x.hi,h.hi);
0138     return res;
0139   }
0140 
0141 #if BOOST_WORKAROUND(BOOST_MSVC,<=1900)
0142 #pragma warning(pop) /* C4800 */
0143 #endif
0144 };
0145 
0146 #if defined(BOOST_MSVC)
0147 #pragma warning(pop) /* C4714 */
0148 #endif
0149 
0150 } /* namespace bloom */
0151 } /* namespace boost */
0152 
0153 #endif