Etterna 0.74.4
Loading...
Searching...
No Matches
PatternModHelpers.h
1#pragma once
2#include <string>
3#include <array>
4#include <vector>
5#include <algorithm>
6#ifndef __aarch64__
7 #include <xmmintrin.h>
8#else
9 //Use sse2neon to transparently provide ARM Neon equivalents of x86_64 SIMD intrinsics
10 #include "sse2neon.h"
11#endif
12#include <numeric>
13#include <cstring>
14
15/* generic pattern mod functions and defs to help either agnostic or dependent
16 * mods do their stuff */
17constexpr float neutral = 1.F;
18
20inline auto
21fastpow(double a, double b) -> float
22{
23 int u[2];
24 std::memcpy(&u, &a, sizeof a);
25 u[1] = static_cast<int>(b * (u[1] - 1072632447) + 1072632447);
26 u[0] = 0;
27 std::memcpy(&a, &u, sizeof a);
28 return static_cast<float>(a);
29}
30
32inline auto
33fastsqrt(float _in) -> float
34{
35 if (_in == 0.F) {
36 return 0.F;
37 }
38 const auto in = _mm_load_ss(&_in);
39 float out;
40 _mm_store_ss(&out, _mm_mul_ss(in, _mm_rsqrt_ss(in)));
41 return out;
42}
43
44template<typename T>
45auto
46sum(const std::vector<T>& v) -> T
47{
48 return std::accumulate(begin(v), end(v), static_cast<T>(0));
49}
50
51template<typename T>
52auto
53mean(const std::vector<T>& v) -> float
54{
55 return static_cast<float>(sum(v)) / static_cast<float>(v.size());
56}
57
58// Coefficient of variation
59inline auto
60cv(const std::vector<float>& input) -> float
61{
62 auto sd = 0.F;
63 const auto average = mean(input);
64 for (auto i : input) {
65 sd += (i - average) * (i - average);
66 }
67
68 return fastsqrt(sd / static_cast<float>(input.size())) / average;
69}
70
71// cv of a vector truncated to a set number of values, or if below, filled with
72// dummy values to reach the desired num_vals
73inline auto
74cv_trunc_fill(const std::vector<float>& input,
75 const int& num_vals,
76 const float& ms_dummy) -> float
77{
78 int input_sz = static_cast<int>(input.size());
79 float sd = 0.F;
80 float average = 0.F;
81 if (input_sz >= num_vals) {
82 for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
83 average += input[i];
84 }
85 average /= static_cast<float>(num_vals);
86
87 for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
88 sd += (input[i] - average) * (input[i] - average);
89 }
90
91 return fastsqrt(sd / static_cast<float>(num_vals)) / average;
92 }
93
94 for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
95 average += input[i];
96 }
97
98 // fill with dummies if input is below desired number of values
99 for (int i = 0; i < num_vals - input_sz; ++i) {
100 average += ms_dummy;
101 }
102 average /= static_cast<float>(num_vals);
103
104 for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
105 sd += (input[i] - average) * (input[i] - average);
106 }
107
108 for (int i = 0; i < num_vals - input_sz; ++i) {
109 sd += (ms_dummy - average) * (ms_dummy - average);
110 }
111
112 return fastsqrt(sd / static_cast<float>(num_vals)) / average;
113}
114
115inline auto
116sum_trunc_fill(const std::vector<float>& input,
117 const int& num_vals,
118 const float& ms_dummy) -> float
119{
120 int input_sz = static_cast<int>(input.size());
121 float sum = 0.F;
122 // use up to num_vals
123 for (int i = 0; i < std::min(input_sz, num_vals); ++i) {
124 sum += input[i];
125 }
126
127 // got enough
128 if (input_sz >= num_vals) {
129 return sum;
130 }
131
132 // fill with dummies if input is below desired number of values
133 for (int i = 0; i < num_vals - static_cast<int>(input_sz); ++i) {
134 sum += ms_dummy;
135 }
136
137 return sum;
138}
139
140inline auto
141div_high_by_low(float a, float b) -> float
142{
143 if (b > a) {
144 std::swap(a, b);
145 }
146 return a / b;
147}
148
149inline auto
150div_low_by_high(float a, float b) -> float
151{
152 if (b > a) {
153 std::swap(a, b);
154 }
155 return b / a;
156}
157
158inline auto
159diff_high_by_low(int a, int b) -> int
160{
161 if (b > a) {
162 std::swap(a, b);
163 }
164 return a - b;
165}
166
167inline auto
168weighted_average(const float& a, const float& b, const float& x, const float& y)
169 -> float
170{
171 return (x * a + ((y - x) * b)) / y;
172}
173
174inline auto
175lerp(float t, float a, float b) -> float
176{
177 return (1.F - t)*a + t*b;
178}