11#include <daw/daw_cpp_feature_check.h>
13#define DAW_JSON_HAS_AVX2_SIMD 1
22namespace daw::simd_impl::avx2 {
27 explicit mask( __m256i value ) noexcept
30 [[nodiscard]] std::uint64_t to_ullong( )
const noexcept {
31 return static_cast<std::uint32_t
>( _mm256_movemask_epi8( m_value ) );
34 [[nodiscard]]
friend mask operator|( mask lhs, mask rhs )
noexcept {
35 return mask( _mm256_or_si256( lhs.m_value, rhs.m_value ) );
38 [[nodiscard]]
friend mask operator&( mask lhs, mask rhs )
noexcept {
39 return mask( _mm256_and_si256( lhs.m_value, rhs.m_value ) );
42 [[nodiscard]]
friend mask operator!( mask value )
noexcept {
43 return mask( _mm256_xor_si256(
44 value.m_value, _mm256_set1_epi8(
static_cast<char>( 0xFF ) ) ) );
48 template<
typename T, std::size_t = 32U>
50 static_assert(
sizeof( T ) == 1,
51 "The AVX2 JSON SIMD implementation supports byte types" );
53 std::is_integral_v<T>,
54 "The AVX2 JSON SIMD implementation requires an integral type" );
58 template<
typename U, std::
size_t MaximumSize>
61 template<
typename Simd,
typename Range,
typename Flag>
62 friend Simd unchecked_load( Range values, Flag );
64 template<
typename Simd,
typename Range,
typename Flag>
65 friend Simd partial_load( Range values, Flag );
67 explicit vec( __m256i value ) noexcept
70 [[nodiscard]]
static __m256i order_bytes( __m256i value )
noexcept {
71 return _mm256_xor_si256(
72 value, _mm256_set1_epi8(
static_cast<char>( 0x80 ) ) );
77 using mask_type = mask;
79 explicit vec( value_type value ) noexcept
80 : m_value( _mm256_set1_epi8(
static_cast<char>( value ) ) ) {}
82 [[nodiscard]]
static constexpr std::size_t size( )
noexcept {
86 [[nodiscard]]
friend mask operator==( vec lhs, vec rhs )
noexcept {
87 return mask( _mm256_cmpeq_epi8( lhs.m_value, rhs.m_value ) );
90 [[nodiscard]]
friend mask operator>=( vec lhs, vec rhs )
noexcept {
91 auto const ordered_lhs = order_bytes( lhs.m_value );
92 auto const ordered_rhs = order_bytes( rhs.m_value );
93 return mask( _mm256_or_si256(
94 _mm256_cmpgt_epi8( ordered_lhs, ordered_rhs ),
95 _mm256_cmpeq_epi8( lhs.m_value, rhs.m_value ) ) );
98 [[nodiscard]]
friend mask operator<=( vec lhs, vec rhs )
noexcept {
99 auto const ordered_lhs = order_bytes( lhs.m_value );
100 auto const ordered_rhs = order_bytes( rhs.m_value );
101 return mask( _mm256_or_si256(
102 _mm256_cmpgt_epi8( ordered_rhs, ordered_lhs ),
103 _mm256_cmpeq_epi8( lhs.m_value, rhs.m_value ) ) );
107 struct flag_default_t {};
108 struct flag_convert_t {};
110 inline constexpr flag_default_t flag_default = { };
111 inline constexpr flag_convert_t flag_convert = { };
113 template<
typename Simd,
typename Range,
typename Flag = flag_default_t>
114 [[nodiscard]]
inline Simd unchecked_load( Range values,
115 Flag = flag_default ) {
116 static_assert( Simd::size( ) == 32 );
117 return Simd( _mm256_loadu_si256(
118 reinterpret_cast<__m256i
const *
>( values.data( ) ) ) );
121 template<
typename Simd,
typename Range,
typename Flag = flag_default_t>
122 [[nodiscard]]
inline Simd partial_load( Range values, Flag = flag_default ) {
123 static_assert( Simd::size( ) == 32 );
124 auto result = _mm256_setzero_si256( );
125 std::memcpy( &result, values.data( ), values.size( ) );
126 return Simd( result );