Lunchbox  1.4.0
bitOperation.h
00001 
00002 /* Copyright (c) 2010, Cedric Stalder <cedric.stalder@gmail.com>
00003  *               2011-2012, Stefan Eilemann <eile@eyescale.ch>
00004  *
00005  * This library is free software; you can redistribute it and/or modify it under
00006  * the terms of the GNU Lesser General Public License version 2.1 as published
00007  * by the Free Software Foundation.
00008  *  
00009  * This library is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00012  * details.
00013  * 
00014  * You should have received a copy of the GNU Lesser General Public License
00015  * along with this library; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  */
00018 
00019 #ifndef LUNCHBOX_BITOPERATION_H
00020 #define LUNCHBOX_BITOPERATION_H
00021 
00022 #include <lunchbox/types.h>
00023 #ifdef _MSC_VER
00024 #  pragma warning (push)
00025 #  pragma warning (disable: 4985) // inconsistent decl of ceil
00026 #    include <intrin.h>
00027 #  pragma warning (pop)
00028 #endif
00029 
00030 namespace lunchbox
00031 {
00033     template< class T > int32_t getIndexOfLastBit( T value );
00034 
00035     template<> inline int32_t getIndexOfLastBit< uint32_t >( uint32_t value )
00036     {
00037 #ifdef __APPLE__
00038         return ::fls( value ) - 1;
00039 #elif defined __GNUC__
00040         return value ? (31 - __builtin_clz( value )) : -1;
00041 #elif defined _MSC_VER
00042         unsigned long i = 0;
00043         return _BitScanReverse( &i, value ) ? i : -1;
00044 #else
00045         int32_t count = -1;
00046         while( value ) 
00047         {
00048           ++count;
00049           value >>= 1;
00050         }
00051         return count;
00052 #endif
00053     }
00054 
00055     template<> inline int32_t getIndexOfLastBit< uint64_t >( uint64_t value )
00056     {
00057 #ifdef  __GNUC__
00058         return value ? (63 - __builtin_clzll( value )) : -1;
00059 #elif defined _WIN64
00060         unsigned long i = 0;
00061         return _BitScanReverse64( &i, value ) ? i : -1;
00062 #else
00063         int32_t count = -1;
00064         while( value ) 
00065         {
00066           ++count;
00067           value >>= 1;
00068         }
00069         return count;
00070 #endif
00071     }
00072 
00073 #if defined(__linux__) && defined(_LP64)
00074     template<> inline int32_t 
00075     getIndexOfLastBit< unsigned long long >( unsigned long long value )
00076         { return getIndexOfLastBit( static_cast< uint64_t >( value )); }
00077 #endif
00078 #ifdef __APPLE__
00079 #  ifdef _LP64
00080     template<> inline
00081     int32_t getIndexOfLastBit< unsigned long >( unsigned long value )
00082         { return getIndexOfLastBit( static_cast< uint64_t >( value )); }
00083 #  else
00084     template<> inline
00085     int32_t getIndexOfLastBit< unsigned long >( unsigned long value )
00086         { return getIndexOfLastBit( static_cast< uint32_t >( value )); }
00087 #  endif
00088 #endif
00089 }
00090 #endif //LUNCHBOX_BITOPERATION_H