Lunchbox
1.6.0
|
00001 00002 /* Copyright (c) 2010, Cedric Stalder <cedric.stalder@gmail.com> 00003 * 2011-2012, Stefan Eilemann <eile@eyescale.ch> 00004 * 2012, Daniel Nachbaur <danielnachbaur@gmail.com> 00005 * 00006 * This library is free software; you can redistribute it and/or modify it under 00007 * the terms of the GNU Lesser General Public License version 2.1 as published 00008 * by the Free Software Foundation. 00009 * 00010 * This library is distributed in the hope that it will be useful, but WITHOUT 00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00012 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00013 * details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this library; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 00020 #ifndef LUNCHBOX_BITOPERATION_H 00021 #define LUNCHBOX_BITOPERATION_H 00022 00023 #include <lunchbox/compiler.h> // GCC version 00024 #include <lunchbox/types.h> 00025 #include <lunchbox/uuid.h> 00026 00027 #ifdef _MSC_VER 00028 # pragma warning (push) 00029 # pragma warning (disable: 4985) // inconsistent decl of ceil 00030 # include <intrin.h> 00031 # pragma warning (pop) 00032 #elif defined __xlC__ 00033 # include <builtins.h> 00034 # include <byteswap.h> 00035 #elif defined (LB_GCC_4_3_OR_OLDER) && !defined(__clang__) && !defined( __APPLE__ ) 00036 # include <byteswap.h> 00037 # define LB_GCC_BSWAP_FUNCTION 00038 #endif 00039 00040 namespace lunchbox 00041 { 00043 template< class T > int32_t getIndexOfLastBit( T value ); 00044 00046 template< class T > void byteswap( T& value ); 00047 00048 // Implementation 00049 template<> inline int32_t getIndexOfLastBit< uint32_t >( uint32_t value ) 00050 { 00051 #ifdef __APPLE__ 00052 return ::fls( value ) - 1; 00053 #elif defined __GNUC__ 00054 return value ? (31 - __builtin_clz( value )) : -1; 00055 #elif defined _MSC_VER 00056 unsigned long i = 0; 00057 return _BitScanReverse( &i, value ) ? i : -1; 00058 #else 00059 int32_t count = -1; 00060 while( value ) 00061 { 00062 ++count; 00063 value >>= 1; 00064 } 00065 return count; 00066 #endif 00067 } 00068 00069 template<> inline int32_t getIndexOfLastBit< uint64_t >( uint64_t value ) 00070 { 00071 #ifdef __GNUC__ 00072 return value ? (63 - __builtin_clzll( value )) : -1; 00073 #elif defined _WIN64 00074 unsigned long i = 0; 00075 return _BitScanReverse64( &i, value ) ? i : -1; 00076 #else 00077 int32_t count = -1; 00078 while( value ) 00079 { 00080 ++count; 00081 value >>= 1; 00082 } 00083 return count; 00084 #endif 00085 } 00086 00087 #if defined(__linux__) && defined(_LP64) 00088 template<> inline int32_t 00089 getIndexOfLastBit< unsigned long long >( unsigned long long value ) 00090 { return getIndexOfLastBit( static_cast< uint64_t >( value )); } 00091 #endif 00092 #ifdef __APPLE__ 00093 # ifdef _LP64 00094 template<> inline 00095 int32_t getIndexOfLastBit< unsigned long >( unsigned long value ) 00096 { return getIndexOfLastBit( static_cast< uint64_t >( value )); } 00097 # else 00098 template<> inline 00099 int32_t getIndexOfLastBit< unsigned long >( unsigned long value ) 00100 { return getIndexOfLastBit( static_cast< uint32_t >( value )); } 00101 # endif 00102 #endif 00103 00104 template<> inline void byteswap( void*& value ) { /*NOP*/ } 00105 template<> inline void byteswap( bool& value ) { /*NOP*/ } 00106 template<> inline void byteswap( char& value ) { /*NOP*/ } 00107 template<> inline void byteswap( signed char& value ) { /*NOP*/ } 00108 template<> inline void byteswap( unsigned char& value ) { /*NOP*/ } 00109 00110 template<> inline void byteswap( uint32_t& value ) 00111 { 00112 #ifdef _MSC_VER 00113 value = _byteswap_ulong( value ); 00114 #elif defined __xlC__ 00115 __store4r( value, &value ); 00116 #elif defined LB_GCC_BSWAP_FUNCTION 00117 value = bswap_32( value ); 00118 #else 00119 value = __builtin_bswap32( value ); 00120 #endif 00121 } 00122 00123 template<> inline void byteswap( int32_t& value ) 00124 { byteswap( reinterpret_cast< uint32_t& >( value )); } 00125 00126 template<> inline void byteswap( float& value ) 00127 { byteswap( reinterpret_cast< uint32_t& >( value )); } 00128 00129 template<> inline void byteswap( uint16_t& value ) 00130 { 00131 #ifdef _MSC_VER 00132 value = _byteswap_ushort( value ); 00133 #elif defined __xlC__ 00134 __store2r( value, &value ); 00135 #else 00136 value = (value>>8) | (value<<8); 00137 #endif 00138 } 00139 00140 template<> inline void byteswap( int16_t& value ) 00141 { byteswap( reinterpret_cast< uint16_t& >( value )); } 00142 00143 template<> inline void byteswap( uint64_t& value ) 00144 { 00145 #ifdef _MSC_VER 00146 value = _byteswap_uint64( value ); 00147 #elif defined __xlC__ 00148 value = __bswap_constant_64( value ); 00149 #elif defined LB_GCC_BSWAP_FUNCTION 00150 value = bswap_64( value ); 00151 #else 00152 value = __builtin_bswap64( value ); 00153 #endif 00154 } 00155 00156 template<> inline void byteswap( int64_t& value ) 00157 { byteswap( reinterpret_cast< uint64_t& >( value )); } 00158 00159 template<> inline void byteswap( double& value ) 00160 { byteswap( reinterpret_cast< uint64_t& >( value )); } 00161 00162 template<> inline void byteswap( uint128_t& value ) 00163 { 00164 byteswap( value.high( )); 00165 byteswap( value.low( )); 00166 } 00167 00168 template<> inline void byteswap( UUID& value ) 00169 { byteswap< uint128_t >( value ); } 00170 00171 template< typename T > 00172 inline void byteswap( typename std::vector< T >& value ) 00173 { 00174 for( size_t i = 0; i < value.size(); ++i ) 00175 byteswap( value[i] ); 00176 } 00177 } 00178 #endif //LUNCHBOX_BITOPERATION_H