File indexing completed on 2026-08-17 08:39:06
0001
0002
0003
0004
0005
0006
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)
0030 #endif
0031
0032 namespace detail{
0033
0034 struct m128ix2
0035 {
0036 __m128i lo,hi;
0037 };
0038
0039
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 }
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
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)
0143 #endif
0144 };
0145
0146 #if defined(BOOST_MSVC)
0147 #pragma warning(pop)
0148 #endif
0149
0150 }
0151 }
0152
0153 #endif