From e66de8e8242d8c2f141f5129033aca8637dec994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=8C=E3=82=82=E3=82=93?= Date: Sat, 10 Apr 2021 23:42:09 +0900 Subject: [PATCH] bitfield: add methods `insert` and `extract` (#9612) --- vlib/bitfield/bitfield.v | 69 +++++++++++++++++++++++++++++++++++ vlib/bitfield/bitfield_test.v | 14 +++++++ 2 files changed, 83 insertions(+) diff --git a/vlib/bitfield/bitfield.v b/vlib/bitfield/bitfield.v index 8b3b3c79bc..c666daa014 100644 --- a/vlib/bitfield/bitfield.v +++ b/vlib/bitfield/bitfield.v @@ -137,6 +137,75 @@ pub fn (mut instance BitField) clear_bit(bitnr int) { 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(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(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) { diff --git a/vlib/bitfield/bitfield_test.v b/vlib/bitfield/bitfield_test.v index 7bcc9e7860..0506264aa4 100644 --- a/vlib/bitfield/bitfield_test.v +++ b/vlib/bitfield/bitfield_test.v @@ -16,6 +16,20 @@ fn test_bf_set_clear_toggle_get() { assert instance.get_bit(47) == 1 } +fn test_bf_insert_extract() { + mut instance := bitfield.new(11) + instance.set_all() + instance.insert(2, 9, 3) + assert instance.extract(2, 1) == 0 + assert instance.extract(2, 8) == 1 + assert instance.extract(10, 1) == 1 + instance.set_all() + instance.insert_lowest_bits_first(2, 9, 3) + assert instance.extract_lowest_bits_first(2, 1) == 1 + assert instance.extract_lowest_bits_first(2, 8) == 3 + assert instance.extract_lowest_bits_first(10, 1) == 0 +} + fn test_bf_and_not_or_xor() { len := 80 mut input1 := bitfield.new(len)