11#include <daw/daw_cpp_feature_check.h>
13#define DAW_JSON_HAS_SSE42_SIMD 1
22namespace daw::simd_impl::sse42 {
27 explicit mask( __m128i value ) noexcept
30 [[nodiscard]] std::uint64_t to_ullong( )
const noexcept {
31 return static_cast<std::uint32_t
>( _mm_movemask_epi8( m_value ) );
34 [[nodiscard]]
friend mask operator|( mask lhs, mask rhs )
noexcept {
35 return mask( _mm_or_si128( lhs.m_value, rhs.m_value ) );
38 [[nodiscard]]
friend mask operator&( mask lhs, mask rhs )
noexcept {
39 return mask( _mm_and_si128( lhs.m_value, rhs.m_value ) );
42 [[nodiscard]]
friend mask operator!( mask value )
noexcept {
43 return mask( _mm_xor_si128( value.m_value,
44 _mm_set1_epi8(
static_cast<char>( 0xFF ) ) ) );
48 template<
typename T, std::size_t = 16U>
50 static_assert(
sizeof( T ) == 1,
51 "The SSE4.2 JSON SIMD implementation supports byte types" );
53 std::is_integral_v<T>,
54 "The SSE4.2 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( __m128i value ) noexcept
70 [[nodiscard]]
static __m128i order_bytes( __m128i value )
noexcept {
71 return _mm_xor_si128( value,
72 _mm_set1_epi8(
static_cast<char>( 0x80 ) ) );
77 using mask_type = mask;
79 explicit vec( value_type value ) noexcept
80 : m_value( _mm_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( _mm_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( _mm_or_si128( _mm_cmpgt_epi8( ordered_lhs, ordered_rhs ),
94 _mm_cmpeq_epi8( lhs.m_value, rhs.m_value ) ) );
97 [[nodiscard]]
friend mask operator<=( vec lhs, vec rhs )
noexcept {
98 auto const ordered_lhs = order_bytes( lhs.m_value );
99 auto const ordered_rhs = order_bytes( rhs.m_value );
100 return mask( _mm_or_si128( _mm_cmpgt_epi8( ordered_rhs, ordered_lhs ),
101 _mm_cmpeq_epi8( lhs.m_value, rhs.m_value ) ) );
105 struct flag_default_t {};
106 struct flag_convert_t {};
108 inline constexpr flag_default_t flag_default = { };
109 inline constexpr flag_convert_t flag_convert = { };
111 template<
typename Simd,
typename Range,
typename Flag = flag_default_t>
112 [[nodiscard]]
inline Simd unchecked_load( Range values,
113 Flag = flag_default ) {
114 static_assert( Simd::size( ) == 16 );
115 return Simd( _mm_loadu_si128(
116 reinterpret_cast<__m128i
const *
>( values.data( ) ) ) );
119 template<
typename Simd,
typename Range,
typename Flag = flag_default_t>
120 [[nodiscard]]
inline Simd partial_load( Range values, Flag = flag_default ) {
121 static_assert( Simd::size( ) == 16 );
122 auto result = _mm_setzero_si128( );
123 std::memcpy( &result, values.data( ), values.size( ) );
124 return Simd( result );