160 lines
3.2 KiB
Go
160 lines
3.2 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package signal
|
|
|
|
import (
|
|
"testing"
|
|
|
|
core "sourcedock.dev/petrbalvin/tensor/internal/core"
|
|
)
|
|
|
|
// Signal bulk-path benchmarks: the wavelet filter banks, the spectral
|
|
// estimators and the finite-difference stencils at analysis-like sizes.
|
|
|
|
func benchWave(b *testing.B, seed, n int, shape ...int) *core.Array {
|
|
b.Helper()
|
|
v := make([]float64, n)
|
|
for i := range v {
|
|
v[i] = float64(i%31)*float64(seed%5)*0.25 + float64(i%13) - 6
|
|
}
|
|
a, err := core.FromFloats(v, shape...)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
return a
|
|
}
|
|
|
|
func BenchmarkDWT4096(b *testing.B) {
|
|
x := benchWave(b, 1, 4096, 4096)
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := DWT(x, 8); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkIDWT4096(b *testing.B) {
|
|
x := benchWave(b, 2, 4096, 4096)
|
|
coef, err := DWT(x, 8)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := IDWT(coef, 8); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkCWTMorlet(b *testing.B) {
|
|
x := benchWave(b, 3, 4096, 4096)
|
|
scales := make([]float64, 32)
|
|
for i := range scales {
|
|
scales[i] = float64(int(1) << (i / 4))
|
|
}
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := CWT(x, Morlet, scales, 1.0/512); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkWelchPSD(b *testing.B) {
|
|
x := benchWave(b, 4, 1<<16, 1<<16)
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, _, err := WelchPSD(x, 1024, 1024, 512, "hann"); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkLombScargle(b *testing.B) {
|
|
t := benchWave(b, 5, 2048, 2048)
|
|
y := benchWave(b, 6, 2048, 2048)
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, _, err := LombScargle(t, y, 0.01, 1, 512); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkSavitzkyGolay(b *testing.B) {
|
|
x := benchWave(b, 7, 1<<18, 1<<18)
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := SavitzkyGolay(x, 11, 3); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkFilterApply(b *testing.B) {
|
|
x := benchWave(b, 8, 1<<18, 1<<18)
|
|
coefB, coefA, err := ButterworthLowPass(4, 1024, 64)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := FilterApply(coefB, coefA, x); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkLaplacian2D(b *testing.B) {
|
|
g := benchWave(b, 9, 512*512, 512, 512)
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := Laplacian(g, 1, 1); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkARMASpectrum(b *testing.B) {
|
|
res := &ARMAResult{
|
|
AR: []float64{0.75, -0.5, 0.2, -0.1},
|
|
MA: []float64{0.4, -0.25, 0.1},
|
|
InnovationVariance: 1.5,
|
|
}
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, _, err := ARMASpectrum(res, 4096); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkNUFFTType1(b *testing.B) {
|
|
const n = 4096
|
|
xv := make([]float64, n)
|
|
cv := make([]complex128, n)
|
|
for i := range n {
|
|
xv[i] = float64(i%1024)/1024 - 0.5
|
|
cv[i] = complex(float64(i%7)*0.5-1, float64(i%5)*0.25)
|
|
}
|
|
xs, err := core.FromFloats(xv, n)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
cs, err := core.FromComplexes(cv, n)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := NUFFTType1(xs, cs, 2048); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|