Add bitset_clz
This commit is contained in:
1 parent
09e117cd57
commit
dbe8817d95
2 files changed
+68
-6
No files matched your search
+32
-6
@@ -25,12 +25,13 @@
|
|||||||
#ifndef MSTARLIB_BITSET_H
|
#ifndef MSTARLIB_BITSET_H
|
||||||
#define MSTARLIB_BITSET_H
|
#define MSTARLIB_BITSET_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include "m-core.h"
|
#include "m-core.h"
|
||||||
|
|
||||||
/********************************** INTERNAL ************************************/
|
/********************************** INTERNAL ************************************/
|
||||||
|
|
||||||
// Define a limb of a bitset
|
// Define a limb of a bitset
|
||||||
typedef unsigned long bitset_limb;
|
typedef uint64_t bitset_limb;
|
||||||
#define BITSET_LIMB_BIT (sizeof(bitset_limb) * CHAR_BIT)
|
#define BITSET_LIMB_BIT (sizeof(bitset_limb) * CHAR_BIT)
|
||||||
|
|
||||||
typedef struct bitset_s {
|
typedef struct bitset_s {
|
||||||
@@ -633,22 +634,47 @@ bitset_not(bitset_t dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
bitset_hash(const bitset_t dest)
|
bitset_hash(const bitset_t set)
|
||||||
{
|
{
|
||||||
BITSETI_CONTRACT(dest);
|
BITSETI_CONTRACT(set);
|
||||||
size_t s = dest->size;
|
size_t s = set->size;
|
||||||
size_t n = s / BITSET_LIMB_BIT;
|
size_t n = s / BITSET_LIMB_BIT;
|
||||||
size_t m = s % BITSET_LIMB_BIT;
|
size_t m = s % BITSET_LIMB_BIT;
|
||||||
M_HASH_DECL(hash);
|
M_HASH_DECL(hash);
|
||||||
for(size_t i = 0 ; i < n; i++)
|
for(size_t i = 0 ; i < n; i++)
|
||||||
M_HASH_UP(hash, dest->ptr[i]);
|
M_HASH_UP(hash, set->ptr[i]);
|
||||||
if (m) {
|
if (m) {
|
||||||
size_t mask = (((bitset_limb)1) << m) - 1;
|
size_t mask = (((bitset_limb)1) << m) - 1;
|
||||||
M_HASH_UP(hash, (dest->ptr[n] & mask));
|
M_HASH_UP(hash, (set->ptr[n] & mask));
|
||||||
}
|
}
|
||||||
return M_HASH_FINAL (hash);
|
return M_HASH_FINAL (hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
bitset_clz(const bitset_t set)
|
||||||
|
{
|
||||||
|
BITSETI_CONTRACT(set);
|
||||||
|
size_t s = set->size;
|
||||||
|
assert (s > 0);
|
||||||
|
size_t n = (s -1) / BITSET_LIMB_BIT;
|
||||||
|
size_t m = s % BITSET_LIMB_BIT;
|
||||||
|
bitset_limb limb = set->ptr[n];
|
||||||
|
if (m) {
|
||||||
|
size_t mask = (((bitset_limb)1) << m) - 1;
|
||||||
|
limb &= mask;
|
||||||
|
} else {
|
||||||
|
m = BITSET_LIMB_BIT;
|
||||||
|
}
|
||||||
|
s = 0;
|
||||||
|
while (limb == 0 && n > 0) {
|
||||||
|
s += m;
|
||||||
|
limb = set->ptr[--n];
|
||||||
|
m = BITSET_LIMB_BIT;
|
||||||
|
}
|
||||||
|
s += m_core_clz64(limb) - (BITSET_LIMB_BIT - m);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
#define BITSET_OPLIST \
|
#define BITSET_OPLIST \
|
||||||
(INIT(bitset_init) \
|
(INIT(bitset_init) \
|
||||||
,INIT_SET(bitset_init_set) \
|
,INIT_SET(bitset_init_set) \
|
||||||
|
|||||||
@@ -313,6 +313,41 @@ static void test_let(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_clz(void)
|
||||||
|
{
|
||||||
|
M_LET(s1, bitset_t) {
|
||||||
|
bitset_push_back(s1, false);
|
||||||
|
assert (bitset_clz(s1) == 1);
|
||||||
|
bitset_push_back(s1, false);
|
||||||
|
assert (bitset_clz(s1) == 2);
|
||||||
|
bitset_set_at(s1, 0, true);
|
||||||
|
assert (bitset_clz(s1) == 1);
|
||||||
|
bitset_set_at(s1, 1, true);
|
||||||
|
assert (bitset_clz(s1) == 0);
|
||||||
|
for(int i = 0; i < 62; i++)
|
||||||
|
bitset_push_back(s1, false);
|
||||||
|
assert (bitset_clz(s1) == 62);
|
||||||
|
bitset_set_at(s1, 63, true);
|
||||||
|
assert (bitset_clz(s1) == 0);
|
||||||
|
bitset_push_back(s1, false);
|
||||||
|
assert (bitset_clz(s1) == 1);
|
||||||
|
bitset_set_at(s1, 64, true);
|
||||||
|
assert (bitset_clz(s1) == 0);
|
||||||
|
for(size_t i = 0; i < 620; i++) {
|
||||||
|
bitset_push_back(s1, false);
|
||||||
|
assert (bitset_clz(s1) == i+1);
|
||||||
|
}
|
||||||
|
bitset_set_at(s1, 64+620, true);
|
||||||
|
assert (bitset_clz(s1) == 0);
|
||||||
|
for(size_t i = 1; i < 64+1+620; i++) {
|
||||||
|
bitset_set_at(s1, i, false);
|
||||||
|
}
|
||||||
|
assert (bitset_clz(s1) == 64+620);
|
||||||
|
bitset_set_at(s1, 0, false);
|
||||||
|
assert (bitset_clz(s1) == 64+620+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
test1();
|
test1();
|
||||||
@@ -320,5 +355,6 @@ int main(void)
|
|||||||
test_str();
|
test_str();
|
||||||
test_logic();
|
test_logic();
|
||||||
test_let();
|
test_let();
|
||||||
|
test_clz();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user