#define CHAR_BITS 8
#define T_T template< typename T > inline
#define T_D( default_type ) template< typename T = default_type > inline
#define T_S template<> inline
//------------------------------------------------------------------------------
#define typecon( condition, tt, ft ) \
typedef typename std::conditional< condition, tt, ft >::type
T_T const auto msb( const T t = 0 )
{
return sizeof t * CHAR_BITS - 1;
}
T_T const auto msb_value( const T t = 0 )
{
typecon( sizeof t == sizeof( iu ), i32u, i64u ) TR;
return (TR)1ULL << msb( t );
}
T_T const auto msb_mask( const T t = 0 )
{
typecon( sizeof t == sizeof( iu ), i32u, i64u ) TR;
return (TR)~msb_value( t );
}
///-----------------------------------------------------------------------------
T_T const auto MSB( const T t = 0 )
{
return sizeof t - 1;
}
T_T const auto MSB_VALUE( const T t = 0 )
{
typecon( sizeof t == sizeof( iu ), i32u, i64u ) TR;
return (TR)0xFFULL << ( (TR)MSB( t ) * CHAR_BITS );
}
T_T const auto MSB_MASK( const T t = 0 )
{
typecon( sizeof t == sizeof( iu ), i32u, i64u ) TR;
return (TR)~MSB_VALUE( t );
}
//------------------------------------------------------------------------------
T_T void real2uexp( const T& r )
{
typecon( sizeof( T ) == sizeof( iu ), i32, i64 ) TR;
*(TR*)&r ^= *(TR*)&r >> msb( r ) | msb_value( r );
}
T_T void uexp2real( const T& r )
{
typecon( sizeof( T ) == sizeof( iu ), i32, i64 ) TR;
*(TR*)&r ^= ~*(TR*)&r >> msb( r ) | msb_value( r );
}
//------------------------------------------------------------------------------
일전에 드보가 쓴 conditional 을 써먹어 봤습니다.
요즘 generic 하게 template 을 많이 작성하다보니 게을러져서 매크로도 만들었구유.
흐린바다에게 주었던 미션인, float 을 radix sort 돌리기 위해,
부호를 기각시킨(음수 범위만큼 양의 방향으로 밀어올림) 지수표현으로 변경하는 매크로를 올렸었는데,
double 타입에도 적용가능하게 확장해 보았습니다.
리턴타입을 늦게 결정해주기 위해 auto 를 사용한 것에 주의.
//------------------------------------------------------------------------------
T_T void real2uexp2( const T& r )
{
if( sizeof r == sizeof(f32) )
{
*(i32*)&r ^= *(i32*)&r >> msb< i32 >() | msb_value< i32 >();
}
else
{
*(i32*)&r ^= *( (i32*)&r + 1 ) >> msb< i32 >();
*( (i32*)&r + 1 ) ^= *( (i32*)&r + 1 ) >> msb< i32 >() | msb_value< i32 >();
}
}
T_T void uexp2real2( const T& r )
{
if( sizeof r == sizeof( f32 ) )
{
*(i32*)&r ^= ~*(i32*)&r >> msb< i32 >() | msb_value< i32 >();
}
else
{
*(i32*)&r ^= ~*( (i32*)&r + 1 ) >> msb< i32 >();
*( (i32*)&r + 1 ) ^= ~*( (i32*)&r + 1 ) >> msb< i32 >() | msb_value< i32 >();
}
}
//------------------------------------------------------------------------------
현실은 64비트 연산비용이 비싸서 이 코드가 더 빠르군유 :)
하지만 역시, 아무타입을 받진 못하니까 명시적으로 한정해주는게 좋겠쥬 :)
inline void real2uexp( const f32& r )
{
*(i32*)&r ^= *(i32*)&r >> msb< i32 >() | msb_value< i32 >();
}
inline void uexp2real( const f32& r )
{
*(i32*)&r ^= ~( *(i32*)&r >> msb< i32 >() ) | msb_value< i32 >();
}
inline void real2uexp( const f64& r )
{
const i32u c = *( (i32*)&r + 1 ) >> msb< i32 >();
*(i32u*)&r ^= c;
*( (i32u*)&r + 1 ) ^= c | msb_value< i32 >();
}
inline void uexp2real( const f64& r )
{
const i32u c = ~( *( (i32*)&r + 1 ) >> msb< i32 >() );
*(i32u*)&r ^= c;
*( (i32u*)&r + 1 ) ^= c | msb_value< i32 >();
}