Creating 8 bit binary data from 4,3, and 1 bit data in Golang - go

I need to form a header (8 bits) using a version (4 bits), count (3 bits), identifier (1 bit). How can I achieve this in Go? For example:
version: 1 (0001)
count: 3 (011)
identifier: 1(1)
Header: 00010111 (23)
I'm doing the following which works but there's a lot of cumbersome code. How can I do this efficiently?
const (
VersionSize binary.Bits = 4
countSize binary.Bits = 3
IdentifierSize binary.Bits = 1
)
type header struct {
version uint8
count uint8
identifier uint8
}
func main() {
headerObj := &header{version:1, count:3, identifier:1}
headerBytes := encode(headerObj)
// prints [23]
fmt.PrintLn(headerBytes)
}
func (h *header) encode() []byte {
var header []byte
vercountIdBinary := toBinary(h.version, versionSize) + toBinary(h.count,countSize) + toBinary(h.identifier, IdentifierSize)
vercountIdByte, _ := strconv.ParseInt(vercountIdBinary, 2, 8)
header = append(header, byte(vercountIdByte))
return header
}
func toBinary(value interface{}, bitSize binary.Bits) string {
format := "%0" + strconv.Itoa(int(bitSize)) + "b"
return fmt.Sprintf(format, value)
}

