2019-07-09 22:11:09 +03:00
|
|
|
module bf
|
|
|
|
|
|
|
|
struct BitField {
|
|
|
|
mut:
|
|
|
|
size int
|
|
|
|
//field *u32
|
|
|
|
field []u32
|
|
|
|
}
|
|
|
|
|
2019-07-10 23:05:50 +03:00
|
|
|
// helper functions
|
2019-07-09 22:11:09 +03:00
|
|
|
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 {
|
2019-07-10 23:05:50 +03:00
|
|
|
// create a mask for the tail
|
2019-07-09 22:11:09 +03:00
|
|
|
mask := u32((1 << tail) - 1)
|
2019-07-10 23:05:50 +03:00
|
|
|
// clear the extra bits
|
2019-07-09 22:11:09 +03:00
|
|
|
instance.field[bitnslots(instance.size) - 1] = instance.field[bitnslots(instance.size) - 1] & mask
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-10 23:05:50 +03:00
|
|
|
// public functions
|
2019-07-09 22:11:09 +03:00
|
|
|
|
|
|
|
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
|
2019-07-10 23:05:50 +03:00
|
|
|
}
|
|
|
|
|