commit eee87050e1b4fcd2524c8e4658a893636a60b6a2 parent 19a9bfa46900630e998bb5d8fa82a6e2a3fa2077 Author: Michael Savage <mikejsavage@gmail.com> Date: Wed Sep 14 20:36:57 +0100 Add int_conversions.h Diffstat:
int_conversions.h | | | 143 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
diff --git a/int_conversions.h b/int_conversions.h @@ -0,0 +1,143 @@ +#ifndef _INT_CONVERSIONS_H_ +#define _INT_CONVERSIONS_H_ + +#include "intrinsics.h" + +/* + * check_T( x ) asserts that x is within T's min/max values and returns ( T ) x + * clamp_T( x ) returns ( T ) x clamped to T's min/max values + */ + +#define IS_SIGNED( T ) ( ( T ) -1 < 0 ) + +template< typename T > +s64 check_s64( T x ) { + if( IS_SIGNED( T ) ) assert( x >= S64_MIN ); + assert( x <= S64_MAX ); + return ( s64 ) x; +} + +template< typename T > +s64 check_s64( T x ) { +#pragma GCC diagnostic push // GCC warns even though the optimiser removes the branch +#pragma GCC diagnostic ignored "-Wsign-compare" + if( IS_SIGNED( T ) ) assert( x >= S64_MIN ); +#pragma GCC diagnostic pop + assert( x <= S64_MAX ); + return ( s64 ) x; +} +template< typename T > +s32 check_s32( T x ) { + if( IS_SIGNED( T ) ) assert( x >= S32_MIN ); + assert( x <= S32_MAX ); + return ( s32 ) x; +} + +template< typename T > +s32 check_s32( T x ) { +#pragma GCC diagnostic push // GCC warns even though the optimiser removes the branch +#pragma GCC diagnostic ignored "-Wsign-compare" + if( IS_SIGNED( T ) ) assert( x >= S32_MIN ); +#pragma GCC diagnostic pop + assert( x <= S32_MAX ); + return ( s32 ) x; +} +template< typename T > +s16 check_s16( T x ) { + if( IS_SIGNED( T ) ) assert( x >= S16_MIN ); + assert( x <= S16_MAX ); + return ( s16 ) x; +} + +template< typename T > +s16 check_s16( T x ) { +#pragma GCC diagnostic push // GCC warns even though the optimiser removes the branch +#pragma GCC diagnostic ignored "-Wsign-compare" + if( IS_SIGNED( T ) ) assert( x >= S16_MIN ); +#pragma GCC diagnostic pop + assert( x <= S16_MAX ); + return ( s16 ) x; +} +template< typename T > +s8 check_s8( T x ) { + if( IS_SIGNED( T ) ) assert( x >= S8_MIN ); + assert( x <= S8_MAX ); + return ( s8 ) x; +} + +template< typename T > +s8 check_s8( T x ) { +#pragma GCC diagnostic push // GCC warns even though the optimiser removes the branch +#pragma GCC diagnostic ignored "-Wsign-compare" + if( IS_SIGNED( T ) ) assert( x >= S8_MIN ); +#pragma GCC diagnostic pop + assert( x <= S8_MAX ); + return ( s8 ) x; +} +template< typename T > +u64 check_u64( T x ) { + assert( x >= 0 && x <= U64_MAX ); + return ( u64 ) x; +} + +template< typename T > +u64 clamp_u64( T x ) { + if( x < 0 ) return 0; + if( x > U64_MAX ) return U64_MAX; + return ( u64 ) x; +} + +template< typename T > +u32 check_u32( T x ) { + assert( x >= 0 && x <= U32_MAX ); + return ( u32 ) x; +} + +template< typename T > +u32 clamp_u32( T x ) { + if( x < 0 ) return 0; + if( x > U32_MAX ) return U32_MAX; + return ( u32 ) x; +} + +template< typename T > +u16 check_u16( T x ) { + assert( x >= 0 && x <= U16_MAX ); + return ( u16 ) x; +} + +template< typename T > +u16 clamp_u16( T x ) { + if( x < 0 ) return 0; + if( x > U16_MAX ) return U16_MAX; + return ( u16 ) x; +} + +template< typename T > +u8 check_u8( T x ) { + assert( x >= 0 && x <= U8_MAX ); + return ( u8 ) x; +} + +template< typename T > +u8 clamp_u8( T x ) { + if( x < 0 ) return 0; + if( x > U8_MAX ) return U8_MAX; + return ( u8 ) x; +} + +/* + * size preserving signed/unsigned conversions + */ + +INLINE s8 to_signed( u8 x ) { return ( s8 ) x; } +INLINE s16 to_signed( u16 x ) { return ( s16 ) x; } +INLINE s32 to_signed( u32 x ) { return ( s32 ) x; } +INLINE s64 to_signed( u64 x ) { return ( s64 ) x; } + +INLINE u8 to_unsigned( s8 x ) { return ( u8 ) x; } +INLINE u16 to_unsigned( s16 x ) { return ( u16 ) x; } +INLINE u32 to_unsigned( s32 x ) { return ( u32 ) x; } +INLINE u64 to_unsigned( s64 x ) { return ( u64 ) x; } + +#endif // _INT_CONVERSIONS_H_