Line data Source code
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/uint128_t.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 : {
42 : /**
43 : * @defgroup bitops Bit Operations.
44 : *
45 : * Example: @include tests/bitOperation.cpp
46 : */
47 : //@{
48 : /**
49 : * @return the position of the last (most significant) set bit, or -1.
50 : * @version 1.8
51 : */
52 : template< class T > int32_t getIndexOfLastBit( T value );
53 :
54 : /** Swap the byte order of the given value. @version 1.5.1 */
55 : template< class T > void byteswap( T& value );
56 : //@}
57 :
58 : /** @cond IGNORE */
59 : // Implementation
60 3 : template<> inline int32_t getIndexOfLastBit< uint32_t >( uint32_t value )
61 : {
62 : #ifdef __APPLE__
63 : return ::fls( value ) - 1;
64 : #elif defined __GNUC__
65 3 : return value ? (31 - __builtin_clz( value )) : -1;
66 : #elif defined _MSC_VER
67 : unsigned long i = 0;
68 : return _BitScanReverse( &i, value ) ? i : -1;
69 : #else
70 : int32_t count = -1;
71 : while( value )
72 : {
73 : ++count;
74 : value >>= 1;
75 : }
76 : return count;
77 : #endif
78 : }
79 :
80 159521360 : template<> inline int32_t getIndexOfLastBit< uint64_t >( uint64_t value )
81 : {
82 : #ifdef __GNUC__
83 159521360 : return value ? (63 - __builtin_clzll( value )) : -1;
84 : #elif defined _WIN64
85 : unsigned long i = 0;
86 : return _BitScanReverse64( &i, value ) ? i : -1;
87 : #else
88 : int32_t count = -1;
89 : while( value )
90 : {
91 : ++count;
92 : value >>= 1;
93 : }
94 : return count;
95 : #endif
96 : }
97 :
98 : #if defined(__linux__) && defined(_LP64)
99 : template<> inline int32_t
100 1 : getIndexOfLastBit< unsigned long long >( unsigned long long value )
101 1 : { return getIndexOfLastBit( static_cast< uint64_t >( value )); }
102 : #endif
103 : #ifdef __APPLE__
104 : # ifdef _LP64
105 : template<> inline
106 : int32_t getIndexOfLastBit< unsigned long >( unsigned long value )
107 : { return getIndexOfLastBit( static_cast< uint64_t >( value )); }
108 : # else
109 : template<> inline
110 : int32_t getIndexOfLastBit< unsigned long >( unsigned long value )
111 : { return getIndexOfLastBit( static_cast< uint32_t >( value )); }
112 : # endif
113 : #endif
114 :
115 : template<> inline void byteswap( void*& ) { /*NOP*/ }
116 : template<> inline void byteswap( bool&) { /*NOP*/ }
117 : template<> inline void byteswap( char& ) { /*NOP*/ }
118 : template<> inline void byteswap( signed char& ) { /*NOP*/ }
119 : template<> inline void byteswap( unsigned char& ) { /*NOP*/ }
120 : template<> inline void byteswap( std::string& ) { /*NOP*/ }
121 :
122 1 : template<> inline void byteswap( uint32_t& value )
123 : {
124 : #ifdef _MSC_VER
125 : value = _byteswap_ulong( value );
126 : #elif defined __xlC__
127 : __store4r( value, &value );
128 : #elif defined LB_GCC_BSWAP_FUNCTION
129 : value = bswap_32( value );
130 : #else
131 1 : value = __builtin_bswap32( value );
132 : #endif
133 1 : }
134 :
135 : template<> inline void byteswap( int32_t& value )
136 : { byteswap( reinterpret_cast< uint32_t& >( value )); }
137 :
138 : template<> inline void byteswap( float& value )
139 : { byteswap( reinterpret_cast< uint32_t& >( value )); }
140 :
141 1 : template<> inline void byteswap( uint16_t& value )
142 : {
143 : #ifdef _MSC_VER
144 : value = _byteswap_ushort( value );
145 : #elif defined __xlC__
146 : __store2r( value, &value );
147 : #else
148 1 : value = (uint16_t)(value>>8) | (uint16_t)(value<<8);
149 : #endif
150 1 : }
151 :
152 : template<> inline void byteswap( int16_t& value )
153 : { byteswap( reinterpret_cast< uint16_t& >( value )); }
154 :
155 : #ifdef __APPLE__
156 : template<> inline void byteswap( unsigned long& value )
157 : { byteswap( reinterpret_cast< unsigned long& >( value )); }
158 : #endif
159 :
160 1 : template<> inline void byteswap( uint64_t& value )
161 : {
162 : #ifdef _MSC_VER
163 : value = _byteswap_uint64( value );
164 : #elif defined __xlC__
165 : value = __bswap_constant_64( value );
166 : #elif defined LB_GCC_BSWAP_FUNCTION
167 : value = bswap_64( value );
168 : #else
169 1 : value = __builtin_bswap64( value );
170 : #endif
171 1 : }
172 :
173 : template<> inline void byteswap( int64_t& value )
174 : { byteswap( reinterpret_cast< uint64_t& >( value )); }
175 :
176 : template<> inline void byteswap( double& value )
177 : { byteswap( reinterpret_cast< uint64_t& >( value )); }
178 :
179 : template<> inline void byteswap( uint128_t& value )
180 : {
181 : byteswap( value.high( ));
182 : byteswap( value.low( ));
183 : }
184 :
185 : template< typename T >
186 : inline void byteswap( typename std::vector< T >& value )
187 : {
188 : for( size_t i = 0; i < value.size(); ++i )
189 : byteswap( value[i] );
190 : }
191 : /** @endcond */
192 :
193 : }
194 : #endif //LUNCHBOX_BITOPERATION_H
|