bf: add reverse(), resize(), pos() and rotate()
parent
f5c8ee4742
commit
c0911ea74b
79
vlib/bf/bf.v
79
vlib/bf/bf.v
|
@ -294,6 +294,26 @@ pub fn hamming (input1 BitField, input2 BitField) int {
|
||||||
return input_xored.popcount()
|
return input_xored.popcount()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (haystack BitField) pos(needle BitField) int {
|
||||||
|
heystack_size := haystack.size
|
||||||
|
needle_size := needle.size
|
||||||
|
diff := heystack_size - needle_size
|
||||||
|
|
||||||
|
// needle longer than haystack; return error code -2
|
||||||
|
if diff < 0 {
|
||||||
|
return -2
|
||||||
|
}
|
||||||
|
for i := 0; i <= diff; i++ {
|
||||||
|
needle_candidate := haystack.slice(i, needle_size + i)
|
||||||
|
if cmp(needle_candidate, needle) {
|
||||||
|
// needle matches a sub-array of haystack; return starting position of the sub-array
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// nothing matched; return -1
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (input BitField) slice(_start int, _end int) BitField {
|
pub fn (input BitField) slice(_start int, _end int) BitField {
|
||||||
// boundary checks
|
// boundary checks
|
||||||
mut start := _start
|
mut start := _start
|
||||||
|
@ -360,3 +380,62 @@ pub fn (input BitField) slice(_start int, _end int) BitField {
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (instance mut BitField) reverse() BitField {
|
||||||
|
size := instance.size
|
||||||
|
bitnslots := bitnslots(size)
|
||||||
|
mut output := new(size)
|
||||||
|
for i:= 0; i < (bitnslots - 1); i++ {
|
||||||
|
for j := 0; j < SLOT_SIZE; j++ {
|
||||||
|
if u32(instance.field[i] >> u32(j)) & u32(1) == u32(1) {
|
||||||
|
bitset(output, size - i * SLOT_SIZE - j - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bits_in_last_input_slot := (size - 1) % SLOT_SIZE + 1
|
||||||
|
for j := 0; j < bits_in_last_input_slot; j++ {
|
||||||
|
if u32(instance.field[bitnslots - 1] >> u32(j)) & u32(1) == u32(1) {
|
||||||
|
bitset(output, bits_in_last_input_slot - j - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (instance mut BitField) resize(size int) {
|
||||||
|
bitnslots := bitnslots(size)
|
||||||
|
old_size := instance.size
|
||||||
|
old_bitnslots := bitnslots(old_size)
|
||||||
|
mut field := [u32(0); bitnslots]
|
||||||
|
for i := 0; i < old_bitnslots && i < bitnslots; i++ {
|
||||||
|
field[i] = instance.field[i]
|
||||||
|
}
|
||||||
|
instance.field = field
|
||||||
|
instance.size = size
|
||||||
|
if size < old_size && size % SLOT_SIZE != 0 {
|
||||||
|
cleartail(instance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (instance BitField) rotate(offset int) BitField {
|
||||||
|
/**
|
||||||
|
* This function "cuts" the bitfield into two and swaps them.
|
||||||
|
* If the offset is positive, the cutting point is counted from the
|
||||||
|
* beginning of the bit array, otherwise from the end.
|
||||||
|
**/
|
||||||
|
size := instance.size
|
||||||
|
// removing extra rotations
|
||||||
|
|
||||||
|
mut offset_internal := offset % size
|
||||||
|
if (offset_internal == 0) {
|
||||||
|
// nothing to shift
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
if offset_internal < 0 {
|
||||||
|
offset_internal = offset_internal + size
|
||||||
|
}
|
||||||
|
|
||||||
|
first_chunk := instance.slice(0, offset_internal)
|
||||||
|
second_chunk := instance.slice(offset_internal, size)
|
||||||
|
output := join(second_chunk, first_chunk)
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
|
@ -202,3 +202,104 @@ fn test_bf_clearall() {
|
||||||
}
|
}
|
||||||
assert result == 1
|
assert result == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_bf_reverse() {
|
||||||
|
rand.seed(time.now().uni)
|
||||||
|
len := 80
|
||||||
|
mut input := bf.new(len)
|
||||||
|
for i := 0; i < len; i++ {
|
||||||
|
if rand.next(2) == 1 {
|
||||||
|
input.setbit(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check := bf.clone(input)
|
||||||
|
output := input.reverse()
|
||||||
|
mut result := 1
|
||||||
|
for i := 0; i < len; i++ {
|
||||||
|
if output.getbit(i) != check.getbit(len - i - 1) {
|
||||||
|
result = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert result == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_bf_resize() {
|
||||||
|
rand.seed(time.now().uni)
|
||||||
|
len := 80
|
||||||
|
mut input := bf.new(len)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
input.resize(rand.next(input.getsize()) + 1)
|
||||||
|
input.setbit(input.getsize() - 1)
|
||||||
|
}
|
||||||
|
assert input.getbit(input.getsize() - 1) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_bf_pos() {
|
||||||
|
/**
|
||||||
|
* set haystack size to 80
|
||||||
|
* test different sizes of needle, from 1 to 80
|
||||||
|
* test different positions of needle, from 0 to where it fits
|
||||||
|
* all haystacks here contain exactly one instanse of needle,
|
||||||
|
* so search should return non-negative-values
|
||||||
|
**/
|
||||||
|
rand.seed(time.now().uni)
|
||||||
|
len := 80
|
||||||
|
mut result := 1
|
||||||
|
for i := 1; i < len; i++ { // needle size
|
||||||
|
for j := 0; j < len - i; j++ { // needle position in the haystack
|
||||||
|
// create the needle
|
||||||
|
mut needle := bf.new(i)
|
||||||
|
|
||||||
|
// fill the needle with random values
|
||||||
|
for k := 0; k < i; k++ {
|
||||||
|
if rand.next(2) == 1 {
|
||||||
|
needle.setbit(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the needle contains at least one set bit, selected randomly
|
||||||
|
r := rand.next(i)
|
||||||
|
needle.setbit(r)
|
||||||
|
|
||||||
|
// create the haystack, make sure it contains the needle
|
||||||
|
mut haystack := bf.clone(needle)
|
||||||
|
|
||||||
|
// if there is space between the start of the haystack and the sought needle, fill it with zeroes
|
||||||
|
if j > 0 {
|
||||||
|
start := bf.new(j)
|
||||||
|
tmp := bf.join(start, haystack)
|
||||||
|
haystack = tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is space between the sought needle and the end of haystack, fill it with zeroes
|
||||||
|
if j + i < len {
|
||||||
|
end := bf.new(len - j - i)
|
||||||
|
tmp2 := bf.join(haystack, end)
|
||||||
|
haystack = tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
// now let's test
|
||||||
|
// the result should be equal to j
|
||||||
|
if haystack.pos(needle) != j {
|
||||||
|
result = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert result == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_bf_rotate() {
|
||||||
|
mut result := 1
|
||||||
|
len := 80
|
||||||
|
for i := 1; i < 80 && result == 1; i++ {
|
||||||
|
mut chunk1 := bf.new(i)
|
||||||
|
chunk2 := bf.new(len - i)
|
||||||
|
chunk1.setall()
|
||||||
|
input := bf.join(chunk1, chunk2)
|
||||||
|
output := input.rotate(i)
|
||||||
|
if output.getbit(len - i - 1) != 0 || output.getbit(len - i) != 1 {
|
||||||
|
result = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert result == 1
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue