bitfield: fix bf.from_bytes/1 ( now, bf.from_bytes(b) == bf.from_str(bf.from_bytes(b).str()) )

pull/7402/head
Delyan Angelov 2020-12-18 21:47:24 +02:00
parent 05f6e8b5aa
commit c5c310280f
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 123 additions and 128 deletions

View File

@ -12,11 +12,10 @@ Bit arrays are stored in data structures called 'BitField'. The structure is
'opaque', i.e. its internals are not available to the end user. This module 'opaque', i.e. its internals are not available to the end user. This module
provides API (functions and methods) for accessing and modifying bit arrays. provides API (functions and methods) for accessing and modifying bit arrays.
*/ */
pub struct BitField { pub struct BitField {
mut: mut:
size int size int
//field *u32 // field *u32
field []u32 field []u32
} }
@ -26,12 +25,36 @@ const (
) )
// public functions // public functions
// from_bytes() converts a byte array into a bitfield. // from_bytes() converts a byte array into a bitfield.
pub fn from_bytes(input []byte) BitField { pub fn from_bytes(input []byte) BitField {
mut output := new(input.len * 8) mut output := new(input.len * 8)
for i, b in input { for i, b in input {
output.field[i / 4] |= u32(b) << ((i % 4) * 8) mut ob := byte(0)
if b & 0b10000000 > 0 {
ob |= 0b00000001
}
if b & 0b01000000 > 0 {
ob |= 0b00000010
}
if b & 0b00100000 > 0 {
ob |= 0b00000100
}
if b & 0b00010000 > 0 {
ob |= 0b00001000
}
if b & 0b00001000 > 0 {
ob |= 0b00010000
}
if b & 0b00000100 > 0 {
ob |= 0b00100000
}
if b & 0b00000010 > 0 {
ob |= 0b01000000
}
if b & 0b00000001 > 0 {
ob |= 0b10000000
}
output.field[i / 4] |= u32(ob) << ((i % 4) * 8)
} }
return output return output
} }
@ -40,7 +63,7 @@ pub fn from_bytes(input []byte) BitField {
// array. Any character different from '0' is treated as '1'. // array. Any character different from '0' is treated as '1'.
pub fn from_str(input string) BitField { pub fn from_str(input string) BitField {
mut output := new(input.len) mut output := new(input.len)
for i in 0..input.len { for i in 0 .. input.len {
if input[i] != `0` { if input[i] != `0` {
output.set_bit(i) output.set_bit(i)
} }
@ -52,11 +75,10 @@ pub fn from_str(input string) BitField {
// return the string // return the string
pub fn (input BitField) str() string { pub fn (input BitField) str() string {
mut output := '' mut output := ''
for i in 0..input.size { for i in 0 .. input.size {
if input.get_bit(i) == 1 { if input.get_bit(i) == 1 {
output = output + '1' output = output + '1'
} } else {
else {
output = output + '0' output = output + '0'
} }
} }
@ -67,18 +89,18 @@ pub fn (input BitField) str() string {
pub fn new(size int) BitField { pub fn new(size int) BitField {
output := BitField{ output := BitField{
size: size size: size
//field: *u32(calloc(zbitnslots(size) * slot_size / 8)) // field: *u32(calloc(zbitnslots(size) * slot_size / 8))
field: []u32{len:zbitnslots(size)} field: []u32{len: zbitnslots(size)}
} }
return output return output
} }
/* /*
pub fn del(instance *BitField) { pub fn del(instance *BitField) {
free(instance.field) free(instance.field)
free(instance) free(instance)
} }
*/ */
// get_bit returns the value (0 or 1) of bit number 'bit_nr' (count from 0). // get_bit returns the value (0 or 1) of bit number 'bit_nr' (count from 0).
pub fn (instance BitField) get_bit(bitnr int) int { pub fn (instance BitField) get_bit(bitnr int) int {
if bitnr >= instance.size { if bitnr >= instance.size {
@ -105,7 +127,7 @@ pub fn (mut instance BitField) clear_bit(bitnr int) {
// set_all sets all bits in the array to 1. // set_all sets all bits in the array to 1.
pub fn (mut instance BitField) set_all() { pub fn (mut instance BitField) set_all() {
for i in 0..zbitnslots(instance.size) { for i in 0 .. zbitnslots(instance.size) {
instance.field[i] = u32(-1) instance.field[i] = u32(-1)
} }
instance.clear_tail() instance.clear_tail()
@ -113,7 +135,7 @@ pub fn (mut instance BitField) set_all() {
// clear_all clears (sets to zero) all bits in the array. // clear_all clears (sets to zero) all bits in the array.
pub fn (mut instance BitField) clear_all() { pub fn (mut instance BitField) clear_all() {
for i in 0..zbitnslots(instance.size) { for i in 0 .. zbitnslots(instance.size) {
instance.field[i] = u32(0) instance.field[i] = u32(0)
} }
} }
@ -134,7 +156,7 @@ pub fn bf_and(input1 BitField, input2 BitField) BitField {
size := min(input1.size, input2.size) size := min(input1.size, input2.size)
bitnslots := zbitnslots(size) bitnslots := zbitnslots(size)
mut output := new(size) mut output := new(size)
for i in 0..bitnslots { for i in 0 .. bitnslots {
output.field[i] = input1.field[i] & input2.field[i] output.field[i] = input1.field[i] & input2.field[i]
} }
output.clear_tail() output.clear_tail()
@ -146,7 +168,7 @@ pub fn bf_not(input BitField) BitField {
size := input.size size := input.size
bitnslots := zbitnslots(size) bitnslots := zbitnslots(size)
mut output := new(size) mut output := new(size)
for i in 0..bitnslots { for i in 0 .. bitnslots {
output.field[i] = ~input.field[i] output.field[i] = ~input.field[i]
} }
output.clear_tail() output.clear_tail()
@ -160,7 +182,7 @@ pub fn bf_or(input1 BitField, input2 BitField) BitField {
size := min(input1.size, input2.size) size := min(input1.size, input2.size)
bitnslots := zbitnslots(size) bitnslots := zbitnslots(size)
mut output := new(size) mut output := new(size)
for i in 0..bitnslots { for i in 0 .. bitnslots {
output.field[i] = input1.field[i] | input2.field[i] output.field[i] = input1.field[i] | input2.field[i]
} }
output.clear_tail() output.clear_tail()
@ -174,7 +196,7 @@ pub fn bf_xor(input1 BitField, input2 BitField) BitField {
size := min(input1.size, input2.size) size := min(input1.size, input2.size)
bitnslots := zbitnslots(size) bitnslots := zbitnslots(size)
mut output := new(size) mut output := new(size)
for i in 0..bitnslots { for i in 0 .. bitnslots {
output.field[i] = input1.field[i] ^ input2.field[i] output.field[i] = input1.field[i] ^ input2.field[i]
} }
output.clear_tail() output.clear_tail()
@ -186,21 +208,17 @@ pub fn join(input1 BitField, input2 BitField) BitField {
output_size := input1.size + input2.size output_size := input1.size + input2.size
mut output := new(output_size) mut output := new(output_size)
// copy the first input to output as is // copy the first input to output as is
for i in 0..zbitnslots(input1.size) { for i in 0 .. zbitnslots(input1.size) {
output.field[i] = input1.field[i] output.field[i] = input1.field[i]
} }
// find offset bit and offset slot // find offset bit and offset slot
offset_bit := input1.size % slot_size offset_bit := input1.size % slot_size
offset_slot := input1.size / slot_size offset_slot := input1.size / slot_size
for i in 0 .. zbitnslots(input2.size) {
for i in 0..zbitnslots(input2.size) { output.field[i + offset_slot] |= u32(input2.field[i] << u32(offset_bit))
output.field[i + offset_slot] |=
u32(input2.field[i] << u32(offset_bit))
} }
/* /*
* If offset_bit is not zero, additional operations are needed. * If offset_bit is not zero, additional operations are needed.
* Number of iterations depends on the nr of slots in output. Two * Number of iterations depends on the nr of slots in output. Two
* options: * options:
* (a) nr of slots in output is the sum of inputs' slots. In this * (a) nr of slots in output is the sum of inputs' slots. In this
@ -211,16 +229,14 @@ pub fn join(input1 BitField, input2 BitField) BitField {
* the last slot of output is greater than the nr of bits in the second * the last slot of output is greater than the nr of bits in the second
* input. * input.
* If offset_bit is zero, no additional copies needed. * If offset_bit is zero, no additional copies needed.
*/ */
if (output_size - 1) % slot_size < (input2.size - 1) % slot_size { if (output_size - 1) % slot_size < (input2.size - 1) % slot_size {
for i in 0..zbitnslots(input2.size) { for i in 0 .. zbitnslots(input2.size) {
output.field[i + offset_slot + 1] |= output.field[i + offset_slot + 1] |= u32(input2.field[i] >> u32(slot_size - offset_bit))
u32(input2.field[i] >> u32(slot_size - offset_bit))
} }
} else if (output_size - 1) % slot_size > (input2.size - 1) % slot_size { } else if (output_size - 1) % slot_size > (input2.size - 1) % slot_size {
for i in 0..zbitnslots(input2.size) - 1 { for i in 0 .. zbitnslots(input2.size) - 1 {
output.field[i + offset_slot + 1] |= output.field[i + offset_slot + 1] |= u32(input2.field[i] >> u32(slot_size - offset_bit))
u32(input2.field[i] >> u32(slot_size - offset_bit))
} }
} }
return output return output
@ -235,7 +251,7 @@ pub fn (instance BitField) get_size() int {
pub fn (instance BitField) clone() BitField { pub fn (instance BitField) clone() BitField {
bitnslots := zbitnslots(instance.size) bitnslots := zbitnslots(instance.size)
mut output := new(instance.size) mut output := new(instance.size)
for i in 0..bitnslots { for i in 0 .. bitnslots {
output.field[i] = instance.field[i] output.field[i] = instance.field[i]
} }
return output return output
@ -244,9 +260,13 @@ pub fn (instance BitField) clone() BitField {
// cmp compares two bit arrays bit by bit and returns 'true' if they are // cmp compares two bit arrays bit by bit and returns 'true' if they are
// identical by length and contents and 'false' otherwise. // identical by length and contents and 'false' otherwise.
pub fn (instance BitField) cmp(input BitField) bool { pub fn (instance BitField) cmp(input BitField) bool {
if instance.size != input.size {return false} if instance.size != input.size {
for i in 0..zbitnslots(instance.size) { return false
if instance.field[i] != input.field[i] {return false} }
for i in 0 .. zbitnslots(instance.size) {
if instance.field[i] != input.field[i] {
return false
}
} }
return true return true
} }
@ -257,14 +277,14 @@ pub fn (instance BitField) pop_count() int {
bitnslots := zbitnslots(size) bitnslots := zbitnslots(size)
tail := size % slot_size tail := size % slot_size
mut count := 0 mut count := 0
for i in 0..bitnslots - 1 { for i in 0 .. bitnslots - 1 {
for j in 0..slot_size { for j in 0 .. slot_size {
if u32(instance.field[i] >> u32(j)) & u32(1) == u32(1) { if u32(instance.field[i] >> u32(j)) & u32(1) == u32(1) {
count++ count++
} }
} }
} }
for j in 0..tail { for j in 0 .. tail {
if u32(instance.field[bitnslots - 1] >> u32(j)) & u32(1) == u32(1) { if u32(instance.field[bitnslots - 1] >> u32(j)) & u32(1) == u32(1) {
count++ count++
} }
@ -284,7 +304,6 @@ pub fn (haystack BitField) pos(needle BitField) int {
heystack_size := haystack.size heystack_size := haystack.size
needle_size := needle.size needle_size := needle.size
diff := heystack_size - needle_size diff := heystack_size - needle_size
// needle longer than haystack; return error code -2 // needle longer than haystack; return error code -2
if diff < 0 { if diff < 0 {
return -2 return -2
@ -312,54 +331,42 @@ pub fn (input BitField) slice(_start int, _end int) BitField {
if start > end { if start > end {
start = end // or panic? start = end // or panic?
} }
mut output := new(end - start) mut output := new(end - start)
start_offset := start % slot_size start_offset := start % slot_size
end_offset := (end - 1) % slot_size end_offset := (end - 1) % slot_size
start_slot := start / slot_size start_slot := start / slot_size
end_slot := (end - 1) / slot_size end_slot := (end - 1) / slot_size
output_slots := zbitnslots(end - start) output_slots := zbitnslots(end - start)
if output_slots > 1 { if output_slots > 1 {
if start_offset != 0 { if start_offset != 0 {
for i in 0..output_slots - 1 { for i in 0 .. output_slots - 1 {
output.field[i] = output.field[i] = u32(input.field[start_slot + i] >> u32(start_offset))
u32(input.field[start_slot + i] >> u32(start_offset)) output.field[i] = output.field[i] | u32(input.field[start_slot + i + 1] << u32(slot_size -
output.field[i] = output.field[i] | start_offset))
u32(input.field[start_slot + i + 1] <<
u32(slot_size - start_offset))
} }
} } else {
else { for i in 0 .. output_slots - 1 {
for i in 0..output_slots - 1 { output.field[i] = u32(input.field[start_slot + i])
output.field[i] =
u32(input.field[start_slot + i])
} }
} }
} }
if start_offset > end_offset { if start_offset > end_offset {
output.field[(end - start - 1) / slot_size] = output.field[(end - start - 1) / slot_size] = u32(input.field[end_slot - 1] >> u32(start_offset))
u32(input.field[end_slot - 1] >> u32(start_offset))
mut mask := u32((1 << (end_offset + 1)) - 1) mut mask := u32((1 << (end_offset + 1)) - 1)
mask = input.field[end_slot] & mask mask = input.field[end_slot] & mask
mask = u32(mask << u32(slot_size - start_offset)) mask = u32(mask << u32(slot_size - start_offset))
output.field[(end - start - 1) / slot_size] |= mask output.field[(end - start - 1) / slot_size] |= mask
} } else if start_offset == 0 {
else if start_offset == 0 {
mut mask := u32(0) mut mask := u32(0)
if end_offset == slot_size - 1 { if end_offset == slot_size - 1 {
mask = u32(-1) mask = u32(-1)
} } else {
else {
mask = u32(u32(1) << u32(end_offset + 1)) mask = u32(u32(1) << u32(end_offset + 1))
mask = mask - u32(1) mask = mask - u32(1)
} }
output.field[(end - start - 1) / slot_size] = output.field[(end - start - 1) / slot_size] = (input.field[end_slot] & mask)
(input.field[end_slot] & mask) } else {
} mut mask := u32(((1 << (end_offset - start_offset + 1)) - 1) << start_offset)
else {
mut mask := u32(((1 << (end_offset - start_offset + 1)) - 1) << start_offset)
mask = input.field[end_slot] & mask mask = input.field[end_slot] & mask
mask = u32(mask >> u32(start_offset)) mask = u32(mask >> u32(start_offset))
output.field[(end - start - 1) / slot_size] |= mask output.field[(end - start - 1) / slot_size] |= mask
@ -373,15 +380,15 @@ pub fn (instance BitField) reverse() BitField {
size := instance.size size := instance.size
bitnslots := zbitnslots(size) bitnslots := zbitnslots(size)
mut output := new(size) mut output := new(size)
for i:= 0; i < (bitnslots - 1); i++ { for i := 0; i < (bitnslots - 1); i++ {
for j in 0..slot_size { for j in 0 .. slot_size {
if u32(instance.field[i] >> u32(j)) & u32(1) == u32(1) { if u32(instance.field[i] >> u32(j)) & u32(1) == u32(1) {
output.set_bit(size - i * slot_size - j - 1) output.set_bit(size - i * slot_size - j - 1)
} }
} }
} }
bits_in_last_input_slot := (size - 1) % slot_size + 1 bits_in_last_input_slot := (size - 1) % slot_size + 1
for j in 0..bits_in_last_input_slot { for j in 0 .. bits_in_last_input_slot {
if u32(instance.field[bitnslots - 1] >> u32(j)) & u32(1) == u32(1) { if u32(instance.field[bitnslots - 1] >> u32(j)) & u32(1) == u32(1) {
output.set_bit(bits_in_last_input_slot - j - 1) output.set_bit(bits_in_last_input_slot - j - 1)
} }
@ -394,7 +401,7 @@ pub fn (mut instance BitField) resize(new_size int) {
new_bitnslots := zbitnslots(new_size) new_bitnslots := zbitnslots(new_size)
old_size := instance.size old_size := instance.size
old_bitnslots := zbitnslots(old_size) old_bitnslots := zbitnslots(old_size)
mut field := []u32{len:new_bitnslots} mut field := []u32{len: new_bitnslots}
for i := 0; i < old_bitnslots && i < new_bitnslots; i++ { for i := 0; i < old_bitnslots && i < new_bitnslots; i++ {
field[i] = instance.field[i] field[i] = instance.field[i]
} }
@ -408,14 +415,15 @@ pub fn (mut instance BitField) resize(new_size int) {
// rotate circular-shifts the bits by 'offset' positions (move // rotate circular-shifts the bits by 'offset' positions (move
// 'offset' bit to 0, 'offset+1' bit to 1, and so on). // 'offset' bit to 0, 'offset+1' bit to 1, and so on).
pub fn (instance BitField) rotate(offset int) BitField { pub fn (instance BitField) rotate(offset int) BitField {
/** /*
*
* This function "cuts" the bitfield into two and swaps them. * This function "cuts" the bitfield into two and swaps them.
* If the offset is positive, the cutting point is counted from the * If the offset is positive, the cutting point is counted from the
* beginning of the bit array, otherwise from the end. * beginning of the bit array, otherwise from the end.
**/ *
*/
size := instance.size size := instance.size
// removing extra rotations // removing extra rotations
mut offset_internal := offset % size mut offset_internal := offset % size
if offset_internal == 0 { if offset_internal == 0 {
// nothing to shift // nothing to shift
@ -424,7 +432,6 @@ pub fn (instance BitField) rotate(offset int) BitField {
if offset_internal < 0 { if offset_internal < 0 {
offset_internal = offset_internal + size offset_internal = offset_internal + size
} }
first_chunk := instance.slice(0, offset_internal) first_chunk := instance.slice(0, offset_internal)
second_chunk := instance.slice(offset_internal, size) second_chunk := instance.slice(offset_internal, size)
output := join(second_chunk, first_chunk) output := join(second_chunk, first_chunk)
@ -432,14 +439,14 @@ pub fn (instance BitField) rotate(offset int) BitField {
} }
// Internal functions // Internal functions
fn (mut instance BitField) clear_tail() { fn (mut instance BitField) clear_tail() {
tail := instance.size % slot_size tail := instance.size % slot_size
if tail != 0 { if tail != 0 {
// create a mask for the tail // create a mask for the tail
mask := u32((1 << tail) - 1) mask := u32((1 << tail) - 1)
// clear the extra bits // clear the extra bits
instance.field[zbitnslots(instance.size) - 1] = instance.field[zbitnslots(instance.size) - 1] & mask instance.field[zbitnslots(instance.size) - 1] = instance.field[zbitnslots(instance.size) -
1] & mask
} }
} }
@ -454,8 +461,7 @@ fn bitslot(size int) int {
fn min(input1 int, input2 int) int { fn min(input1 int, input2 int) int {
if input1 < input2 { if input1 < input2 {
return input1 return input1
} } else {
else {
return input2 return input2
} }
} }

View File

@ -1,5 +1,4 @@
import bitfield import bitfield
import rand import rand
fn test_bf_new_size() { fn test_bf_new_size() {
@ -26,7 +25,7 @@ fn test_bf_and_not_or_xor() {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
input1.set_bit(i) input1.set_bit(i)
} }
if rand.intn(2) == 1{ if rand.intn(2) == 1 {
input2.set_bit(i) input2.set_bit(i)
} }
i++ i++
@ -38,7 +37,9 @@ fn test_bf_and_not_or_xor() {
output2 := bitfield.bf_and(bf_or, bf_not) output2 := bitfield.bf_and(bf_or, bf_not)
mut result := 1 mut result := 1
for i < len { for i < len {
if output1.get_bit(i) != output2.get_bit(i) {result = 0} if output1.get_bit(i) != output2.get_bit(i) {
result = 0
}
} }
assert result == 1 assert result == 1
} }
@ -46,7 +47,7 @@ fn test_bf_and_not_or_xor() {
fn test_clone_cmp() { fn test_clone_cmp() {
len := 80 len := 80
mut input := bitfield.new(len) mut input := bitfield.new(len)
for i in 0..len { for i in 0 .. len {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
input.set_bit(i) input.set_bit(i)
} }
@ -59,7 +60,7 @@ fn test_clone_cmp() {
fn test_slice_join() { fn test_slice_join() {
len := 80 len := 80
mut input := bitfield.new(len) mut input := bitfield.new(len)
for i in 0..len { for i in 0 .. len {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
input.set_bit(i) input.set_bit(i)
} }
@ -82,7 +83,7 @@ fn test_pop_count() {
len := 80 len := 80
mut count0 := 0 mut count0 := 0
mut input := bitfield.new(len) mut input := bitfield.new(len)
for i in 0..len { for i in 0 .. len {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
input.set_bit(i) input.set_bit(i)
count0++ count0++
@ -97,7 +98,7 @@ fn test_hamming() {
mut count := 0 mut count := 0
mut input1 := bitfield.new(len) mut input1 := bitfield.new(len)
mut input2 := bitfield.new(len) mut input2 := bitfield.new(len)
for i in 0..len { for i in 0 .. len {
match rand.intn(4) { match rand.intn(4) {
0, 1 { 0, 1 {
input1.set_bit(i) input1.set_bit(i)
@ -111,40 +112,33 @@ fn test_hamming() {
input1.set_bit(i) input1.set_bit(i)
input2.set_bit(i) input2.set_bit(i)
} }
else { else {}
}
} }
} }
assert count == bitfield.hamming(input1, input2) assert count == bitfield.hamming(input1, input2)
} }
fn test_bf_from_bytes() { fn test_bf_from_bytes() {
input := [byte(0xF0), byte(0x0F), byte(0xF0), byte(0xFF)] input := [byte(0x01), 0xF0, 0x0F, 0xF0, 0xFF]
output := bitfield.from_bytes(input) output := bitfield.from_bytes(input).str()
mut result := 1 assert output == '00000001' + '11110000' + '00001111' + '11110000' + '11111111'
for i in 0..input.len * 8 { newoutput := bitfield.from_str(output).str()
if (input[i / 8] >> (i % 8)) & 1 != output.get_bit(i) { assert newoutput == output
result = 0
}
}
assert result == 1
} }
fn test_bf_from_str() { fn test_bf_from_str() {
len := 80 len := 80
mut input := '' mut input := ''
for _ in 0..len { for _ in 0 .. len {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
input = input + '1' input = input + '1'
} } else {
else {
input = input + '0' input = input + '0'
} }
} }
output := bitfield.from_str(input) output := bitfield.from_str(input)
mut result := 1 mut result := 1
for i in 0..len { for i in 0 .. len {
if input[i] != output.get_bit(i) + 48 { if input[i] != output.get_bit(i) + 48 {
result = 0 result = 0
} }
@ -155,23 +149,22 @@ fn test_bf_from_str() {
fn test_bf_bf2str() { fn test_bf_bf2str() {
len := 80 len := 80
mut input := bitfield.new(len) mut input := bitfield.new(len)
for i in 0..len { for i in 0 .. len {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
input.set_bit(i) input.set_bit(i)
} }
} }
mut check := '' mut check := ''
for i in 0..len { for i in 0 .. len {
if input.get_bit(i) == 1 { if input.get_bit(i) == 1 {
check = check + '1' check = check + '1'
} } else {
else {
check = check + '0' check = check + '0'
} }
} }
output := input.str() output := input.str()
mut result := 1 mut result := 1
for i in 0..len { for i in 0 .. len {
if check[i] != output[i] { if check[i] != output[i] {
result = 0 result = 0
} }
@ -184,7 +177,7 @@ fn test_bf_set_all() {
mut input := bitfield.new(len) mut input := bitfield.new(len)
input.set_all() input.set_all()
mut result := 1 mut result := 1
for i in 0..len { for i in 0 .. len {
if input.get_bit(i) != 1 { if input.get_bit(i) != 1 {
result = 0 result = 0
} }
@ -195,14 +188,14 @@ fn test_bf_set_all() {
fn test_bf_clear_all() { fn test_bf_clear_all() {
len := 80 len := 80
mut input := bitfield.new(len) mut input := bitfield.new(len)
for i in 0..len { for i in 0 .. len {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
input.set_bit(i) input.set_bit(i)
} }
} }
input.clear_all() input.clear_all()
mut result := 1 mut result := 1
for i in 0..len { for i in 0 .. len {
if input.get_bit(i) != 0 { if input.get_bit(i) != 0 {
result = 0 result = 0
} }
@ -213,7 +206,7 @@ fn test_bf_clear_all() {
fn test_bf_reverse() { fn test_bf_reverse() {
len := 80 len := 80
mut input := bitfield.new(len) mut input := bitfield.new(len)
for i in 0..len { for i in 0 .. len {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
input.set_bit(i) input.set_bit(i)
} }
@ -221,7 +214,7 @@ fn test_bf_reverse() {
check := input.clone() check := input.clone()
output := input.reverse() output := input.reverse()
mut result := 1 mut result := 1
for i in 0..len { for i in 0 .. len {
if output.get_bit(i) != check.get_bit(len - i - 1) { if output.get_bit(i) != check.get_bit(len - i - 1) {
result = 0 result = 0
} }
@ -232,7 +225,7 @@ fn test_bf_reverse() {
fn test_bf_resize() { fn test_bf_resize() {
len := 80 len := 80
mut input := bitfield.new(rand.intn(len) + 1) mut input := bitfield.new(rand.intn(len) + 1)
for _ in 0..100 { for _ in 0 .. 100 {
input.resize(rand.intn(len) + 1) input.resize(rand.intn(len) + 1)
input.set_bit(input.get_size() - 1) input.set_bit(input.get_size() - 1)
} }
@ -240,48 +233,44 @@ fn test_bf_resize() {
} }
fn test_bf_pos() { fn test_bf_pos() {
/** /*
*
* set haystack size to 80 * set haystack size to 80
* test different sizes of needle, from 1 to 80 * test different sizes of needle, from 1 to 80
* test different positions of needle, from 0 to where it fits * test different positions of needle, from 0 to where it fits
* all haystacks here contain exactly one instanse of needle, * all haystacks here contain exactly one instanse of needle,
* so search should return non-negative-values * so search should return non-negative-values
**/ *
*/
len := 80 len := 80
mut result := 1 mut result := 1
for i := 1; i < len; i++ { // needle size for i := 1; i < len; i++ { // needle size
for j in 0..len - i { // needle position in the haystack for j in 0 .. len - i { // needle position in the haystack
// create the needle // create the needle
mut needle := bitfield.new(i) mut needle := bitfield.new(i)
// fill the needle with random values // fill the needle with random values
for k in 0..i { for k in 0 .. i {
if rand.intn(2) == 1 { if rand.intn(2) == 1 {
needle.set_bit(k) needle.set_bit(k)
} }
} }
// make sure the needle contains at least one set bit, selected randomly // make sure the needle contains at least one set bit, selected randomly
r := rand.intn(i) r := rand.intn(i)
needle.set_bit(r) needle.set_bit(r)
// create the haystack, make sure it contains the needle // create the haystack, make sure it contains the needle
mut haystack := needle.clone() mut haystack := needle.clone()
// if there is space between the start of the haystack and the sought needle, fill it with zeroes // if there is space between the start of the haystack and the sought needle, fill it with zeroes
if j > 0 { if j > 0 {
start := bitfield.new(j) start := bitfield.new(j)
tmp := bitfield.join(start, haystack) tmp := bitfield.join(start, haystack)
haystack = tmp haystack = tmp
} }
// if there is space between the sought needle and the end of haystack, fill it with zeroes // if there is space between the sought needle and the end of haystack, fill it with zeroes
if j + i < len { if j + i < len {
end := bitfield.new(len - j - i) end := bitfield.new(len - j - i)
tmp2 := bitfield.join(haystack, end) tmp2 := bitfield.join(haystack, end)
haystack = tmp2 haystack = tmp2
} }
// now let's test // now let's test
// the result should be equal to j // the result should be equal to j
if haystack.pos(needle) != j { if haystack.pos(needle) != j {
@ -308,13 +297,13 @@ fn test_bf_rotate() {
assert result == 1 assert result == 1
} }
fn test_bf_printing(){ fn test_bf_printing() {
len := 80 len := 80
mut input := bitfield.new(len) mut input := bitfield.new(len)
for i in 0..len { for i in 0 .. len {
if rand.intn(2) == 0 { if rand.intn(2) == 0 {
input.set_bit(i) input.set_bit(i)
} }
} }
// the following should convert the bitfield input into a string automatically // the following should convert the bitfield input into a string automatically
println(input) println(input)