MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Kernels.cpp
Go to the documentation of this file.
1#include "Kernels.hpp"
2
6
8
9namespace {
10
11 constexpr double two_pi = 2.0 * std::numbers::pi;
12
13 [[nodiscard]] double interpolate_table(std::span<const double> table, double x) noexcept
14 {
15 return sample_table(table, (std::clamp(x, -1.0, 1.0) + 1.0) * 0.5);
16 }
17
18 inline void wrap_revolution(double& phase) noexcept
19 {
20 if (phase >= two_pi) {
21 phase -= two_pi;
22 } else if (phase < 0.0) {
23 phase += two_pi;
24 }
25 }
26
27 [[nodiscard]] double sum_of(std::span<const double> values) noexcept
28 {
29 const double* data = values.data();
30 const size_t count = values.size();
31
32 double s0 = 0.0;
33 double s1 = 0.0;
34 double s2 = 0.0;
35 double s3 = 0.0;
36 size_t k = 0;
37 for (; k + 4 <= count; k += 4) {
38 s0 += data[k];
39 s1 += data[k + 1];
40 s2 += data[k + 2];
41 s3 += data[k + 3];
42 }
43
44 double tail = 0.0;
45 for (; k < count; ++k)
46 tail += data[k];
47 return ((s0 + s1) + (s2 + s3)) + tail;
48 }
49
50 void rotate_rotors(
51 const double* __restrict cos_step, const double* __restrict sin_step,
52 double* __restrict re, double* __restrict im, size_t n) noexcept
53 {
54 for (size_t i = 0; i < n; ++i) {
55 const double next_re = re[i] * cos_step[i] - im[i] * sin_step[i];
56 const double next_im = re[i] * sin_step[i] + im[i] * cos_step[i];
57 const double correction = 1.5 - 0.5 * (next_re * next_re + next_im * next_im);
58
59 re[i] = next_re * correction;
60 im[i] = next_im * correction;
61 }
62 }
63
64 void logistic_map(
65 const double* __restrict cells, double* __restrict mapped, double r, size_t n) noexcept
66 {
67 for (size_t i = 0; i < n; ++i)
68 mapped[i] = r * cells[i] * (1.0 - cells[i]);
69 }
70
71 void blend_neighbours(
72 double* __restrict cells, const double* __restrict mapped, double epsilon, size_t n) noexcept
73 {
74 const double keep = 1.0 - epsilon;
75 const double share = 0.5 * epsilon;
76
77 if (n == 1) {
78 cells[0] = keep * mapped[0] + share * (mapped[0] + mapped[0]);
79 return;
80 }
81
82 cells[0] = keep * mapped[0] + share * (mapped[n - 1] + mapped[1]);
83 for (size_t i = 1; i + 1 < n; ++i)
84 cells[i] = keep * mapped[i] + share * (mapped[i - 1] + mapped[i + 1]);
85 cells[n - 1] = keep * mapped[n - 1] + share * (mapped[n - 2] + mapped[0]);
86 }
87
88}
89
90double horner(std::span<const double> coefficients, double x) noexcept
91{
92 double result = 0.0;
93 for (const double c : coefficients)
94 result = result * x + c;
95 return result;
96}
97
98double weighted_sum(std::span<const double> window, std::span<const double> coefs) noexcept
99{
100 const size_t count = std::min(window.size(), coefs.size());
101 const double* a = window.data();
102 const double* b = coefs.data();
103
104 double s0 = 0.0;
105 double s1 = 0.0;
106 double s2 = 0.0;
107 double s3 = 0.0;
108 size_t k = 0;
109 for (; k + 4 <= count; k += 4) {
110 s0 += a[k] * b[k];
111 s1 += a[k + 1] * b[k + 1];
112 s2 += a[k + 2] * b[k + 2];
113 s3 += a[k + 3] * b[k + 3];
114 }
115
116 double tail = 0.0;
117 for (; k < count; ++k)
118 tail += a[k] * b[k];
119 return ((s0 + s1) + (s2 + s3)) + tail;
120}
121
122double tapped_sum(std::span<const double> window, std::span<const double> coefs) noexcept
123{
124 if (window.empty())
125 return 0.0;
126
127 const auto reach = static_cast<double>(window.size() - 1);
128 double sum = 0.0;
129
130 for (size_t j = 0; j + 1 < coefs.size(); j += 2) {
131 const double lag = coefs[j];
132 if (!(lag >= 0.0) || lag > reach)
133 continue;
134
135 const auto index = static_cast<size_t>(lag);
136 const double fraction = lag - static_cast<double>(index);
137 double value = window[index];
138 if (fraction > 0.0 && index + 1 < window.size())
139 value += (window[index + 1] - value) * fraction;
140
141 sum += coefs[j + 1] * value;
142 }
143 return sum;
144}
145
146double table_lookup(std::span<const double> window, std::span<const double> coefs) noexcept
147{
148 return interpolate_table(coefs, window.empty() ? 0.0 : window.front());
149}
150
151double table_lookup_previous(std::span<const double> window, std::span<const double> coefs) noexcept
152{
153 return interpolate_table(coefs, window.size() > 1 ? window[1] : 0.0);
154}
155
156double chebyshev_series(std::span<const double> window, std::span<const double> coefs) noexcept
157{
158 if (coefs.empty())
159 return 0.0;
160
161 const double x = std::clamp(window.empty() ? 0.0 : window.front(), -1.0, 1.0);
162 double b1 = 0.0;
163 double b2 = 0.0;
164
165 for (size_t k = coefs.size() - 1; k >= 1; --k) {
166 const double b0 = coefs[k] + 2.0 * x * b1 - b2;
167 b2 = b1;
168 b1 = b0;
169 }
170 return coefs.front() + x * b1 - b2;
171}
172
173double iterated_polynomial(std::span<const double> window, std::span<const double> coefs) noexcept
174{
175 return horner(coefs, window.size() > 1 ? window[1] : 0.0);
176}
177
178std::vector<double> phasor_bank_state(
179 std::span<const double> increments,
180 std::span<const double> scales,
181 std::span<const double> am_increments,
182 std::span<const double> phases,
183 std::span<const double> am_phases)
184{
185 const size_t n = increments.size();
186 std::vector<double> state(1 + 5 * n, 0.0);
187 state.front() = static_cast<double>(n);
188
189 for (size_t i = 0; i < n; ++i) {
190 state.at(1 + i) = increments[i];
191 state.at(1 + n + i) = i < scales.size() ? scales[i] : 1.0;
192 state.at(1 + 2 * n + i) = i < am_increments.size() ? am_increments[i] : 0.0;
193 state.at(1 + 3 * n + i) = i < phases.size() ? phases[i] : 0.0;
194 state.at(1 + 4 * n + i) = i < am_phases.size() ? am_phases[i] : 0.0;
195 }
196 return state;
197}
198
199std::vector<double> rotor_bank_state(
200 std::span<const double> increments,
201 std::span<const double> scales,
202 std::span<const double> phases)
203{
204 const size_t n = increments.size();
205 std::vector<double> state(1 + 5 * n, 0.0);
206 state.front() = static_cast<double>(n);
207
208 for (size_t i = 0; i < n; ++i) {
209 const double phase = i < phases.size() ? phases[i] : 0.0;
210 state.at(1 + i) = std::cos(increments[i]);
211 state.at(1 + n + i) = std::sin(increments[i]);
212 state.at(1 + 2 * n + i) = i < scales.size() ? scales[i] : 1.0;
213 state.at(1 + 3 * n + i) = std::cos(phase);
214 state.at(1 + 4 * n + i) = std::sin(phase);
215 }
216 return state;
217}
218
219double rotor_bank(std::span<const double>, std::span<double> coefs) noexcept
220{
221 if (coefs.empty())
222 return 0.0;
223
224 const auto n = static_cast<size_t>(std::max(coefs.front(), 0.0));
225 if (n == 0 || coefs.size() < 1 + 5 * n)
226 return 0.0;
227
228 const auto cos_step = coefs.subspan(1, n);
229 const auto sin_step = coefs.subspan(1 + n, n);
230 const auto scales = coefs.subspan(1 + 2 * n, n);
231 const auto re = coefs.subspan(1 + 3 * n, n);
232 const auto im = coefs.subspan(1 + 4 * n, n);
233
234 rotate_rotors(cos_step.data(), sin_step.data(), re.data(), im.data(), n);
235 return weighted_sum(scales, im);
236}
237
238double phasor_bank(std::span<const double>, std::span<double> coefs) noexcept
239{
240 if (coefs.empty())
241 return 0.0;
242
243 const auto n = static_cast<size_t>(std::max(coefs.front(), 0.0));
244 if (n == 0 || coefs.size() < 1 + 5 * n)
245 return 0.0;
246
247 const auto increments = coefs.subspan(1, n);
248 const auto scales = coefs.subspan(1 + n, n);
249 const auto am_increments = coefs.subspan(1 + 2 * n, n);
250 const auto phases = coefs.subspan(1 + 3 * n, n);
251 const auto am_phases = coefs.subspan(1 + 4 * n, n);
252
253 double sum = 0.0;
254 for (size_t i = 0; i < n; ++i) {
255 phases[i] += increments[i];
256 wrap_revolution(phases[i]);
257
258 const double swell = 0.5 + 0.5 * std::sin(am_phases[i]);
259
260 am_phases[i] += am_increments[i];
261 wrap_revolution(am_phases[i]);
262
263 sum += scales[i] * swell * std::sin(phases[i]);
264 }
265 return sum;
266}
267
268double polynomial_lags(std::span<const double> window, std::span<const double> coefs) noexcept
269{
270 if (coefs.size() < 2)
271 return 0.0;
272
273 const auto lags = static_cast<size_t>(std::max(coefs[0], 0.0));
274 const auto powers = static_cast<size_t>(std::max(coefs[1], 0.0)) + 1;
275 if (coefs.size() < 2 + lags * powers)
276 return 0.0;
277
278 double sum = 0.0;
279 const size_t reach = std::min(lags, window.size());
280 for (size_t k = 0; k < reach; ++k) {
281 const double w = window[k];
282 double power = 1.0;
283 for (size_t j = 0; j < powers; ++j) {
284 sum += coefs[2 + k * powers + j] * power;
285 power *= w;
286 }
287 }
288 return sum;
289}
290
291double fourier_series(std::span<const double> window, std::span<const double> coefs) noexcept
292{
293 if (coefs.empty())
294 return 0.0;
295
296 const double phase = window.empty() ? 0.0 : window.front();
297 const double c1 = std::cos(phase);
298 const double s1 = std::sin(phase);
299
300 double ck = c1;
301 double sk = s1;
302 double sum = coefs.front();
303
304 for (size_t i = 1; i < coefs.size(); i += 2) {
305 sum += coefs[i] * ck;
306 if (i + 1 < coefs.size())
307 sum += coefs[i + 1] * sk;
308
309 const double next_c = ck * c1 - sk * s1;
310 sk = sk * c1 + ck * s1;
311 ck = next_c;
312 }
313 return sum;
314}
315
316double breakpoint_curve(std::span<const double> window, std::span<const double> coefs) noexcept
317{
318 const size_t points = coefs.size() / 2;
319 if (points == 0)
320 return 0.0;
321
322 const double x = window.empty() ? 0.0 : window.front();
323 if (x <= coefs[0])
324 return coefs[1];
325 if (x >= coefs[2 * (points - 1)])
326 return coefs[2 * (points - 1) + 1];
327
328 size_t i = 0;
329 while (i + 2 < points && x > coefs[2 * (i + 1)])
330 ++i;
331
332 const double x0 = coefs[2 * i];
333 const double x1 = coefs[2 * (i + 1)];
334 const double y0 = coefs[2 * i + 1];
335 const double y1 = coefs[2 * (i + 1) + 1];
336 if (x1 <= x0)
337 return y0;
338 return y0 + (y1 - y0) * (x - x0) / (x1 - x0);
339}
340
341double pattern_lookup(std::span<const double> window, std::span<const double> coefs) noexcept
342{
343 if (coefs.size() < 5 || !(coefs[3] > coefs[2]))
344 return 0.0;
345
346 const auto levels = static_cast<uint32_t>(std::max(coefs[0], 1.0));
347 const auto count = static_cast<size_t>(std::max(coefs[1], 1.0));
348 const auto table = coefs.subspan(4);
349
350 size_t total = 1;
351 for (size_t i = 0; i < count; ++i) {
352 if (total > table.size() / levels)
353 return 0.0;
354 total *= levels;
355 }
356
357 const Lattice1D lattice { .resolution = levels, .bounds = { .min = coefs[2], .max = coefs[3] } };
358
359 size_t index = 0;
360 size_t stride = 1;
361 for (size_t i = 0; i < count; ++i) {
362 const double value = i < window.size() ? window[i] : 0.0;
363 index += static_cast<size_t>(lattice.cell_at(value)) * stride;
364 stride *= levels;
365 }
366 return table[index];
367}
368
369double dilate(std::span<const double> window, std::span<const double> coefs) noexcept
370{
371 const size_t count = std::min(window.size(), coefs.size());
372 if (count == 0)
373 return 0.0;
374
375 double b0 = window[0] + coefs[0];
376 double b1 = b0;
377 double b2 = b0;
378 double b3 = b0;
379 size_t k = 1;
380 for (; k + 4 <= count; k += 4) {
381 b0 = std::max(b0, window[k] + coefs[k]);
382 b1 = std::max(b1, window[k + 1] + coefs[k + 1]);
383 b2 = std::max(b2, window[k + 2] + coefs[k + 2]);
384 b3 = std::max(b3, window[k + 3] + coefs[k + 3]);
385 }
386 for (; k < count; ++k)
387 b0 = std::max(b0, window[k] + coefs[k]);
388 return std::max(std::max(b0, b1), std::max(b2, b3));
389}
390
391double erode(std::span<const double> window, std::span<const double> coefs) noexcept
392{
393 const size_t count = std::min(window.size(), coefs.size());
394 if (count == 0)
395 return 0.0;
396
397 double b0 = window[0] - coefs[0];
398 double b1 = b0;
399 double b2 = b0;
400 double b3 = b0;
401 size_t k = 1;
402 for (; k + 4 <= count; k += 4) {
403 b0 = std::min(b0, window[k] - coefs[k]);
404 b1 = std::min(b1, window[k + 1] - coefs[k + 1]);
405 b2 = std::min(b2, window[k + 2] - coefs[k + 2]);
406 b3 = std::min(b3, window[k + 3] - coefs[k + 3]);
407 }
408 for (; k < count; ++k)
409 b0 = std::min(b0, window[k] - coefs[k]);
410 return std::min(std::min(b0, b1), std::min(b2, b3));
411}
412
413double quantile(std::span<const double> window, std::span<const double> coefs)
414{
415 const size_t n = window.size();
416 if (n == 0)
417 return 0.0;
418
419 thread_local std::vector<double> scratch;
420 scratch.assign(window.begin(), window.end());
421
422 const double q = std::clamp(coefs.empty() ? 0.5 : coefs.front(), 0.0, 1.0);
423 const double position = q * static_cast<double>(n - 1);
424 const auto lower = static_cast<size_t>(position);
425 const double fraction = position - static_cast<double>(lower);
426
427 const auto nth = scratch.begin() + static_cast<std::ptrdiff_t>(lower);
428 std::nth_element(scratch.begin(), nth, scratch.end());
429 const double low = *nth;
430
431 if (fraction <= 0.0 || lower + 1 >= n)
432 return low;
433
434 const double high = *std::min_element(nth + 1, scratch.end());
435 return low + (high - low) * fraction;
436}
437
438double zscore(std::span<const double> window, std::span<const double> coefs) noexcept
439{
440 if (window.size() < 3)
441 return 0.0;
442
443 const auto past = window.subspan(1);
444 const double mean = sum_of(past) / static_cast<double>(past.size());
445
446 const double floor = coefs.empty() ? 1e-12 : std::max(coefs.front(), 1e-12);
447 const double deviation = std::max(Stochastic::Estimate::stddev(past), floor);
448 return (window.front() - mean) / deviation;
449}
450
451double goertzel(std::span<const double> window, std::span<const double> coefs) noexcept
452{
453 const size_t n = window.size();
454 if (n == 0)
455 return 0.0;
456
457 const double scale = 4.0 / (static_cast<double>(n) * static_cast<double>(n));
458 double total = 0.0;
459
460 for (size_t j = 0; j + 1 < coefs.size(); j += 2) {
461 const double coeff = 2.0 * std::cos(two_pi * coefs[j]);
462 double s1 = 0.0;
463 double s2 = 0.0;
464 for (const double x : window) {
465 const double s = x + coeff * s1 - s2;
466 s2 = s1;
467 s1 = s;
468 }
469 total += coefs[j + 1] * scale * (s1 * s1 + s2 * s2 - coeff * s1 * s2);
470 }
471 return total;
472}
473
474double modular_recurrence(std::span<const double> window, std::span<const double> coefs) noexcept
475{
476 if (coefs.empty())
477 return 0.0;
478
479 const double sum = weighted_sum(window, coefs.subspan(1));
480 const double modulus = coefs.front();
481 if (modulus <= 0.0)
482 return sum;
483 return wrap(sum, 0.0, modulus);
484}
485
486std::vector<double> kuramoto_state(
487 std::span<const double> omegas, double coupling, std::span<const double> phases)
488{
489 const size_t n = omegas.size();
490 std::vector<double> state(2 + 2 * n, 0.0);
491 state.front() = static_cast<double>(n);
492 state.at(1) = coupling;
493
494 for (size_t i = 0; i < n; ++i) {
495 state.at(2 + i) = omegas[i];
496 state.at(2 + n + i) = i < phases.size() ? phases[i] : 0.0;
497 }
498 return state;
499}
500
501double kuramoto(std::span<const double>, std::span<double> coefs) noexcept
502{
503 if (coefs.size() < 2)
504 return 0.0;
505
506 const auto n = static_cast<size_t>(std::max(coefs.front(), 0.0));
507 if (n == 0 || coefs.size() < 2 + 2 * n)
508 return 0.0;
509
510 const double coupling = coefs[1];
511 const auto omegas = coefs.subspan(2, n);
512 const auto phases = coefs.subspan(2 + n, n);
513 const double inverse = 1.0 / static_cast<double>(n);
514
515 constexpr size_t cached = 256;
516 std::array<double, cached> cosines;
517 std::array<double, cached> sines;
518 const bool reuse = n <= cached;
519
520 double field_cos = 0.0;
521 double field_sin = 0.0;
522 for (size_t i = 0; i < n; ++i) {
523 const double c = std::cos(phases[i]);
524 const double s = std::sin(phases[i]);
525 if (reuse) {
526 cosines[i] = c;
527 sines[i] = s;
528 }
529 field_cos += c;
530 field_sin += s;
531 }
532 field_cos *= inverse;
533 field_sin *= inverse;
534
535 double mix = 0.0;
536 for (size_t i = 0; i < n; ++i) {
537 const double c = reuse ? cosines[i] : std::cos(phases[i]);
538 const double s = reuse ? sines[i] : std::sin(phases[i]);
539 const double pull = coupling * (field_sin * c - field_cos * s);
540 phases[i] += omegas[i] + pull;
541 wrap_revolution(phases[i]);
542 mix += std::sin(phases[i]);
543 }
544 return mix * inverse;
545}
546
547std::vector<double> coupled_map_lattice_state(
548 std::span<const double> cells, double r, double epsilon)
549{
550 const size_t n = cells.size();
551 std::vector<double> state(3 + 2 * n, 0.0);
552 state.front() = static_cast<double>(n);
553 state.at(1) = r;
554 state.at(2) = epsilon;
555
556 for (size_t i = 0; i < n; ++i)
557 state.at(3 + i) = cells[i];
558 return state;
559}
560
561double coupled_map_lattice(std::span<const double>, std::span<double> coefs) noexcept
562{
563 if (coefs.size() < 3)
564 return 0.0;
565
566 const auto n = static_cast<size_t>(std::max(coefs.front(), 0.0));
567 if (n == 0 || coefs.size() < 3 + 2 * n)
568 return 0.0;
569
570 const double r = coefs[1];
571 const double epsilon = coefs[2];
572 const auto cells = coefs.subspan(3, n);
573 const auto mapped = coefs.subspan(3 + n, n);
574
575 logistic_map(cells.data(), mapped.data(), r, n);
576 blend_neighbours(cells.data(), mapped.data(), epsilon, n);
577 return sum_of(cells) / static_cast<double>(n) - 0.5;
578}
579
580std::vector<double> lorenz_state(
581 double dt, double sigma, double rho, double beta, double x, double y, double z)
582{
583 return { sigma, rho, beta, dt, x, y, z };
584}
585
586double lorenz_attractor(std::span<const double>, std::span<double> coefs) noexcept
587{
588 if (coefs.size() < 7)
589 return 0.0;
590
591 const double sigma = coefs[0];
592 const double rho = coefs[1];
593 const double beta = coefs[2];
594 const double dt = coefs[3];
595
596 using Vec = std::array<double, 3>;
597 const auto derivative = [sigma, rho, beta](const Vec& p) -> Vec {
598 return { sigma * (p[1] - p[0]), p[0] * (rho - p[2]) - p[1], p[0] * p[1] - beta * p[2] };
599 };
600 const auto advanced = [](const Vec& p, const Vec& d, double h) -> Vec {
601 return { p[0] + h * d[0], p[1] + h * d[1], p[2] + h * d[2] };
602 };
603
604 const Vec start { coefs[4], coefs[5], coefs[6] };
605 const Vec k1 = derivative(start);
606 const Vec k2 = derivative(advanced(start, k1, 0.5 * dt));
607 const Vec k3 = derivative(advanced(start, k2, 0.5 * dt));
608 const Vec k4 = derivative(advanced(start, k3, dt));
609
610 for (size_t i = 0; i < 3; ++i)
611 coefs[4 + i] = start[i] + dt / 6.0 * (k1[i] + 2.0 * k2[i] + 2.0 * k3[i] + k4[i]);
612
613 return coefs[4];
614}
615
616std::vector<double> step_sequence_state(std::span<const double> values, double threshold)
617{
618 std::vector<double> state(4 + values.size(), 0.0);
619 state.at(0) = threshold;
620 state.at(1) = 0.0;
621 state.at(2) = 1.0;
622 state.at(3) = static_cast<double>(values.size());
623
624 for (size_t i = 0; i < values.size(); ++i)
625 state.at(4 + i) = values[i];
626 return state;
627}
628
629double step_sequence(std::span<const double> window, std::span<double> coefs) noexcept
630{
631 if (coefs.size() < 5)
632 return 0.0;
633
634 const auto n = static_cast<size_t>(std::max(coefs[3], 0.0));
635 if (n == 0 || coefs.size() < 4 + n)
636 return 0.0;
637
638 const bool high = !window.empty() && window.front() > coefs[0];
639 const bool latched = coefs[2] > 0.5;
640 auto cursor = static_cast<size_t>(std::max(coefs[1], 0.0)) % n;
641
642 if (high && !latched)
643 cursor = (cursor + 1) % n;
644
645 coefs[1] = static_cast<double>(cursor);
646 coefs[2] = high ? 1.0 : 0.0;
647 return coefs[4 + cursor];
648}
649
650} // namespace MayaFlux::Kinesis::Discrete
std::optional< glm::vec3 > position
Definition Decoder.cpp:93
std::vector< glm::vec2 > * points
uint32_t h
Definition InkPress.cpp:29
Pure functions of a newest-first window and an array of numbers.
std::weak_ptr< Core::Window > window
Definition Picker.cpp:23
uint32_t total
size_t a
size_t b
double q
glm::vec3 value
std::vector< std::byte > values
Definition VDBWriter.cpp:26
uint32_t index
Definition VKDevice.cpp:122
size_t count
float threshold
static double stddev(std::span< const double > samples) noexcept
Standard deviation of a span.
Definition Estimate.cpp:224
std::vector< double > rotor_bank_state(std::span< const double > increments, std::span< const double > scales, std::span< const double > phases)
Builds the array rotor_bank reads and writes.
Definition Kernels.cpp:199
double horner(std::span< const double > coefficients, double x) noexcept
Horner evaluation, coefficients highest power first.
Definition Kernels.cpp:90
std::vector< double > sum(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Sum per window.
Definition Analysis.cpp:469
double modular_recurrence(std::span< const double > window, std::span< const double > coefs) noexcept
Weighted sum wrapped into [0, modulus).
Definition Kernels.cpp:474
double phasor_bank(std::span< const double >, std::span< double > coefs) noexcept
Sum of N sinusoidal partials, each with its own slow amplitude swell.
Definition Kernels.cpp:238
double table_lookup(std::span< const double > window, std::span< const double > coefs) noexcept
Transfer table indexed by the current value.
Definition Kernels.cpp:146
std::vector< double > power(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Power (sum of squares) per window.
Definition Analysis.cpp:70
double rotor_bank(std::span< const double >, std::span< double > coefs) noexcept
Sum of N sinusoids advanced by complex rotation instead of a sine call.
Definition Kernels.cpp:219
double polynomial_lags(std::span< const double > window, std::span< const double > coefs) noexcept
Polynomial in several lags at once.
Definition Kernels.cpp:268
double weighted_sum(std::span< const double > window, std::span< const double > coefs) noexcept
Sum of window[k] * coefs[k] over the shorter of the two.
Definition Kernels.cpp:98
double kuramoto(std::span< const double >, std::span< double > coefs) noexcept
Kuramoto oscillators pulled toward their mean phase.
Definition Kernels.cpp:501
std::vector< double > kuramoto_state(std::span< const double > omegas, double coupling, std::span< const double > phases)
Builds the array kuramoto reads and writes.
Definition Kernels.cpp:486
double iterated_polynomial(std::span< const double > window, std::span< const double > coefs) noexcept
Polynomial of the previous value, coefs highest power first.
Definition Kernels.cpp:173
double goertzel(std::span< const double > window, std::span< const double > coefs) noexcept
Weighted energy of the window at chosen frequencies.
Definition Kernels.cpp:451
double pattern_lookup(std::span< const double > window, std::span< const double > coefs) noexcept
Table indexed by the recent shape of the window.
Definition Kernels.cpp:341
double erode(std::span< const double > window, std::span< const double > coefs) noexcept
Minimum over the window of window[k] - coefs[k], the grayscale erosion.
Definition Kernels.cpp:391
double dilate(std::span< const double > window, std::span< const double > coefs) noexcept
Maximum over the window of window[k] + coefs[k], the grayscale dilation.
Definition Kernels.cpp:369
double quantile(std::span< const double > window, std::span< const double > coefs)
Quantile of the whole window, interpolating between ranks.
Definition Kernels.cpp:413
double table_lookup_previous(std::span< const double > window, std::span< const double > coefs) noexcept
table_lookup indexed by window[1] instead of window[0].
Definition Kernels.cpp:151
std::vector< double > coupled_map_lattice_state(std::span< const double > cells, double r, double epsilon)
Builds the array coupled_map_lattice reads and writes.
Definition Kernels.cpp:547
std::vector< double > phasor_bank_state(std::span< const double > increments, std::span< const double > scales, std::span< const double > am_increments, std::span< const double > phases, std::span< const double > am_phases)
Builds the array phasor_bank reads and writes.
Definition Kernels.cpp:178
std::vector< double > step_sequence_state(std::span< const double > values, double threshold)
Builds the array step_sequence reads and writes.
Definition Kernels.cpp:616
double lorenz_attractor(std::span< const double >, std::span< double > coefs) noexcept
Lorenz system stepped once by fourth order Runge-Kutta, returning x.
Definition Kernels.cpp:586
double step_sequence(std::span< const double > window, std::span< double > coefs) noexcept
Table of values advanced by a trigger.
Definition Kernels.cpp:629
double breakpoint_curve(std::span< const double > window, std::span< const double > coefs) noexcept
Piecewise linear curve through (x, y) points.
Definition Kernels.cpp:316
double tapped_sum(std::span< const double > window, std::span< const double > coefs) noexcept
Sum of gain * window[lag] over (lag, gain) pairs.
Definition Kernels.cpp:122
std::vector< double > lorenz_state(double dt, double sigma, double rho, double beta, double x, double y, double z)
Builds the array lorenz_attractor reads and writes.
Definition Kernels.cpp:580
double coupled_map_lattice(std::span< const double >, std::span< double > coefs) noexcept
Ring of logistic maps with nearest neighbour coupling.
Definition Kernels.cpp:561
double fourier_series(std::span< const double > window, std::span< const double > coefs) noexcept
Fourier series of a phase.
Definition Kernels.cpp:291
std::vector< double > mean(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Arithmetic mean per window.
Definition Analysis.cpp:200
double chebyshev_series(std::span< const double > window, std::span< const double > coefs) noexcept
Sum of coefs[k] * T_k(window[0]) over Chebyshev polynomials.
Definition Kernels.cpp:156
double zscore(std::span< const double > window, std::span< const double > coefs) noexcept
How far the newest value sits from the rest of the window, in standard deviations.
Definition Kernels.cpp:438
double sample_table(std::span< const double > table, double t) noexcept
Read an evenly spaced table at a position in [0, 1], interpolating linearly.
Definition Scalar.hpp:79
Tendency< D, float > scale(const Tendency< D, float > &t, float factor)
Uniform scaling of a scalar-output tendency.
Definition Tendency.hpp:98
T wrap(T x, T lo, T hi) noexcept
Wrap x into [lo, hi) with modulo semantics.
Definition Scalar.hpp:218
uint32_t resolution
Cell count. Zero is invalid.
Definition Lattice.hpp:228
A regular subdivision of an AABB1D into a number of cells.
Definition Lattice.hpp:227