lotus/fr32/fr32.go

158 lines
2.7 KiB
Go
Raw Normal View History

2020-05-28 17:15:15 +00:00
package fr32
import (
"math/bits"
"runtime"
"sync"
"github.com/filecoin-project/specs-actors/actors/abi"
)
2020-05-29 15:21:10 +00:00
var MTTresh = uint64(32 << 20)
2020-05-28 17:15:15 +00:00
2020-05-28 22:17:23 +00:00
func mtChunkCount(usz abi.PaddedPieceSize) uint64 {
2020-05-29 15:21:10 +00:00
threads := (uint64(usz)) / MTTresh
2020-05-28 22:17:23 +00:00
if threads > uint64(runtime.NumCPU()) {
2020-05-28 17:15:15 +00:00
threads = 1 << (32 - bits.LeadingZeros32(uint32(runtime.NumCPU())))
}
2020-05-28 22:17:23 +00:00
if threads == 0 {
return 1
}
if threads > 64 {
return 64 // avoid too large buffers
}
return threads
}
func mt(in, out []byte, padLen int, op func(unpadded, padded []byte)) {
threads := mtChunkCount(abi.PaddedPieceSize(padLen))
threadBytes := abi.PaddedPieceSize(padLen / int(threads))
2020-05-28 17:15:15 +00:00
var wg sync.WaitGroup
2020-05-28 22:17:23 +00:00
wg.Add(int(threads))
2020-05-28 17:15:15 +00:00
2020-05-28 22:17:23 +00:00
for i := 0; i < int(threads); i++ {
2020-05-28 17:15:15 +00:00
go func(thread int) {
defer wg.Done()
start := threadBytes * abi.PaddedPieceSize(thread)
end := start + threadBytes
op(in[start.Unpadded():end.Unpadded()], out[start:end])
}(i)
}
wg.Wait()
}
// Assumes len(in)%127==0 and len(out)%128==0
func Pad(in, out []byte) {
2020-05-29 15:21:10 +00:00
if len(out) > int(MTTresh) {
2020-05-28 17:49:25 +00:00
mt(in, out, len(out), pad)
return
}
pad(in, out)
}
func pad(in, out []byte) {
2020-05-28 17:15:15 +00:00
chunks := len(out) / 128
for chunk := 0; chunk < chunks; chunk++ {
inOff := chunk * 127
outOff := chunk * 128
copy(out[outOff:outOff+31], in[inOff:inOff+31])
t := in[inOff+31] >> 6
out[outOff+31] = in[inOff+31] & 0x3f
var v byte
for i := 32; i < 64; i++ {
v = in[inOff+i]
out[outOff+i] = (v << 2) | t
t = v >> 6
}
t = v >> 4
out[outOff+63] &= 0x3f
for i := 64; i < 96; i++ {
v = in[inOff+i]
out[outOff+i] = (v << 4) | t
t = v >> 4
}
t = v >> 2
out[outOff+95] &= 0x3f
for i := 96; i < 127; i++ {
v = in[inOff+i]
out[outOff+i] = (v << 6) | t
t = v >> 2
}
out[outOff+127] = t & 0x3f
}
}
// Assumes len(in)%128==0 and len(out)%127==0
func Unpad(in []byte, out []byte) {
2020-05-29 15:21:10 +00:00
if len(in) > int(MTTresh) {
2020-05-28 17:49:25 +00:00
mt(out, in, len(in), unpad)
2020-05-28 17:15:15 +00:00
return
}
2020-05-28 17:49:25 +00:00
unpad(out, in)
}
func unpad(out, in []byte) {
2020-05-28 17:15:15 +00:00
chunks := len(in) / 128
for chunk := 0; chunk < chunks; chunk++ {
inOffNext := chunk*128 + 1
outOff := chunk * 127
at := in[chunk*128]
for i := 0; i < 32; i++ {
next := in[i+inOffNext]
out[outOff+i] = at
//out[i] |= next << 8
at = next
}
out[outOff+31] |= at << 6
for i := 32; i < 64; i++ {
next := in[i+inOffNext]
out[outOff+i] = at >> 2
out[outOff+i] |= next << 6
at = next
}
out[outOff+63] ^= (at << 6) ^ (at << 4)
for i := 64; i < 96; i++ {
next := in[i+inOffNext]
out[outOff+i] = at >> 4
out[outOff+i] |= next << 4
at = next
}
out[outOff+95] ^= (at << 4) ^ (at << 2)
for i := 96; i < 127; i++ {
next := in[i+inOffNext]
out[outOff+i] = at >> 6
out[outOff+i] |= next << 2
at = next
}
}
}