Lunchbox  1.8.0
bitOperation.h
1 
2 /* Copyright (c) 2010, Cedric Stalder <cedric.stalder@gmail.com>
3  * 2011-2012, Stefan Eilemann <eile@eyescale.ch>
4  * 2012, Daniel Nachbaur <danielnachbaur@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License version 2.1 as published
8  * by the Free Software Foundation.
9  *
10  * This library is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifndef LUNCHBOX_BITOPERATION_H
21 #define LUNCHBOX_BITOPERATION_H
22 
23 #include <lunchbox/compiler.h> // GCC version
24 #include <lunchbox/types.h>
25 #include <lunchbox/uuid.h>
26 
27 #ifdef _MSC_VER
28 # pragma warning (push)
29 # pragma warning (disable: 4985) // inconsistent decl of ceil
30 # include <intrin.h>
31 # pragma warning (pop)
32 #elif defined __xlC__
33 # include <builtins.h>
34 # include <byteswap.h>
35 #elif defined (LB_GCC_4_3_OR_OLDER) && !defined(__clang__) && !defined( __APPLE__ )
36 # include <byteswap.h>
37 # define LB_GCC_BSWAP_FUNCTION
38 #endif
39 
40 namespace lunchbox
41 {
43  template< class T > int32_t getIndexOfLastBit( T value );
44 
46  template< class T > void byteswap( T& value );
47 
48  // Implementation
49  template<> inline int32_t getIndexOfLastBit< uint32_t >( uint32_t value )
50  {
51 #ifdef __APPLE__
52  return ::fls( value ) - 1;
53 #elif defined __GNUC__
54  return value ? (31 - __builtin_clz( value )) : -1;
55 #elif defined _MSC_VER
56  unsigned long i = 0;
57  return _BitScanReverse( &i, value ) ? i : -1;
58 #else
59  int32_t count = -1;
60  while( value )
61  {
62  ++count;
63  value >>= 1;
64  }
65  return count;
66 #endif
67  }
68 
69  template<> inline int32_t getIndexOfLastBit< uint64_t >( uint64_t value )
70  {
71 #ifdef __GNUC__
72  return value ? (63 - __builtin_clzll( value )) : -1;
73 #elif defined _WIN64
74  unsigned long i = 0;
75  return _BitScanReverse64( &i, value ) ? i : -1;
76 #else
77  int32_t count = -1;
78  while( value )
79  {
80  ++count;
81  value >>= 1;
82  }
83  return count;
84 #endif
85  }
86 
87 #if defined(__linux__) && defined(_LP64)
88  template<> inline int32_t
89  getIndexOfLastBit< unsigned long long >( unsigned long long value )
90  { return getIndexOfLastBit( static_cast< uint64_t >( value )); }
91 #endif
92 #ifdef __APPLE__
93 # ifdef _LP64
94  template<> inline
95  int32_t getIndexOfLastBit< unsigned long >( unsigned long value )
96  { return getIndexOfLastBit( static_cast< uint64_t >( value )); }
97 # else
98  template<> inline
99  int32_t getIndexOfLastBit< unsigned long >( unsigned long value )
100  { return getIndexOfLastBit( static_cast< uint32_t >( value )); }
101 # endif
102 #endif
103 
104  template<> inline void byteswap( void*& ) { /*NOP*/ }
105  template<> inline void byteswap( bool&) { /*NOP*/ }
106  template<> inline void byteswap( char& ) { /*NOP*/ }
107  template<> inline void byteswap( signed char& ) { /*NOP*/ }
108  template<> inline void byteswap( unsigned char& ) { /*NOP*/ }
109 
110  template<> inline void byteswap( uint32_t& value )
111  {
112 #ifdef _MSC_VER
113  value = _byteswap_ulong( value );
114 #elif defined __xlC__
115  __store4r( value, &value );
116 #elif defined LB_GCC_BSWAP_FUNCTION
117  value = bswap_32( value );
118 #else
119  value = __builtin_bswap32( value );
120 #endif
121  }
122 
123  template<> inline void byteswap( int32_t& value )
124  { byteswap( reinterpret_cast< uint32_t& >( value )); }
125 
126  template<> inline void byteswap( float& value )
127  { byteswap( reinterpret_cast< uint32_t& >( value )); }
128 
129  template<> inline void byteswap( uint16_t& value )
130  {
131 #ifdef _MSC_VER
132  value = _byteswap_ushort( value );
133 #elif defined __xlC__
134  __store2r( value, &value );
135 #else
136  value = (value>>8) | (value<<8);
137 #endif
138  }
139 
140  template<> inline void byteswap( int16_t& value )
141  { byteswap( reinterpret_cast< uint16_t& >( value )); }
142 
143  template<> inline void byteswap( uint64_t& value )
144  {
145 #ifdef _MSC_VER
146  value = _byteswap_uint64( value );
147 #elif defined __xlC__
148  value = __bswap_constant_64( value );
149 #elif defined LB_GCC_BSWAP_FUNCTION
150  value = bswap_64( value );
151 #else
152  value = __builtin_bswap64( value );
153 #endif
154  }
155 
156  template<> inline void byteswap( int64_t& value )
157  { byteswap( reinterpret_cast< uint64_t& >( value )); }
158 
159  template<> inline void byteswap( double& value )
160  { byteswap( reinterpret_cast< uint64_t& >( value )); }
161 
162  template<> inline void byteswap( uint128_t& value )
163  {
164  byteswap( value.high( ));
165  byteswap( value.low( ));
166  }
167 
168  template<> inline void byteswap( UUID& value )
169  { byteswap< uint128_t >( value ); }
170 
171  template< typename T >
172  inline void byteswap( typename std::vector< T >& value )
173  {
174  for( size_t i = 0; i < value.size(); ++i )
175  byteswap( value[i] );
176  }
177 }
178 #endif //LUNCHBOX_BITOPERATION_H