Packing and unpacking bits into a number can be achieved simply with bit masking and shifting.
For example to pack bits into a number, mask and assign the first, then shift left the result with the bits number or the next data (to make enough room for it). Then mask the 2nd number, and "add" it using bitwise OR. Then shift again with the size of the 3rd number, and repeat.
To unpack: mask the result with the size of the last field, and you got the last number. Shift right the data with the size of the decoded number, and mask with the next (in reverse order) number's size, and you got the number. Repeat this process until you have decoded all numbers.
For example, this packs identifier to most significant bits, count in middle and version to least significant bits, but you may do the opposite order by packing fields in reverse order:
const (
BitsVersion = 4
BitsCount = 3
BitsId = 1
)
const (
MaskVersion = 1<<BitsVersion - 1
MaskCount = 1<<BitsCount - 1
MaskId = 1<<BitsId - 1
)
type header struct {
version uint8
count uint8
identifier uint8
}
func (h *header) ToByte() uint8 {
var b uint8
b = h.identifier & MaskId
b <<= BitsCount
b |= h.count & MaskCount
b <<= BitsVersion
b |= h.version & MaskVersion
return b
}
func (h *header) ParseByte(b uint8) {
h.version = b & MaskVersion
b >>= BitsVersion
h.count = b & MaskCount
b >>= BitsCount
h.identifier = b & MaskId
}
Testing it:
h := &header{
version: 3,
count: 2,
identifier: 1,
}
fmt.Printf("%+v\n", h)
b := h.ToByte()
h2 := &header{}
h2.ParseByte(b)
fmt.Printf("%+v\n", h2)
Which will output (try it on the Go Playground):
&{version:3 count:2 identifier:1}
&{version:3 count:2 identifier:1}
Note: the above example encodes the fields in id-count-version order. The order of fields doesn't matter as long as both the packing and unpacking works with the same order. If you need reverse order (version-count-id), simply reverse the order in which fields are packed / unpacked. Here's how to do that:
func (h *header) ToByte() uint8 {
var b uint8
b = h.version & MaskVersion
b <<= BitsCount
b |= h.count & MaskCount
b <<= BitsId
b |= h.identifier & MaskId
return b
}
func (h *header) ParseByte(b uint8) {
h.identifier = b & MaskId
b >>= BitsId
h.count = b & MaskCount
b >>= BitsCount
h.version = b & MaskVersion
}
This outputs the same. Try this one on the Go Playground.
Note that if you have to do this with multiple data, targeting an io.Writer stream, you may use the github.com/icza/bitio library (disclosure: I'm the author).

Related

How to unpack 2, 2 and 3 bits out of a byte

Assuming I have 3 bytes (2x2bits and 1x3bits) packed like this:
func pack(a, b, c byte) byte { // is there a more efficient way to pack them?
return a<<6 | b<<4 | c
}
func main() {
v := pack(1, 2, 6)
a := v >> 6
b := v >> 4 // wrong
c := v & 7
fmt.Println(v, a, b, c)
}
How do I unpack b?
You need to mask off the unused bits like you've already done for c. I also added masks to the pack function, to prevent accidental overlapping of values:
const (
threeBits = 0x7
twoBits = 0x3
)
func pack(a, b, c byte) byte {
return a<<6 | b&twoBits<<4 | c&threeBits
}
func main() {
v := pack(1, 2, 6)
a := v >> 6
b := v >> 4 & twoBits
c := v & threeBits
fmt.Println(v, a, b, c)
}

Compare bits in two arrays

I've got stuck with ex4.1 for the book which says:
Write a function that counts the number of bits that are different in two SHA256 hashes.
The partial solution I came up with is pasted below, but it's wrong - it counts number of different bytes not bits.
Could you please point me in the right direction?
package main
import (
"crypto/sha256"
"fmt"
)
var s1 string = "unodostresquatro"
var s2 string = "UNODOSTRESQUATRO"
var h1 = sha256.Sum256([]byte(s1))
var h2 = sha256.Sum256([]byte(s2))
func main() {
fmt.Printf("s1: %s h1: %X h1 type: %T\n", s1, h1, h1)
fmt.Printf("s2: %s h2: %X h2 type: %T\n", s2, h2, h2)
fmt.Printf("Number of different bits: %d\n", 8 * DifferentBits(h1, h2))
}
func DifferentBits(c1 [32]uint8, c2 [32]uint8) int {
var counter int
for x := range c1 {
if c1[x] != c2[x] {
counter += 1
}
}
return counter
}
The Go Programming Language
Alan A. A. Donovan · Brian W.Kernighan
Exercise 4.1: Write a function that counts the number of bits that
are different in two SHA256 hashes.
The C Programming Language
Brian W.Kernighan · Dennis M. Ritchie
Exercise 2-9. In a two's complement number system, x &= (x-1) deletes
the rightmost 1-bit in x. Use this observation to write a faster
version of bitcount.
Bit Twiddling Hacks
Sean Eron Anderson
Counting bits set, Brian Kernighan's way
unsigned int v; // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v; c++)
{
v &= v - 1; // clear the least significant bit set
}
For exercise 4.1, you are counting the number of bytes that are different. Count the number of bits that are different. For example,
package main
import (
"crypto/sha256"
"fmt"
)
func BitsDifference(h1, h2 *[sha256.Size]byte) int {
n := 0
for i := range h1 {
for b := h1[i] ^ h2[i]; b != 0; b &= b - 1 {
n++
}
}
return n
}
func main() {
s1 := "unodostresquatro"
s2 := "UNODOSTRESQUATRO"
h1 := sha256.Sum256([]byte(s1))
h2 := sha256.Sum256([]byte(s2))
fmt.Println(BitsDifference(&h1, &h2))
}
Output:
139
Here is how I would do it
package main
import (
"crypto/sha256"
"fmt"
)
var (
s1 string = "unodostresquatro"
s2 string = "UNODOSTRESQUATRO"
h1 = sha256.Sum256([]byte(s1))
h2 = sha256.Sum256([]byte(s2))
)
func main() {
fmt.Printf("s1: %s h1: %X h1 type: %T\n", s1, h1, h1)
fmt.Printf("s2: %s h2: %X h2 type: %T\n", s2, h2, h2)
fmt.Printf("Number of different bits: %d\n", DifferentBits(h1, h2))
}
// bitCount counts the number of bits set in x
func bitCount(x uint8) int {
count := 0
for x != 0 {
x &= x - 1
count++
}
return count
}
func DifferentBits(c1 [32]uint8, c2 [32]uint8) int {
var counter int
for x := range c1 {
counter += bitCount(c1[x] ^ c2[x])
}
return counter
}
Playground

getting bits out of a 32bit unsigned integer using bitshift in go lang

I have a 32bit unsigned integer and I want to divide it in 3 uint16 values. I want first 15bits, then 2 bits and then last 15 bits.
I am trying something like -
val >> 17
val >> 2
val >> 15
apart from first value, other 2 are not right and I know that but now able to figure out how to fix that?
Go play ground
For example,
package main
import "fmt"
func decode(bits uint32) (uint16, uint16, uint16) {
// first 15bits, then 2 bits and then last 15 bits.
const mask2 = ^uint32(0) >> (32 - 2)
const mask15 = ^uint32(0) >> (32 - 15)
b1 := uint16(bits >> (32 - 15))
b2 := uint16(bits >> (32 - 15 - 2) & mask2)
b3 := uint16(bits & mask15)
return b1, b2, b3
}
func main() {
b := uint32(4628440)
b1, b2, b3 := decode(b)
fmt.Printf("%032b %015b %02b %015b\n", b, b1, b2, b3)
fmt.Printf("%d %d-%d-%d\n", b, b1, b2, b3)
}
Output:
00000000010001101001111111011000 000000000100011 01 001111111011000
4628440 35-1-8152
A helper function to extract a range of bits makes this easy to understand (and test).
package main
import "fmt"
// extractUint16 extracts n bits of a from the given offset.
func extractUint16(a uint32, offset, n uint) uint16 {
return uint16((a >> offset) & (1<<n - 1))
}
func main() {
input := uint32(4628440)
a := extractUint16(input, 17, 15)
b := extractUint16(input, 15, 2)
c := extractUint16(input, 0, 15)
fmt.Println(a, b, c)
}

Convert rune to int?

In the following code, I iterate over a string rune by rune, but I'll actually need an int to perform some checksum calculation. Do I really need to encode the rune into a []byte, then convert it to a string and then use Atoi to get an int out of the rune? Is this the idiomatic way to do it?
// The string `s` only contains digits.
var factor int
for i, c := range s[:12] {
if i % 2 == 0 {
factor = 1
} else {
factor = 3
}
buf := make([]byte, 1)
_ = utf8.EncodeRune(buf, c)
value, _ := strconv.Atoi(string(buf))
sum += value * factor
}
On the playground: http://play.golang.org/p/noWDYjn5rJ
The problem is simpler than it looks. You convert a rune value to an int value with int(r). But your code implies you want the integer value out of the ASCII (or UTF-8) representation of the digit, which you can trivially get with r - '0' as a rune, or int(r - '0') as an int. Be aware that out-of-range runes will corrupt that logic.
For example, sum += (int(c) - '0') * factor,
package main
import (
"fmt"
"strconv"
"unicode/utf8"
)
func main() {
s := "9780486653556"
var factor, sum1, sum2 int
for i, c := range s[:12] {
if i%2 == 0 {
factor = 1
} else {
factor = 3
}
buf := make([]byte, 1)
_ = utf8.EncodeRune(buf, c)
value, _ := strconv.Atoi(string(buf))
sum1 += value * factor
sum2 += (int(c) - '0') * factor
}
fmt.Println(sum1, sum2)
}
Output:
124 124
why don't you do only "string(rune)".
s:="12345678910"
var factor,sum int
for i,x:=range s{
if i%2==0{
factor=1
}else{
factor=3
}
xstr:=string(x) //x is rune converted to string
xint,_:=strconv.Atoi(xstr)
sum+=xint*factor
}
fmt.Println(sum)
val, _ := strconv.Atoi(string(v))
Where v is a rune
More concise but same idea as above

Returning the lenght of a vector idiomatically

I'm writing a function that returns a sequence of numbers of variable length:
func fib(n int) ??? {
retval := ???
a, b := 0, 1
for ; n > 0; n-- {
??? // append a onto retval here
c := a + b
a = b
b = c
}
}
It can be observed that the final length of the returned sequence will be n. How and what should fib return to achieve idiomatic Go? If the length was not known in advance, how would the return value, and usage differ? How do I insert values into retval?
Here, we know how many numbers; we want n Fibonacci numbers.
package main
import "fmt"
func fib(n int) (f []int) {
if n < 0 {
n = 0
}
f = make([]int, n)
a, b := 0, 1
for i := 0; i < len(f); i++ {
f[i] = a
a, b = b, a+b
}
return
}
func main() {
f := fib(7)
fmt.Println(len(f), f)
}
Output: 7 [0 1 1 2 3 5 8]
Here, we don't know how many numbers; we want all the Fibonacci numbers less than or equal to n.
package main
import "fmt"
func fibMax(n int) (f []int) {
a, b := 0, 1
for a <= n {
f = append(f, a)
a, b = b, a+b
}
return
}
func main() {
f := fibMax(42)
fmt.Println(len(f), f)
}
Output: 10 [0 1 1 2 3 5 8 13 21 34]
You could also use IntVector from the Go vector package. Note that type IntVector []int.
Don't use Vectors, use slices. Here are some mapping of various vector operations to idiomatic slice operations.

Resources