strusBase  0.17
bitOperations.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Patrick P. Frey
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 #ifndef _STRUS_BASE_BIT_OPERATIONS_HPP_INCLUDED
9 #define _STRUS_BASE_BIT_OPERATIONS_HPP_INCLUDED
10 #include "strus/base/stdint.h"
11 #include <cstdlib>
12 #include <cstring>
13 
14 namespace strus {
15 
17 {
18  static inline unsigned int bitCount( uint32_t v)
19  {
20 #ifdef __GNUC__
21  return __builtin_popcount( v);
22 #else
23  // Taken from 'http://graphics.stanford.edu/~seander/bithacks.html':
24  v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
25  v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
26  return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
27 #endif
28  }
29 
30  static inline unsigned int bitCount( uint64_t x)
31  {
32 #ifdef __GNUC__
33  return __builtin_popcountll( x);
34 #else
35  // Taken from 'https://en.wikipedia.org/wiki/Hamming_weight':
36  const uint64_t m1 = 0x5555555555555555; //binary: 0101...
37  const uint64_t m2 = 0x3333333333333333; //binary: 00110011..
38  const uint64_t m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones ...
39  const uint64_t m8 = 0x00ff00ff00ff00ff; //binary: 8 zeros, 8 ones ...
40  const uint64_t m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones ...
41  const uint64_t m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones
42  const uint64_t hff = 0xffffffffffffffff; //binary: all ones
43  const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...
44 
45  x -= (x >> 1) & m1; //put count of each 2 bits into those 2 bits
46  x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits
47  x = (x + (x >> 4)) & m4; //put count of each 8 bits into those 8 bits
48  return (x * h01)>>56; //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
49 #endif
50  }
51 
52  static inline unsigned int bitScanReverse( const uint32_t& idx)
53  {
54 #ifdef __x86_64__
55  uint32_t result;
56  if (!idx) return 0;
57  asm(" bsr %1, %0 \n" : "=r"(result) : "r"(idx) );
58  return result+1;
59 #else
60  uint32_t xx = idx;
61  if (!xx) return 0;
62  int ee = 1;
63  if ((xx & 0xFFff0000)) { ee +=16; xx >>=16; }
64  if ((xx & 0x0000Ff00)) { ee += 8; xx >>= 8; }
65  if ((xx & 0x000000F0)) { ee += 4; xx >>= 4; }
66  if ((xx & 0x0000000C)) { ee += 2; xx >>= 2; }
67  if ((xx & 0x00000002)) { ee += 1; }
68  return ee;
69 #endif
70  }
71 
72  static inline unsigned int bitScanReverse( const uint16_t& idx)
73  {
74  uint32_t xx = idx;
75  if (!xx) return 0;
76 #ifdef __x86_64__
77  uint32_t result;
78  asm(" bsr %1, %0 \n" : "=r"(result) : "r"(xx) );
79  return result+1;
80 #else
81  int ee = 1;
82  if ((xx & 0xFf00)) { ee += 8; xx >>= 8; }
83  if ((xx & 0x00F0)) { ee += 4; xx >>= 4; }
84  if ((xx & 0x000C)) { ee += 2; xx >>= 2; }
85  if ((xx & 0x0002)) { ee += 1; }
86  return ee;
87 #endif
88  }
89 
90  static inline unsigned int bitScanReverse( const uint8_t& idx)
91  {
92  uint32_t xx = idx;
93  if (!xx) return 0;
94 #ifdef __x86_64__
95  uint32_t result;
96  asm(" bsr %1, %0 \n" : "=r"(result) : "r"(xx) );
97  return result+1;
98 #else
99  int ee = 1;
100  if ((xx & 0xF0)) { ee += 4; xx >>= 4; }
101  if ((xx & 0x0C)) { ee += 2; xx >>= 2; }
102  if ((xx & 0x02)) { ee += 1; }
103  return ee;
104 #endif
105  }
106 
107  static inline unsigned int bitScanForward( const uint32_t& idx)
108  {
109 #ifdef __x86_64__
110  uint32_t result;
111  if (!idx) return 0;
112  asm(" bsf %1, %0 \n" : "=r"(result) : "r"(idx) );
113  return result+1;
114 #else
115  return ffs( idx);
116 #endif
117  }
118 
119  static inline unsigned int bitScanForward( const uint64_t& idx)
120  {
121 #ifdef __x86_64__
122  uint64_t result;
123  if (!idx) return 0;
124  asm(" bsfq %1, %0 \n" : "=r"(result) : "r"(idx) );
125  return (unsigned int)(result+1);
126 #elif __LONG_MAX__ == 0x7FffFFff || defined __OpenBSD__
127  if (!idx) return 0;
128  uint32_t result_incr = 0;
129  uint32_t idx_lo = idx;
130  if (!idx_lo)
131  {
132  result_incr += 32;
133  idx_lo = (idx >> 32);
134  }
135  uint32_t result = ffs( idx_lo);
136  return (unsigned int)(result+result_incr);
137 #else
138  return ffsl( idx);
139 #endif
140  }
141 
142  static inline uint64_t bitInsert( const uint64_t& bitset, unsigned int bi)
143  {
144  uint64_t mask = ((uint64_t)1<<bi)-1;
145  return ((bitset &~ mask) << 1) | ((uint64_t)1<<bi) | (bitset & mask);
146  }
147 };
148 }//namespace
149 #endif
static unsigned int bitCount(uint64_t x)
Definition: bitOperations.hpp:30
static unsigned int bitCount(uint32_t v)
Definition: bitOperations.hpp:18
static unsigned int bitScanReverse(const uint32_t &idx)
Definition: bitOperations.hpp:52
static unsigned int bitScanForward(const uint64_t &idx)
Definition: bitOperations.hpp:119
static unsigned int bitScanReverse(const uint8_t &idx)
Definition: bitOperations.hpp:90
Definition: bitset.hpp:31
static unsigned int bitScanForward(const uint32_t &idx)
Definition: bitOperations.hpp:107
static unsigned int bitScanReverse(const uint16_t &idx)
Definition: bitOperations.hpp:72
Definition: bitOperations.hpp:16
static uint64_t bitInsert(const uint64_t &bitset, unsigned int bi)
Definition: bitOperations.hpp:142