Lunchbox  1.6.0
bitOperation.h
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