2013-10-06 15:07:42 +03:00
# pragma once
2015-08-17 18:14:29 +03:00
# ifdef _MSC_VER
# include <intrin.h>
# else
# include <x86intrin.h>
# endif
2015-06-24 14:53:47 +03:00
# define IS_LE_MACHINE // only draft
2015-02-04 20:59:34 +05:30
2015-09-26 23:46:04 +03:00
union v128
2014-09-06 20:30:13 +04:00
{
2015-09-26 23:46:04 +03:00
template < typename T , std : : size_t N , std : : size_t M > class masked_array_t // array type accessed as (index ^ M)
2014-10-07 17:35:44 +04:00
{
2015-09-26 23:46:04 +03:00
T m_data [ N ] ;
2014-10-07 17:35:44 +04:00
2015-09-26 23:46:04 +03:00
public :
T & operator [ ] ( std : : size_t index )
{
return m_data [ index ^ M ] ;
}
2014-10-07 17:35:44 +04:00
2015-09-26 23:46:04 +03:00
const T & operator [ ] ( std : : size_t index ) const
{
return m_data [ index ^ M ] ;
}
2014-10-07 17:35:44 +04:00
2015-09-26 23:46:04 +03:00
T & at ( std : : size_t index )
{
return ( index ^ M ) < N ? m_data [ index ^ M ] : throw std : : out_of_range ( __FUNCTION__ ) ;
}
const T & at ( std : : size_t index ) const
{
return ( index ^ M ) < N ? m_data [ index ^ M ] : throw std : : out_of_range ( __FUNCTION__ ) ;
}
} ;
2014-10-07 17:35:44 +04:00
2015-09-14 19:32:35 +03:00
# ifdef IS_LE_MACHINE
template < typename T , std : : size_t N = 16 / sizeof ( T ) > using normal_array_t = masked_array_t < T , N , 0 > ;
template < typename T , std : : size_t N = 16 / sizeof ( T ) > using reversed_array_t = masked_array_t < T , N , N - 1 > ;
# else
template < typename T , std : : size_t N = 16 / sizeof ( T ) > using normal_array_t = masked_array_t < T , N , N - 1 > ;
template < typename T , std : : size_t N = 16 / sizeof ( T ) > using reversed_array_t = masked_array_t < T , N , 0 > ;
# endif
2014-10-07 17:35:44 +04:00
2015-09-14 19:32:35 +03:00
normal_array_t < u64 > _u64 ;
normal_array_t < s64 > _s64 ;
reversed_array_t < u64 > u64r ;
reversed_array_t < s64 > s64r ;
2014-10-07 17:35:44 +04:00
2015-09-14 19:32:35 +03:00
normal_array_t < u32 > _u32 ;
normal_array_t < s32 > _s32 ;
reversed_array_t < u32 > u32r ;
reversed_array_t < s32 > s32r ;
2014-10-07 17:35:44 +04:00
2015-09-14 19:32:35 +03:00
normal_array_t < u16 > _u16 ;
normal_array_t < s16 > _s16 ;
reversed_array_t < u16 > u16r ;
reversed_array_t < s16 > s16r ;
2014-10-07 17:35:44 +04:00
2015-09-14 19:32:35 +03:00
normal_array_t < u8 > _u8 ;
normal_array_t < s8 > _s8 ;
reversed_array_t < u8 > u8r ;
reversed_array_t < s8 > s8r ;
2014-10-07 17:35:44 +04:00
2015-09-14 19:32:35 +03:00
normal_array_t < f32 > _f ;
normal_array_t < f64 > _d ;
reversed_array_t < f32 > fr ;
reversed_array_t < f64 > dr ;
2014-10-07 17:35:44 +04:00
2014-10-08 01:37:04 +04:00
__m128 vf ;
__m128i vi ;
2015-03-21 17:29:33 +03:00
__m128d vd ;
2014-09-06 20:30:13 +04:00
class bit_array_128
{
2015-09-14 19:32:35 +03:00
u64 m_data [ 2 ] ;
2014-09-06 20:30:13 +04:00
public :
class bit_element
{
u64 & data ;
const u64 mask ;
public :
bit_element ( u64 & data , const u64 mask )
: data ( data )
, mask ( mask )
{
}
2015-09-26 23:46:04 +03:00
operator bool ( ) const
2014-09-06 20:30:13 +04:00
{
return ( data & mask ) ! = 0 ;
}
2015-09-26 23:46:04 +03:00
bit_element & operator = ( const bool right )
2014-09-06 20:30:13 +04:00
{
if ( right )
{
data | = mask ;
}
else
{
data & = ~ mask ;
}
return * this ;
}
2015-09-26 23:46:04 +03:00
bit_element & operator = ( const bit_element & right )
2014-09-06 20:30:13 +04:00
{
if ( right )
{
data | = mask ;
}
else
{
data & = ~ mask ;
}
return * this ;
}
} ;
2015-02-04 20:59:34 +05:30
// Index 0 returns the MSB and index 127 returns the LSB
2015-09-14 19:32:35 +03:00
bit_element operator [ ] ( u32 index )
2014-09-06 20:30:13 +04:00
{
2015-02-04 20:59:34 +05:30
# ifdef IS_LE_MACHINE
2015-09-14 19:32:35 +03:00
return bit_element ( m_data [ 1 - ( index > > 6 ) ] , 0x8000000000000000ull > > ( index & 0x3F ) ) ;
2015-02-04 20:59:34 +05:30
# else
2015-09-14 19:32:35 +03:00
return bit_element ( m_data [ index > > 6 ] , 0x8000000000000000ull > > ( index & 0x3F ) ) ;
2015-02-04 20:59:34 +05:30
# endif
2014-09-06 20:30:13 +04:00
}
2015-02-04 20:59:34 +05:30
// Index 0 returns the MSB and index 127 returns the LSB
2015-09-14 19:32:35 +03:00
bool operator [ ] ( u32 index ) const
2014-09-06 20:30:13 +04:00
{
2015-02-04 20:59:34 +05:30
# ifdef IS_LE_MACHINE
2015-09-14 19:32:35 +03:00
return ( m_data [ 1 - ( index > > 6 ) ] & ( 0x8000000000000000ull > > ( index & 0x3F ) ) ) ! = 0 ;
2015-02-04 20:59:34 +05:30
# else
2015-09-14 19:32:35 +03:00
return ( m_data [ index > > 6 ] & ( 0x8000000000000000ull > > ( index & 0x3F ) ) ) ! = 0 ;
2015-02-04 20:59:34 +05:30
# endif
2014-09-06 20:30:13 +04:00
}
2015-09-14 19:32:35 +03:00
bit_element at ( u32 index )
{
2015-09-26 23:46:04 +03:00
if ( index > = 128 ) throw std : : out_of_range ( __FUNCTION__ ) ;
2015-09-14 19:32:35 +03:00
return operator [ ] ( index ) ;
}
bool at ( u32 index ) const
{
2015-09-26 23:46:04 +03:00
if ( index > = 128 ) throw std : : out_of_range ( __FUNCTION__ ) ;
2015-09-14 19:32:35 +03:00
return operator [ ] ( index ) ;
}
}
_bit ;
2014-09-06 20:30:13 +04:00
2015-08-06 16:31:13 +03:00
static v128 from64 ( u64 _0 , u64 _1 = 0 )
2014-09-06 20:30:13 +04:00
{
2015-08-06 16:31:13 +03:00
v128 ret ;
2014-09-15 02:17:24 +04:00
ret . _u64 [ 0 ] = _0 ;
ret . _u64 [ 1 ] = _1 ;
2014-09-06 20:30:13 +04:00
return ret ;
}
2015-08-06 16:31:13 +03:00
static v128 from64r ( u64 _1 , u64 _0 = 0 )
2014-10-07 17:35:44 +04:00
{
return from64 ( _0 , _1 ) ;
}
2015-08-06 16:31:13 +03:00
static v128 from32 ( u32 _0 , u32 _1 = 0 , u32 _2 = 0 , u32 _3 = 0 )
2014-09-06 20:30:13 +04:00
{
2015-08-06 16:31:13 +03:00
v128 ret ;
2014-09-15 02:17:24 +04:00
ret . _u32 [ 0 ] = _0 ;
ret . _u32 [ 1 ] = _1 ;
ret . _u32 [ 2 ] = _2 ;
ret . _u32 [ 3 ] = _3 ;
2014-09-06 20:30:13 +04:00
return ret ;
}
2015-08-06 16:31:13 +03:00
static v128 from32r ( u32 _3 , u32 _2 = 0 , u32 _1 = 0 , u32 _0 = 0 )
2014-10-02 14:29:20 +04:00
{
2014-10-07 17:35:44 +04:00
return from32 ( _0 , _1 , _2 , _3 ) ;
2014-10-02 14:29:20 +04:00
}
2015-08-06 16:31:13 +03:00
static v128 from32p ( u32 value )
2014-10-02 14:29:20 +04:00
{
2015-08-06 16:31:13 +03:00
v128 ret ;
2015-03-29 14:00:10 +03:00
ret . vi = _mm_set1_epi32 ( static_cast < s32 > ( value ) ) ;
return ret ;
}
2015-08-06 16:31:13 +03:00
static v128 from16p ( u16 value )
2015-03-29 14:00:10 +03:00
{
2015-08-06 16:31:13 +03:00
v128 ret ;
2015-03-29 14:00:10 +03:00
ret . vi = _mm_set1_epi16 ( static_cast < s16 > ( value ) ) ;
2014-10-08 01:37:04 +04:00
return ret ;
}
2015-08-06 16:31:13 +03:00
static v128 from8p ( u8 value )
2014-10-08 01:37:04 +04:00
{
2015-08-06 16:31:13 +03:00
v128 ret ;
2015-03-29 14:00:10 +03:00
ret . vi = _mm_set1_epi8 ( static_cast < s8 > ( value ) ) ;
2014-10-02 14:29:20 +04:00
return ret ;
}
2015-08-06 16:31:13 +03:00
static v128 fromBit ( u32 bit )
2014-09-06 20:30:13 +04:00
{
2015-08-06 16:31:13 +03:00
v128 ret = { } ;
2014-09-06 20:30:13 +04:00
ret . _bit [ bit ] = true ;
return ret ;
}
2015-08-06 16:31:13 +03:00
static v128 fromV ( __m128i value )
2014-10-08 01:37:04 +04:00
{
2015-08-06 16:31:13 +03:00
v128 ret ;
2014-10-08 01:37:04 +04:00
ret . vi = value ;
return ret ;
}
2015-08-06 16:31:13 +03:00
static v128 fromF ( __m128 value )
2015-03-21 02:36:05 +03:00
{
2015-08-06 16:31:13 +03:00
v128 ret ;
2015-03-21 02:36:05 +03:00
ret . vf = value ;
return ret ;
}
2015-08-06 16:31:13 +03:00
static v128 fromD ( __m128d value )
2015-03-21 17:29:33 +03:00
{
2015-08-06 16:31:13 +03:00
v128 ret ;
2015-03-21 17:29:33 +03:00
ret . vd = value ;
return ret ;
}
2015-09-14 19:32:35 +03:00
static inline v128 add8 ( const v128 & left , const v128 & right )
2014-09-06 20:30:13 +04:00
{
2014-10-08 01:37:04 +04:00
return fromV ( _mm_add_epi8 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 add16 ( const v128 & left , const v128 & right )
2015-03-21 02:36:05 +03:00
{
return fromV ( _mm_add_epi16 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 add32 ( const v128 & left , const v128 & right )
2015-03-21 02:36:05 +03:00
{
return fromV ( _mm_add_epi32 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 addfs ( const v128 & left , const v128 & right )
2015-03-21 02:36:05 +03:00
{
return fromF ( _mm_add_ps ( left . vf , right . vf ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 addfd ( const v128 & left , const v128 & right )
2015-03-21 17:29:33 +03:00
{
return fromD ( _mm_add_pd ( left . vd , right . vd ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 sub8 ( const v128 & left , const v128 & right )
2014-10-08 01:37:04 +04:00
{
return fromV ( _mm_sub_epi8 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 sub16 ( const v128 & left , const v128 & right )
2015-03-21 02:36:05 +03:00
{
return fromV ( _mm_sub_epi16 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 sub32 ( const v128 & left , const v128 & right )
2015-03-21 02:36:05 +03:00
{
return fromV ( _mm_sub_epi32 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 subfs ( const v128 & left , const v128 & right )
2015-03-21 02:36:05 +03:00
{
return fromF ( _mm_sub_ps ( left . vf , right . vf ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 subfd ( const v128 & left , const v128 & right )
2015-03-21 17:29:33 +03:00
{
return fromD ( _mm_sub_pd ( left . vd , right . vd ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 maxu8 ( const v128 & left , const v128 & right )
2015-03-21 02:36:05 +03:00
{
return fromV ( _mm_max_epu8 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 minu8 ( const v128 & left , const v128 & right )
2014-10-08 01:37:04 +04:00
{
return fromV ( _mm_min_epu8 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 eq8 ( const v128 & left , const v128 & right )
2014-09-06 20:30:13 +04:00
{
2014-10-08 01:37:04 +04:00
return fromV ( _mm_cmpeq_epi8 ( left . vi , right . vi ) ) ;
2015-03-29 14:00:10 +03:00
}
2015-09-14 19:32:35 +03:00
static inline v128 eq16 ( const v128 & left , const v128 & right )
2015-03-29 14:00:10 +03:00
{
return fromV ( _mm_cmpeq_epi16 ( left . vi , right . vi ) ) ;
}
2015-09-14 19:32:35 +03:00
static inline v128 eq32 ( const v128 & left , const v128 & right )
2015-03-29 14:00:10 +03:00
{
return fromV ( _mm_cmpeq_epi32 ( left . vi , right . vi ) ) ;
2014-09-06 20:30:13 +04:00
}
2015-09-14 19:32:35 +03:00
bool operator = = ( const v128 & right ) const
2014-09-06 20:30:13 +04:00
{
2015-09-14 19:32:35 +03:00
return _u64 [ 0 ] = = right . _u64 [ 0 ] & & _u64 [ 1 ] = = right . _u64 [ 1 ] ;
2014-09-06 20:30:13 +04:00
}
2015-09-14 19:32:35 +03:00
bool operator ! = ( const v128 & right ) const
2014-09-06 20:30:13 +04:00
{
2015-09-14 19:32:35 +03:00
return _u64 [ 0 ] ! = right . _u64 [ 0 ] | | _u64 [ 1 ] ! = right . _u64 [ 1 ] ;
2014-09-06 20:30:13 +04:00
}
2015-09-26 23:46:04 +03:00
bool is_any_1 ( ) const // check if any bit is 1
2015-04-01 17:01:04 +03:00
{
return _u64 [ 0 ] | | _u64 [ 1 ] ;
}
2015-09-26 23:46:04 +03:00
bool is_any_0 ( ) const // check if any bit is 0
2015-04-01 17:01:04 +03:00
{
return ~ _u64 [ 0 ] | | ~ _u64 [ 1 ] ;
}
2014-10-08 01:37:04 +04:00
// result = (~left) & (right)
2015-09-14 19:32:35 +03:00
static inline v128 andnot ( const v128 & left , const v128 & right )
2014-10-08 01:37:04 +04:00
{
return fromV ( _mm_andnot_si128 ( left . vi , right . vi ) ) ;
}
2014-09-06 20:30:13 +04:00
void clear ( )
{
2015-09-14 19:32:35 +03:00
_u64 [ 0 ] = 0 ;
_u64 [ 1 ] = 0 ;
2014-09-06 20:30:13 +04:00
}
2015-01-12 21:12:06 +03:00
std : : string to_hex ( ) const ;
2014-09-06 20:30:13 +04:00
2015-01-12 21:12:06 +03:00
std : : string to_xyzw ( ) const ;
2014-09-06 20:30:13 +04:00
2015-09-14 19:32:35 +03:00
static inline v128 byteswap ( const v128 val )
2014-09-06 20:30:13 +04:00
{
2015-06-24 14:53:47 +03:00
return fromV ( _mm_shuffle_epi8 ( val . vi , _mm_set_epi8 ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ) ) ) ;
2014-09-06 20:30:13 +04:00
}
} ;
2015-08-06 16:31:13 +03:00
CHECK_SIZE_ALIGN ( v128 , 16 , 16 ) ;
2015-05-28 18:14:22 +03:00
2015-08-06 16:31:13 +03:00
inline v128 operator | ( const v128 & left , const v128 & right )
2015-06-24 14:53:47 +03:00
{
2015-08-06 16:31:13 +03:00
return v128 : : fromV ( _mm_or_si128 ( left . vi , right . vi ) ) ;
2015-06-24 14:53:47 +03:00
}
2015-08-06 16:31:13 +03:00
inline v128 operator & ( const v128 & left , const v128 & right )
2015-06-24 14:53:47 +03:00
{
2015-08-06 16:31:13 +03:00
return v128 : : fromV ( _mm_and_si128 ( left . vi , right . vi ) ) ;
2015-06-24 14:53:47 +03:00
}
2015-08-06 16:31:13 +03:00
inline v128 operator ^ ( const v128 & left , const v128 & right )
2015-06-24 14:53:47 +03:00
{
2015-08-06 16:31:13 +03:00
return v128 : : fromV ( _mm_xor_si128 ( left . vi , right . vi ) ) ;
2015-06-24 14:53:47 +03:00
}
2015-08-06 16:31:13 +03:00
inline v128 operator ~ ( const v128 & other )
2015-06-24 14:53:47 +03:00
{
2015-08-06 16:31:13 +03:00
return v128 : : from64 ( ~ other . _u64 [ 0 ] , ~ other . _u64 [ 1 ] ) ;
2015-06-24 14:53:47 +03:00
}
2015-09-14 19:32:35 +03:00
template < typename T , std : : size_t Size = sizeof ( T ) > struct se_storage
{
static_assert ( ! Size , " Bad se_storage<> type " ) ;
} ;
2013-11-19 23:10:23 +02:00
2015-09-14 19:32:35 +03:00
template < typename T > struct se_storage < T , 2 >
2014-09-04 13:21:23 +04:00
{
2015-09-14 19:32:35 +03:00
using type = u16 ;
2015-11-26 11:13:33 +03:00
[ [ deprecated ] ] static constexpr u16 _swap ( u16 src ) // for reference
2015-09-15 19:23:17 +03:00
{
return ( src > > 8 ) | ( src < < 8 ) ;
}
2015-11-26 11:13:33 +03:00
static inline u16 swap ( u16 src )
{
# if defined(__GNUG__)
return __builtin_bswap16 ( src ) ;
# else
return _byteswap_ushort ( src ) ;
# endif
}
2015-09-14 19:32:35 +03:00
static inline u16 to ( const T & src )
2014-09-04 13:21:23 +04:00
{
2015-11-26 11:13:33 +03:00
return swap ( reinterpret_cast < const u16 & > ( src ) ) ;
2015-01-11 12:33:05 +03:00
}
2015-09-14 19:32:35 +03:00
static inline T from ( u16 src )
2015-01-11 12:33:05 +03:00
{
2015-11-26 11:13:33 +03:00
const u16 result = swap ( src ) ;
2015-09-14 19:32:35 +03:00
return reinterpret_cast < const T & > ( result ) ;
2014-09-04 13:21:23 +04:00
}
} ;
2015-09-14 19:32:35 +03:00
template < typename T > struct se_storage < T , 4 >
2014-09-04 13:21:23 +04:00
{
2015-09-14 19:32:35 +03:00
using type = u32 ;
2015-11-26 11:13:33 +03:00
[ [ deprecated ] ] static constexpr u32 _swap ( u32 src ) // for reference
2015-09-15 19:23:17 +03:00
{
return ( src > > 24 ) | ( src < < 24 ) | ( ( src > > 8 ) & 0x0000ff00 ) | ( ( src < < 8 ) & 0x00ff0000 ) ;
}
2015-11-26 11:13:33 +03:00
static inline u32 swap ( u32 src )
{
# if defined(__GNUG__)
return __builtin_bswap32 ( src ) ;
# else
return _byteswap_ulong ( src ) ;
# endif
}
2015-09-14 19:32:35 +03:00
static inline u32 to ( const T & src )
2015-01-11 12:33:05 +03:00
{
2015-11-26 11:13:33 +03:00
return swap ( reinterpret_cast < const u32 & > ( src ) ) ;
2015-01-11 12:33:05 +03:00
}
2015-09-14 19:32:35 +03:00
static inline T from ( u32 src )
2014-09-04 13:21:23 +04:00
{
2015-11-26 11:13:33 +03:00
const u32 result = swap ( src ) ;
2015-09-14 19:32:35 +03:00
return reinterpret_cast < const T & > ( result ) ;
2014-09-04 13:21:23 +04:00
}
} ;
2015-09-14 19:32:35 +03:00
template < typename T > struct se_storage < T , 8 >
2014-09-04 13:21:23 +04:00
{
2015-09-14 19:32:35 +03:00
using type = u64 ;
2015-11-26 11:13:33 +03:00
[ [ deprecated ] ] static constexpr u64 _swap ( u64 src ) // for reference
2015-09-15 19:23:17 +03:00
{
return ( src > > 56 ) | ( src < < 56 ) |
( ( src > > 40 ) & 0x000000000000ff00 ) |
( ( src > > 24 ) & 0x0000000000ff0000 ) |
( ( src > > 8 ) & 0x00000000ff000000 ) |
( ( src < < 8 ) & 0x000000ff00000000 ) |
( ( src < < 24 ) & 0x0000ff0000000000 ) |
( ( src < < 40 ) & 0x00ff000000000000 ) ;
}
2015-11-26 11:13:33 +03:00
static inline u64 swap ( u64 src )
{
# if defined(__GNUG__)
return __builtin_bswap64 ( src ) ;
# else
return _byteswap_uint64 ( src ) ;
# endif
}
2015-09-14 19:32:35 +03:00
static inline u64 to ( const T & src )
2014-09-04 13:21:23 +04:00
{
2015-11-26 11:13:33 +03:00
return swap ( reinterpret_cast < const u64 & > ( src ) ) ;
2015-01-11 12:33:05 +03:00
}
2015-09-14 19:32:35 +03:00
static inline T from ( u64 src )
2015-01-11 12:33:05 +03:00
{
2015-11-26 11:13:33 +03:00
const u64 result = swap ( src ) ;
2015-09-14 19:32:35 +03:00
return reinterpret_cast < const T & > ( result ) ;
2014-09-04 13:21:23 +04:00
}
} ;
2015-09-14 19:32:35 +03:00
template < typename T > struct se_storage < T , 16 >
2015-01-11 12:33:05 +03:00
{
2015-09-14 19:32:35 +03:00
using type = v128 ;
static inline v128 to ( const T & src )
2015-01-11 12:33:05 +03:00
{
2015-09-14 19:32:35 +03:00
return v128 : : byteswap ( reinterpret_cast < const v128 & > ( src ) ) ;
2015-01-11 12:33:05 +03:00
}
2015-09-14 19:32:35 +03:00
static inline T from ( const v128 & src )
2015-01-11 12:33:05 +03:00
{
2015-09-14 19:32:35 +03:00
const v128 result = v128 : : byteswap ( src ) ;
return reinterpret_cast < const T & > ( result ) ;
2015-01-11 12:33:05 +03:00
}
} ;
2015-09-14 19:32:35 +03:00
template < typename T > using se_storage_t = typename se_storage < T > : : type ;
2013-11-19 23:10:23 +02:00
2015-09-14 19:32:35 +03:00
template < typename T1 , typename T2 > struct se_convert
2013-11-19 23:10:23 +02:00
{
2015-09-14 19:32:35 +03:00
using type_from = std : : remove_cv_t < T1 > ;
using type_to = std : : remove_cv_t < T2 > ;
using stype_from = se_storage_t < std : : remove_cv_t < T1 > > ;
using stype_to = se_storage_t < std : : remove_cv_t < T2 > > ;
using storage_from = se_storage < std : : remove_cv_t < T1 > > ;
using storage_to = se_storage < std : : remove_cv_t < T2 > > ;
2013-11-19 23:10:23 +02:00
2015-09-14 19:32:35 +03:00
static inline std : : enable_if_t < std : : is_same < type_from , type_to > : : value , stype_to > convert ( const stype_from & data )
{
return data ;
}
2013-11-19 23:10:23 +02:00
2015-09-14 19:32:35 +03:00
static inline stype_to convert ( const stype_from & data , . . . )
{
return storage_to : : to ( storage_from : : from ( data ) ) ;
}
2013-11-19 23:10:23 +02:00
} ;
2015-09-26 23:46:04 +03:00
static struct se_raw_tag_t { } constexpr se_raw { } ;
2015-09-15 19:23:17 +03:00
2015-09-18 01:41:14 +03:00
template < typename T , bool Se = true > class se_t ;
// se_t with switched endianness
template < typename T > class se_t < T , true >
2015-01-11 12:33:05 +03:00
{
2015-09-26 23:46:04 +03:00
using type = typename std : : remove_cv < T > : : type ;
2015-09-15 19:23:17 +03:00
using stype = se_storage_t < type > ;
using storage = se_storage < type > ;
2015-01-11 12:33:05 +03:00
2015-09-14 19:32:35 +03:00
stype m_data ;
2015-01-11 12:33:05 +03:00
2015-09-15 19:23:17 +03:00
static_assert ( ! std : : is_union < type > : : value & & ! std : : is_class < type > : : value | | std : : is_same < type , v128 > : : value | | std : : is_same < type , u128 > : : value , " se_t<> error: invalid type (struct or union) " ) ;
2015-09-14 19:32:35 +03:00
static_assert ( ! std : : is_pointer < type > : : value , " se_t<> error: invalid type (pointer) " ) ;
static_assert ( ! std : : is_reference < type > : : value , " se_t<> error: invalid type (reference) " ) ;
static_assert ( ! std : : is_array < type > : : value , " se_t<> error: invalid type (array) " ) ;
static_assert ( ! std : : is_enum < type > : : value , " se_t<> error: invalid type (enumeration), use integral type instead " ) ;
static_assert ( alignof ( type ) = = alignof ( stype ) , " se_t<> error: unexpected alignment " ) ;
2015-01-11 12:33:05 +03:00
2015-09-26 23:46:04 +03:00
template < typename T2 , typename = void > struct bool_converter
2015-09-18 01:41:14 +03:00
{
static inline bool to_bool ( const se_t < T2 > & value )
{
return static_cast < bool > ( value . value ( ) ) ;
}
} ;
2015-09-26 23:46:04 +03:00
template < typename T2 > struct bool_converter < T2 , std : : enable_if_t < std : : is_integral < T2 > : : value > >
2015-09-18 01:41:14 +03:00
{
static inline bool to_bool ( const se_t < T2 > & value )
{
return value . m_data ! = 0 ;
}
} ;
2015-09-14 19:32:35 +03:00
public :
se_t ( ) = default ;
2015-01-11 12:33:05 +03:00
2015-09-15 19:23:17 +03:00
se_t ( const se_t & right ) = default ;
2015-01-11 12:33:05 +03:00
2015-09-26 23:46:04 +03:00
se_t ( type value )
2015-09-14 19:32:35 +03:00
: m_data ( storage : : to ( value ) )
{
}
2015-09-18 01:41:14 +03:00
2015-09-15 19:23:17 +03:00
// construct directly from raw data (don't use)
2015-09-26 23:46:04 +03:00
constexpr se_t ( const stype & raw_value , const se_raw_tag_t & )
2015-09-15 19:23:17 +03:00
: m_data ( raw_value )
{
}
2015-09-26 23:46:04 +03:00
type value ( ) const
2014-09-16 14:52:04 +02:00
{
2015-09-14 19:32:35 +03:00
return storage : : from ( m_data ) ;
}
2014-09-16 14:52:04 +02:00
2015-09-15 19:23:17 +03:00
// access underlying raw data (don't use)
2015-09-26 23:46:04 +03:00
constexpr const stype & raw_data ( ) const noexcept
2014-09-16 14:52:04 +02:00
{
2015-09-14 19:32:35 +03:00
return m_data ;
}
se_t & operator = ( const se_t & ) = default ;
2014-09-16 14:52:04 +02:00
2015-09-26 23:46:04 +03:00
se_t & operator = ( type value )
2014-09-16 14:52:04 +02:00
{
2015-09-14 19:32:35 +03:00
return m_data = storage : : to ( value ) , * this ;
}
2014-11-19 16:16:30 +02:00
2015-09-26 23:46:04 +03:00
operator type ( ) const
2015-09-14 19:32:35 +03:00
{
2015-09-18 01:41:14 +03:00
return storage : : from ( m_data ) ;
2015-09-14 19:32:35 +03:00
}
2015-09-15 19:23:17 +03:00
// optimization
2015-09-26 23:46:04 +03:00
explicit operator bool ( ) const
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return bool_converter < type > : : to_bool ( * this ) ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-26 23:46:04 +03:00
template < typename T2 > std : : enable_if_t < IS_BINARY_COMPARABLE ( T , T2 ) , se_t & > operator & = ( const se_t < T2 > & right )
2015-09-15 19:23:17 +03:00
{
return m_data & = right . raw_data ( ) , * this ;
}
// optimization
2015-09-26 23:46:04 +03:00
template < typename CT > std : : enable_if_t < IS_INTEGRAL ( T ) & & std : : is_convertible < CT , T > : : value , se_t & > operator & = ( CT right )
2015-09-15 19:23:17 +03:00
{
return m_data & = storage : : to ( right ) , * this ;
}
// optimization
2015-09-26 23:46:04 +03:00
template < typename T2 > std : : enable_if_t < IS_BINARY_COMPARABLE ( T , T2 ) , se_t & > operator | = ( const se_t < T2 > & right )
2015-09-15 19:23:17 +03:00
{
return m_data | = right . raw_data ( ) , * this ;
}
// optimization
2015-09-26 23:46:04 +03:00
template < typename CT > std : : enable_if_t < IS_INTEGRAL ( T ) & & std : : is_convertible < CT , T > : : value , se_t & > operator | = ( CT right )
2015-09-15 19:23:17 +03:00
{
return m_data | = storage : : to ( right ) , * this ;
}
// optimization
2015-09-26 23:46:04 +03:00
template < typename T2 > std : : enable_if_t < IS_BINARY_COMPARABLE ( T , T2 ) , se_t & > operator ^ = ( const se_t < T2 > & right )
2015-09-15 19:23:17 +03:00
{
return m_data ^ = right . raw_data ( ) , * this ;
}
// optimization
2015-09-26 23:46:04 +03:00
template < typename CT > std : : enable_if_t < IS_INTEGRAL ( T ) & & std : : is_convertible < CT , T > : : value , se_t & > operator ^ = ( CT right )
2015-09-15 19:23:17 +03:00
{
return m_data ^ = storage : : to ( right ) , * this ;
}
2015-09-14 19:32:35 +03:00
} ;
2015-09-18 01:41:14 +03:00
// se_t with native endianness
2015-09-14 19:32:35 +03:00
template < typename T > class se_t < T , false >
{
2015-09-26 23:46:04 +03:00
using type = typename std : : remove_cv < T > : : type ;
2013-10-06 15:07:42 +03:00
2015-09-14 19:32:35 +03:00
type m_data ;
2013-10-06 15:07:42 +03:00
2015-09-15 19:23:17 +03:00
static_assert ( ! std : : is_union < type > : : value & & ! std : : is_class < type > : : value | | std : : is_same < type , v128 > : : value | | std : : is_same < type , u128 > : : value , " se_t<> error: invalid type (struct or union) " ) ;
2015-09-14 19:32:35 +03:00
static_assert ( ! std : : is_pointer < type > : : value , " se_t<> error: invalid type (pointer) " ) ;
static_assert ( ! std : : is_reference < type > : : value , " se_t<> error: invalid type (reference) " ) ;
static_assert ( ! std : : is_array < type > : : value , " se_t<> error: invalid type (array) " ) ;
static_assert ( ! std : : is_enum < type > : : value , " se_t<> error: invalid type (enumeration), use integral type instead " ) ;
2013-10-06 15:07:42 +03:00
2015-09-14 19:32:35 +03:00
public :
se_t ( ) = default ;
2014-02-22 04:53:06 +02:00
2015-09-14 19:32:35 +03:00
se_t ( const se_t & ) = default ;
2013-10-06 15:07:42 +03:00
2015-09-26 23:46:04 +03:00
constexpr se_t ( type value )
2015-09-18 01:41:14 +03:00
: m_data ( value )
2015-06-24 14:53:47 +03:00
{
2014-11-19 16:16:30 +02:00
}
2014-09-16 14:23:58 +03:00
2015-09-26 23:46:04 +03:00
type value ( ) const
2014-11-19 16:16:30 +02:00
{
2015-06-24 14:53:47 +03:00
return m_data ;
2014-11-19 16:16:30 +02:00
}
2015-01-12 21:12:06 +03:00
2015-09-14 19:32:35 +03:00
se_t & operator = ( const se_t & value ) = default ;
2014-09-16 14:23:58 +03:00
2015-09-26 23:46:04 +03:00
se_t & operator = ( type value )
2015-09-14 19:32:35 +03:00
{
return m_data = value , * this ;
2014-09-16 14:23:58 +03:00
}
2015-09-26 23:46:04 +03:00
operator type ( ) const
2014-11-19 16:16:30 +02:00
{
2015-09-18 01:41:14 +03:00
return m_data ;
2014-11-19 16:16:30 +02:00
}
2015-09-26 23:46:04 +03:00
template < typename CT > std : : enable_if_t < IS_INTEGRAL ( T ) & & std : : is_convertible < CT , T > : : value , se_t & > operator & = ( const CT & right )
2015-09-15 19:23:17 +03:00
{
return m_data & = right , * this ;
}
2014-09-05 21:54:06 +04:00
2015-09-26 23:46:04 +03:00
template < typename CT > std : : enable_if_t < IS_INTEGRAL ( T ) & & std : : is_convertible < CT , T > : : value , se_t & > operator | = ( const CT & right )
2015-09-15 19:23:17 +03:00
{
return m_data | = right , * this ;
}
2015-09-26 23:46:04 +03:00
template < typename CT > std : : enable_if_t < IS_INTEGRAL ( T ) & & std : : is_convertible < CT , T > : : value , se_t & > operator ^ = ( const CT & right )
2015-09-15 19:23:17 +03:00
{
return m_data ^ = right , * this ;
}
} ;
2015-06-24 14:53:47 +03:00
2015-09-18 01:41:14 +03:00
// se_t with native endianness (alias)
template < typename T > using nse_t = se_t < T , false > ;
2015-09-14 19:32:35 +03:00
template < typename T , bool Se , typename T1 > inline se_t < T , Se > & operator + = ( se_t < T , Se > & left , const T1 & right )
{
auto value = left . value ( ) ;
return left = ( value + = right ) ;
}
2015-06-24 14:53:47 +03:00
2015-09-14 19:32:35 +03:00
template < typename T , bool Se , typename T1 > inline se_t < T , Se > & operator - = ( se_t < T , Se > & left , const T1 & right )
{
auto value = left . value ( ) ;
return left = ( value - = right ) ;
}
2015-06-24 14:53:47 +03:00
2015-09-14 19:32:35 +03:00
template < typename T , bool Se , typename T1 > inline se_t < T , Se > & operator * = ( se_t < T , Se > & left , const T1 & right )
{
auto value = left . value ( ) ;
return left = ( value * = right ) ;
}
2014-02-22 04:53:06 +02:00
2015-09-14 19:32:35 +03:00
template < typename T , bool Se , typename T1 > inline se_t < T , Se > & operator / = ( se_t < T , Se > & left , const T1 & right )
2015-06-24 14:53:47 +03:00
{
2015-09-14 19:32:35 +03:00
auto value = left . value ( ) ;
return left = ( value / = right ) ;
2015-06-24 14:53:47 +03:00
}
2015-09-14 19:32:35 +03:00
template < typename T , bool Se , typename T1 > inline se_t < T , Se > & operator % = ( se_t < T , Se > & left , const T1 & right )
2015-06-24 14:53:47 +03:00
{
2015-09-14 19:32:35 +03:00
auto value = left . value ( ) ;
return left = ( value % = right ) ;
2015-06-24 14:53:47 +03:00
}
2015-09-14 19:32:35 +03:00
template < typename T , bool Se , typename T1 > inline se_t < T , Se > & operator < < = ( se_t < T , Se > & left , const T1 & right )
2015-06-24 14:53:47 +03:00
{
2015-09-14 19:32:35 +03:00
auto value = left . value ( ) ;
return left = ( value < < = right ) ;
2015-06-24 14:53:47 +03:00
}
2015-09-14 19:32:35 +03:00
template < typename T , bool Se , typename T1 > inline se_t < T , Se > & operator > > = ( se_t < T , Se > & left , const T1 & right )
2015-06-24 14:53:47 +03:00
{
2015-09-14 19:32:35 +03:00
auto value = left . value ( ) ;
return left = ( value > > = right ) ;
}
template < typename T , bool Se > inline se_t < T , Se > operator + + ( se_t < T , Se > & left , int )
2015-06-24 14:53:47 +03:00
{
2015-09-14 19:32:35 +03:00
auto value = left . value ( ) ;
auto result = value + + ;
left = value ;
2015-06-24 14:53:47 +03:00
return result ;
}
2015-09-14 19:32:35 +03:00
template < typename T , bool Se > inline se_t < T , Se > operator - - ( se_t < T , Se > & left , int )
2015-06-24 14:53:47 +03:00
{
2015-09-14 19:32:35 +03:00
auto value = left . value ( ) ;
auto result = value - - ;
left = value ;
2015-06-24 14:53:47 +03:00
return result ;
}
2015-09-14 19:32:35 +03:00
template < typename T , bool Se > inline se_t < T , Se > & operator + + ( se_t < T , Se > & right )
{
auto value = right . value ( ) ;
return right = + + value ;
}
template < typename T , bool Se > inline se_t < T , Se > & operator - - ( se_t < T , Se > & right )
{
auto value = right . value ( ) ;
return right = - - value ;
}
2015-09-15 19:23:17 +03:00
// optimization
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_BINARY_COMPARABLE ( T1 , T2 ) , bool > operator = = ( const se_t < T1 > & left , const se_t < T2 > & right )
{
return left . raw_data ( ) = = right . raw_data ( ) ;
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGRAL ( T1 ) & & IS_INTEGER ( T2 ) & & sizeof ( T1 ) > = sizeof ( T2 ) , bool > operator = = ( const se_t < T1 > & left , T2 right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return left . raw_data ( ) = = se_storage < T1 > : : to ( right ) ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGER ( T1 ) & & IS_INTEGRAL ( T2 ) & & sizeof ( T1 ) < = sizeof ( T2 ) , bool > operator = = ( T1 left , const se_t < T2 > & right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return se_storage < T2 > : : to ( left ) = = right . raw_data ( ) ;
2015-09-15 19:23:17 +03:00
}
// optimization
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_BINARY_COMPARABLE ( T1 , T2 ) , bool > operator ! = ( const se_t < T1 > & left , const se_t < T2 > & right )
{
return left . raw_data ( ) ! = right . raw_data ( ) ;
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGRAL ( T1 ) & & IS_INTEGER ( T2 ) & & sizeof ( T1 ) > = sizeof ( T2 ) , bool > operator ! = ( const se_t < T1 > & left , T2 right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return left . raw_data ( ) ! = se_storage < T1 > : : to ( right ) ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGER ( T1 ) & & IS_INTEGRAL ( T2 ) & & sizeof ( T1 ) < = sizeof ( T2 ) , bool > operator ! = ( T1 left , const se_t < T2 > & right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return se_storage < T2 > : : to ( left ) ! = right . raw_data ( ) ;
2015-09-15 19:23:17 +03:00
}
// optimization
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_BINARY_COMPARABLE ( T1 , T2 ) & & sizeof ( T1 ) > = 4 , se_t < decltype ( T1 ( ) & T2 ( ) ) > > operator & ( const se_t < T1 > & left , const se_t < T2 > & right )
{
2015-09-18 01:41:14 +03:00
return { left . raw_data ( ) & right . raw_data ( ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGRAL ( T1 ) & & IS_INTEGER ( T2 ) & & sizeof ( T1 ) > = sizeof ( T2 ) & & sizeof ( T1 ) > = 4 , se_t < decltype ( T1 ( ) & T2 ( ) ) > > operator & ( const se_t < T1 > & left , T2 right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return { left . raw_data ( ) & se_storage < T1 > : : to ( right ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGER ( T1 ) & & IS_INTEGRAL ( T2 ) & & sizeof ( T1 ) < = sizeof ( T2 ) & & sizeof ( T2 ) > = 4 , se_t < decltype ( T1 ( ) & T2 ( ) ) > > operator & ( T1 left , const se_t < T2 > & right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return { se_storage < T2 > : : to ( left ) & right . raw_data ( ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_BINARY_COMPARABLE ( T1 , T2 ) & & sizeof ( T1 ) > = 4 , se_t < decltype ( T1 ( ) | T2 ( ) ) > > operator | ( const se_t < T1 > & left , const se_t < T2 > & right )
{
2015-09-18 01:41:14 +03:00
return { left . raw_data ( ) | right . raw_data ( ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGRAL ( T1 ) & & IS_INTEGER ( T2 ) & & sizeof ( T1 ) > = sizeof ( T2 ) & & sizeof ( T1 ) > = 4 , se_t < decltype ( T1 ( ) | T2 ( ) ) > > operator | ( const se_t < T1 > & left , T2 right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return { left . raw_data ( ) | se_storage < T1 > : : to ( right ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGER ( T1 ) & & IS_INTEGRAL ( T2 ) & & sizeof ( T1 ) < = sizeof ( T2 ) & & sizeof ( T2 ) > = 4 , se_t < decltype ( T1 ( ) | T2 ( ) ) > > operator | ( T1 left , const se_t < T2 > & right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return { se_storage < T2 > : : to ( left ) | right . raw_data ( ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_BINARY_COMPARABLE ( T1 , T2 ) & & sizeof ( T1 ) > = 4 , se_t < decltype ( T1 ( ) ^ T2 ( ) ) > > operator ^ ( const se_t < T1 > & left , const se_t < T2 > & right )
{
2015-09-18 01:41:14 +03:00
return { left . raw_data ( ) ^ right . raw_data ( ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGRAL ( T1 ) & & IS_INTEGER ( T2 ) & & sizeof ( T1 ) > = sizeof ( T2 ) & & sizeof ( T1 ) > = 4 , se_t < decltype ( T1 ( ) ^ T2 ( ) ) > > operator ^ ( const se_t < T1 > & left , T2 right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return { left . raw_data ( ) ^ se_storage < T1 > : : to ( right ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T1 , typename T2 > inline std : : enable_if_t < IS_INTEGER ( T1 ) & & IS_INTEGRAL ( T2 ) & & sizeof ( T1 ) < = sizeof ( T2 ) & & sizeof ( T2 ) > = 4 , se_t < decltype ( T1 ( ) ^ T2 ( ) ) > > operator ^ ( T1 left , const se_t < T2 > & right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return { se_storage < T2 > : : to ( left ) ^ right . raw_data ( ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
// optimization
2015-09-18 01:41:14 +03:00
template < typename T > inline std : : enable_if_t < IS_INTEGRAL ( T ) & & sizeof ( T ) > = 4 , se_t < decltype ( ~ T ( ) ) > > operator ~ ( const se_t < T > & right )
2015-09-15 19:23:17 +03:00
{
2015-09-18 01:41:14 +03:00
return { ~ right . raw_data ( ) , se_raw } ;
2015-09-15 19:23:17 +03:00
}
2015-09-14 19:32:35 +03:00
# ifdef IS_LE_MACHINE
template < typename T > using be_t = se_t < T , true > ;
template < typename T > using le_t = se_t < T , false > ;
# else
template < typename T > using be_t = se_t < T , false > ;
template < typename T > using le_t = se_t < T , true > ;
# endif
2014-09-01 20:16:44 +04:00
2015-09-26 23:46:04 +03:00
template < typename T , bool Se , typename = void > struct to_se
2014-09-01 20:16:44 +04:00
{
2015-09-26 23:46:04 +03:00
using type = typename std : : conditional < std : : is_arithmetic < T > : : value | | std : : is_enum < T > : : value , se_t < T , Se > , T > : : type ;
2015-01-28 15:59:16 +03:00
} ;
2014-09-01 20:16:44 +04:00
2015-09-26 23:46:04 +03:00
template < typename T , bool Se > struct to_se < const T , Se , std : : enable_if_t < ! std : : is_array < T > : : value > > // move const qualifier
2015-06-15 20:00:08 +03:00
{
2015-09-26 23:46:04 +03:00
using type = const typename to_se < T , Se > : : type ;
2015-06-15 20:00:08 +03:00
} ;
2015-09-26 23:46:04 +03:00
template < typename T , bool Se > struct to_se < volatile T , Se , std : : enable_if_t < ! std : : is_array < T > : : value & & ! std : : is_const < T > : : value > > // move volatile qualifier
2015-06-15 20:00:08 +03:00
{
2015-09-26 23:46:04 +03:00
using type = volatile typename to_se < T , Se > : : type ;
2015-06-15 20:00:08 +03:00
} ;
2015-09-26 23:46:04 +03:00
template < typename T , bool Se > struct to_se < T [ ] , Se >
2015-01-28 15:59:16 +03:00
{
2015-09-26 23:46:04 +03:00
using type = typename to_se < T , Se > : : type [ ] ;
2015-01-28 15:59:16 +03:00
} ;
2015-09-26 23:46:04 +03:00
template < typename T , bool Se , std : : size_t N > struct to_se < T [ N ] , Se >
2015-01-28 15:59:16 +03:00
{
2015-09-26 23:46:04 +03:00
using type = typename to_se < T , Se > : : type [ N ] ;
2014-09-01 20:16:44 +04:00
} ;
2015-09-26 23:46:04 +03:00
template < bool Se > struct to_se < u128 , Se > { using type = se_t < u128 , Se > ; } ;
template < bool Se > struct to_se < v128 , Se > { using type = se_t < v128 , Se > ; } ;
template < bool Se > struct to_se < bool , Se > { using type = bool ; } ;
template < bool Se > struct to_se < char , Se > { using type = char ; } ;
template < bool Se > struct to_se < u8 , Se > { using type = u8 ; } ;
template < bool Se > struct to_se < s8 , Se > { using type = s8 ; } ;
2014-09-05 15:24:37 +04:00
2015-09-26 23:46:04 +03:00
# ifdef IS_LE_MACHINE
template < typename T > using to_be_t = typename to_se < T , true > : : type ;
template < typename T > using to_le_t = typename to_se < T , false > : : type ;
# else
template < typename T > using to_be_t = typename to_se < T , false > : : type ;
template < typename T > using to_le_t = typename to_se < T , true > : : type ;
# endif
2015-06-15 00:52:22 +03:00
2015-06-15 20:00:08 +03:00
2015-09-26 23:46:04 +03:00
template < typename T , typename = void > struct to_ne
2015-06-15 20:00:08 +03:00
{
2015-09-26 23:46:04 +03:00
using type = T ;
2015-06-15 20:00:08 +03:00
} ;
2015-09-26 23:46:04 +03:00
template < typename T , bool Se > struct to_ne < se_t < T , Se > >
2015-06-13 04:31:45 +03:00
{
2015-09-26 23:46:04 +03:00
using type = typename std : : remove_cv < T > : : type ;
2015-06-13 04:31:45 +03:00
} ;
2015-09-26 23:46:04 +03:00
template < typename T > struct to_ne < const T , std : : enable_if_t < ! std : : is_array < T > : : value > > // move const qualifier
2015-06-13 04:31:45 +03:00
{
2015-09-26 23:46:04 +03:00
using type = const typename to_ne < T > : : type ;
2015-06-13 04:31:45 +03:00
} ;
2015-09-26 23:46:04 +03:00
template < typename T > struct to_ne < volatile T , std : : enable_if_t < ! std : : is_array < T > : : value & & ! std : : is_const < T > : : value > > // move volatile qualifier
2015-06-13 04:31:45 +03:00
{
2015-09-26 23:46:04 +03:00
using type = volatile typename to_ne < T > : : type ;
2015-06-13 04:31:45 +03:00
} ;
2015-09-26 23:46:04 +03:00
template < typename T > struct to_ne < T [ ] >
2015-06-13 04:31:45 +03:00
{
2015-09-26 23:46:04 +03:00
using type = typename to_ne < T > : : type [ ] ;
2015-06-13 04:31:45 +03:00
} ;
2015-05-27 06:11:59 +03:00
2015-09-26 23:46:04 +03:00
template < typename T , std : : size_t N > struct to_ne < T [ N ] >
2015-06-13 04:31:45 +03:00
{
2015-09-26 23:46:04 +03:00
using type = typename to_ne < T > : : type [ N ] ;
2015-06-13 04:31:45 +03:00
} ;
2015-06-15 15:24:37 +03:00
// restore native endianness for T: returns T for be_t<T> or le_t<T>, T otherwise
template < typename T > using to_ne_t = typename to_ne < T > : : type ;