bf: add a module implementing operations with bit arrays (#1049)
parent
26af513e1b
commit
c4fcfcec88
|
@ -0,0 +1,179 @@
|
|||
module bf
|
||||
|
||||
struct BitField {
|
||||
mut:
|
||||
size int
|
||||
//field *u32
|
||||
field []u32
|
||||
}
|
||||
|
||||
/* helper functions */
|
||||
const (
|
||||
SLOT_SIZE = 32
|
||||
)
|
||||
|
||||
fn bitmask(bitnr int) u32 {
|
||||
return u32(1 << (bitnr % SLOT_SIZE))
|
||||
}
|
||||
|
||||
fn bitslot(size int) int {
|
||||
return size / SLOT_SIZE
|
||||
}
|
||||
|
||||
fn bitget(instance BitField, bitnr int) int {
|
||||
return (instance.field[bitslot(bitnr)] >> u32(bitnr % SLOT_SIZE)) & 1
|
||||
}
|
||||
|
||||
fn bitset(instance BitField, bitnr int) {
|
||||
instance.field[bitslot(bitnr)] = instance.field[bitslot(bitnr)] | bitmask(bitnr)
|
||||
}
|
||||
|
||||
fn bitclear(instance BitField, bitnr int) {
|
||||
instance.field[bitslot(bitnr)] = instance.field[bitslot(bitnr)] & ~bitmask(bitnr)
|
||||
}
|
||||
|
||||
fn bittoggle(instance BitField, bitnr int) {
|
||||
instance.field[bitslot(bitnr)] = instance.field[bitslot(bitnr)] ^ bitmask(bitnr)
|
||||
}
|
||||
/*
|
||||
#define BITTEST(a, b) ((a)->field[BITSLOT(b)] & BITMASK(b))
|
||||
*/
|
||||
|
||||
fn min(input1 int, input2 int) int {
|
||||
if input1 < input2 {
|
||||
return input1
|
||||
}
|
||||
else {
|
||||
return input2
|
||||
}
|
||||
}
|
||||
|
||||
fn bitnslots(length int) int {
|
||||
return (length - 1) / SLOT_SIZE + 1
|
||||
}
|
||||
|
||||
fn cleartail(instance BitField) {
|
||||
tail := instance.size % SLOT_SIZE
|
||||
if tail != 0 {
|
||||
/* create a mask for the tail */
|
||||
mask := u32((1 << tail) - 1)
|
||||
/* clear the extra bits */
|
||||
instance.field[bitnslots(instance.size) - 1] = instance.field[bitnslots(instance.size) - 1] & mask
|
||||
}
|
||||
}
|
||||
|
||||
/* public functions */
|
||||
|
||||
pub fn new(size int) BitField {
|
||||
output := BitField{
|
||||
size: size
|
||||
//field: *u32(calloc(bitnslots(size) * SLOT_SIZE / 8))
|
||||
field: [u32(0); bitnslots(size)]
|
||||
}
|
||||
return output
|
||||
}
|
||||
/*
|
||||
pub fn del(instance *BitField) {
|
||||
free(instance.field)
|
||||
free(instance)
|
||||
}
|
||||
*/
|
||||
pub fn (instance BitField) getbit(bitnr int) int {
|
||||
if bitnr >= instance.size {return 0}
|
||||
return bitget(instance, bitnr)
|
||||
}
|
||||
|
||||
pub fn (instance mut BitField) setbit(bitnr int) {
|
||||
if bitnr >= instance.size {return}
|
||||
bitset(instance, bitnr)
|
||||
}
|
||||
|
||||
pub fn (instance mut BitField) clearbit(bitnr int) {
|
||||
if bitnr >= instance.size {return}
|
||||
bitclear(instance, bitnr)
|
||||
}
|
||||
|
||||
pub fn (instance mut BitField) togglebit(bitnr int) {
|
||||
if bitnr >= instance.size {return}
|
||||
bittoggle(instance, bitnr)
|
||||
}
|
||||
|
||||
pub fn bfand(input1 BitField, input2 BitField) BitField {
|
||||
size := min(input1.size, input2.size)
|
||||
bitnslots := bitnslots(size)
|
||||
mut output := new(size)
|
||||
mut i := 0
|
||||
for i < bitnslots {
|
||||
output.field[i] = input1.field[i] & input2.field[i]
|
||||
i++
|
||||
}
|
||||
cleartail(output)
|
||||
return output
|
||||
}
|
||||
|
||||
pub fn bfnot(input BitField) BitField {
|
||||
size := input.size
|
||||
bitnslots := bitnslots(size)
|
||||
mut output := new(size)
|
||||
mut i := 0
|
||||
for i < bitnslots {
|
||||
output.field[i] = ~input.field[i]
|
||||
i++
|
||||
}
|
||||
cleartail(output)
|
||||
return output
|
||||
}
|
||||
|
||||
pub fn bfor(input1 BitField, input2 BitField) BitField {
|
||||
size := min(input1.size, input2.size)
|
||||
bitnslots := bitnslots(size)
|
||||
mut output := new(size)
|
||||
mut i := 0
|
||||
for i < bitnslots {
|
||||
output.field[i] = input1.field[i] | input2.field[i]
|
||||
i++
|
||||
}
|
||||
cleartail(output)
|
||||
return output
|
||||
}
|
||||
|
||||
pub fn bfxor(input1 BitField, input2 BitField) BitField {
|
||||
size := min(input1.size, input2.size)
|
||||
bitnslots := bitnslots(size)
|
||||
mut output := new(size)
|
||||
mut i := 0
|
||||
for i < bitnslots {
|
||||
output.field[i] = input1.field[i] ^ input2.field[i]
|
||||
i++
|
||||
}
|
||||
cleartail(output)
|
||||
return output
|
||||
}
|
||||
|
||||
pub fn print(instance BitField) {
|
||||
mut i := 0
|
||||
for i < instance.size {
|
||||
if instance.getbit(i) == 1 {
|
||||
print('1')
|
||||
}
|
||||
else {
|
||||
print('0')
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (instance BitField) getsize() int {
|
||||
return instance.size
|
||||
}
|
||||
|
||||
pub fn clone(input BitField) BitField {
|
||||
bitnslots := bitnslots(input.size)
|
||||
mut output := new(input.size)
|
||||
mut i := 0
|
||||
for i < bitnslots {
|
||||
output.field[i] = input.field[i]
|
||||
i++
|
||||
}
|
||||
return output
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import bf
|
||||
|
||||
import rand
|
||||
|
||||
fn test_bf_new_size() {
|
||||
instance := bf.new(5)
|
||||
assert instance.getsize() == 5
|
||||
}
|
||||
|
||||
fn test_bf_set_clear_toggle_get() {
|
||||
mut instance := bf.new(5)
|
||||
instance.setbit(4)
|
||||
assert instance.getbit(4) == 1
|
||||
instance.clearbit(4)
|
||||
assert instance.getbit(4) == 0
|
||||
instance.togglebit(4)
|
||||
assert instance.getbit(4) == 1
|
||||
}
|
||||
|
||||
fn test_bf_and_not_or_xor() {
|
||||
rand.seed()
|
||||
len := 80
|
||||
mut input1 := bf.new(len)
|
||||
mut input2 := bf.new(len)
|
||||
mut i := 0
|
||||
for i < len {
|
||||
if rand.next(2) == 1 {
|
||||
input1.setbit(i)
|
||||
}
|
||||
if rand.next(2) == 1{
|
||||
input2.setbit(i)
|
||||
}
|
||||
i++
|
||||
}
|
||||
output1 := bf.bfxor(input1, input2)
|
||||
bfand := bf.bfand(input1, input2)
|
||||
bfor := bf.bfor(input1, input2)
|
||||
bfnot := bf.bfnot(bfand)
|
||||
output2 := bf.bfand(bfor, bfnot)
|
||||
mut result := 1
|
||||
for i < len {
|
||||
if output1.getbit(i) != output2.getbit(i) {result = 0}
|
||||
}
|
||||
assert result == 1
|
||||
}
|
Loading…
Reference in New Issue