Skip to content

Commit 8bf2533

Browse files
authored
add some span_t api (#91)
* code refactoring (add some `span_t` api); * update tests; * mse/nmse optimization;
1 parent 002d389 commit 8bf2533

File tree

6 files changed

+270
-188
lines changed

6 files changed

+270
-188
lines changed

benchs/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ cpmaddpackage(NAME kissfft
3636

3737
set(SOURCES
3838
main.cpp
39+
audio.cpp
3940
fft.cpp
4041
ifft.cpp
4142
adaptive.cpp

benchs/audio.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <benchmark/benchmark.h>
2+
#include <dsplib.h>
3+
4+
static void BM_COMPRESSOR(benchmark::State& state) {
5+
const int fs = 16000;
6+
dsplib::arr_real x = dsplib::randn(fs);
7+
auto comp = dsplib::Compressor(fs);
8+
for (auto _ : state) {
9+
auto y = comp.process(x);
10+
x[0] += 1e-5;
11+
benchmark::DoNotOptimize(y);
12+
}
13+
}
14+
15+
static void BM_LIMITER(benchmark::State& state) {
16+
const int fs = 16000;
17+
dsplib::arr_real x = dsplib::randn(fs);
18+
auto limt = dsplib::Limiter(fs);
19+
for (auto _ : state) {
20+
auto y = limt.process(x);
21+
x[0] += 1e-5;
22+
benchmark::DoNotOptimize(y);
23+
}
24+
}
25+
26+
static void BM_AGC(benchmark::State& state) {
27+
const int fs = 16000;
28+
dsplib::arr_real x = dsplib::randn(fs);
29+
auto agc = dsplib::Agc();
30+
for (auto _ : state) {
31+
auto y = agc.process(x);
32+
x[0] += 1e-5;
33+
benchmark::DoNotOptimize(y);
34+
}
35+
}
36+
37+
BENCHMARK(BM_COMPRESSOR)->Unit(benchmark::kMicrosecond)->MinTime(5);
38+
BENCHMARK(BM_LIMITER)->Unit(benchmark::kMicrosecond)->MinTime(5);
39+
BENCHMARK(BM_AGC)->Unit(benchmark::kMicrosecond)->MinTime(5);

include/dsplib/math.h

Lines changed: 56 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ namespace dsplib {
1010
//TODO: mark noexcept
1111

1212
//exponential
13-
arr_real exp(const arr_real& arr);
13+
arr_real exp(span_real arr);
1414
real_t exp(real_t v);
15-
arr_cmplx exp(const arr_cmplx& arr);
15+
arr_cmplx exp(span_cmplx arr);
1616
cmplx_t exp(cmplx_t v);
1717

1818
//complex exponential for zero Re and non-zero Im
1919
//faster then exp()
20-
arr_cmplx expj(const arr_real& im);
21-
cmplx_t expj(real_t im);
20+
arr_cmplx expj(span_real w);
21+
cmplx_t expj(real_t w);
2222

2323
//hyperbolic tangent
24-
arr_real tanh(arr_real x);
25-
arr_cmplx tanh(arr_cmplx x);
24+
arr_real tanh(span_real x);
25+
arr_cmplx tanh(span_cmplx x);
2626

2727
//max element
2828
real_t max(span_real arr);
@@ -43,8 +43,8 @@ auto min(const T1& v1, const T2& v2) -> decltype(v1 + v2) {
4343
}
4444

4545
// range of values (maximum - minimum)
46-
real_t peak2peak(const arr_real& arr);
47-
cmplx_t peak2peak(const arr_cmplx& arr);
46+
real_t peak2peak(span_real arr);
47+
cmplx_t peak2peak(span_cmplx arr);
4848

4949
//max element index
5050
int argmax(span_real arr);
@@ -55,66 +55,66 @@ int argmin(span_real arr);
5555
int argmin(span_cmplx arr);
5656

5757
//absolute value and complex magnitude
58-
arr_real abs(const arr_real& arr) noexcept;
58+
arr_real abs(span_real arr) noexcept;
5959
real_t abs(real_t v) noexcept;
60-
arr_real abs(const arr_cmplx& arr) noexcept;
60+
arr_real abs(span_cmplx arr) noexcept;
6161
real_t abs(cmplx_t v) noexcept;
6262
void abs(inplace_real arr) noexcept;
6363

6464
//phase angle in the interval [-pi, pi] for each element of a complex array z
65-
arr_real angle(const arr_cmplx& arr);
65+
arr_real angle(span_cmplx arr);
6666
real_t angle(cmplx_t v);
6767

6868
//round
6969
real_t round(const real_t& x) noexcept;
7070
cmplx_t round(const cmplx_t& x) noexcept;
71-
arr_real round(const arr_real& arr) noexcept;
72-
arr_cmplx round(const arr_cmplx& arr) noexcept;
71+
arr_real round(span_real arr) noexcept;
72+
arr_cmplx round(span_cmplx arr) noexcept;
7373
void round(inplace_real arr) noexcept;
7474
void round(inplace_cmplx arr) noexcept;
7575

7676
//array sum
77-
real_t sum(const arr_real& arr);
78-
cmplx_t sum(const arr_cmplx& arr);
77+
real_t sum(span_real arr);
78+
cmplx_t sum(span_cmplx arr);
7979
int sum(const std::vector<bool>& arr);
8080

8181
// cumulative sum
8282
// example: cumsum([1, 2, 3, 4, 5]) -> [1, 3, 6, 10, 15]
83-
arr_real cumsum(const arr_real& x, Direction dir = Direction::Forward);
84-
arr_cmplx cumsum(const arr_cmplx& x, Direction dir = Direction::Forward);
83+
arr_real cumsum(span_real x, Direction dir = Direction::Forward);
84+
arr_cmplx cumsum(span_cmplx x, Direction dir = Direction::Forward);
8585

8686
//array dot
87-
real_t dot(const arr_real& x1, const arr_real& x2);
88-
cmplx_t dot(const arr_cmplx& x1, const arr_cmplx& x2);
87+
real_t dot(span_real x1, span_real x2);
88+
cmplx_t dot(span_cmplx x1, span_cmplx x2);
8989

9090
//array mean
91-
real_t mean(const arr_real& arr);
92-
cmplx_t mean(const arr_cmplx& arr);
91+
real_t mean(span_real arr);
92+
cmplx_t mean(span_cmplx arr);
9393

9494
//standard deviation
95-
real_t stddev(const arr_real& arr);
96-
real_t stddev(const arr_cmplx& arr);
95+
real_t stddev(span_real arr);
96+
real_t stddev(span_cmplx arr);
9797

9898
//median
99-
real_t median(const arr_real& arr);
99+
real_t median(span_real arr);
100100

101101
//linear or rank correlation
102102
//TODO: add p-value result
103-
real_t corr(const arr_real& x, const arr_real& y, Correlation type = Correlation::Pearson);
103+
real_t corr(span_real x, span_real y, Correlation type = Correlation::Pearson);
104104

105105
//sort array elements
106106
//result: [sorted array, sort index]
107107
std::pair<arr_real, arr_int> sort(const arr_real& x, Direction dir = Direction::Ascend);
108108

109109
//determine if array is sorted
110-
bool issorted(const arr_real& x, Direction dir = Direction::Ascend);
110+
bool issorted(span_real x, Direction dir = Direction::Ascend);
111111

112112
//real part
113-
arr_real real(const arr_cmplx& x);
113+
arr_real real(span_cmplx x);
114114
real_t real(const cmplx_t& x);
115115

116116
//imag part
117-
arr_real imag(const arr_cmplx& x);
117+
arr_real imag(span_cmplx x);
118118
real_t imag(const cmplx_t& x);
119119

120120
//complex pairing
@@ -194,33 +194,33 @@ arr_cmplx power(const arr_cmplx& x, int n);
194194
//square root (only positive values)
195195
//TODO: add complex result for negative or complex input
196196
real_t sqrt(real_t x) noexcept;
197-
arr_real sqrt(const arr_real& arr) noexcept;
197+
arr_real sqrt(span_real arr) noexcept;
198198
void sqrt(inplace_real arr) noexcept;
199199

200200
//array log
201-
arr_real log(const arr_real& arr);
202-
arr_real log2(const arr_real& arr);
203-
arr_real log10(const arr_real& arr);
201+
arr_real log(span_real arr);
202+
arr_real log2(span_real arr);
203+
arr_real log10(span_real arr);
204204

205205
real_t log(const real_t& x);
206206
real_t log2(const real_t& x);
207207
real_t log10(const real_t& x);
208208

209209
//array rms
210-
real_t rms(const arr_real& arr);
211-
real_t rms(const arr_cmplx& arr);
210+
real_t rms(span_real arr);
211+
real_t rms(span_cmplx arr);
212212

213213
//trigonometric functions
214-
arr_real sin(const arr_real& arr);
215-
arr_real cos(const arr_real& arr);
214+
arr_real sin(span_real arr);
215+
arr_real cos(span_real arr);
216216

217217
//decrease sample rate by integer factor
218-
arr_real downsample(const arr_real& arr, int n, int phase = 0);
219-
arr_cmplx downsample(const arr_cmplx& arr, int n, int phase = 0);
218+
arr_real downsample(span_real arr, int n, int phase = 0);
219+
arr_cmplx downsample(span_cmplx arr, int n, int phase = 0);
220220

221221
//increase sample rate by integer factor
222-
arr_real upsample(const arr_real& arr, int n, int phase = 0);
223-
arr_cmplx upsample(const arr_cmplx& arr, int n, int phase = 0);
222+
arr_real upsample(span_real arr, int n, int phase = 0);
223+
arr_cmplx upsample(span_cmplx arr, int n, int phase = 0);
224224

225225
//abs(x)^2
226226
arr_real abs2(const arr_cmplx& x) noexcept;
@@ -238,35 +238,27 @@ constexpr real_t abs2(const real_t& x) noexcept {
238238
}
239239

240240
//from degrees to radians
241-
arr_real deg2rad(const arr_real& x);
241+
arr_real deg2rad(span_real x);
242242
real_t deg2rad(const real_t& x);
243243

244244
//from radians to degrees
245-
arr_real rad2deg(const arr_real& x);
245+
arr_real rad2deg(span_real x);
246246
real_t rad2deg(const real_t& x);
247247

248248
//vector norms
249249
//p=1, sum(abs(x))
250250
//p=2, euclidean norm of vector, sum(abs(x).^2)^(1/2)
251251
//p>0, sum(abs(x).^p)^(1/p)
252-
real_t norm(const arr_real& x, int p = 2);
253-
real_t norm(const arr_cmplx& x, int p = 2);
252+
real_t norm(span_real x, int p = 2);
253+
real_t norm(span_cmplx x, int p = 2);
254254

255255
//Mean squared error
256-
inline real_t mse(const arr_real& x, const arr_real& y) {
257-
return mean(abs2(x - y));
258-
}
259-
inline real_t mse(const arr_cmplx& x, const arr_cmplx& y) {
260-
return mean(abs2(x - y));
261-
}
256+
real_t mse(span_real x, span_real y);
257+
real_t mse(span_cmplx x, span_cmplx y);
262258

263259
//Normalized mean squared error
264-
inline real_t nmse(const arr_real& x, const arr_real& y) {
265-
return mse(x, y) / sum(abs2(x));
266-
}
267-
inline real_t nmse(const arr_cmplx& x, const arr_cmplx& y) {
268-
return mse(x, y) / sum(abs2(x));
269-
}
260+
real_t nmse(span_real x, span_real y);
261+
real_t nmse(span_cmplx x, span_cmplx y);
270262

271263
//signum function
272264
constexpr int sign(const real_t& x) noexcept {
@@ -283,17 +275,17 @@ inline cmplx_t sign(const cmplx_t& x) noexcept {
283275
//----------------------------------------------------------------------------------------
284276
//convert power <-> decibels: db = 10 * log10(pow)
285277
real_t pow2db(real_t v) noexcept;
286-
arr_real pow2db(const arr_real& arr) noexcept;
278+
arr_real pow2db(span_real arr) noexcept;
287279
real_t db2pow(real_t v) noexcept;
288-
arr_real db2pow(const arr_real& arr) noexcept;
280+
arr_real db2pow(span_real arr) noexcept;
289281
void pow2db(inplace_real arr) noexcept;
290282
void db2pow(inplace_real arr) noexcept;
291283

292284
//convert magnitude <-> decibels: db = 20 * log10(mag)
293285
real_t mag2db(real_t v) noexcept;
294-
arr_real mag2db(const arr_real& arr) noexcept;
286+
arr_real mag2db(span_real arr) noexcept;
295287
real_t db2mag(real_t v) noexcept;
296-
arr_real db2mag(const arr_real& arr) noexcept;
288+
arr_real db2mag(span_real arr) noexcept;
297289
void mag2db(inplace_real arr) noexcept;
298290
void db2mag(inplace_real arr) noexcept;
299291

@@ -320,11 +312,11 @@ arr_int primes(uint32_t n);
320312
//missing data
321313

322314
//determine if any array element is NaN
323-
bool anynan(const arr_real& x);
324-
bool anynan(const arr_cmplx& x);
315+
bool anynan(span_real x);
316+
bool anynan(span_cmplx x);
325317

326318
//determine if any array element is Inf or -Inf
327-
bool anyinf(const arr_real& x);
328-
bool anyinf(const arr_cmplx& x);
319+
bool anyinf(span_real x);
320+
bool anyinf(span_cmplx x);
329321

330322
} // namespace dsplib

lib/corr.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
#include "dsplib/array.h"
22
#include "dsplib/keywords.h"
33
#include "dsplib/math.h"
4-
#include "dsplib/utils.h"
54

65
namespace dsplib {
76

87
namespace {
98

10-
real_t _pearson_corr(const arr_real& x, const arr_real& y) noexcept {
9+
real_t _pearson_corr(span_real x, span_real y) noexcept {
1110
const int n = x.size();
1211
real_t sum_x = 0;
1312
real_t sum_y = 0;
@@ -30,7 +29,7 @@ real_t _pearson_corr(const arr_real& x, const arr_real& y) noexcept {
3029
return corr;
3130
}
3231

33-
std::vector<int> _get_ranks(const arr_real& x) noexcept {
32+
std::vector<int> _get_ranks(span_real x) noexcept {
3433
const int n = x.size();
3534
const auto [_, x_idx] = sort(x);
3635
std::vector<int> rank(n);
@@ -40,19 +39,19 @@ std::vector<int> _get_ranks(const arr_real& x) noexcept {
4039
return rank;
4140
}
4241

43-
real_t _spearman_corr(const arr_real& x, const arr_real& y) noexcept {
44-
const auto x_rank = _get_ranks(x);
45-
const auto y_rank = _get_ranks(y);
42+
real_t _spearman_corr(span_real x, span_real y) noexcept {
43+
const arr_real x_rank = _get_ranks(x);
44+
const arr_real y_rank = _get_ranks(y);
4645
//FIXIT: valid only for unique values
4746
const auto r = _pearson_corr(x_rank, y_rank);
4847
return r;
4948
}
5049

5150
//TODO: N * log(N) optimization (combine nc/nd calculation with sort)
52-
real_t _kendall_corr(const arr_real& x, const arr_real& y) noexcept {
51+
real_t _kendall_corr(span_real x, span_real y) noexcept {
5352
const int n = x.size();
5453
const auto [_, x_idx] = sort(x);
55-
const auto ybyx = y[x_idx];
54+
const auto ybyx = arr_real(y)[x_idx];
5655

5756
int n_c = 0;
5857
int n_d = 0;
@@ -72,7 +71,7 @@ real_t _kendall_corr(const arr_real& x, const arr_real& y) noexcept {
7271

7372
} // namespace
7473

75-
real_t corr(const arr_real& x, const arr_real& y, Correlation type) {
74+
real_t corr(span_real x, span_real y, Correlation type) {
7675
DSPLIB_ASSERT(x.size() == y.size(), "Array size must be equal");
7776
switch (type) {
7877
case Correlation::Pearson:

0 commit comments

Comments
 (0)