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 <servus/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>
53 : int32_t getIndexOfLastBit(T value);
54 :
55 : /** Swap the byte order of the given value. @version 1.5.1 */
56 : template <class T>
57 : void byteswap(T& value);
58 : //@}
59 :
60 : /** @cond IGNORE */
61 : // Implementation
62 : template <>
63 3 : inline int32_t getIndexOfLastBit<uint32_t>(uint32_t value)
64 : {
65 : #ifdef __APPLE__
66 : return ::fls(value) - 1;
67 : #elif defined __GNUC__
68 3 : return value ? (31 - __builtin_clz(value)) : -1;
69 : #elif defined _MSC_VER
70 : unsigned long i = 0;
71 : return _BitScanReverse(&i, value) ? i : -1;
72 : #else
73 : int32_t count = -1;
74 : while (value)
75 : {
76 : ++count;
77 : value >>= 1;
78 : }
79 : return count;
80 : #endif
81 : }
82 :
83 : template <>
84 1 : inline int32_t getIndexOfLastBit<uint64_t>(uint64_t value)
85 : {
86 : #ifdef __GNUC__
87 1 : return value ? (63 - __builtin_clzll(value)) : -1;
88 : #elif defined _WIN64
89 : unsigned long i = 0;
90 : return _BitScanReverse64(&i, value) ? i : -1;
91 : #else
92 : int32_t count = -1;
93 : while (value)
94 : {
95 : ++count;
96 : value >>= 1;
97 : }
98 : return count;
99 : #endif
100 : }
101 :
102 : #if defined(__linux__) && defined(_LP64)
103 : template <>
104 1 : inline int32_t getIndexOfLastBit<unsigned long long>(unsigned long long value)
105 : {
106 1 : return getIndexOfLastBit(static_cast<uint64_t>(value));
107 : }
108 : #endif
109 : #ifdef __APPLE__
110 : #ifdef _LP64
111 : template <>
112 : inline int32_t getIndexOfLastBit<unsigned long>(unsigned long value)
113 : {
114 : return getIndexOfLastBit(static_cast<uint64_t>(value));
115 : }
116 : #else
117 : template <>
118 : inline int32_t getIndexOfLastBit<unsigned long>(unsigned long value)
119 : {
120 : return getIndexOfLastBit(static_cast<uint32_t>(value));
121 : }
122 : #endif
123 : #endif
124 :
125 : template <>
126 : inline void byteswap(void*&)
127 : { /*NOP*/
128 : }
129 : template <>
130 : inline void byteswap(bool&)
131 : { /*NOP*/
132 : }
133 : template <>
134 : inline void byteswap(char&)
135 : { /*NOP*/
136 : }
137 : template <>
138 : inline void byteswap(signed char&)
139 : { /*NOP*/
140 : }
141 : template <>
142 : inline void byteswap(unsigned char&)
143 : { /*NOP*/
144 : }
145 : template <>
146 : inline void byteswap(std::string&)
147 : { /*NOP*/
148 : }
149 :
150 : template <>
151 1 : inline void byteswap(uint32_t& value)
152 : {
153 : #ifdef _MSC_VER
154 : value = _byteswap_ulong(value);
155 : #elif defined __xlC__
156 : __store4r(value, &value);
157 : #elif defined LB_GCC_BSWAP_FUNCTION
158 : value = bswap_32(value);
159 : #else
160 1 : value = __builtin_bswap32(value);
161 : #endif
162 1 : }
163 :
164 : template <>
165 : inline void byteswap(int32_t& value)
166 : {
167 : byteswap(reinterpret_cast<uint32_t&>(value));
168 : }
169 :
170 : template <>
171 : inline void byteswap(float& value)
172 : {
173 : byteswap(reinterpret_cast<uint32_t&>(value));
174 : }
175 :
176 : template <>
177 1 : inline void byteswap(uint16_t& value)
178 : {
179 : #ifdef _MSC_VER
180 : value = _byteswap_ushort(value);
181 : #elif defined __xlC__
182 : __store2r(value, &value);
183 : #else
184 1 : value = (uint16_t)(value >> 8) | (uint16_t)(value << 8);
185 : #endif
186 1 : }
187 :
188 : template <>
189 : inline void byteswap(int16_t& value)
190 : {
191 : byteswap(reinterpret_cast<uint16_t&>(value));
192 : }
193 :
194 : #ifdef __APPLE__
195 : template <>
196 : inline void byteswap(unsigned long& value)
197 : {
198 : byteswap(reinterpret_cast<unsigned long&>(value));
199 : }
200 : #endif
201 :
202 : template <>
203 1 : inline void byteswap(uint64_t& value)
204 : {
205 : #ifdef _MSC_VER
206 : value = _byteswap_uint64(value);
207 : #elif defined __xlC__
208 : value = __bswap_constant_64(value);
209 : #elif defined LB_GCC_BSWAP_FUNCTION
210 : value = bswap_64(value);
211 : #else
212 1 : value = __builtin_bswap64(value);
213 : #endif
214 1 : }
215 :
216 : template <>
217 : inline void byteswap(int64_t& value)
218 : {
219 : byteswap(reinterpret_cast<uint64_t&>(value));
220 : }
221 :
222 : template <>
223 : inline void byteswap(double& value)
224 : {
225 : byteswap(reinterpret_cast<uint64_t&>(value));
226 : }
227 :
228 : template <>
229 : inline void byteswap(servus::uint128_t& value)
230 : {
231 : byteswap(value.high());
232 : byteswap(value.low());
233 : }
234 :
235 : template <typename T>
236 : inline void byteswap(typename std::vector<T>& value)
237 : {
238 : for (size_t i = 0; i < value.size(); ++i)
239 : byteswap(value[i]);
240 : }
241 : /** @endcond */
242 : }
243 : #endif // LUNCHBOX_BITOPERATION_H
|