Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cBits.h
Go to the documentation of this file.
1 //
4 //
5 
6 #ifndef _INC_cBits_H
7 #define _INC_cBits_H
8 #ifndef NO_PRAGMA_ONCE
9 #pragma once
10 #endif
11 
12 #include "GrayCore.h"
13 #include "cUnitTestDecl.h"
14 
15 namespace Gray
16 {
17  UNITTEST2_PREDEF(cBits);
18 
19  typedef unsigned short BIT_SIZE_t;
20  typedef unsigned int BIT_ENUM_t;
22  {
26  BITOP_TOGGLE = -1,
27  BITOP_CLR = 0,
28  BITOP_SET = 1,
29  };
30 
31 #ifndef _1BITMASK
32 #define _1BITMASK(b) (((size_t)1)<<(b))
33 #endif
34 
35 #ifdef USE_INT64 // native support for literal HEX constant UINT 64 bit.
36 #if defined(_MSC_VER) || defined(__WATCOMC__)
37 #define CUINT64(h,l) 0x##h##l##ui64
38 #else
39 #define CUINT64(h,l) 0x##h##l##ULL
40 #endif
41 #elif defined(USE_LITTLE_ENDIAN)
42 #define CUINT64(h,l) { 0x##l, 0x##h } // for use with cUInt64
43 #else
44 #define CUINT64(h,l) { 0x##h, 0x##l } // for use with cUInt64
45 #endif
46 
47  struct GRAYCORE_LINK cBits // static
48  {
51 
52  static const BYTE k_8 = 8;
53 
54  static constexpr size_t GetSizeBytes(BIT_ENUM_t nBits) noexcept
55  {
57 #define GETSIZEBYTES(nBits) (((nBits)+7)/8) // equiv for use in const
58  return (nBits + 7) / k_8;
59  }
60 
61  template <typename TYPE>
62  static constexpr TYPE Mask1(BIT_ENUM_t nBit) noexcept
63  {
67  return ((TYPE)1) << nBit;
68  }
69  template <typename TYPE>
70  static constexpr bool IsMask1(TYPE nVal) noexcept
71  {
73  return (nVal != 0) && ((nVal & (nVal - 1)) == 0) ;
74  }
75 
76  template <typename TYPE>
77  static constexpr bool IsSet(TYPE nVal, BIT_ENUM_t nBit) noexcept
78  {
80  return (nVal & Mask1<TYPE>(nBit)) ? true : false ;
81  }
82  template <typename TYPE>
83  static constexpr bool IsClear(TYPE nVal, BIT_ENUM_t nBit) noexcept
84  {
86  return (nVal & Mask1<TYPE>(nBit)) ? false : true ;
87  }
88 
89  template <typename TYPE>
90  static constexpr TYPE SetBit(TYPE nVal, BIT_ENUM_t nBit) noexcept
91  {
92  return nVal | Mask1<TYPE>(nBit);
93  }
94  template <typename TYPE>
95  static constexpr TYPE ClearBit(TYPE nVal, BIT_ENUM_t nBit) noexcept
96  {
97  return nVal & ~Mask1<TYPE>(nBit);
98  }
99 
100  template <typename TYPE>
101  static constexpr bool HasMask(TYPE nVal, TYPE nMask) noexcept
102  {
104  return (nVal & nMask) != 0;
105  }
106 
107  template <typename TYPE>
108  static inline BIT_ENUM_t Highest1Bit(TYPE nMask) noexcept
109  {
116 
117  BIT_ENUM_t nBitsHighest = 0;
118  while (nMask != 0)
119  {
120  nMask >>= 1;
121  nBitsHighest++;
122  }
123  return nBitsHighest;
124  }
125 
126  template <typename TYPE>
127  static inline BIT_ENUM_t Count1Bits(TYPE nMask) noexcept
128  {
131 
132  BIT_ENUM_t nBits = 0; // accumulates the total bits set in nVal
133  for (; nMask; nBits++)
134  {
135  nMask &= nMask - 1; // clear the least significant bit set
136  }
137  return nBits;
138  }
139 
140  template <typename TYPE>
141  static inline TYPE Rotl(TYPE nVal, BIT_ENUM_t nBits) noexcept
142  {
145  return (nVal << nBits) | (nVal >> ((sizeof(nVal) * k_8) - nBits));
146  }
147  template <typename TYPE>
148  static inline TYPE Rotr(TYPE nVal, BIT_ENUM_t nBits) noexcept
149  {
151  return (nVal >> nBits) | (nVal << ((sizeof(nVal) * k_8) - nBits));
152  }
153 
154  template <typename TYPE>
155  static inline TYPE Reverse(TYPE nVal) noexcept
156  {
158 
159  TYPE nTemp = nVal; // nTemp will have the reversed bits of nVal.
160  for (size_t i = (sizeof(nVal) * k_8 - 1); i > 0; i--)
161  {
162  nTemp |= (nVal & 1);
163  nTemp <<= 1;
164  nVal >>= 1;
165  }
166  return nTemp | (nVal & 1);
167  }
168 
169 #if 0
170  template <typename TYPE>
171  static inline TYPE Op(TYPE nVal, BITOP_TYPE eBitOp, TYPE nValMask = 1)
172  {
173  // TODO or,and,xor/not //
174  }
175 #endif
177  };
178 
179  // Override implementations of templates.
180 
181 #if defined(__GNUC__)
182  template <>
183  inline BIT_ENUM_t cBits::Count1Bits<UINT32>(UINT32 nMask) // static
184  {
185  return ::__builtin_popcount(nMask);
186  }
187  template <>
188  inline BIT_ENUM_t cBits::Highest1Bit<UINT32>(UINT32 nMask) // static
189  {
190  // Use intrinsic function
191  if (nMask == 0)
192  return 0;
193  return 32 - __builtin_clz(nMask);
194  }
195 
196 #if defined(USE_INT64)
197  template <>
198  inline BIT_ENUM_t cBits::Count1Bits<UINT64>(UINT64 nMask) // static
199  {
200  return ::__builtin_popcountll(nMask);
201  }
202  template <>
203  inline BIT_ENUM_t cBits::Highest1Bit<UINT64>(UINT64 nMask) // static
204  {
205  // Use intrinsic function
206  if (nMask == 0)
207  return 0;
208  return 64 - __builtin_clzll(nMask);
209  }
210 #endif
211 
212 #else
213 
214  template <>
215  inline BIT_ENUM_t cBits::Count1Bits<UINT32>(UINT32 nVal) noexcept
216  {
218  nVal = (nVal & 0x55555555) + ((nVal & 0xAAAAAAAA) >> 1);
219  nVal = (nVal & 0x33333333) + ((nVal & 0xCCCCCCCC) >> 2);
220  nVal = (nVal + (nVal >> 4)) & 0x0F0F0F0F;
221  nVal = (nVal + (nVal >> 16));
222  nVal = (nVal + (nVal >> 8)) & 0x3F;
223  return (BIT_ENUM_t)nVal;
224  }
225 
226 #endif
227 
228 #ifdef _MSC_VER
229  template <>
230  inline UINT32 cBits::Rotl<UINT32>(UINT32 nVal, BIT_ENUM_t nBits) noexcept
231  {
232  return ::_rotl(nVal, (int)nBits);
233  }
234  template <>
235  inline UINT32 cBits::Rotr<UINT32>(UINT32 nVal, BIT_ENUM_t nBits) noexcept
236  {
237  return ::_rotr(nVal, (int)nBits);
238  }
239 
240 #if !defined(_MANAGED)
241  template <>
242  inline BIT_ENUM_t cBits::Highest1Bit<UINT32>(UINT32 nMask) noexcept
243  {
244  // Use intrinsic function
245  DWORD nRet;
246  if (::_BitScanReverse(&nRet, nMask))
247  return (BIT_ENUM_t)(nRet + 1);
248  return 0;
249  }
250 #endif
251 
252 #if defined(USE_INT64) && ! defined(UNDER_CE) && defined(_MSC_VER) // _INTEGRAL_MAX_BITS >= 64
253 #ifdef USE_64BIT
254  template <>
255  inline BIT_ENUM_t cBits::Highest1Bit<UINT64>(UINT64 nMask) noexcept
256  {
257  // Use intrinsic function
258  DWORD nRet;
259  if (::_BitScanReverse64(&nRet, nMask))
260  return (BIT_ENUM_t)(nRet + 1);
261  return 0;
262  }
263 #endif
264  template <>
265  inline UINT64 cBits::Rotl<UINT64>(UINT64 nVal, BIT_ENUM_t nBits) noexcept
266  {
267  return ::_rotl64(nVal, (int)nBits);
268  }
269  template <>
270  inline UINT64 cBits::Rotr<UINT64>(UINT64 nVal, BIT_ENUM_t nBits) noexcept
271  {
272  return ::_rotr64(nVal, (int)nBits);
273  }
274 #endif // USE_INT64
275 #endif // _MSC_VER
276 
277  template <>
278  inline BYTE cBits::Reverse<BYTE>(BYTE nVal) noexcept
279  {
282 #ifdef USE_INT64
283  return (BYTE)(((nVal * CUINT64(2, 02020202)) & CUINT64(0108, 84422010)) % 1023);
284 #else
285  return (BYTE)((((nVal * 0x0802LU & 0x22110LU) | (nVal * 0x8020LU & 0x88440LU)) * 0x10101LU) >> 16);
286 #endif
287  }
288  template <>
289  inline UINT32 cBits::Reverse<UINT32>(UINT32 nVal) noexcept
290  {
292  nVal = (((nVal & 0xaaaaaaaa) >> 1) | ((nVal & 0x55555555) << 1));
293  nVal = (((nVal & 0xcccccccc) >> 2) | ((nVal & 0x33333333) << 2));
294  nVal = (((nVal & 0xf0f0f0f0) >> 4) | ((nVal & 0x0f0f0f0f) << 4));
295  nVal = (((nVal & 0xff00ff00) >> 8) | ((nVal & 0x00ff00ff) << 8));
296  return((nVal >> 16) | (nVal << 16));
297  }
298 
299  template <>
300  inline ULONG cBits::Reverse<ULONG>(ULONG nVal) noexcept // static
301  {
303 #ifdef USE_LONG_AS_INT64
304  return Reverse<UINT64>(nVal);
305 #else
306  return Reverse<UINT32>(nVal);
307 #endif
308  }
309 
310  template <typename TYPE = UINT32>
312  {
315  protected:
317  public:
318  cBitmask(TYPE uVal = 0) noexcept : m_uVal(uVal)
319  {
320  }
321  void SetBit(BIT_ENUM_t nBit) noexcept
322  {
323  m_uVal = cBits::SetBit(m_uVal, nBit);
324  }
325  void ClearBit(BIT_ENUM_t nBit) noexcept
326  {
327  m_uVal = cBits::ClearBit(m_uVal, nBit);
328  }
329  bool IsSet(BIT_ENUM_t nBit) const noexcept
330  {
331  return cBits::IsSet(m_uVal, nBit);
332  }
333  operator TYPE () const noexcept
334  {
335  return m_uVal;
336  }
337  };
338 }
339 
340 #endif // _INC_cBits_H
#define GRAYCORE_LINK
Definition: GrayCore.h:47
#define TYPE
Definition: StrT.cpp:38
#define CUINT64(h, l)
Definition: cBits.h:39
#define UNITTEST2_PREDEF(x)
Definition: cUnitTestDecl.h:19
#define UNITTEST_FRIEND(n)
Define this in the class body to be unit tested. Allow the unit test to access private/protected stuf...
Definition: cUnitTestDecl.h:17
Definition: cBits.h:312
void ClearBit(BIT_ENUM_t nBit) noexcept
Definition: cBits.h:325
void SetBit(BIT_ENUM_t nBit) noexcept
Definition: cBits.h:321
cBitmask(TYPE uVal=0) noexcept
Definition: cBits.h:318
TYPE m_uVal
Definition: cBits.h:316
bool IsSet(BIT_ENUM_t nBit) const noexcept
Definition: cBits.h:329
< The main namespace for all Core functions.
Definition: GrayCore.cpp:14
BITOP_TYPE
Definition: cBits.h:22
@ BITOP_SET
OR bit operation to set bits.
Definition: cBits.h:28
@ BITOP_CLR
AND/NOT bit operation to clear bits.
Definition: cBits.h:27
@ BITOP_TOGGLE
XOR bit operation to flip bits. Also used for unknown bit state.
Definition: cBits.h:26
unsigned short BIT_SIZE_t
number of bits in some intrinsic type. <= 256 ?
Definition: cBits.h:17
unsigned int BIT_ENUM_t
Enumerate number of bits or address a single bit in some array of bits.
Definition: cBits.h:20
Definition: cBits.h:48
static BIT_ENUM_t Highest1Bit(TYPE nMask) noexcept
Definition: cBits.h:108
static constexpr bool IsClear(TYPE nVal, BIT_ENUM_t nBit) noexcept
Definition: cBits.h:83
static constexpr bool HasMask(TYPE nVal, TYPE nMask) noexcept
Definition: cBits.h:101
static BIT_ENUM_t Count1Bits(TYPE nMask) noexcept
Definition: cBits.h:127
static TYPE Rotl(TYPE nVal, BIT_ENUM_t nBits) noexcept
Definition: cBits.h:141
static constexpr TYPE Mask1(BIT_ENUM_t nBit) noexcept
Definition: cBits.h:62
static constexpr size_t GetSizeBytes(BIT_ENUM_t nBits) noexcept
Definition: cBits.h:54
static constexpr bool IsMask1(TYPE nVal) noexcept
Definition: cBits.h:70
static TYPE Reverse(TYPE nVal) noexcept
Definition: cBits.h:155
static TYPE Rotr(TYPE nVal, BIT_ENUM_t nBits) noexcept
Definition: cBits.h:148
static constexpr bool IsSet(TYPE nVal, BIT_ENUM_t nBit) noexcept
Definition: cBits.h:77
static constexpr TYPE ClearBit(TYPE nVal, BIT_ENUM_t nBit) noexcept
Definition: cBits.h:95
static constexpr TYPE SetBit(TYPE nVal, BIT_ENUM_t nBit) noexcept
Definition: cBits.h:90