influxdb/pkg/encoding/simple8b/encoding.go

997 lines
22 KiB
Go
Raw Normal View History

2018-09-28 14:51:47 +00:00
// Package simple8b implements the 64bit integer encoding algoritm as published
// by Ann and Moffat in "Index compression using 64-bit words", Softw. Pract. Exper. 2010; 40:131147
//
// It is capable of encoding multiple integers with values betweeen 0 and to 1^60 -1, in a single word.
//
// Imported from github.com/jwilder/encoding
package simple8b
// Simple8b is 64bit word-sized encoder that packs multiple integers into a single word using
// a 4 bit selector values and up to 60 bits for the remaining values. Integers are encoded using
// the following table:
//
// ┌──────────────┬─────────────────────────────────────────────────────────────┐
// │ Selector │ 0 1 2 3 4 5 6 7 8 9 0 11 12 13 14 15│
// ├──────────────┼─────────────────────────────────────────────────────────────┤
// │ Bits │ 0 0 1 2 3 4 5 6 7 8 10 12 15 20 30 60│
// ├──────────────┼─────────────────────────────────────────────────────────────┤
// │ N │ 240 120 60 30 20 15 12 10 8 7 6 5 4 3 2 1│
// ├──────────────┼─────────────────────────────────────────────────────────────┤
// │ Wasted Bits│ 60 60 0 0 0 0 12 0 4 4 0 0 0 0 0 0│
// └──────────────┴─────────────────────────────────────────────────────────────┘
//
// For example, when the number of values can be encoded using 4 bits, selected 5 is encoded in the
// 4 most significant bits followed by 15 values encoded used 4 bits each in the remaing 60 bits.
import (
"encoding/binary"
"errors"
"fmt"
"unsafe"
)
const MaxValue = (1 << 60) - 1
// Encoder converts a stream of unsigned 64bit integers to a compressed byte slice.
type Encoder struct {
// most recently written integers that have not been flushed
buf []uint64
// index in buf of the head of the buf
h int
// index in buf of the tail of the buf
t int
// index into bytes of written bytes
bp int
// current bytes written and flushed
bytes []byte
b []byte
}
// NewEncoder returns an Encoder able to convert uint64s to compressed byte slices
func NewEncoder() *Encoder {
return &Encoder{
buf: make([]uint64, 240),
b: make([]byte, 8),
bytes: make([]byte, 128),
}
}
func (e *Encoder) SetValues(v []uint64) {
e.buf = v
e.t = len(v)
e.h = 0
e.bytes = e.bytes[:0]
}
func (e *Encoder) Reset() {
e.t = 0
e.h = 0
e.bp = 0
e.buf = e.buf[:240]
e.b = e.b[:8]
e.bytes = e.bytes[:128]
}
func (e *Encoder) Write(v uint64) error {
if e.t >= len(e.buf) {
if err := e.flush(); err != nil {
return err
}
}
// The buf is full but there is space at the front, just shift
// the values down for now. TODO: use ring buffer
if e.t >= len(e.buf) {
copy(e.buf, e.buf[e.h:])
e.t -= e.h
e.h = 0
}
e.buf[e.t] = v
e.t += 1
return nil
}
func (e *Encoder) flush() error {
if e.t == 0 {
return nil
}
// encode as many values into one as we can
encoded, n, err := Encode(e.buf[e.h:e.t])
if err != nil {
return err
}
binary.BigEndian.PutUint64(e.b, encoded)
if e.bp+8 > len(e.bytes) {
e.bytes = append(e.bytes, e.b...)
e.bp = len(e.bytes)
} else {
copy(e.bytes[e.bp:e.bp+8], e.b)
e.bp += 8
}
// Move the head forward since we encoded those values
e.h += n
// If we encoded them all, reset the head/tail pointers to the beginning
if e.h == e.t {
e.h = 0
e.t = 0
}
return nil
}
func (e *Encoder) Bytes() ([]byte, error) {
for e.t > 0 {
if err := e.flush(); err != nil {
return nil, err
}
}
return e.bytes[:e.bp], nil
}
// Decoder converts a compressed byte slice to a stream of unsigned 64bit integers.
type Decoder struct {
bytes []byte
buf [240]uint64
i int
n int
}
// NewDecoder returns a Decoder from a byte slice
func NewDecoder(b []byte) *Decoder {
return &Decoder{
bytes: b,
}
}
// Next returns true if there are remaining values to be read. Successive
// calls to Next advance the current element pointer.
func (d *Decoder) Next() bool {
d.i += 1
if d.i >= d.n {
d.read()
}
return len(d.bytes) >= 8 || (d.i >= 0 && d.i < d.n)
}
func (d *Decoder) SetBytes(b []byte) {
d.bytes = b
d.i = 0
d.n = 0
}
// Read returns the current value. Successive calls to Read return the same
// value.
func (d *Decoder) Read() uint64 {
v := d.buf[d.i]
return v
}
func (d *Decoder) read() {
if len(d.bytes) < 8 {
return
}
v := binary.BigEndian.Uint64(d.bytes[:8])
d.bytes = d.bytes[8:]
d.n, _ = Decode(&d.buf, v)
d.i = 0
}
type packing struct {
n, bit int
unpack func(uint64, *[240]uint64)
pack func([]uint64) uint64
}
var selector [16]packing = [16]packing{
packing{240, 0, unpack240, pack240},
packing{120, 0, unpack120, pack120},
packing{60, 1, unpack60, pack60},
packing{30, 2, unpack30, pack30},
packing{20, 3, unpack20, pack20},
packing{15, 4, unpack15, pack15},
packing{12, 5, unpack12, pack12},
packing{10, 6, unpack10, pack10},
packing{8, 7, unpack8, pack8},
packing{7, 8, unpack7, pack7},
packing{6, 10, unpack6, pack6},
packing{5, 12, unpack5, pack5},
packing{4, 15, unpack4, pack4},
packing{3, 20, unpack3, pack3},
packing{2, 30, unpack2, pack2},
packing{1, 60, unpack1, pack1},
}
// Count returns the number of integers encoded in the byte slice
func CountBytes(b []byte) (int, error) {
var count int
for len(b) >= 8 {
v := binary.BigEndian.Uint64(b[:8])
b = b[8:]
sel := v >> 60
if sel >= 16 {
return 0, fmt.Errorf("invalid selector value: %v", sel)
}
count += selector[sel].n
}
if len(b) > 0 {
return 0, fmt.Errorf("invalid slice len remaining: %v", len(b))
}
return count, nil
}
// Count returns the number of integers encoded within an uint64
func Count(v uint64) (int, error) {
sel := v >> 60
if sel >= 16 {
return 0, fmt.Errorf("invalid selector value: %v", sel)
}
return selector[sel].n, nil
}
func ForEach(b []byte, fn func(v uint64) bool) error {
for len(b) >= 8 {
v := binary.BigEndian.Uint64(b[:8])
b = b[8:]
sel := v >> 60
if sel >= 16 {
return fmt.Errorf("invalid selector value: %v", sel)
}
n := selector[sel].n
bits := uint(selector[sel].bit)
mask := uint64(^(int64(^0) << bits))
for i := 0; i < n; i++ {
val := v & mask
if !fn(val) {
return nil
}
v = v >> bits
}
}
return nil
}
func CountBytesBetween(b []byte, min, max uint64) (int, error) {
var count int
for len(b) >= 8 {
v := binary.BigEndian.Uint64(b[:8])
b = b[8:]
sel := v >> 60
if sel >= 16 {
return 0, fmt.Errorf("invalid selector value: %v", sel)
}
// If the max value that could be encoded by the uint64 is less than the min
// skip the whole thing.
maxValue := uint64((1 << uint64(selector[sel].bit)) - 1)
if maxValue < min {
continue
}
mask := uint64(^(int64(^0) << uint(selector[sel].bit)))
for i := 0; i < selector[sel].n; i++ {
val := v & mask
if val >= min && val < max {
count++
} else if val > max {
break
}
v = v >> uint(selector[sel].bit)
}
}
if len(b) > 0 {
return 0, fmt.Errorf("invalid slice len remaining: %v", len(b))
}
return count, nil
}
// Encode packs as many values into a single uint64. It returns the packed
// uint64, how many values from src were packed, or an error if the values exceed
// the maximum value range.
func Encode(src []uint64) (value uint64, n int, err error) {
if canPack(src, 240, 0) {
return uint64(0), 240, nil
} else if canPack(src, 120, 0) {
return 1 << 60, 120, nil
} else if canPack(src, 60, 1) {
return pack60(src[:60]), 60, nil
} else if canPack(src, 30, 2) {
return pack30(src[:30]), 30, nil
} else if canPack(src, 20, 3) {
return pack20(src[:20]), 20, nil
} else if canPack(src, 15, 4) {
return pack15(src[:15]), 15, nil
} else if canPack(src, 12, 5) {
return pack12(src[:12]), 12, nil
} else if canPack(src, 10, 6) {
return pack10(src[:10]), 10, nil
} else if canPack(src, 8, 7) {
return pack8(src[:8]), 8, nil
} else if canPack(src, 7, 8) {
return pack7(src[:7]), 7, nil
} else if canPack(src, 6, 10) {
return pack6(src[:6]), 6, nil
} else if canPack(src, 5, 12) {
return pack5(src[:5]), 5, nil
} else if canPack(src, 4, 15) {
return pack4(src[:4]), 4, nil
} else if canPack(src, 3, 20) {
return pack3(src[:3]), 3, nil
} else if canPack(src, 2, 30) {
return pack2(src[:2]), 2, nil
} else if canPack(src, 1, 60) {
return pack1(src[:1]), 1, nil
} else {
if len(src) > 0 {
return 0, 0, fmt.Errorf("value out of bounds: %v", src)
}
return 0, 0, nil
}
}
// Encode returns a packed slice of the values from src. If a value is over
// 1 << 60, an error is returned. The input src is modified to avoid extra
// allocations. If you need to re-use, use a copy.
func EncodeAll(src []uint64) ([]uint64, error) {
i := 0
// Re-use the input slice and write encoded values back in place
dst := src
j := 0
for {
if i >= len(src) {
break
}
remaining := src[i:]
if canPack(remaining, 240, 0) {
dst[j] = 0
i += 240
} else if canPack(remaining, 120, 0) {
dst[j] = 1 << 60
i += 120
} else if canPack(remaining, 60, 1) {
dst[j] = pack60(src[i : i+60])
i += 60
} else if canPack(remaining, 30, 2) {
dst[j] = pack30(src[i : i+30])
i += 30
} else if canPack(remaining, 20, 3) {
dst[j] = pack20(src[i : i+20])
i += 20
} else if canPack(remaining, 15, 4) {
dst[j] = pack15(src[i : i+15])
i += 15
} else if canPack(remaining, 12, 5) {
dst[j] = pack12(src[i : i+12])
i += 12
} else if canPack(remaining, 10, 6) {
dst[j] = pack10(src[i : i+10])
i += 10
} else if canPack(remaining, 8, 7) {
dst[j] = pack8(src[i : i+8])
i += 8
} else if canPack(remaining, 7, 8) {
dst[j] = pack7(src[i : i+7])
i += 7
} else if canPack(remaining, 6, 10) {
dst[j] = pack6(src[i : i+6])
i += 6
} else if canPack(remaining, 5, 12) {
dst[j] = pack5(src[i : i+5])
i += 5
} else if canPack(remaining, 4, 15) {
dst[j] = pack4(src[i : i+4])
i += 4
} else if canPack(remaining, 3, 20) {
dst[j] = pack3(src[i : i+3])
i += 3
} else if canPack(remaining, 2, 30) {
dst[j] = pack2(src[i : i+2])
i += 2
} else if canPack(remaining, 1, 60) {
dst[j] = pack1(src[i : i+1])
i += 1
} else {
return nil, fmt.Errorf("value out of bounds")
}
j += 1
}
return dst[:j], nil
}
func Decode(dst *[240]uint64, v uint64) (n int, err error) {
sel := v >> 60
if sel >= 16 {
return 0, fmt.Errorf("invalid selector value: %b", sel)
}
selector[sel].unpack(v, dst)
return selector[sel].n, nil
}
// Decode writes the uncompressed values from src to dst. It returns the number
// of values written or an error.
func DecodeAll(dst, src []uint64) (value int, err error) {
j := 0
for _, v := range src {
sel := v >> 60
if sel >= 16 {
return 0, fmt.Errorf("invalid selector value: %b", sel)
}
selector[sel].unpack(v, (*[240]uint64)(unsafe.Pointer(&dst[j])))
j += selector[sel].n
}
return j, nil
}
// DecodeBytesBigEndian writes the compressed, big-endian values from src to dst. It returns the number
// of values written or an error.
func DecodeBytesBigEndian(dst []uint64, src []byte) (value int, err error) {
if len(src)&7 != 0 {
return 0, errors.New("src length is not multiple of 8")
}
i := 0
j := 0
for i < len(src) {
v := binary.BigEndian.Uint64(src[i:])
sel := (v >> 60) & 0xf
selector[sel].unpack(v, (*[240]uint64)(unsafe.Pointer(&dst[j])))
j += selector[sel].n
i += 8
}
return j, nil
}
// canPack returs true if n elements from in can be stored using bits per element
func canPack(src []uint64, n, bits int) bool {
if len(src) < n {
return false
}
end := len(src)
if n < end {
end = n
}
// Selector 0,1 are special and use 0 bits to encode runs of 1's
if bits == 0 {
for _, v := range src {
if v != 1 {
return false
}
}
return true
}
max := uint64((1 << uint64(bits)) - 1)
for i := 0; i < end; i++ {
if src[i] > max {
return false
}
}
return true
}
// pack240 packs 240 ones from in using 1 bit each
func pack240(src []uint64) uint64 {
return 0
}
// pack120 packs 120 ones from in using 1 bit each
func pack120(src []uint64) uint64 {
return 0
}
// pack60 packs 60 values from in using 1 bit each
func pack60(src []uint64) uint64 {
return 2<<60 |
src[0] |
src[1]<<1 |
src[2]<<2 |
src[3]<<3 |
src[4]<<4 |
src[5]<<5 |
src[6]<<6 |
src[7]<<7 |
src[8]<<8 |
src[9]<<9 |
src[10]<<10 |
src[11]<<11 |
src[12]<<12 |
src[13]<<13 |
src[14]<<14 |
src[15]<<15 |
src[16]<<16 |
src[17]<<17 |
src[18]<<18 |
src[19]<<19 |
src[20]<<20 |
src[21]<<21 |
src[22]<<22 |
src[23]<<23 |
src[24]<<24 |
src[25]<<25 |
src[26]<<26 |
src[27]<<27 |
src[28]<<28 |
src[29]<<29 |
src[30]<<30 |
src[31]<<31 |
src[32]<<32 |
src[33]<<33 |
src[34]<<34 |
src[35]<<35 |
src[36]<<36 |
src[37]<<37 |
src[38]<<38 |
src[39]<<39 |
src[40]<<40 |
src[41]<<41 |
src[42]<<42 |
src[43]<<43 |
src[44]<<44 |
src[45]<<45 |
src[46]<<46 |
src[47]<<47 |
src[48]<<48 |
src[49]<<49 |
src[50]<<50 |
src[51]<<51 |
src[52]<<52 |
src[53]<<53 |
src[54]<<54 |
src[55]<<55 |
src[56]<<56 |
src[57]<<57 |
src[58]<<58 |
src[59]<<59
}
// pack30 packs 30 values from in using 2 bits each
func pack30(src []uint64) uint64 {
return 3<<60 |
src[0] |
src[1]<<2 |
src[2]<<4 |
src[3]<<6 |
src[4]<<8 |
src[5]<<10 |
src[6]<<12 |
src[7]<<14 |
src[8]<<16 |
src[9]<<18 |
src[10]<<20 |
src[11]<<22 |
src[12]<<24 |
src[13]<<26 |
src[14]<<28 |
src[15]<<30 |
src[16]<<32 |
src[17]<<34 |
src[18]<<36 |
src[19]<<38 |
src[20]<<40 |
src[21]<<42 |
src[22]<<44 |
src[23]<<46 |
src[24]<<48 |
src[25]<<50 |
src[26]<<52 |
src[27]<<54 |
src[28]<<56 |
src[29]<<58
}
// pack20 packs 20 values from in using 3 bits each
func pack20(src []uint64) uint64 {
return 4<<60 |
src[0] |
src[1]<<3 |
src[2]<<6 |
src[3]<<9 |
src[4]<<12 |
src[5]<<15 |
src[6]<<18 |
src[7]<<21 |
src[8]<<24 |
src[9]<<27 |
src[10]<<30 |
src[11]<<33 |
src[12]<<36 |
src[13]<<39 |
src[14]<<42 |
src[15]<<45 |
src[16]<<48 |
src[17]<<51 |
src[18]<<54 |
src[19]<<57
}
// pack15 packs 15 values from in using 3 bits each
func pack15(src []uint64) uint64 {
return 5<<60 |
src[0] |
src[1]<<4 |
src[2]<<8 |
src[3]<<12 |
src[4]<<16 |
src[5]<<20 |
src[6]<<24 |
src[7]<<28 |
src[8]<<32 |
src[9]<<36 |
src[10]<<40 |
src[11]<<44 |
src[12]<<48 |
src[13]<<52 |
src[14]<<56
}
// pack12 packs 12 values from in using 5 bits each
func pack12(src []uint64) uint64 {
return 6<<60 |
src[0] |
src[1]<<5 |
src[2]<<10 |
src[3]<<15 |
src[4]<<20 |
src[5]<<25 |
src[6]<<30 |
src[7]<<35 |
src[8]<<40 |
src[9]<<45 |
src[10]<<50 |
src[11]<<55
}
// pack10 packs 10 values from in using 6 bits each
func pack10(src []uint64) uint64 {
return 7<<60 |
src[0] |
src[1]<<6 |
src[2]<<12 |
src[3]<<18 |
src[4]<<24 |
src[5]<<30 |
src[6]<<36 |
src[7]<<42 |
src[8]<<48 |
src[9]<<54
}
// pack8 packs 8 values from in using 7 bits each
func pack8(src []uint64) uint64 {
return 8<<60 |
src[0] |
src[1]<<7 |
src[2]<<14 |
src[3]<<21 |
src[4]<<28 |
src[5]<<35 |
src[6]<<42 |
src[7]<<49
}
// pack7 packs 7 values from in using 8 bits each
func pack7(src []uint64) uint64 {
return 9<<60 |
src[0] |
src[1]<<8 |
src[2]<<16 |
src[3]<<24 |
src[4]<<32 |
src[5]<<40 |
src[6]<<48
}
// pack6 packs 6 values from in using 10 bits each
func pack6(src []uint64) uint64 {
return 10<<60 |
src[0] |
src[1]<<10 |
src[2]<<20 |
src[3]<<30 |
src[4]<<40 |
src[5]<<50
}
// pack5 packs 5 values from in using 12 bits each
func pack5(src []uint64) uint64 {
return 11<<60 |
src[0] |
src[1]<<12 |
src[2]<<24 |
src[3]<<36 |
src[4]<<48
}
// pack4 packs 4 values from in using 15 bits each
func pack4(src []uint64) uint64 {
return 12<<60 |
src[0] |
src[1]<<15 |
src[2]<<30 |
src[3]<<45
}
// pack3 packs 3 values from in using 20 bits each
func pack3(src []uint64) uint64 {
return 13<<60 |
src[0] |
src[1]<<20 |
src[2]<<40
}
// pack2 packs 2 values from in using 30 bits each
func pack2(src []uint64) uint64 {
return 14<<60 |
src[0] |
src[1]<<30
}
// pack1 packs 1 values from in using 60 bits each
func pack1(src []uint64) uint64 {
return 15<<60 |
src[0]
}
func unpack240(v uint64, dst *[240]uint64) {
for i := range dst {
dst[i] = 1
}
}
func unpack120(v uint64, dst *[240]uint64) {
for i := range dst[:120] {
dst[i] = 1
}
}
func unpack60(v uint64, dst *[240]uint64) {
dst[0] = v & 1
dst[1] = (v >> 1) & 1
dst[2] = (v >> 2) & 1
dst[3] = (v >> 3) & 1
dst[4] = (v >> 4) & 1
dst[5] = (v >> 5) & 1
dst[6] = (v >> 6) & 1
dst[7] = (v >> 7) & 1
dst[8] = (v >> 8) & 1
dst[9] = (v >> 9) & 1
dst[10] = (v >> 10) & 1
dst[11] = (v >> 11) & 1
dst[12] = (v >> 12) & 1
dst[13] = (v >> 13) & 1
dst[14] = (v >> 14) & 1
dst[15] = (v >> 15) & 1
dst[16] = (v >> 16) & 1
dst[17] = (v >> 17) & 1
dst[18] = (v >> 18) & 1
dst[19] = (v >> 19) & 1
dst[20] = (v >> 20) & 1
dst[21] = (v >> 21) & 1
dst[22] = (v >> 22) & 1
dst[23] = (v >> 23) & 1
dst[24] = (v >> 24) & 1
dst[25] = (v >> 25) & 1
dst[26] = (v >> 26) & 1
dst[27] = (v >> 27) & 1
dst[28] = (v >> 28) & 1
dst[29] = (v >> 29) & 1
dst[30] = (v >> 30) & 1
dst[31] = (v >> 31) & 1
dst[32] = (v >> 32) & 1
dst[33] = (v >> 33) & 1
dst[34] = (v >> 34) & 1
dst[35] = (v >> 35) & 1
dst[36] = (v >> 36) & 1
dst[37] = (v >> 37) & 1
dst[38] = (v >> 38) & 1
dst[39] = (v >> 39) & 1
dst[40] = (v >> 40) & 1
dst[41] = (v >> 41) & 1
dst[42] = (v >> 42) & 1
dst[43] = (v >> 43) & 1
dst[44] = (v >> 44) & 1
dst[45] = (v >> 45) & 1
dst[46] = (v >> 46) & 1
dst[47] = (v >> 47) & 1
dst[48] = (v >> 48) & 1
dst[49] = (v >> 49) & 1
dst[50] = (v >> 50) & 1
dst[51] = (v >> 51) & 1
dst[52] = (v >> 52) & 1
dst[53] = (v >> 53) & 1
dst[54] = (v >> 54) & 1
dst[55] = (v >> 55) & 1
dst[56] = (v >> 56) & 1
dst[57] = (v >> 57) & 1
dst[58] = (v >> 58) & 1
dst[59] = (v >> 59) & 1
}
func unpack30(v uint64, dst *[240]uint64) {
dst[0] = v & 3
dst[1] = (v >> 2) & 3
dst[2] = (v >> 4) & 3
dst[3] = (v >> 6) & 3
dst[4] = (v >> 8) & 3
dst[5] = (v >> 10) & 3
dst[6] = (v >> 12) & 3
dst[7] = (v >> 14) & 3
dst[8] = (v >> 16) & 3
dst[9] = (v >> 18) & 3
dst[10] = (v >> 20) & 3
dst[11] = (v >> 22) & 3
dst[12] = (v >> 24) & 3
dst[13] = (v >> 26) & 3
dst[14] = (v >> 28) & 3
dst[15] = (v >> 30) & 3
dst[16] = (v >> 32) & 3
dst[17] = (v >> 34) & 3
dst[18] = (v >> 36) & 3
dst[19] = (v >> 38) & 3
dst[20] = (v >> 40) & 3
dst[21] = (v >> 42) & 3
dst[22] = (v >> 44) & 3
dst[23] = (v >> 46) & 3
dst[24] = (v >> 48) & 3
dst[25] = (v >> 50) & 3
dst[26] = (v >> 52) & 3
dst[27] = (v >> 54) & 3
dst[28] = (v >> 56) & 3
dst[29] = (v >> 58) & 3
}
func unpack20(v uint64, dst *[240]uint64) {
dst[0] = v & 7
dst[1] = (v >> 3) & 7
dst[2] = (v >> 6) & 7
dst[3] = (v >> 9) & 7
dst[4] = (v >> 12) & 7
dst[5] = (v >> 15) & 7
dst[6] = (v >> 18) & 7
dst[7] = (v >> 21) & 7
dst[8] = (v >> 24) & 7
dst[9] = (v >> 27) & 7
dst[10] = (v >> 30) & 7
dst[11] = (v >> 33) & 7
dst[12] = (v >> 36) & 7
dst[13] = (v >> 39) & 7
dst[14] = (v >> 42) & 7
dst[15] = (v >> 45) & 7
dst[16] = (v >> 48) & 7
dst[17] = (v >> 51) & 7
dst[18] = (v >> 54) & 7
dst[19] = (v >> 57) & 7
}
func unpack15(v uint64, dst *[240]uint64) {
dst[0] = v & 15
dst[1] = (v >> 4) & 15
dst[2] = (v >> 8) & 15
dst[3] = (v >> 12) & 15
dst[4] = (v >> 16) & 15
dst[5] = (v >> 20) & 15
dst[6] = (v >> 24) & 15
dst[7] = (v >> 28) & 15
dst[8] = (v >> 32) & 15
dst[9] = (v >> 36) & 15
dst[10] = (v >> 40) & 15
dst[11] = (v >> 44) & 15
dst[12] = (v >> 48) & 15
dst[13] = (v >> 52) & 15
dst[14] = (v >> 56) & 15
}
func unpack12(v uint64, dst *[240]uint64) {
dst[0] = v & 31
dst[1] = (v >> 5) & 31
dst[2] = (v >> 10) & 31
dst[3] = (v >> 15) & 31
dst[4] = (v >> 20) & 31
dst[5] = (v >> 25) & 31
dst[6] = (v >> 30) & 31
dst[7] = (v >> 35) & 31
dst[8] = (v >> 40) & 31
dst[9] = (v >> 45) & 31
dst[10] = (v >> 50) & 31
dst[11] = (v >> 55) & 31
}
func unpack10(v uint64, dst *[240]uint64) {
dst[0] = v & 63
dst[1] = (v >> 6) & 63
dst[2] = (v >> 12) & 63
dst[3] = (v >> 18) & 63
dst[4] = (v >> 24) & 63
dst[5] = (v >> 30) & 63
dst[6] = (v >> 36) & 63
dst[7] = (v >> 42) & 63
dst[8] = (v >> 48) & 63
dst[9] = (v >> 54) & 63
}
func unpack8(v uint64, dst *[240]uint64) {
dst[0] = v & 127
dst[1] = (v >> 7) & 127
dst[2] = (v >> 14) & 127
dst[3] = (v >> 21) & 127
dst[4] = (v >> 28) & 127
dst[5] = (v >> 35) & 127
dst[6] = (v >> 42) & 127
dst[7] = (v >> 49) & 127
}
func unpack7(v uint64, dst *[240]uint64) {
dst[0] = v & 255
dst[1] = (v >> 8) & 255
dst[2] = (v >> 16) & 255
dst[3] = (v >> 24) & 255
dst[4] = (v >> 32) & 255
dst[5] = (v >> 40) & 255
dst[6] = (v >> 48) & 255
}
func unpack6(v uint64, dst *[240]uint64) {
dst[0] = v & 1023
dst[1] = (v >> 10) & 1023
dst[2] = (v >> 20) & 1023
dst[3] = (v >> 30) & 1023
dst[4] = (v >> 40) & 1023
dst[5] = (v >> 50) & 1023
}
func unpack5(v uint64, dst *[240]uint64) {
dst[0] = v & 4095
dst[1] = (v >> 12) & 4095
dst[2] = (v >> 24) & 4095
dst[3] = (v >> 36) & 4095
dst[4] = (v >> 48) & 4095
}
func unpack4(v uint64, dst *[240]uint64) {
dst[0] = v & 32767
dst[1] = (v >> 15) & 32767
dst[2] = (v >> 30) & 32767
dst[3] = (v >> 45) & 32767
}
func unpack3(v uint64, dst *[240]uint64) {
dst[0] = v & 1048575
dst[1] = (v >> 20) & 1048575
dst[2] = (v >> 40) & 1048575
}
func unpack2(v uint64, dst *[240]uint64) {
dst[0] = v & 1073741823
dst[1] = (v >> 30) & 1073741823
}
func unpack1(v uint64, dst *[240]uint64) {
dst[0] = v & 1152921504606846975
}