-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
279 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
// Copyright (c) 2023 Xu Shaohua <[email protected]>. All rights reserved. | ||
// Use of this source is governed by GNU General Public License | ||
// that can be found in the LICENSE file. | ||
|
||
#ifndef CII_BIT_H | ||
#define CII_BIT_H | ||
|
||
#include <stdbool.h> | ||
#include <stddef.h> | ||
|
||
typedef struct bit_s bit_t; | ||
|
||
/** | ||
* Create a bit vector with fixed |length| and sets all the bits to zero. | ||
* | ||
* @param length | ||
* @return | ||
*/ | ||
extern bit_t* bit_new(size_t length); | ||
|
||
/** | ||
* Get fixed length of a bit vector. | ||
* | ||
* @param set | ||
* @return | ||
*/ | ||
extern size_t bit_length(bit_t* set); | ||
|
||
/** | ||
* Returns number of bits with one values in a bit vector. | ||
* | ||
* @param set | ||
* @return | ||
*/ | ||
extern size_t bit_count_ones(bit_t* set); | ||
|
||
/** | ||
* Returns number of bits with zero values in a bit vector. | ||
* @param set | ||
* @return | ||
*/ | ||
extern size_t bit_count_zeros(bit_t* set); | ||
|
||
/** | ||
* Deallocate and clear a bit vector. | ||
* | ||
* @param set | ||
*/ | ||
extern void bit_free(bit_t** set); | ||
|
||
/** | ||
* Check bit at |index| is set or not. | ||
* | ||
* @param set | ||
* @param index | ||
* @return | ||
*/ | ||
extern bool bit_get(bit_t* set, size_t index); | ||
|
||
/** | ||
* update bit value at |index| and returns old value. | ||
* | ||
* @param set | ||
* @param index | ||
* @param value | ||
* @return | ||
*/ | ||
extern bool bit_put(bit_t* set, size_t index, bool value); | ||
|
||
/** | ||
* Clear bits in range [start, end) in a bit vector. | ||
* | ||
* @param set | ||
* @param start | ||
* @param end | ||
*/ | ||
extern void bit_clear(bit_t* set, size_t start, size_t end); | ||
|
||
/** | ||
* Set bits in range [start, end) in a bit vector. | ||
* | ||
* @param set | ||
* @param start | ||
* @param end | ||
*/ | ||
extern void bit_set(bit_t* set, size_t start, size_t end); | ||
|
||
/** | ||
* Toggle bits in range [start, end) in a bit vector. | ||
* | ||
* @param set | ||
* @param start | ||
* @param end | ||
*/ | ||
extern void bit_not(bit_t* set, size_t start, size_t end); | ||
|
||
/** | ||
* Check whether bit vector s is less than t. | ||
* | ||
* @param s | ||
* @param t | ||
* @return | ||
*/ | ||
extern bool bit_less(bit_t* s, bit_t* t); | ||
|
||
/** | ||
* Check whether bit vector s equals to t. | ||
* | ||
* @param s | ||
* @param t | ||
* @return | ||
*/ | ||
extern bool bit_equal(bit_t* s, bit_t* t); | ||
|
||
/** | ||
* Check whether bit vector s is less than or equal to t. | ||
* | ||
* @param s | ||
* @param t | ||
* @return | ||
*/ | ||
extern bool bit_less_equal(bit_t* s, bit_t* t); | ||
|
||
/** | ||
* Calls |apply| for each bit in set. | ||
* @param s | ||
* @param apply | ||
* @param user_data | ||
*/ | ||
extern void bit_map(bit_t* s, | ||
void(*apply)(size_t index, bool is_set, void* user_data), | ||
void* user_data); | ||
|
||
/** | ||
* Returns the union of s and t, denoted s + t. | ||
* @param s | ||
* @param t | ||
* @return | ||
*/ | ||
extern bit_t* bit_union(bit_t* s, bit_t* t); | ||
|
||
/** | ||
* Returns the intersection of s and t, denoted s * t. | ||
* @param s | ||
* @param t | ||
* @return | ||
*/ | ||
extern bit_t* bit_inter(bit_t* s, bit_t* t); | ||
|
||
/** | ||
* Returns the difference of s and t, denoted s - t. | ||
* @param s | ||
* @param t | ||
* @return | ||
*/ | ||
extern bit_t* bit_minus(bit_t* s, bit_t* t); | ||
|
||
/** | ||
* Returns the symmetric difference of s and t, denoted s / t. | ||
* @param s | ||
* @param t | ||
* @return | ||
*/ | ||
extern bit_t* bit_diff(bit_t* s, bit_t* t); | ||
|
||
#endif // CII_BIT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Copyright (c) 2023 Xu Shaohua <[email protected]>. All rights reserved. | ||
// Use of this source is governed by GNU General Public License | ||
// that can be found in the LICENSE file. | ||
|
||
#include "cii/bit.h" | ||
|
||
#include <stdarg.h> | ||
#include <string.h> | ||
#include <stdint.h> | ||
|
||
#include "cii/assert.h" | ||
#include "cii/mem.h" | ||
|
||
struct bit_s { | ||
// The |length| field gives the number of bits in the vector. | ||
size_t length; | ||
|
||
// |bytes| points to at least [length / 8] bytes. | ||
// The bits are accessed by indexing bytes. | ||
uint8_t* bytes; | ||
size_t* words; | ||
}; | ||
|
||
// Bytes per word. | ||
static size_t bpw() { | ||
return 8 * sizeof(size_t); | ||
} | ||
|
||
// Computes the number of words needed for a bit vector of length bits. | ||
static size_t num_words(size_t length) { | ||
return ((length + bpw() - 1) & (~(bpw() - 1))) / bpw(); | ||
} | ||
|
||
bit_t* bit_new(size_t length) { | ||
bit_t* set; | ||
NEW(set); | ||
if (length > 0) { | ||
set->words = CALLOC(num_words(length), sizeof(size_t)); | ||
} else { | ||
set->words = NULL; | ||
} | ||
set->length = length; | ||
set->bytes = (uint8_t*) set->words; | ||
|
||
return set; | ||
} | ||
|
||
void bit_free(bit_t** set) { | ||
assert(set != NULL && *set != NULL); | ||
FREE((*set)->words); | ||
FREE(*set); | ||
} | ||
|
||
size_t bit_length(bit_t* set) { | ||
assert(set != NULL); | ||
return set->length; | ||
} | ||
|
||
size_t bit_count_ones(bit_t* set) { | ||
assert(set != NULL); | ||
size_t length = 0; | ||
const uint8_t kCount[] = { | ||
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 | ||
}; | ||
const size_t n_words = num_words(set->length); | ||
for (size_t i = 0; i < n_words; ++i) { | ||
uint8_t c = set->bytes[i]; | ||
length += kCount[c & 0x0F] + kCount[c >> 4]; | ||
} | ||
|
||
return length; | ||
} | ||
|
||
size_t bit_count_zeros(bit_t* set) { | ||
assert(set != NULL); | ||
return bit_length(set) - bit_count_ones(set); | ||
} | ||
|
||
static bool bit_get_bit(bit_t* set, size_t index) { | ||
return (set->bytes[ index / 8] >> (index % 8)) & 1; | ||
} | ||
|
||
bool bit_get(bit_t* set, size_t index) { | ||
assert(set != NULL); | ||
assert(index < set->length); | ||
return bit_get_bit(set, index); | ||
} | ||
|
||
bool bit_put(bit_t* set, size_t index, bool value) { | ||
assert(set != NULL); | ||
assert(index < set->length); | ||
const bool prev = bit_get_bit(set, index); | ||
if (value) { | ||
set->bytes[index / 8] |= 1 << (index % 8); | ||
} else { | ||
set->bytes[index / 8] &= ~(1 << (index % 8)); | ||
} | ||
return prev; | ||
} | ||
|
||
void bit_clear(bit_t* set, size_t start, size_t end) { | ||
|
||
} | ||
|
||
void bit_set(bit_t* set, size_t start, size_t end) { | ||
|
||
} | ||
|
||
void bit_not(bit_t* set, size_t start, size_t end) { | ||
|
||
} |