├── README.md ├── LICENSE.md └── bithax.h /README.md: -------------------------------------------------------------------------------- 1 | A single C header files containing functions with different bit twiddling hacks and a short explanation. 2 | I've put them together for myself as a cheatsheet and to play around with them. 3 | If you know any hacks not included, just submit a PR, or if you encounter any wrong stuff or a typo! 4 | 5 | Short hack assortment: 6 | * Number multiplication, division 7 | * Even, odd and power checks 8 | * Uppercase, lowercase 9 | * Set, clear and flip bits 10 | * Insert and extract bitfields into words 11 | * Convert LSL, MSB, trailing bits 12 | * Masked copy 13 | * Bit swap 14 | * Population count 15 | * Bit island count 16 | * Bit scans 17 | * Lexiocographic permutations 18 | * Swapping without temporaries 19 | * Size comparison: min() and max() functions without branching 20 | * Modular additions 21 | * Power rounding 22 | * Significant masking 23 | * Logbase2 of power2 calculation using deBruijin sequence 24 | * Fast inverse sqrt 25 | * Bit reversion 26 | * Masked color operations 27 | * XOR en/decryption 28 | * Branchless assignments 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | This is free and unencumbered software released into the public domain. 3 | 4 | Anyone is free to copy, modify, publish, use, compile, sell, or 5 | distribute this software, either in source code form or as a compiled 6 | binary, for any purpose, commercial or non-commercial, and by any 7 | means. 8 | 9 | In jurisdictions that recognize copyright laws, the author or authors 10 | of this software dedicate any and all copyright interest in the 11 | software to the public domain. We make this dedication for the benefit 12 | of the public at large and to the detriment of our heirs and 13 | successors. We intend this dedication to be an overt act of 14 | relinquishment in perpetuity of all present and future rights to this 15 | software under copyright law. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | For more information, please refer to 26 | -------------------------------------------------------------------------------- /bithax.h: -------------------------------------------------------------------------------- 1 | // Welcome to my little collection of bitwise hacks! 2 | // I've put this together because I also wanted to learn more bitwise hacks, so I created a cheat sheet in C (but also useable in C++). 3 | // Here you will find some common but also some of the most evil bitwise hacks, for integers and floats. 4 | // These should be translateable to any programming language, which has bitwise operations, but some of them depend on the two complement representation and IEEE 754. 5 | // Happy journey! ༼☯﹏☯༽ 6 | // 7 | // Mario "pinsrq" 8 | 9 | // Some good material on the topic: 10 | // https://www.youtube.com/watch?v=ZusiKXcz_ac 11 | // https://graphics.stanford.edu/~seander/bithacks.html 12 | // https://www.amazon.de/Hackers-Delight-Henry-S-Warren/dp/0321842685 13 | // https://www.techiedelight.com/bit-hacks-part-4-playing-letters-english-alphabet/ 14 | // https://codeforwin.org/2018/05/10-cool-bitwise-operator-hacks-and-tricks.html 15 | // https://www.youtube.com/watch?v=ZRNO-ewsNcQ 16 | 17 | #ifndef BITHAX_H 18 | #define BITHAX_H 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | // Clears all bits, settings the number to zero. 29 | // Maybe you know it from assembly - setting a to zero by using: 30 | // xorq %rax, %rax for example. 31 | // It's exactly the same: 32 | static inline void set_x_to_zero(int32_t *const x) { 33 | *x ^= *x; 34 | } 35 | 36 | // Set's the memory to zero using a self XOR. 37 | // Same as memset(buf, 0, len). 38 | static inline void xor_zero_memory(void *const buf, const size_t len) { 39 | uint8_t *i = (uint8_t*)buf; 40 | const uint8_t *const end = i + len; 41 | for (; i < end; ++i) { 42 | *i ^= *i; 43 | } 44 | } 45 | 46 | // Swaps the content of the two buffers "a" and "b" using a XOR swap. 47 | // Both buffer must have the same size "len". 48 | // Usage: 49 | // int main() { 50 | // int a = 10; 51 | // int b = 3; 52 | // mem_swap(&a, &b, sizeof(int)); 53 | // printf("%d %d", a, b); 54 | // } 55 | static inline void mem_swap(void* const a, void* const b, const size_t len) { 56 | uint8_t *ai = (uint8_t*)a; 57 | uint8_t *bi = (uint8_t*)b; 58 | const uint8_t* const end = bi + len; 59 | for (; bi < end; ++ai, ++bi) { 60 | *ai ^= *bi; 61 | *bi ^= *ai; 62 | *ai ^= *bi; 63 | } 64 | } 65 | 66 | // Returns x * 2 67 | static inline uint8_t multiply_by_2(const uint8_t x) { 68 | return x << 1; 69 | } 70 | 71 | // Returns x / 2 72 | static inline uint8_t divide_by_2(const uint8_t x) { 73 | return x >> 1; 74 | } 75 | 76 | // Returns x * 10 77 | static inline int32_t multiply_by_10(const int32_t x){ 78 | return x + x + ( x << 3 ); 79 | } 80 | 81 | // Returns x / 10 82 | static inline int32_t divide_by_10(const int32_t x){ 83 | return (int32_t)(((int64_t)x * INT64_C(0xCCCCCCCD)) >> INT64_C(35)); 84 | } 85 | 86 | // Returns true if 'x is even, else false. 87 | static inline bool is_event_or_odd(const uint8_t x) { 88 | return !(x & 1); 89 | } 90 | 91 | // Returns true if 'x' is a power of 2, else false. 92 | static inline bool is_power_of_2(const uint8_t x) { 93 | return !(x & (x - 1)); 94 | } 95 | 96 | // Returns x as uppercase letter. 97 | // If we carefully analyze, we will notice that ASCII codes of lowercase and uppercase characters differ only in their third significant bit. 98 | // For uppercase characters, the bit is 0 and for lowercase characters the bit is 1. We just have toggle that bit on or off! 99 | // ' ' (space) has the ASCII code of 00100000 and _ (underscore) has an ASCII code of 01011111 100 | // If we take OR of an uppercase characters with, the third significant bit will be set and we will get its lowercase equivalent. 101 | // If we take AND of a lowercase character with, the third significant bit will be unset and we will get its uppercase equivalent. 102 | // If we take XOR of an uppercase or lowercase characters with, only its third significant bit will be toggled. i.e. lowercase becomes uppercase and vice versa. 103 | static inline char to_uppercase(const char x) { 104 | return x & '_'; 105 | } 106 | 107 | // Returns x as lowercase letter. 108 | // If we carefully analyze, we will notice that ASCII codes of lowercase and uppercase characters differ only in their third significant bit. 109 | // For uppercase characters, the bit is 0 and for lowercase characters the bit is 1. We just have toggle that bit on or off! 110 | // ' ' (space) has the ASCII code of 00100000 and _ (underscore) has an ASCII code of 01011111 111 | // If we take OR of an uppercase characters with, the third significant bit will be set and we will get its lowercase equivalent. 112 | // If we take AND of a lowercase character with, the third significant bit will be unset and we will get its uppercase equivalent. 113 | // If we take XOR of an uppercase or lowercase characters with, only its third significant bit will be toggled. i.e. lowercase becomes uppercase and vice versa. 114 | static inline char to_lowercase(const char x) { 115 | return x | ' '; 116 | } 117 | 118 | 119 | // Returns x as uppercase letter if it was lowercase, if x was lowecase it returns x as uppercase. 120 | // If we carefully analyze, we will notice that ASCII codes of lowercase and uppercase characters differ only in their third significant bit. 121 | // For uppercase characters, the bit is 0 and for lowercase characters the bit is 1. We just have toggle that bit on or off! 122 | // ' ' (space) has the ASCII code of 00100000 and _ (underscore) has an ASCII code of 01011111 123 | // If we take OR of an uppercase characters with, the third significant bit will be set and we will get its lowercase equivalent. 124 | // If we take AND of a lowercase character with, the third significant bit will be unset and we will get its uppercase equivalent. 125 | // If we take XOR of an uppercase or lowercase characters with, only its third significant bit will be toggled. i.e. lowercase becomes uppercase and vice versa. 126 | static inline char invert_case(const char x) { 127 | return x ^ ' '; 128 | } 129 | 130 | // Sets the rightmost bit to 1. (Produces all 1's if none) 131 | // x 10100111 132 | // x & (x+1) 10101111 133 | static inline uint8_t set_rightmost_bit(const uint8_t x) { 134 | return x & (x + 1); 135 | } 136 | 137 | // Sets the rightmost bit to 0. (Produces 0 if none) 138 | // x 01011000 139 | // x & (x-1) 01010000 140 | static inline uint8_t clear_rightmost_bit(const uint8_t x) { 141 | return x & (x - 1); 142 | } 143 | 144 | // Sets the 'bit' in 'v' to 1. (The 'bit' is like an index of an array from 0-7 in an 8-bit integer.) 145 | // bit 5 // so the 5th bit 146 | // x 10100101 147 | // 1 << bit 00010000 148 | // v | (1 << bit) 10110101 149 | static inline uint8_t set_bit(const uint8_t x, const uint8_t bit) { 150 | return x | (1 << bit); 151 | } 152 | 153 | // Sets the 'bit' in 'v' to 0. (The 'bit' is like an index of an array from 0-7 in an 8-bit integer.) 154 | // bit 5 // so the 5th bit 155 | // x 10110101 156 | // 1 << bit 00010000 157 | // ~(1 << bit) 11101111 158 | // x & ~(1 << bit) 10100101 159 | static inline uint8_t clear_bit(const uint8_t x, const uint8_t bit) { 160 | return x & ~(1 << bit); 161 | } 162 | 163 | // Flips the 'bit' in 'v' - setting it to 0 if it was 1 - if it was 0 it becomes 1. (The 'bit' is like an index of an array from 0-7 in an 8-bit integer.) 164 | // bit 5 // so the 5th bit 165 | // x 10110101 166 | // 1 << bit 00010000 167 | // x ^ (1 << bit) 10100101 168 | static inline uint8_t flip_bit(const uint8_t x, const uint8_t bit) { 169 | return x ^ (1 << bit); 170 | } 171 | 172 | // Extracts the bitfield from 'v' using a 'mask' and a 'shift'. 173 | // shift 3 // shift = 3 - shift defines how many digits to the right from the latest mask digit - 3 here 174 | // x 10110101 175 | // mask 00011000 176 | // x & mask 00010000 177 | // x & mask >> shift 00000011 178 | static inline uint8_t extract_bitfield(const uint8_t x, const uint8_t mask, const uint8_t shift) { 179 | return (x & mask) >> shift; 180 | } 181 | 182 | // Convert's the trailig zero bits to a 1. 183 | // x 01101000 <- trailing zero bits 184 | // x - 1 01100111 185 | // (x - 1) | x 01101111 186 | static inline uint32_t convert_trailing_0s_to_1s(const uint32_t x) { 187 | return (x - 1) | x; 188 | } 189 | 190 | // Extracts the LSB (least significant bit) which is 1 from x. 191 | // For two complement: 192 | // -x = ~x + 1 193 | // x 01101000 194 | // -x 10011000 195 | // x & -x 00001000 196 | static inline uint32_t extract_1_lsb(const uint32_t x) { 197 | return x & -x; 198 | } 199 | 200 | // Copies bits from b into a where mask[bit] = 1 201 | // a 0101010001011110 202 | // b 1111011011011000 203 | // mask 0100010110110110 204 | // b & mask 0100010010010000 205 | // a & ~mask 0001000001001000 206 | // (b&mask) | (a&~mask) 0101010011011000 207 | static inline uint32_t masked_copy(const uint32_t a, const uint32_t b, const uint32_t mask) { 208 | return (b & mask) | (a & ~mask); 209 | } 210 | 211 | // Swaps the bit in x at index a with the bit in x at index b. 212 | // x 01001100 213 | // a 3 214 | // b 5 215 | // p 1 ^ 0 1 216 | // x ^ (p << a) 217 | // x ^ (p << b) 218 | // x 01101100 219 | static inline uint32_t swap_bits(uint32_t x, const uint32_t a, const uint32_t b) { 220 | const uint32_t p = (x >> a) ^ (x >> b) & 1; 221 | x ^= (p << a); 222 | x ^= (p << b); 223 | return x; 224 | } 225 | 226 | // Kerninghan's population count (popcnt). 227 | // Count's the number of 1 bits. 228 | // x 011001000 229 | // x = x & (x - 1) 011000000 <- zero lowest 1 bit 230 | // r = 0, reduce 011001000 231 | // r = 1, reduce 011000000 232 | // r = 2, reduce 010000000 233 | // r = 3, reduce 000000000 234 | // result 3 235 | static inline uint8_t population_count(uint32_t x) { 236 | uint8_t i; 237 | for (i = 0; x != 0; ++i) { 238 | x &= (x - 1); // zero lowest 1 bit as long as x is not zero 239 | } 240 | return i; // iteration count = population count 241 | } 242 | 243 | // Counts the amount of bit islands. 244 | // A bit island is a group of 1 bits. The groups may be seperated by 0s. 245 | // x 1111001111001110 246 | // bit islands of x 1111__1111__111 247 | // seperated by ____00____00___ 248 | // bit islands = 3 249 | // x 1111001111001110 250 | // x >> 1 0111100111100111 251 | // x ^ (x >> 1) 1000101000101001 <- mask 252 | // popcnt(x ^ (x >> 1)) 6 253 | // if x begins with 1 first island will be ignored so: 254 | // (x & 1) ensures counting 255 | // (x & 1) + 256 | // 6 >> 1 3 257 | // result 3 258 | static inline uint32_t count_bit_islands(const uint32_t x) { 259 | return (x & 1) + (population_count(x ^ (x >> 1)) >> 1); 260 | } 261 | 262 | // Bit scan forwards. 263 | // Finds the index of the lowest 1 bit. 264 | static inline int8_t bit_scan_forwards(uint32_t x) { 265 | if (x == 0) { 266 | return -1; 267 | } 268 | x &= -x; 269 | uint8_t count = 0; 270 | if (x & 0xFFFFFFFF) { 271 | count += 16; 272 | } 273 | if (x & 0xFF00FF00) { 274 | count += 8; 275 | } 276 | if (x & 0xF0F0F0F0) { 277 | count += 4; 278 | } 279 | if (x & 0xCCCCCCCC) { 280 | count += 2; 281 | } 282 | if (x & 0xAAAAAAAA) { 283 | count += 1; 284 | } 285 | return count; 286 | } 287 | 288 | // Computes the next lexicographic permutation. 289 | static inline int32_t next_lexicographic_permutation(const uint32_t x) { 290 | const uint32_t t = (x | (x - 1)) + 1; 291 | return t | ((((t & -(int32_t)t) / (x & -(int32_t)x)) >> 1) - 1); 292 | } 293 | 294 | // Inserts the 'bitfield' from 'v' using a 'mask' and a 'shift'. 295 | // shift 3 // shift = 3 - shift defines how many digits to the right from the latest mask digit - 3 here 296 | // bitfield 00000110 297 | // x 10110101 298 | // mask 00011100 299 | // x & ~mask 10100001 300 | // (x & ~mask) | (bitfield << shift) 10111001 301 | static inline uint8_t insert_bitfield(const uint8_t x, const uint8_t bitfield, const uint8_t mask, const uint8_t shift) { 302 | return (x & ~mask) | (bitfield << shift); 303 | } 304 | 305 | // Swaps both numbers without a temporary value. Note: the asterix '*' if for derefencing the pointer - it is not a bitwise operation. If you use this algorithm with normal variables, just leave it away. 306 | // x 00101010 307 | // y 10101110 308 | // x ^= y 10000100 309 | // y ^= x 00101010 310 | // x ^= y 10101110 311 | static inline void xor_swap(uint8_t *const x, uint8_t *const y) { 312 | // if x equals y, there is nothing to do and xoring each other will zero out both, so we only swap if they're not equal 313 | if (*x != *y) { 314 | *x ^= *y; 315 | *y ^= *x; 316 | *x ^= *y; 317 | } 318 | } 319 | 320 | // Returns the smaller integer of x and y but without a brach (if/else/ternary, goto etc..) 321 | // Normally min is implemented something like this: 322 | // return x < y ? x : y; 323 | // But we have a branch there so let's do it witout. (The branch free min could be used to merge arrays for example.) 324 | // If x < y, then -(x < y) => -1 => all 1's in two complement representation. 325 | // So we have y ^ (x ^ y) => x 326 | // If x >= y, then -(x < y) => 0 so y ^ 0 is y. 327 | static inline uint8_t min(const uint8_t x, const uint8_t y) { 328 | return y ^ ((x ^ y) & -(x < y)); 329 | } 330 | 331 | // Returns the larger integer of x and y but without a brach (if/else/ternary, goto etc..) 332 | // Normally max is implemented something like this: 333 | // return x > y ? x : y; 334 | // But we have a branch there so let's do it witout. (The branch free min could be used to merge arrays for example.) 335 | // Same tricks as with min() above. 336 | static inline uint8_t max(const uint8_t x, const uint8_t y) { 337 | return x ^ ((x ^ y) & -(x < y)); 338 | } 339 | 340 | // Calculates (x + y) % n assuming 0 <= x <= n && 0 <= y <= n but without a branch (if/else/ternary, goto etc..) 341 | // Normally this could be implemented like: 342 | // return (x + y) % n; 343 | // But division is expensive so or even better: 344 | // uint8_t t = x + y; 345 | // return (t < n) ? t : t - n; 346 | // Let's do it without with the same trick used in min() above: 347 | static inline uint8_t modular_addition(const uint8_t x, const uint8_t y, const uint8_t mod) { 348 | const uint8_t t = x + y; 349 | return t - (mod & - (t >= mod)); 350 | } 351 | 352 | // Returns the mask of the least-significant 1-bit in x. 353 | // x 00000101 354 | // -x 11111011 355 | // x & -x 00000001 356 | static inline uint8_t least_significat_mask(const uint8_t x) { 357 | return x & -x; 358 | } 359 | 360 | // Compute log x, where x is a power of 2. 361 | // A deBrujin sequence s of length 2y is a cyclic 0-1 sequence such that 362 | // each of the 2y 0-1 strings of length y occurs exactly once as a substring of s. 363 | // 00011101 * pow(2, 4) => 11010000 364 | // 11010000 >> 5 => 6 365 | // lookup_table[6] => 4 366 | static inline uint32_t logbase2_of_power2(const uint32_t x) { 367 | const uint64_t de_bruijin = 0x022fdd63cc95386d; 368 | static const uint32_t lookup_table[64] = { 369 | 0,1,2,53,3,7,54,27,4,38,41,8,34,55,48,28,62, 370 | 5,39,46,44,42,22,9,24,35,59,56,49,18,29,11,63, 371 | 52,6,26,37,40,33,47,61,45,43,21,23,58,17,10,51, 372 | 25,36,32,60,20,57,16,50,31,19,15,30,14,13,12 373 | }; 374 | return lookup_table[(x * de_bruijin) >> 58]; 375 | } 376 | 377 | // Rounds up the number to a power of 2. 378 | static inline uint64_t round_up_to_pow2(uint64_t x) { 379 | // x 0010000001010000 380 | --x; // 0010000001010000 - flips rightmost 1 bit to zero and fills the right with 1's. 381 | x |= x >> (1 << 0); // 0011000001101111 - shift all one bits 1 bit position to the right and OR these together. 382 | x |= x >> (1 << 1); // 0011110001111111 - shift all one bits 2 bit positions to the right and OR these together. 383 | x |= x >> (1 << 2); // 0011111111111111 - shift all one bits 4 bit positions to the right and OR these together. 384 | x |= x >> (1 << 3); // etc - shift all one bits 8 bit positions to the right and OR these together. 385 | x |= x >> (1 << 4); // etc - shift all one bits 16 bit positions to the right and OR these together. 386 | x |= x >> (1 << 5); // 0100000000000000 - shift all one bits 32 bit positions to the right and OR these together. Not is is eactly one bit less than the power of two. 387 | return ++x; // 1000000000000000 - after the increment we get the full power to since increment flips the leftmost bit and clears all others. 388 | } 389 | 390 | // Fast method to calculate the inver square root (modified quake version.) 391 | // Used an approximation constant and newton's method to calculate it via a the magic number. 392 | // See https://en.wikipedia.org/wiki/Fast_inverse_square_root 393 | static inline float fast_inversed_sqrt(const float x) { 394 | const float x2 = x * .5f; 395 | const uint32_t i = 0x5F3759DF - (*(const uint32_t *const)&x >> 1); 396 | const float y = *(const float *const)&i; 397 | return y * (1.5F - (x2 * y * y)); 398 | } 399 | 400 | // Reverses the bits of the integer. 401 | // See https://stackoverflow.com/questions/178265/what-is-the-most-hard-to-understand-piece-of-c-code-you-know 402 | static inline uint32_t reverse_bits(uint32_t x) { 403 | x = (((x & 0xAAAAAAAA) >> 1) | ((x & 0x55555555) << 1)); 404 | x = (((x & 0xCCCCCCCC) >> 2) | ((x & 0x33333333) << 2)); 405 | x = (((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4)); 406 | x = (((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8)); 407 | return ((x >> 16) | (x << 16)); 408 | } 409 | 410 | // XOR if assignment branch: 411 | // if (x == a) 412 | // x = b; 413 | // if (x == b) 414 | // x = a; 415 | static inline void if_x_equals_a(int32_t *const x, const int32_t a, const int32_t b) { 416 | *x = a ^ b ^ *x; //if (x == a) x = b 417 | } 418 | 419 | // XOR encryption !NOT CRYPTOGRAPHICALLY SECURE! 420 | // Parameter "c" must point to a char buffer of "len" length. 421 | static inline void encrypt_decrypt(char *c, const size_t len, const uint8_t key) { 422 | const char* const end = c + len; 423 | while (c < end) { 424 | *c++ ^= key; 425 | } 426 | } 427 | 428 | #ifdef __cplusplus 429 | } 430 | #endif 431 | 432 | #endif 433 | --------------------------------------------------------------------------------