bf: add basic documentation
parent
732099fa08
commit
bd95f5bf8f
80
vlib/bf/bf.v
80
vlib/bf/bf.v
|
@ -1,5 +1,18 @@
|
||||||
module bf
|
module bf
|
||||||
|
|
||||||
|
/*
|
||||||
|
bf (BitField) is a module (shared library for V programming language) for
|
||||||
|
manipulating arrays of bits, i.e. series of zeroes and ones spread across an
|
||||||
|
array of storage units (unsigned 32-bit integers).
|
||||||
|
|
||||||
|
BitField structure
|
||||||
|
------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
provides API (functions and methods) for accessing and modifying bit arrays.
|
||||||
|
*/
|
||||||
|
|
||||||
struct BitField {
|
struct BitField {
|
||||||
mut:
|
mut:
|
||||||
size int
|
size int
|
||||||
|
@ -64,6 +77,9 @@ fn cleartail(instance BitField) {
|
||||||
|
|
||||||
// public functions
|
// public functions
|
||||||
|
|
||||||
|
// str2bf() converts a string of characters ('0' and '1') to a bit
|
||||||
|
// array. Any character different from '0' is treated as '1'.
|
||||||
|
|
||||||
pub fn str2bf(input string) BitField {
|
pub fn str2bf(input string) BitField {
|
||||||
mut output := new(input.len)
|
mut output := new(input.len)
|
||||||
for i := 0; i < input.len; i++ {
|
for i := 0; i < input.len; i++ {
|
||||||
|
@ -74,6 +90,9 @@ pub fn str2bf(input string) BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// string() converts the bit array to a string of characters ('0' and '1') and
|
||||||
|
// return the string
|
||||||
|
|
||||||
pub fn (input BitField) string() string {
|
pub fn (input BitField) string() string {
|
||||||
mut output := ''
|
mut output := ''
|
||||||
for i := 0; i < input.size; i++ {
|
for i := 0; i < input.size; i++ {
|
||||||
|
@ -87,6 +106,8 @@ pub fn (input BitField) string() string {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//new() creates an empty bit array of capable of storing 'size' bits.
|
||||||
|
|
||||||
pub fn new(size int) BitField {
|
pub fn new(size int) BitField {
|
||||||
output := BitField{
|
output := BitField{
|
||||||
size: size
|
size: size
|
||||||
|
@ -101,21 +122,31 @@ pub fn del(instance *BitField) {
|
||||||
free(instance)
|
free(instance)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// getbit() returns the value (0 or 1) of bit number 'bit_nr' (count from
|
||||||
|
// 0)
|
||||||
|
|
||||||
pub fn (instance BitField) getbit(bitnr int) int {
|
pub fn (instance BitField) getbit(bitnr int) int {
|
||||||
if bitnr >= instance.size {return 0}
|
if bitnr >= instance.size {return 0}
|
||||||
return bitget(instance, bitnr)
|
return bitget(instance, bitnr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setbit() set bit number 'bit_nr' to 1 (count from 0)
|
||||||
|
|
||||||
pub fn (instance mut BitField) setbit(bitnr int) {
|
pub fn (instance mut BitField) setbit(bitnr int) {
|
||||||
if bitnr >= instance.size {return}
|
if bitnr >= instance.size {return}
|
||||||
bitset(instance, bitnr)
|
bitset(instance, bitnr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clearbit() clears (sets to zero) bit number 'bit_nr' (count from 0)
|
||||||
|
|
||||||
pub fn (instance mut BitField) clearbit(bitnr int) {
|
pub fn (instance mut BitField) clearbit(bitnr int) {
|
||||||
if bitnr >= instance.size {return}
|
if bitnr >= instance.size {return}
|
||||||
bitclear(instance, bitnr)
|
bitclear(instance, bitnr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setall() sets all bits in the array to 1
|
||||||
|
|
||||||
pub fn (instance mut BitField) setall() {
|
pub fn (instance mut BitField) setall() {
|
||||||
for i := 0; i < bitnslots(instance.size); i++ {
|
for i := 0; i < bitnslots(instance.size); i++ {
|
||||||
instance.field[i] = u32(-1)
|
instance.field[i] = u32(-1)
|
||||||
|
@ -123,17 +154,26 @@ pub fn (instance mut BitField) setall() {
|
||||||
cleartail(instance)
|
cleartail(instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clearall() clears (sets to zero) all bits in the array
|
||||||
|
|
||||||
pub fn (instance mut BitField) clearall() {
|
pub fn (instance mut BitField) clearall() {
|
||||||
for i := 0; i < bitnslots(instance.size); i++ {
|
for i := 0; i < bitnslots(instance.size); i++ {
|
||||||
instance.field[i] = u32(0)
|
instance.field[i] = u32(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// togglebit() change the value (from 0 to 1 or from 1 to 0) of bit
|
||||||
|
// number 'bit_nr'
|
||||||
|
|
||||||
pub fn (instance mut BitField) togglebit(bitnr int) {
|
pub fn (instance mut BitField) togglebit(bitnr int) {
|
||||||
if bitnr >= instance.size {return}
|
if bitnr >= instance.size {return}
|
||||||
bittoggle(instance, bitnr)
|
bittoggle(instance, bitnr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bfand() perform logical AND operation on every pair of bits from 'input1'
|
||||||
|
// and 'input2' and return the result as a new array. If inputs differ in size,
|
||||||
|
// the tail of the longer one is ignored.
|
||||||
|
|
||||||
pub fn bfand(input1 BitField, input2 BitField) BitField {
|
pub fn bfand(input1 BitField, input2 BitField) BitField {
|
||||||
size := min(input1.size, input2.size)
|
size := min(input1.size, input2.size)
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := bitnslots(size)
|
||||||
|
@ -147,6 +187,8 @@ pub fn bfand(input1 BitField, input2 BitField) BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bfnot() toggle all bits in a bit array and return the result as a new array
|
||||||
|
|
||||||
pub fn bfnot(input BitField) BitField {
|
pub fn bfnot(input BitField) BitField {
|
||||||
size := input.size
|
size := input.size
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := bitnslots(size)
|
||||||
|
@ -160,6 +202,10 @@ pub fn bfnot(input BitField) BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bfor() perform logical OR operation on every pair of bits from 'input1' and
|
||||||
|
// 'input2' and return the result as a new array. If inputs differ in size, the
|
||||||
|
// tail of the longer one is ignored.
|
||||||
|
|
||||||
pub fn bfor(input1 BitField, input2 BitField) BitField {
|
pub fn bfor(input1 BitField, input2 BitField) BitField {
|
||||||
size := min(input1.size, input2.size)
|
size := min(input1.size, input2.size)
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := bitnslots(size)
|
||||||
|
@ -173,6 +219,10 @@ pub fn bfor(input1 BitField, input2 BitField) BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bfxor(input1 BitField, input2 BitField) perform logical XOR operation on
|
||||||
|
// every pair of bits from 'input1' and 'input2' and return the result as a new
|
||||||
|
// array. If inputs differ in size, the tail of the longer one is ignored.
|
||||||
|
|
||||||
pub fn bfxor(input1 BitField, input2 BitField) BitField {
|
pub fn bfxor(input1 BitField, input2 BitField) BitField {
|
||||||
size := min(input1.size, input2.size)
|
size := min(input1.size, input2.size)
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := bitnslots(size)
|
||||||
|
@ -186,6 +236,8 @@ pub fn bfxor(input1 BitField, input2 BitField) BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// join() concatenates two bit arrays and return the result as a new array.
|
||||||
|
|
||||||
pub fn join(input1 BitField, input2 BitField) BitField {
|
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)
|
||||||
|
@ -233,6 +285,9 @@ pub fn join(input1 BitField, input2 BitField) BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// print(instance BitField) send the content of a bit array to stdout as a
|
||||||
|
// string of characters ('0' and '1').
|
||||||
|
|
||||||
pub fn print(instance BitField) {
|
pub fn print(instance BitField) {
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for i < instance.size {
|
for i < instance.size {
|
||||||
|
@ -246,10 +301,14 @@ pub fn print(instance BitField) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getsize() returns the number of bits the array can hold
|
||||||
|
|
||||||
pub fn (instance BitField) getsize() int {
|
pub fn (instance BitField) getsize() int {
|
||||||
return instance.size
|
return instance.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clone() create a copy of a bit array
|
||||||
|
|
||||||
pub fn clone(input BitField) BitField {
|
pub fn clone(input BitField) BitField {
|
||||||
bitnslots := bitnslots(input.size)
|
bitnslots := bitnslots(input.size)
|
||||||
mut output := new(input.size)
|
mut output := new(input.size)
|
||||||
|
@ -261,6 +320,9 @@ pub fn clone(input BitField) BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cmp() compare two bit arrays bit by bit and return 'true' if they are
|
||||||
|
// identical by length and contents and 'false' otherwise.
|
||||||
|
|
||||||
pub fn cmp(input1 BitField, input2 BitField) bool {
|
pub fn cmp(input1 BitField, input2 BitField) bool {
|
||||||
if input1.size != input2.size {return false}
|
if input1.size != input2.size {return false}
|
||||||
for i := 0; i < bitnslots(input1.size); i++ {
|
for i := 0; i < bitnslots(input1.size); i++ {
|
||||||
|
@ -269,6 +331,8 @@ pub fn cmp(input1 BitField, input2 BitField) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// popcount() returns the number of set bits (ones) in the array
|
||||||
|
|
||||||
pub fn (instance BitField) popcount() int {
|
pub fn (instance BitField) popcount() int {
|
||||||
size := instance.size
|
size := instance.size
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := bitnslots(size)
|
||||||
|
@ -289,11 +353,16 @@ pub fn (instance BitField) popcount() int {
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hamming () compute the Hamming distance between two bit arrays.
|
||||||
|
|
||||||
pub fn hamming (input1 BitField, input2 BitField) int {
|
pub fn hamming (input1 BitField, input2 BitField) int {
|
||||||
input_xored := bfxor(input1, input2)
|
input_xored := bfxor(input1, input2)
|
||||||
return input_xored.popcount()
|
return input_xored.popcount()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pos() checks if the array contains a sub-array 'needle' and returns its
|
||||||
|
// position if it does, -1 if it does not, and -2 on error.
|
||||||
|
|
||||||
pub fn (haystack BitField) pos(needle BitField) int {
|
pub fn (haystack BitField) pos(needle BitField) int {
|
||||||
heystack_size := haystack.size
|
heystack_size := haystack.size
|
||||||
needle_size := needle.size
|
needle_size := needle.size
|
||||||
|
@ -314,6 +383,9 @@ pub fn (haystack BitField) pos(needle BitField) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// slice() return a sub-array of bits between 'start_bit_nr' (included) and
|
||||||
|
// 'end_bit_nr' (excluded)
|
||||||
|
|
||||||
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
|
||||||
|
@ -381,6 +453,9 @@ pub fn (input BitField) slice(_start int, _end int) BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reverse() reverses the order of bits in the array (swap the first with the
|
||||||
|
// last, the second with the last but one and so on)
|
||||||
|
|
||||||
pub fn (instance mut BitField) reverse() BitField {
|
pub fn (instance mut BitField) reverse() BitField {
|
||||||
size := instance.size
|
size := instance.size
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := bitnslots(size)
|
||||||
|
@ -401,6 +476,8 @@ pub fn (instance mut BitField) reverse() BitField {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resize() changes the size of the bit array to 'new_size'
|
||||||
|
|
||||||
pub fn (instance mut BitField) resize(size int) {
|
pub fn (instance mut BitField) resize(size int) {
|
||||||
bitnslots := bitnslots(size)
|
bitnslots := bitnslots(size)
|
||||||
old_size := instance.size
|
old_size := instance.size
|
||||||
|
@ -416,6 +493,9 @@ pub fn (instance mut BitField) resize(size int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rotate(offset int) circular-shift the bits by 'offset' positions (move
|
||||||
|
// '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.
|
||||||
|
|
Loading…
Reference in New Issue