-
Notifications
You must be signed in to change notification settings - Fork 7
/
bf_ops.c
107 lines (89 loc) · 2.43 KB
/
bf_ops.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <memory.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "bf_types.h"
#include "bf_hash.h"
//Bloom operations
bool _bf_test_bit(bf_cell_t *bv, bf_m_t n) {
return (bv[n / BF_BITS_PER_CELL] & ((bf_cell_t)1 << ((BF_BITS_PER_CELL - 1) - (n % BF_BITS_PER_CELL)))) != 0;
}
void _bf_jump_bit(bf_cell_t *bv, bf_m_t n) {
bv[n / BF_BITS_PER_CELL] |= ((bf_cell_t)1 << ((BF_BITS_PER_CELL - 1) - (n % BF_BITS_PER_CELL )) );
}
bf_m_t _bf_make_m_power_of_two(bf_m_t m, bf_m_t *new_m, bf_hp_t *power) {
bf_hp_t hp = 1;
bf_m_t aligned_m = 2;
do {
hp++;
aligned_m *= 2;
} while (aligned_m < m && hp < ( sizeof(m) * 8));
if (new_m) *new_m = aligned_m;
if (power) *power = hp;
return aligned_m;
}
void bf_add(bloom_filter_t *bf, const char element[]) {
bf_k_t k = bf->k;
bf_m_t Ki[k];
bf_hashes(element, Ki, k, bf->hash_part);
bf_k_t i;
for (i=0; i<k; i++)
_bf_jump_bit(bf->space, Ki[i]);
}
bool bf_check(bloom_filter_t *bf, const char element[]) {
bf_k_t k = bf->k;
bf_m_t Ki[k];
bf_hashes(element, Ki, k, bf->hash_part);
bf_k_t i;
for (i=0; i<k; i++)
if (!_bf_test_bit(bf->space, Ki[i]))
return false;
return true;
}
bool bf_check_then_add(bloom_filter_t *bf, const char element[]) {
bf_k_t k = bf->k;
bf_m_t Ki[k];
bf_hashes(element, Ki, k, bf->hash_part);
bool present = true;
bf_k_t i;
for (i=0; i<k; i++)
if (!_bf_test_bit(bf->space, Ki[i])) {
present = false;
break;
}
if (!present)
for (i=0; i<k; i++)
_bf_jump_bit(bf->space, Ki[i]);
return present;
}
bloom_filter_t *bf_create(bf_m_t m, bf_k_t k) {
//TODO: check m and k
if (!m || !k)
return NULL;
bf_hp_t hp;
bf_m_t aligned_m;
_bf_make_m_power_of_two(m, &aligned_m, &hp);
if (hp * k > BF_HASH_MAX_WIDTH)
return NULL;
size_t cells = (aligned_m + ( BF_BITS_PER_CELL - 1)) / BF_BITS_PER_CELL ;
bf_cell_t *space = calloc(cells, sizeof(bf_cell_t));
if (!space)
return NULL;
bloom_filter_t *bf = malloc(sizeof(bloom_filter_t));
if (!bf) {
free(space);
return NULL;
}
bf->m = aligned_m;
bf->k = k;
bf->hash_part = hp;
bf->space = space;
return bf;
}
void bf_destroy(bloom_filter_t *bf) {
if (bf) {
if (bf->space)
free(bf->space);
free(bf);
}
}