|
|
|
@@ -97,6 +97,57 @@ func analyzeO1RangeGo(swin []int32, dstP []uint32, hist *[32]uint16) (partSum ui
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func analyzeO2RangeGo(swin []int32, dstP []uint32, hist *[32]uint16) (partSum uint64, overflow bool) {
|
|
|
|
|
swin = swin[:len(dstP)+2]
|
|
|
|
|
for j := 0; j+2 < len(swin); j++ {
|
|
|
|
|
r := swin[j+2] - 2*swin[j+1] + swin[j]
|
|
|
|
|
if r == -2147483648 {
|
|
|
|
|
overflow = true
|
|
|
|
|
}
|
|
|
|
|
f := uint32(r<<1) ^ uint32(r>>31)
|
|
|
|
|
dstP[j] = f
|
|
|
|
|
partSum += uint64(f)
|
|
|
|
|
bl := 0
|
|
|
|
|
for v := f; v > 0; v >>= 1 {
|
|
|
|
|
bl++
|
|
|
|
|
}
|
|
|
|
|
if bl > 31 {
|
|
|
|
|
bl = 31
|
|
|
|
|
}
|
|
|
|
|
hist[bl]++
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func analyzeResRangeGo(swin []int32, dstP []uint32, hist *[32]uint16) (partSum uint64, overflow bool) {
|
|
|
|
|
for j := 0; j < len(swin); j++ {
|
|
|
|
|
r := swin[j]
|
|
|
|
|
if r == -2147483648 {
|
|
|
|
|
overflow = true
|
|
|
|
|
}
|
|
|
|
|
f := uint32(r<<1) ^ uint32(r>>31)
|
|
|
|
|
dstP[j] = f
|
|
|
|
|
partSum += uint64(f)
|
|
|
|
|
bl := 0
|
|
|
|
|
for v := f; v > 0; v >>= 1 {
|
|
|
|
|
bl++
|
|
|
|
|
}
|
|
|
|
|
if bl > 31 {
|
|
|
|
|
bl = 31
|
|
|
|
|
}
|
|
|
|
|
hist[bl]++
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodeMono24Go(src []byte, dst []int32) {
|
|
|
|
|
for i := 0; i < len(dst); i++ {
|
|
|
|
|
off := 3 * i
|
|
|
|
|
u := uint32(src[off]) | uint32(src[off+1])<<8 | uint32(src[off+2])<<16
|
|
|
|
|
dst[i] = int32(u<<8) >> 8
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- Differential tests ---
|
|
|
|
|
|
|
|
|
|
func TestFLACDecodeMono16(t *testing.T) {
|
|
|
|
@@ -328,3 +379,101 @@ func TestFLACFastStereoSums(t *testing.T) {
|
|
|
|
|
func foldAbs(v int32) uint64 {
|
|
|
|
|
return uint64(uint32(v<<1) ^ uint32(v>>31))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// runAnalyzeTest is the shared harness for the analyzeO*Range family.
|
|
|
|
|
func runAnalyzeTest(t *testing.T, k *Kernel, name string, order int, ref func([]int32, []uint32, *[32]uint16) (uint64, bool)) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
rng := rand.New(rand.NewSource(int64(order)*100 + 7))
|
|
|
|
|
for iter := 0; iter < 200; iter++ {
|
|
|
|
|
n := 1 + rng.Intn(128)
|
|
|
|
|
swin := make([]int32, n+order)
|
|
|
|
|
for i := range swin {
|
|
|
|
|
swin[i] = int32(rng.Intn(1<<20) - 1<<19)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goDstP := make([]uint32, n)
|
|
|
|
|
var goHist [32]uint16
|
|
|
|
|
goSum, goOvf := ref(swin, goDstP, &goHist)
|
|
|
|
|
|
|
|
|
|
jitDstP := make([]uint32, n)
|
|
|
|
|
var jitHist [32]uint16
|
|
|
|
|
args := make([]byte, 72)
|
|
|
|
|
PutPtr(args, 0, unsafe.Pointer(&swin[0]))
|
|
|
|
|
PutUint64(args, 8, uint64(len(swin)))
|
|
|
|
|
PutUint64(args, 16, uint64(cap(swin)))
|
|
|
|
|
PutPtr(args, 24, unsafe.Pointer(&jitDstP[0]))
|
|
|
|
|
PutUint64(args, 32, uint64(n))
|
|
|
|
|
PutUint64(args, 40, uint64(cap(jitDstP)))
|
|
|
|
|
PutPtr(args, 48, unsafe.Pointer(&jitHist[0]))
|
|
|
|
|
|
|
|
|
|
out, err := k.CallFunc(name, args)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("iter %d: %v", iter, err)
|
|
|
|
|
}
|
|
|
|
|
jitSum := GetUint64(out, 56)
|
|
|
|
|
jitOvf := out[64] != 0
|
|
|
|
|
|
|
|
|
|
if jitSum != goSum {
|
|
|
|
|
t.Fatalf("iter %d: partSum: JIT=%d Go=%d", iter, jitSum, goSum)
|
|
|
|
|
}
|
|
|
|
|
if jitOvf != goOvf {
|
|
|
|
|
t.Fatalf("iter %d: overflow: JIT=%v Go=%v", iter, jitOvf, goOvf)
|
|
|
|
|
}
|
|
|
|
|
for i := range goDstP {
|
|
|
|
|
if jitDstP[i] != goDstP[i] {
|
|
|
|
|
t.Fatalf("iter %d: dstP[%d]: JIT=%d Go=%d", iter, i, jitDstP[i], goDstP[i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if jitHist != goHist {
|
|
|
|
|
t.Fatalf("iter %d: hist mismatch", iter)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestFLACAnalyzeO2Range(t *testing.T) {
|
|
|
|
|
k := loadFLACKernel(t)
|
|
|
|
|
runAnalyzeTest(t, k, "analyzeO2RangeAVX2", 2, analyzeO2RangeGo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestFLACAnalyzeResRange(t *testing.T) {
|
|
|
|
|
k := loadFLACKernel(t)
|
|
|
|
|
// analyzeResRange has order 0: swin IS the residual (no prediction).
|
|
|
|
|
runAnalyzeTest(t, k, "analyzeResRangeAVX2", 0, analyzeResRangeGo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestFLACDecodeMono24(t *testing.T) {
|
|
|
|
|
k := loadFLACKernel(t)
|
|
|
|
|
rng := rand.New(rand.NewSource(55))
|
|
|
|
|
|
|
|
|
|
for iter := 0; iter < 500; iter++ {
|
|
|
|
|
n := rng.Intn(256)
|
|
|
|
|
src := make([]byte, 3*n)
|
|
|
|
|
rng.Read(src)
|
|
|
|
|
|
|
|
|
|
goDst := make([]int32, n)
|
|
|
|
|
decodeMono24Go(src, goDst)
|
|
|
|
|
|
|
|
|
|
jitDst := make([]int32, n)
|
|
|
|
|
args := make([]byte, 48)
|
|
|
|
|
if len(src) > 0 {
|
|
|
|
|
PutPtr(args, 0, unsafe.Pointer(&src[0]))
|
|
|
|
|
}
|
|
|
|
|
PutUint64(args, 8, uint64(len(src)))
|
|
|
|
|
PutUint64(args, 16, uint64(cap(src)))
|
|
|
|
|
if n > 0 {
|
|
|
|
|
PutPtr(args, 24, unsafe.Pointer(&jitDst[0]))
|
|
|
|
|
}
|
|
|
|
|
PutUint64(args, 32, uint64(n))
|
|
|
|
|
PutUint64(args, 40, uint64(cap(jitDst)))
|
|
|
|
|
|
|
|
|
|
_, err := k.CallFunc("decodeMono24AVX2", args)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("iter %d: %v", iter, err)
|
|
|
|
|
}
|
|
|
|
|
for i := range goDst {
|
|
|
|
|
if jitDst[i] != goDst[i] {
|
|
|
|
|
t.Fatalf("iter %d: dst[%d]: JIT=%d Go=%d", iter, i, jitDst[i], goDst[i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|