// Copyright 2014 by Sascha L. Teichmann // Use of this source code is governed by the MIT license // that can be found in the LICENSE file. package common import ( "encoding/binary" "strconv" ) const ( numBitsPerComponent = 12 maxPositive = 2048 modulo = 4096 ) type ( KeyTransformer func(int64) int64 KeyEncoder func(int64) ([]byte, error) KeyDecoder func([]byte) (int64, error) KeySplitter func(int64) (int16, int16, int16) KeyJoiner func(int16, int16, int16) int64 ) // Constructs a database key out of byte slice. func DecodeStringFromBytes(key []byte) (pos int64, err error) { return strconv.ParseInt(string(key), 10, 64) } // Encode a block pos to byte slice. func EncodeStringToBytes(key int64) ([]byte, error) { return []byte(strconv.FormatInt(key, 10)), nil } func EncodeToBigEndian(key int64) (enc []byte, err error) { enc = make([]byte, 8) binary.BigEndian.PutUint64(enc, uint64(key)) return } func DecodeFromBigEndian(key []byte) (int64, error) { return int64(binary.BigEndian.Uint64(key)), nil } func XYZToInterleaved(x, y, z int16) (result int64) { const end = 1 << (numBitsPerComponent + 1) setmask := int64(1) for mask := int16(1); mask != end; mask <<= 1 { if x&mask != 0 { result |= setmask } setmask <<= 1 if y&mask != 0 { result |= setmask } setmask <<= 1 if z&mask != 0 { result |= setmask } setmask <<= 1 } return } func InterleavedToXYZ(c int64) (x, y, z int16) { const end = 1 << (numBitsPerComponent + 1) for mask := int16(1); mask != end; mask <<= 1 { if c&1 == 1 { x |= mask } c >>= 1 if c&1 == 1 { y |= mask } c >>= 1 if c&1 == 1 { z |= mask } c >>= 1 } if x >= 1<= 1<= 1<= 0 { return i % modulo } return modulo - (-i)%modulo } // Only to match the C++ code. func PlainToXYZ(i int64) (x, y, z int16) { x = unsignedToSigned(pythonModulo(int16(i))) i = (i - int64(x)) / modulo y = unsignedToSigned(pythonModulo(int16(i))) i = (i - int64(y)) / modulo z = unsignedToSigned(pythonModulo(int16(i))) return } func TransformPlainToInterleaved(pos int64) int64 { x, y, z := PlainToXYZ(pos) return XYZToInterleaved(x, y, z) } func TransformInterleavedPlain(pos int64) int64 { x, y, z := InterleavedToXYZ(pos) return XYZToPlain(x, y, z) }