555 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			555 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			V
		
	
	
module bitfield
 | 
						|
 | 
						|
/*
 | 
						|
bitfield is a module 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.
 | 
						|
*/
 | 
						|
pub struct BitField {
 | 
						|
mut:
 | 
						|
	size int
 | 
						|
	// field *u32
 | 
						|
	field []u32
 | 
						|
}
 | 
						|
 | 
						|
// helper functions
 | 
						|
const (
 | 
						|
	slot_size = 32
 | 
						|
)
 | 
						|
 | 
						|
// from_bytes converts a byte array into a bitfield.
 | 
						|
// [0x0F, 0x01] => 0000 1111 0000 0001
 | 
						|
pub fn from_bytes(input []u8) BitField {
 | 
						|
	mut output := new(input.len * 8)
 | 
						|
	for i, b in input {
 | 
						|
		mut ob := u8(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
 | 
						|
}
 | 
						|
 | 
						|
// from_bytes_lowest_bits_first converts a byte array into a bitfield
 | 
						|
// [0x0F, 0x01] => 1111 0000 1000 0000
 | 
						|
pub fn from_bytes_lowest_bits_first(input []u8) BitField {
 | 
						|
	mut output := new(input.len * 8)
 | 
						|
	for i, b in input {
 | 
						|
		output.field[i / 4] |= u32(b) << ((i % 4) * 8)
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// from_str converts a string of characters ('0' and '1') to a bit
 | 
						|
// array. Any character different from '0' is treated as '1'.
 | 
						|
pub fn from_str(input string) BitField {
 | 
						|
	mut output := new(input.len)
 | 
						|
	for i in 0 .. input.len {
 | 
						|
		if input[i] != `0` {
 | 
						|
			output.set_bit(i)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// str converts the bit array to a string of characters ('0' and '1') and
 | 
						|
// return the string
 | 
						|
pub fn (input BitField) str() string {
 | 
						|
	mut output := ''
 | 
						|
	for i in 0 .. input.size {
 | 
						|
		if input.get_bit(i) == 1 {
 | 
						|
			output = output + '1'
 | 
						|
		} else {
 | 
						|
			output = output + '0'
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// new creates an empty bit array of capable of storing 'size' bits.
 | 
						|
pub fn new(size int) BitField {
 | 
						|
	output := BitField{
 | 
						|
		size: size
 | 
						|
		// field: *u32(calloc(zbitnslots(size) * slot_size / 8))
 | 
						|
		field: []u32{len: zbitnslots(size)}
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// frees the memory allocated for the bitfield instance
 | 
						|
[unsafe]
 | 
						|
pub fn (instance &BitField) free() {
 | 
						|
	unsafe {
 | 
						|
		instance.field.free()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// 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 {
 | 
						|
	if bitnr >= instance.size {
 | 
						|
		return 0
 | 
						|
	}
 | 
						|
	return int((instance.field[bitslot(bitnr)] >> (bitnr % bitfield.slot_size)) & u32(1))
 | 
						|
}
 | 
						|
 | 
						|
// set_bit sets bit number 'bit_nr' to 1 (count from 0).
 | 
						|
pub fn (mut instance BitField) set_bit(bitnr int) {
 | 
						|
	if bitnr >= instance.size {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	instance.field[bitslot(bitnr)] |= bitmask(bitnr)
 | 
						|
}
 | 
						|
 | 
						|
// clear_bit clears (sets to zero) bit number 'bit_nr' (count from 0).
 | 
						|
pub fn (mut instance BitField) clear_bit(bitnr int) {
 | 
						|
	if bitnr >= instance.size {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	instance.field[bitslot(bitnr)] &= ~bitmask(bitnr)
 | 
						|
}
 | 
						|
 | 
						|
// extract returns the value converted from a slice of bit numbers
 | 
						|
// from 'start' by the length of 'len'.
 | 
						|
// 0101 (1, 2) => 0b10
 | 
						|
pub fn (instance BitField) extract(start int, len int) u64 {
 | 
						|
	// panic?
 | 
						|
	if start < 0 {
 | 
						|
		return 0
 | 
						|
	}
 | 
						|
	mut output := u64(0)
 | 
						|
	for i in 0 .. len {
 | 
						|
		output |= u64(instance.get_bit(start + len - i - 1)) << i
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// insert sets bit numbers from 'start' to 'len' length with
 | 
						|
// the value converted from the number 'value'.
 | 
						|
// 0000 (1, 2, 0b10) => 0100
 | 
						|
pub fn (mut instance BitField) insert<T>(start int, len int, _value T) {
 | 
						|
	// panic?
 | 
						|
	if start < 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	mut value := _value
 | 
						|
	for i in 0 .. len {
 | 
						|
		pos := start + len - i - 1
 | 
						|
		if value & 1 == 1 {
 | 
						|
			instance.set_bit(pos)
 | 
						|
		} else {
 | 
						|
			instance.clear_bit(pos)
 | 
						|
		}
 | 
						|
		value >>= 1
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// extract returns the value converted from a slice of bit numbers
 | 
						|
// from 'start' by the length of 'len'.
 | 
						|
// 0101 (1, 2) => 0b01
 | 
						|
pub fn (instance BitField) extract_lowest_bits_first(start int, len int) u64 {
 | 
						|
	// panic?
 | 
						|
	if start < 0 {
 | 
						|
		return 0
 | 
						|
	}
 | 
						|
	mut output := u64(0)
 | 
						|
	for i in 0 .. len {
 | 
						|
		output |= u64(instance.get_bit(start + i)) << i
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// insert sets bit numbers from 'start' to 'len' length with
 | 
						|
// the value converted from the number 'value'.
 | 
						|
// 0000 (1, 2, 0b10) => 0010
 | 
						|
pub fn (mut instance BitField) insert_lowest_bits_first<T>(start int, len int, _value T) {
 | 
						|
	// panic?
 | 
						|
	if start < 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	mut value := _value
 | 
						|
	for pos in start .. start + len {
 | 
						|
		if value & 1 == 1 {
 | 
						|
			instance.set_bit(pos)
 | 
						|
		} else {
 | 
						|
			instance.clear_bit(pos)
 | 
						|
		}
 | 
						|
		value >>= 1
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// set_all sets all bits in the array to 1.
 | 
						|
pub fn (mut instance BitField) set_all() {
 | 
						|
	for i in 0 .. zbitnslots(instance.size) {
 | 
						|
		instance.field[i] = u32(-1)
 | 
						|
	}
 | 
						|
	instance.clear_tail()
 | 
						|
}
 | 
						|
 | 
						|
// clear_all clears (sets to zero) all bits in the array.
 | 
						|
pub fn (mut instance BitField) clear_all() {
 | 
						|
	for i in 0 .. zbitnslots(instance.size) {
 | 
						|
		instance.field[i] = u32(0)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// toggle_bit changes the value (from 0 to 1 or from 1 to 0) of bit
 | 
						|
// number 'bit_nr'.
 | 
						|
pub fn (mut instance BitField) toggle_bit(bitnr int) {
 | 
						|
	if bitnr >= instance.size {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	instance.field[bitslot(bitnr)] ^= bitmask(bitnr)
 | 
						|
}
 | 
						|
 | 
						|
// bf_and performs logical AND operation on every pair of bits from 'input1' and
 | 
						|
// 'input2' and returns the result as a new array. If inputs differ in size,
 | 
						|
// the tail of the longer one is ignored.
 | 
						|
pub fn bf_and(input1 BitField, input2 BitField) BitField {
 | 
						|
	size := min(input1.size, input2.size)
 | 
						|
	bitnslots := zbitnslots(size)
 | 
						|
	mut output := new(size)
 | 
						|
	for i in 0 .. bitnslots {
 | 
						|
		output.field[i] = input1.field[i] & input2.field[i]
 | 
						|
	}
 | 
						|
	output.clear_tail()
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// bf_not toggles all bits in a bit array and returns the result as a new array.
 | 
						|
pub fn bf_not(input BitField) BitField {
 | 
						|
	size := input.size
 | 
						|
	bitnslots := zbitnslots(size)
 | 
						|
	mut output := new(size)
 | 
						|
	for i in 0 .. bitnslots {
 | 
						|
		output.field[i] = ~input.field[i]
 | 
						|
	}
 | 
						|
	output.clear_tail()
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// bf_or performs logical OR operation on every pair of bits from 'input1' and
 | 
						|
// 'input2' and returns the result as a new array. If inputs differ in size,
 | 
						|
// the tail of the longer one is ignored.
 | 
						|
pub fn bf_or(input1 BitField, input2 BitField) BitField {
 | 
						|
	size := min(input1.size, input2.size)
 | 
						|
	bitnslots := zbitnslots(size)
 | 
						|
	mut output := new(size)
 | 
						|
	for i in 0 .. bitnslots {
 | 
						|
		output.field[i] = input1.field[i] | input2.field[i]
 | 
						|
	}
 | 
						|
	output.clear_tail()
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// bf_xor perform logical XOR operation on every pair of bits from 'input1' and
 | 
						|
// 'input2' and returns the result as a new array. If inputs differ in size,
 | 
						|
// the tail of the longer one is ignored.
 | 
						|
pub fn bf_xor(input1 BitField, input2 BitField) BitField {
 | 
						|
	size := min(input1.size, input2.size)
 | 
						|
	bitnslots := zbitnslots(size)
 | 
						|
	mut output := new(size)
 | 
						|
	for i in 0 .. bitnslots {
 | 
						|
		output.field[i] = input1.field[i] ^ input2.field[i]
 | 
						|
	}
 | 
						|
	output.clear_tail()
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// join concatenates two bit arrays and return the result as a new array.
 | 
						|
pub fn join(input1 BitField, input2 BitField) BitField {
 | 
						|
	output_size := input1.size + input2.size
 | 
						|
	mut output := new(output_size)
 | 
						|
	// copy the first input to output as is
 | 
						|
	for i in 0 .. zbitnslots(input1.size) {
 | 
						|
		output.field[i] = input1.field[i]
 | 
						|
	}
 | 
						|
	// find offset bit and offset slot
 | 
						|
	offset_bit := input1.size % bitfield.slot_size
 | 
						|
	offset_slot := input1.size / bitfield.slot_size
 | 
						|
	for i in 0 .. zbitnslots(input2.size) {
 | 
						|
		output.field[i + offset_slot] |= u32(input2.field[i] << u32(offset_bit))
 | 
						|
	}
 | 
						|
	/*
 | 
						|
	* If offset_bit is not zero, additional operations are needed.
 | 
						|
	 * Number of iterations depends on the nr of slots in output. Two
 | 
						|
	 * options:
 | 
						|
	 * (a) nr of slots in output is the sum of inputs' slots. In this
 | 
						|
	 * case, the nr of bits in the last slot of output is less than the
 | 
						|
	 * nr of bits in the second input (i.e. ), OR
 | 
						|
	 * (b) nr of slots of output is the sum of inputs' slots less one
 | 
						|
	 * (i.e. less iterations needed). In this case, the nr of bits in
 | 
						|
	 * the last slot of output is greater than the nr of bits in the second
 | 
						|
	 * input.
 | 
						|
	 * If offset_bit is zero, no additional copies needed.
 | 
						|
	*/
 | 
						|
	if (output_size - 1) % bitfield.slot_size < (input2.size - 1) % bitfield.slot_size {
 | 
						|
		for i in 0 .. zbitnslots(input2.size) {
 | 
						|
			output.field[i + offset_slot + 1] |= u32(input2.field[i] >> u32(bitfield.slot_size - offset_bit))
 | 
						|
		}
 | 
						|
	} else if (output_size - 1) % bitfield.slot_size > (input2.size - 1) % bitfield.slot_size {
 | 
						|
		for i in 0 .. zbitnslots(input2.size) - 1 {
 | 
						|
			output.field[i + offset_slot + 1] |= u32(input2.field[i] >> u32(bitfield.slot_size - offset_bit))
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// get_size returns the number of bits the array can hold.
 | 
						|
pub fn (instance BitField) get_size() int {
 | 
						|
	return instance.size
 | 
						|
}
 | 
						|
 | 
						|
// clone creates a copy of a bit array.
 | 
						|
pub fn (instance BitField) clone() BitField {
 | 
						|
	bitnslots := zbitnslots(instance.size)
 | 
						|
	mut output := new(instance.size)
 | 
						|
	for i in 0 .. bitnslots {
 | 
						|
		output.field[i] = instance.field[i]
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// == compares 2 bitfields, and returns true when they are equal
 | 
						|
pub fn (a BitField) == (b BitField) bool {
 | 
						|
	if a.size != b.size {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	for i in 0 .. zbitnslots(a.size) {
 | 
						|
		if a.field[i] != b.field[i] {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
// pop_count returns the number of set bits (ones) in the array.
 | 
						|
pub fn (instance BitField) pop_count() int {
 | 
						|
	size := instance.size
 | 
						|
	bitnslots := zbitnslots(size)
 | 
						|
	tail := size % bitfield.slot_size
 | 
						|
	mut count := 0
 | 
						|
	for i in 0 .. bitnslots - 1 {
 | 
						|
		for j in 0 .. bitfield.slot_size {
 | 
						|
			if u32(instance.field[i] >> u32(j)) & u32(1) == u32(1) {
 | 
						|
				count++
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	for j in 0 .. tail {
 | 
						|
		if u32(instance.field[bitnslots - 1] >> u32(j)) & u32(1) == u32(1) {
 | 
						|
			count++
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return count
 | 
						|
}
 | 
						|
 | 
						|
// hamming computes the Hamming distance between two bit arrays.
 | 
						|
pub fn hamming(input1 BitField, input2 BitField) int {
 | 
						|
	input_xored := bf_xor(input1, input2)
 | 
						|
	return input_xored.pop_count()
 | 
						|
}
 | 
						|
 | 
						|
// 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 {
 | 
						|
	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 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
 | 
						|
}
 | 
						|
 | 
						|
// slice returns 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 {
 | 
						|
	// boundary checks
 | 
						|
	mut start := _start
 | 
						|
	mut end := _end
 | 
						|
	if end > input.size {
 | 
						|
		end = input.size // or panic?
 | 
						|
	}
 | 
						|
	if start > end {
 | 
						|
		start = end // or panic?
 | 
						|
	}
 | 
						|
	mut output := new(end - start)
 | 
						|
	start_offset := start % bitfield.slot_size
 | 
						|
	end_offset := (end - 1) % bitfield.slot_size
 | 
						|
	start_slot := start / bitfield.slot_size
 | 
						|
	end_slot := (end - 1) / bitfield.slot_size
 | 
						|
	output_slots := zbitnslots(end - start)
 | 
						|
	if output_slots > 1 {
 | 
						|
		if start_offset != 0 {
 | 
						|
			for i in 0 .. output_slots - 1 {
 | 
						|
				output.field[i] = u32(input.field[start_slot + i] >> u32(start_offset))
 | 
						|
				output.field[i] = output.field[i] | u32(input.field[start_slot + i + 1] << u32(bitfield.slot_size - start_offset))
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			for i in 0 .. output_slots - 1 {
 | 
						|
				output.field[i] = u32(input.field[start_slot + i])
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if start_offset > end_offset {
 | 
						|
		output.field[(end - start - 1) / bitfield.slot_size] = u32(input.field[end_slot - 1] >> u32(start_offset))
 | 
						|
		mut mask := u32((1 << (end_offset + 1)) - 1)
 | 
						|
		mask = input.field[end_slot] & mask
 | 
						|
		mask = u32(mask << u32(bitfield.slot_size - start_offset))
 | 
						|
		output.field[(end - start - 1) / bitfield.slot_size] |= mask
 | 
						|
	} else if start_offset == 0 {
 | 
						|
		mut mask := u32(0)
 | 
						|
		if end_offset == bitfield.slot_size - 1 {
 | 
						|
			mask = u32(-1)
 | 
						|
		} else {
 | 
						|
			mask = u32(u32(1) << u32(end_offset + 1))
 | 
						|
			mask = mask - u32(1)
 | 
						|
		}
 | 
						|
		output.field[(end - start - 1) / bitfield.slot_size] = (input.field[end_slot] & mask)
 | 
						|
	} else {
 | 
						|
		mut mask := u32(((1 << (end_offset - start_offset + 1)) - 1) << start_offset)
 | 
						|
		mask = input.field[end_slot] & mask
 | 
						|
		mask = u32(mask >> u32(start_offset))
 | 
						|
		output.field[(end - start - 1) / bitfield.slot_size] |= mask
 | 
						|
	}
 | 
						|
	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 BitField) reverse() BitField {
 | 
						|
	size := instance.size
 | 
						|
	bitnslots := zbitnslots(size)
 | 
						|
	mut output := new(size)
 | 
						|
	for i := 0; i < (bitnslots - 1); i++ {
 | 
						|
		for j in 0 .. bitfield.slot_size {
 | 
						|
			if u32(instance.field[i] >> u32(j)) & u32(1) == u32(1) {
 | 
						|
				output.set_bit(size - i * bitfield.slot_size - j - 1)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	bits_in_last_input_slot := (size - 1) % bitfield.slot_size + 1
 | 
						|
	for j in 0 .. bits_in_last_input_slot {
 | 
						|
		if u32(instance.field[bitnslots - 1] >> u32(j)) & u32(1) == u32(1) {
 | 
						|
			output.set_bit(bits_in_last_input_slot - j - 1)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return output
 | 
						|
}
 | 
						|
 | 
						|
// resize changes the size of the bit array to 'new_size'.
 | 
						|
pub fn (mut instance BitField) resize(new_size int) {
 | 
						|
	new_bitnslots := zbitnslots(new_size)
 | 
						|
	old_size := instance.size
 | 
						|
	old_bitnslots := zbitnslots(old_size)
 | 
						|
	mut field := []u32{len: new_bitnslots}
 | 
						|
	for i := 0; i < old_bitnslots && i < new_bitnslots; i++ {
 | 
						|
		field[i] = instance.field[i]
 | 
						|
	}
 | 
						|
	instance.field = field.clone()
 | 
						|
	instance.size = new_size
 | 
						|
	if new_size < old_size && new_size % bitfield.slot_size != 0 {
 | 
						|
		instance.clear_tail()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// rotate circular-shifts 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 {
 | 
						|
	/*
 | 
						|
	*
 | 
						|
	 * 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
 | 
						|
}
 | 
						|
 | 
						|
// Internal functions
 | 
						|
// clear_tail clears the extra bits that are not part of the bitfield, but yet are allocated
 | 
						|
fn (mut instance BitField) clear_tail() {
 | 
						|
	tail := instance.size % bitfield.slot_size
 | 
						|
	if tail != 0 {
 | 
						|
		// create a mask for the tail
 | 
						|
		mask := u32((1 << tail) - 1)
 | 
						|
		// clear the extra bits
 | 
						|
		instance.field[zbitnslots(instance.size) - 1] = instance.field[zbitnslots(instance.size) - 1] & mask
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// bitmask is the bitmask needed to access a particular bit at offset bitnr
 | 
						|
fn bitmask(bitnr int) u32 {
 | 
						|
	return u32(u32(1) << u32(bitnr % bitfield.slot_size))
 | 
						|
}
 | 
						|
 | 
						|
// bitslot is the slot index (i.e. the integer) where a particular bit is located
 | 
						|
fn bitslot(size int) int {
 | 
						|
	return size / bitfield.slot_size
 | 
						|
}
 | 
						|
 | 
						|
// min returns the minimum of 2 integers; it is here to avoid importing math just for that
 | 
						|
fn min(input1 int, input2 int) int {
 | 
						|
	if input1 < input2 {
 | 
						|
		return input1
 | 
						|
	} else {
 | 
						|
		return input2
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// zbitnslots returns the minimum number of whole integers, needed to represent a bitfield of size length
 | 
						|
fn zbitnslots(length int) int {
 | 
						|
	return (length - 1) / bitfield.slot_size + 1
 | 
						|
}
 |