#ifndef INCLUDE_GUARD_BIT_UTILS_H
#define INCLUDE_GUARD_BIT_UTILS_H

#include <cstdint>      // uint32_t, uint64_t

/**
 * Computes the parity of a 32-bit word (0 for even bit count and 1 otherwise)
 */
int bitParity(uint32_t x);

/**
 * Counts the number of set bits (`1`s in binary) in the number `x`
 */
int bitCount(uint32_t x);

/**
 * Gets the index of the LSB (least significant bit) in a 32-bit word
 *
 * @condition `x != 0`, for `x == 0` undefined behaviour
 */
int bitScanLS(uint32_t x);

/**
 * 32-bit Parallel DEPosit (aka PDEP)
 *
 * Writes the `val` bits into the positions of the set bits in `mask`.
 *
 * Example:
 *  val:   **** **** **** 1.1.
 * mask:   1... 1... 1... 1...
 *  res:   1... .... 1... ....
 */
uint32_t bitDeposit(uint32_t val, uint32_t mask);

/**
 * Gets the next lexicographically ordered permutation of an n-bit word.
 * 
 * Let `val` be a bit-word with `n` bits set, then this procedire computes a
 * `n` bit word wich is the next element in the lexicographically ordered
 * sequence of `n` bit words. For example
 * 
 *           val -> bitNextPerm(val)
 *      00010011 -> 00010101
 *      00010101 -> 00010110
 *      00010110 -> 00011001
 *      00011001 -> 00011010
 *      00011010 -> 00011100
 *      00011100 -> 00100011
 *
 * @condition `x != 0`, for `x == 0` undefined behaviour due to `bitScanLS`
 *
 * see: https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
 */
uint32_t bitNextPerm(uint32_t val);

#endif /* BIT_UTILS_INCLUDE_GUARD_H */
