1032 lines
22 KiB
Go
1032 lines
22 KiB
Go
// 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:131–147
|
||
//
|
||
// 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{
|
||
{240, 0, unpack240, pack240},
|
||
{120, 0, unpack120, pack120},
|
||
{60, 1, unpack60, pack60},
|
||
{30, 2, unpack30, pack30},
|
||
{20, 3, unpack20, pack20},
|
||
{15, 4, unpack15, pack15},
|
||
{12, 5, unpack12, pack12},
|
||
{10, 6, unpack10, pack10},
|
||
{8, 7, unpack8, pack8},
|
||
{7, 8, unpack7, pack7},
|
||
{6, 10, unpack6, pack6},
|
||
{5, 12, unpack5, pack5},
|
||
{4, 15, unpack4, pack4},
|
||
{3, 20, unpack3, pack3},
|
||
{2, 30, unpack2, pack2},
|
||
{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
|
||
}
|
||
}
|
||
|
||
const (
|
||
S8B_BIT_SIZE = 60
|
||
)
|
||
|
||
var (
|
||
numBits = [...][2]byte{
|
||
// { number of values, max bits per value }
|
||
{60, 1},
|
||
{30, 2},
|
||
{20, 3},
|
||
{15, 4},
|
||
{12, 5},
|
||
{10, 6},
|
||
{8, 7},
|
||
{7, 8},
|
||
{6, 10},
|
||
{5, 12},
|
||
{4, 15},
|
||
{3, 20},
|
||
{2, 30},
|
||
{1, 60},
|
||
}
|
||
ErrValueOutOfBounds = errors.New("value out of bounds")
|
||
)
|
||
|
||
// 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
|
||
|
||
NEXTVALUE:
|
||
for i < len(src) {
|
||
remaining := src[i:]
|
||
|
||
// try to pack run of 240 or 120 1s
|
||
if len(remaining) >= 120 {
|
||
// Invariant: len(a) is fixed to 120 or 240 values
|
||
var a []uint64
|
||
if len(remaining) >= 240 {
|
||
a = remaining[:240]
|
||
} else {
|
||
a = remaining[:120]
|
||
}
|
||
|
||
// search for the longest sequence of 1s in a
|
||
// Postcondition: k equals the index of the last 1 or -1
|
||
k := 0
|
||
for k = range a {
|
||
if a[k] != 1 {
|
||
k--
|
||
break
|
||
}
|
||
}
|
||
|
||
v := uint64(0)
|
||
switch {
|
||
case k == 239:
|
||
// 240 1s
|
||
i += 240
|
||
|
||
case k >= 119:
|
||
// at least 120 1s
|
||
v = 1 << 60
|
||
i += 120
|
||
|
||
default:
|
||
goto CODES
|
||
}
|
||
|
||
dst[j] = v
|
||
j++
|
||
continue
|
||
}
|
||
|
||
CODES:
|
||
for code := range numBits {
|
||
intN := int(numBits[code][0])
|
||
bitN := numBits[code][1]
|
||
if intN > len(remaining) {
|
||
continue
|
||
}
|
||
|
||
maxVal := uint64(1 << (bitN & 0x3f))
|
||
val := uint64(code+2) << S8B_BIT_SIZE
|
||
|
||
for k, inV := range remaining {
|
||
if k < intN {
|
||
if inV >= maxVal {
|
||
continue CODES
|
||
}
|
||
val |= inV << ((byte(k) * bitN) & 0x3f)
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
dst[j] = val
|
||
j += 1
|
||
i += intN
|
||
continue NEXTVALUE
|
||
}
|
||
return nil, ErrValueOutOfBounds
|
||
}
|
||
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) & 0xf
|
||
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
|
||
}
|