first commit
This commit is contained in:
597
ebtn/bit_array.h
Normal file
597
ebtn/bit_array.h
Normal file
@@ -0,0 +1,597 @@
|
||||
#ifndef _BIT_ARRAY_H_
|
||||
#define _BIT_ARRAY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
// #define BIT_ARRAY_CONFIG_64
|
||||
|
||||
// here can change to uint64_t, if you system is 64bit.
|
||||
#ifdef BIT_ARRAY_CONFIG_64
|
||||
typedef uint64_t bit_array_t;
|
||||
#define BIT_ARRAY_BIT(n) (1ULL << (n))
|
||||
#else
|
||||
typedef uint32_t bit_array_t;
|
||||
#define BIT_ARRAY_BIT(n) (1UL << (n))
|
||||
#endif
|
||||
typedef bit_array_t bit_array_val_t;
|
||||
|
||||
#define BIT_ARRAY_BITS (sizeof(bit_array_val_t) * 8)
|
||||
|
||||
#define BIT_ARRAY_BIT_WORD(bit) ((bit) / BIT_ARRAY_BITS)
|
||||
#define BIT_ARRAY_BIT_INDEX(bit) ((bit_array_val_t)(bit) & (BIT_ARRAY_BITS - 1U))
|
||||
|
||||
#define BIT_ARRAY_MASK(bit) BIT_ARRAY_BIT(BIT_ARRAY_BIT_INDEX(bit))
|
||||
#define BIT_ARRAY_ELEM(addr, bit) ((addr)[BIT_ARRAY_BIT_WORD(bit)])
|
||||
|
||||
// word of all 1s
|
||||
#define BIT_ARRAY_WORD_MAX (~(bit_array_val_t)0)
|
||||
|
||||
#define BIT_ARRAY_SUB_MASK(nbits) ((nbits) ? BIT_ARRAY_WORD_MAX >> (BIT_ARRAY_BITS - (nbits)) : (bit_array_val_t)0)
|
||||
|
||||
// A possibly faster way to combine two words with a mask
|
||||
// #define bitmask_merge(a,b,abits) ((a & abits) | (b & ~abits))
|
||||
#define bitmask_merge(a, b, abits) (b ^ ((a ^ b) & abits))
|
||||
|
||||
/**
|
||||
* @brief This macro computes the number of bit array variables necessary to
|
||||
* represent a bitmap with @a num_bits.
|
||||
*
|
||||
* @param num_bits Number of bits.
|
||||
*/
|
||||
#define BIT_ARRAY_BITMAP_SIZE(num_bits) (1 + ((num_bits)-1) / BIT_ARRAY_BITS)
|
||||
|
||||
/**
|
||||
* @brief Define an array of bit array variables.
|
||||
*
|
||||
* This macro defines an array of bit array variables containing at least
|
||||
* @a num_bits bits.
|
||||
*
|
||||
* @note
|
||||
* If used from file scope, the bits of the array are initialized to zero;
|
||||
* if used from within a function, the bits are left uninitialized.
|
||||
*
|
||||
* @cond INTERNAL_HIDDEN
|
||||
* @note
|
||||
* This macro should be replicated in the PREDEFINED field of the documentation
|
||||
* Doxyfile.
|
||||
* @endcond
|
||||
*
|
||||
* @param name Name of array of bit array variables.
|
||||
* @param num_bits Number of bits needed.
|
||||
*/
|
||||
#define BIT_ARRAY_DEFINE(name, num_bits) bit_array_t name[BIT_ARRAY_BITMAP_SIZE(num_bits)]
|
||||
|
||||
#if 1
|
||||
// See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
|
||||
static inline bit_array_val_t _windows_popcount(bit_array_val_t w)
|
||||
{
|
||||
w = w - ((w >> 1) & (bit_array_val_t) ~(bit_array_val_t)0 / 3);
|
||||
w = (w & (bit_array_val_t) ~(bit_array_val_t)0 / 15 * 3) + ((w >> 2) & (bit_array_val_t) ~(bit_array_val_t)0 / 15 * 3);
|
||||
w = (w + (w >> 4)) & (bit_array_val_t) ~(bit_array_val_t)0 / 255 * 15;
|
||||
return (bit_array_val_t)(w * ((bit_array_val_t) ~(bit_array_val_t)0 / 255)) >> (sizeof(bit_array_val_t) - 1) * 8;
|
||||
}
|
||||
|
||||
#define POPCOUNT(x) _windows_popcount(x)
|
||||
#else
|
||||
#define POPCOUNT(x) (unsigned)__builtin_popcountll(x)
|
||||
#endif
|
||||
|
||||
#define bits_in_top_word(nbits) ((nbits) ? BIT_ARRAY_BIT_INDEX((nbits)-1) + 1 : 0)
|
||||
|
||||
static inline void _bit_array_mask_top_word(bit_array_t *target, int num_bits)
|
||||
{
|
||||
// Mask top word
|
||||
int num_of_words = BIT_ARRAY_BITMAP_SIZE(num_bits);
|
||||
int bits_active = bits_in_top_word(num_bits);
|
||||
target[num_of_words - 1] &= BIT_ARRAY_SUB_MASK(bits_active);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bit Array test a bit.
|
||||
*
|
||||
* This routine tests whether bit number @a bit of @a target is set or not.
|
||||
*
|
||||
* @param target Address of bit array variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*
|
||||
* @return true if the bit was set, false if it wasn't.
|
||||
*/
|
||||
static inline int bit_array_get(const bit_array_t *target, int bit)
|
||||
{
|
||||
bit_array_val_t val = BIT_ARRAY_ELEM(target, bit);
|
||||
|
||||
return (1 & (val >> (bit & (BIT_ARRAY_BITS - 1)))) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bit Array clear a bit.
|
||||
*
|
||||
* Bit Array clear bit number @a bit of @a target.
|
||||
*
|
||||
* @param target Address of bit array variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*/
|
||||
static inline void bit_array_clear(bit_array_t *target, int bit)
|
||||
{
|
||||
bit_array_val_t mask = BIT_ARRAY_MASK(bit);
|
||||
|
||||
BIT_ARRAY_ELEM(target, bit) &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bit Array set a bit.
|
||||
*
|
||||
* Bit Array set bit number @a bit of @a target.
|
||||
*
|
||||
* @param target Address of bit array variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*/
|
||||
static inline void bit_array_set(bit_array_t *target, int bit)
|
||||
{
|
||||
bit_array_val_t mask = BIT_ARRAY_MASK(bit);
|
||||
|
||||
BIT_ARRAY_ELEM(target, bit) |= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bit Array toggle a bit.
|
||||
*
|
||||
* Bit Array toggle bit number @a bit of @a target.
|
||||
*
|
||||
* @param target Address of bit array variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
*/
|
||||
static inline void bit_array_toggle(bit_array_t *target, int bit)
|
||||
{
|
||||
bit_array_val_t mask = BIT_ARRAY_MASK(bit);
|
||||
|
||||
BIT_ARRAY_ELEM(target, bit) ^= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Bit Array set a bit to a given value.
|
||||
*
|
||||
* Bit Array set bit number @a bit of @a target to value @a val.
|
||||
*
|
||||
* @param target Address of bit array variable or array.
|
||||
* @param bit Bit number (starting from 0).
|
||||
* @param val true for 1, false for 0.
|
||||
*/
|
||||
static inline void bit_array_assign(bit_array_t *target, int bit, int val)
|
||||
{
|
||||
bit_array_val_t mask = BIT_ARRAY_MASK(bit);
|
||||
|
||||
if (val)
|
||||
{
|
||||
BIT_ARRAY_ELEM(target, bit) |= mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
BIT_ARRAY_ELEM(target, bit) &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bit_array_clear_all(bit_array_t *target, int num_bits)
|
||||
{
|
||||
memset((void *)target, 0, BIT_ARRAY_BITMAP_SIZE(num_bits) * sizeof(bit_array_val_t));
|
||||
}
|
||||
|
||||
static inline void bit_array_set_all(bit_array_t *target, int num_bits)
|
||||
{
|
||||
memset((void *)target, 0xff, BIT_ARRAY_BITMAP_SIZE(num_bits) * sizeof(bit_array_val_t));
|
||||
_bit_array_mask_top_word(target, num_bits);
|
||||
}
|
||||
|
||||
static inline void bit_array_toggle_all(bit_array_t *target, int num_bits)
|
||||
{
|
||||
for (int i = 0; i < BIT_ARRAY_BITMAP_SIZE(num_bits); i++)
|
||||
{
|
||||
target[i] ^= BIT_ARRAY_WORD_MAX;
|
||||
}
|
||||
_bit_array_mask_top_word(target, num_bits);
|
||||
}
|
||||
|
||||
//
|
||||
// Strings and printing
|
||||
//
|
||||
|
||||
// Construct a BIT_ARRAY from a substring with given on and off characters.
|
||||
|
||||
// From string method
|
||||
static inline void bit_array_from_str(bit_array_t *bitarr, const char *str)
|
||||
{
|
||||
int i, index;
|
||||
int space = 0;
|
||||
int len = strlen(str);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
index = i - space;
|
||||
if (strchr("1", str[i]) != NULL)
|
||||
{
|
||||
bit_array_set(bitarr, index);
|
||||
}
|
||||
else if (strchr("0", str[i]) != NULL)
|
||||
{
|
||||
bit_array_clear(bitarr, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
// error.
|
||||
space++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a char array to write to. `str` must be bitarr->num_of_bits+1 in length
|
||||
// Terminates string with '\0'
|
||||
static inline char *bit_array_to_str(const bit_array_t *bitarr, int num_bits, char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_bits; i++)
|
||||
{
|
||||
str[i] = bit_array_get(bitarr, i) ? '1' : '0';
|
||||
}
|
||||
|
||||
str[num_bits] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// Takes a char array to write to. `str` must be bitarr->num_of_bits+1 in length
|
||||
// Terminates string with '\0'
|
||||
static inline char *bit_array_to_str_8(const bit_array_t *bitarr, int num_bits, char *str)
|
||||
{
|
||||
int i;
|
||||
int space = 0;
|
||||
|
||||
for (i = 0; i < num_bits; i++)
|
||||
{
|
||||
str[i + space] = bit_array_get(bitarr, i) ? '1' : '0';
|
||||
|
||||
if ((i + 1) % 8 == 0)
|
||||
{
|
||||
space++;
|
||||
str[i + space] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
str[num_bits + space] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
//
|
||||
// Get and set words (internal use only -- no bounds checking)
|
||||
//
|
||||
|
||||
static inline bit_array_val_t _bit_array_get_word(const bit_array_t *target, int num_bits, int start)
|
||||
{
|
||||
int word_index = BIT_ARRAY_BIT_WORD(start);
|
||||
int word_offset = BIT_ARRAY_BIT_INDEX(start);
|
||||
|
||||
bit_array_val_t result = target[word_index] >> word_offset;
|
||||
|
||||
int bits_taken = BIT_ARRAY_BITS - word_offset;
|
||||
|
||||
// word_offset is now the number of bits we need from the next word
|
||||
// Check the next word has at least some bits
|
||||
if (word_offset > 0 && start + bits_taken < num_bits)
|
||||
{
|
||||
result |= target[word_index + 1] << (BIT_ARRAY_BITS - word_offset);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Set 64 bits from a particular start position
|
||||
// Doesn't extend bit array
|
||||
static inline void _bit_array_set_word(bit_array_t *target, int num_bits, int start, bit_array_val_t word)
|
||||
{
|
||||
int word_index = BIT_ARRAY_BIT_WORD(start);
|
||||
int word_offset = BIT_ARRAY_BIT_INDEX(start);
|
||||
|
||||
if (word_offset == 0)
|
||||
{
|
||||
target[word_index] = word;
|
||||
}
|
||||
else
|
||||
{
|
||||
target[word_index] = (word << word_offset) | (target[word_index] & BIT_ARRAY_SUB_MASK(word_offset));
|
||||
|
||||
if (word_index + 1 < BIT_ARRAY_BITMAP_SIZE(num_bits))
|
||||
{
|
||||
target[word_index + 1] = (word >> (BIT_ARRAY_BITS - word_offset)) | (target[word_index + 1] & (BIT_ARRAY_WORD_MAX << word_offset));
|
||||
}
|
||||
}
|
||||
|
||||
// Mask top word
|
||||
_bit_array_mask_top_word(target, num_bits);
|
||||
}
|
||||
|
||||
//
|
||||
// Fill a region (internal use only)
|
||||
//
|
||||
|
||||
// FillAction is fill with 0 or 1 or toggle
|
||||
typedef enum
|
||||
{
|
||||
ZERO_REGION,
|
||||
FILL_REGION,
|
||||
SWAP_REGION
|
||||
} FillAction;
|
||||
|
||||
static inline void _bit_array_set_region(bit_array_t *target, int start, int length, FillAction action)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
int first_word = BIT_ARRAY_BIT_WORD(start);
|
||||
int last_word = BIT_ARRAY_BIT_WORD(start + length - 1);
|
||||
int foffset = BIT_ARRAY_BIT_INDEX(start);
|
||||
int loffset = BIT_ARRAY_BIT_INDEX(start + length - 1);
|
||||
|
||||
if (first_word == last_word)
|
||||
{
|
||||
bit_array_val_t mask = BIT_ARRAY_SUB_MASK(length) << foffset;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case ZERO_REGION:
|
||||
target[first_word] &= ~mask;
|
||||
break;
|
||||
case FILL_REGION:
|
||||
target[first_word] |= mask;
|
||||
break;
|
||||
case SWAP_REGION:
|
||||
target[first_word] ^= mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set first word
|
||||
switch (action)
|
||||
{
|
||||
case ZERO_REGION:
|
||||
target[first_word] &= BIT_ARRAY_SUB_MASK(foffset);
|
||||
break;
|
||||
case FILL_REGION:
|
||||
target[first_word] |= ~BIT_ARRAY_SUB_MASK(foffset);
|
||||
break;
|
||||
case SWAP_REGION:
|
||||
target[first_word] ^= ~BIT_ARRAY_SUB_MASK(foffset);
|
||||
break;
|
||||
}
|
||||
|
||||
int i;
|
||||
|
||||
// Set whole words
|
||||
switch (action)
|
||||
{
|
||||
case ZERO_REGION:
|
||||
for (i = first_word + 1; i < last_word; i++)
|
||||
target[i] = (bit_array_val_t)0;
|
||||
break;
|
||||
case FILL_REGION:
|
||||
for (i = first_word + 1; i < last_word; i++)
|
||||
target[i] = BIT_ARRAY_WORD_MAX;
|
||||
break;
|
||||
case SWAP_REGION:
|
||||
for (i = first_word + 1; i < last_word; i++)
|
||||
target[i] ^= BIT_ARRAY_WORD_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set last word
|
||||
switch (action)
|
||||
{
|
||||
case ZERO_REGION:
|
||||
target[last_word] &= ~BIT_ARRAY_SUB_MASK(loffset + 1);
|
||||
break;
|
||||
case FILL_REGION:
|
||||
target[last_word] |= BIT_ARRAY_SUB_MASK(loffset + 1);
|
||||
break;
|
||||
case SWAP_REGION:
|
||||
target[last_word] ^= BIT_ARRAY_SUB_MASK(loffset + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the number of bits set (hamming weight)
|
||||
static inline int bit_array_num_bits_set(bit_array_t *target, int num_bits)
|
||||
{
|
||||
int i;
|
||||
|
||||
int num_of_bits_set = 0;
|
||||
|
||||
for (i = 0; i < BIT_ARRAY_BITMAP_SIZE(num_bits); i++)
|
||||
{
|
||||
if (target[i] > 0)
|
||||
{
|
||||
num_of_bits_set += POPCOUNT(target[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return num_of_bits_set;
|
||||
}
|
||||
|
||||
// Get the number of bits not set (1 - hamming weight)
|
||||
static inline int bit_array_num_bits_cleared(bit_array_t *target, int num_bits)
|
||||
{
|
||||
return num_bits - bit_array_num_bits_set(target, num_bits);
|
||||
}
|
||||
|
||||
// Copy bits from one array to another
|
||||
// Note: use MACRO bit_array_copy
|
||||
// Destination and source can be the same bit_array and
|
||||
// src/dst regions can overlap
|
||||
static inline void bit_array_copy(bit_array_t *dst, int dstindx, const bit_array_t *src, int srcindx, int length, int src_num_bits, int dst_num_bits)
|
||||
{
|
||||
// Num of full words to copy
|
||||
int num_of_full_words = length / BIT_ARRAY_BITS;
|
||||
int i;
|
||||
|
||||
int bits_in_last_word = bits_in_top_word(length);
|
||||
|
||||
if (dst == src && srcindx > dstindx)
|
||||
{
|
||||
// Work left to right
|
||||
for (i = 0; i < num_of_full_words; i++)
|
||||
{
|
||||
bit_array_val_t word = _bit_array_get_word(src, src_num_bits, srcindx + i * BIT_ARRAY_BITS);
|
||||
_bit_array_set_word(dst, dst_num_bits, dstindx + i * BIT_ARRAY_BITS, word);
|
||||
}
|
||||
|
||||
if (bits_in_last_word > 0)
|
||||
{
|
||||
bit_array_val_t src_word = _bit_array_get_word(src, src_num_bits, srcindx + i * BIT_ARRAY_BITS);
|
||||
bit_array_val_t dst_word = _bit_array_get_word(dst, dst_num_bits, dstindx + i * BIT_ARRAY_BITS);
|
||||
|
||||
bit_array_val_t mask = BIT_ARRAY_SUB_MASK(bits_in_last_word);
|
||||
bit_array_val_t word = bitmask_merge(src_word, dst_word, mask);
|
||||
|
||||
_bit_array_set_word(dst, dst_num_bits, dstindx + num_of_full_words * BIT_ARRAY_BITS, word);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Work right to left
|
||||
for (i = 0; i < num_of_full_words; i++)
|
||||
{
|
||||
bit_array_val_t word = _bit_array_get_word(src, src_num_bits, srcindx + length - (i + 1) * BIT_ARRAY_BITS);
|
||||
_bit_array_set_word(dst, dst_num_bits, dstindx + length - (i + 1) * BIT_ARRAY_BITS, word);
|
||||
}
|
||||
|
||||
if (bits_in_last_word > 0)
|
||||
{
|
||||
bit_array_val_t src_word = _bit_array_get_word(src, src_num_bits, srcindx);
|
||||
bit_array_val_t dst_word = _bit_array_get_word(dst, dst_num_bits, dstindx);
|
||||
|
||||
bit_array_val_t mask = BIT_ARRAY_SUB_MASK(bits_in_last_word);
|
||||
bit_array_val_t word = bitmask_merge(src_word, dst_word, mask);
|
||||
_bit_array_set_word(dst, dst_num_bits, dstindx, word);
|
||||
}
|
||||
}
|
||||
|
||||
_bit_array_mask_top_word(dst, dst_num_bits);
|
||||
}
|
||||
|
||||
// copy all of src to dst. dst is resized to match src.
|
||||
static inline void bit_array_copy_all(bit_array_t *dst, const bit_array_t *src, int num_bits)
|
||||
{
|
||||
for (int i = 0; i < BIT_ARRAY_BITMAP_SIZE(num_bits); i++)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Logic operators
|
||||
//
|
||||
|
||||
// Destination can be the same as one or both of the sources
|
||||
static inline void bit_array_and(bit_array_t *dest, const bit_array_t *src1, const bit_array_t *src2, int num_bits)
|
||||
{
|
||||
for (int i = 0; i < BIT_ARRAY_BITMAP_SIZE(num_bits); i++)
|
||||
{
|
||||
dest[i] = src1[i] & src2[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bit_array_or(bit_array_t *dest, const bit_array_t *src1, const bit_array_t *src2, int num_bits)
|
||||
{
|
||||
for (int i = 0; i < BIT_ARRAY_BITMAP_SIZE(num_bits); i++)
|
||||
{
|
||||
dest[i] = src1[i] | src2[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bit_array_xor(bit_array_t *dest, const bit_array_t *src1, const bit_array_t *src2, int num_bits)
|
||||
{
|
||||
for (int i = 0; i < BIT_ARRAY_BITMAP_SIZE(num_bits); i++)
|
||||
{
|
||||
dest[i] = src1[i] ^ src2[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bit_array_not(bit_array_t *dest, const bit_array_t *src, int num_bits)
|
||||
{
|
||||
for (int i = 0; i < BIT_ARRAY_BITMAP_SIZE(num_bits); i++)
|
||||
{
|
||||
dest[i] = ~src[i];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Shift array left/right. If fill is zero, filled with 0, otherwise 1
|
||||
//
|
||||
|
||||
// Shift towards LSB / lower index
|
||||
static inline void bit_array_shift_right(bit_array_t *target, int num_bits, int shift_dist, int fill)
|
||||
{
|
||||
if (shift_dist >= num_bits)
|
||||
{
|
||||
fill ? bit_array_set_all(target, num_bits) : bit_array_clear_all(target, num_bits);
|
||||
return;
|
||||
}
|
||||
else if (shift_dist == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FillAction action = fill ? FILL_REGION : ZERO_REGION;
|
||||
|
||||
int cpy_length = num_bits - shift_dist;
|
||||
bit_array_copy(target, 0, target, shift_dist, cpy_length, num_bits, num_bits);
|
||||
|
||||
_bit_array_set_region(target, cpy_length, shift_dist, action);
|
||||
}
|
||||
|
||||
// Shift towards MSB / higher index
|
||||
static inline void bit_array_shift_left(bit_array_t *target, int num_bits, int shift_dist, int fill)
|
||||
{
|
||||
if (shift_dist >= num_bits)
|
||||
{
|
||||
fill ? bit_array_set_all(target, num_bits) : bit_array_clear_all(target, num_bits);
|
||||
return;
|
||||
}
|
||||
else if (shift_dist == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FillAction action = fill ? FILL_REGION : ZERO_REGION;
|
||||
|
||||
int cpy_length = num_bits - shift_dist;
|
||||
bit_array_copy(target, shift_dist, target, 0, cpy_length, num_bits, num_bits);
|
||||
_bit_array_set_region(target, 0, shift_dist, action);
|
||||
}
|
||||
|
||||
//
|
||||
// Comparisons
|
||||
//
|
||||
|
||||
// Compare two bit arrays by value stored, with index 0 being the Least
|
||||
// Significant Bit (LSB). Arrays must have the same length.
|
||||
// returns:
|
||||
// >0 iff bitarr1 > bitarr2
|
||||
// 0 iff bitarr1 == bitarr2
|
||||
// <0 iff bitarr1 < bitarr2
|
||||
static inline int bit_array_cmp(const bit_array_t *bitarr1, const bit_array_t *bitarr2, int num_bits)
|
||||
{
|
||||
return memcmp(bitarr1, bitarr2, BIT_ARRAY_BITMAP_SIZE(num_bits) * sizeof(bit_array_val_t));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _BIT_ARRAY_H_ */
|
||||
Reference in New Issue
Block a user