50 return x == y || std::abs(x - y) <
F_EPSILON;
63inline auto fraction(std::floating_point
auto x)
noexcept
65 return x - std::trunc(x);
82 return x - std::floor(x);
90 thread_local unsigned long s_next = 1;
91 s_next = s_next * 1103515245 + 12345;
92 return s_next / 65536 % 32768;
98template<std::
floating_po
int T>
101 constexpr auto FAST_RAND_RATIO =
static_cast<T
>(1.0 / 32768);
102 return fastRand() * upper * FAST_RAND_RATIO;
109template<std::
integral T>
112 constexpr float FAST_RAND_RATIO = 1.f / 32768;
113 return static_cast<T
>(
fastRand() *
static_cast<float>(upper) * FAST_RAND_RATIO);
119template<
typename T>
requires std::is_arithmetic_v<T>
125template<std::
floating_po
int T>
128 constexpr auto FAST_RAND_RATIO =
static_cast<T
>(1.0 / 32767);
129 return fastRand() * upper * FAST_RAND_RATIO;
135template<std::
unsigned_
integral T>
143 constexpr float FAST_RAND_RATIO = 1.f / 32768;
150 return static_cast<T
>(
fastRand() * (upper + 1.f) * FAST_RAND_RATIO);
157template<std::
signed_
integral T>
165 constexpr float FAST_RAND_RATIO = 1.f / 32768;
172 const auto fupper =
static_cast<float>(upper);
173 const float r = fupper + std::copysign(1.f, fupper);
175 return static_cast<T
>(
fastRand() * r * FAST_RAND_RATIO);
183template<
typename T>
requires std::is_arithmetic_v<T>
188inline bool oneIn(
unsigned chance)
noexcept {
return 0 == (
fastRand() % chance); }
193static void roundAt(T& value,
const T& where,
const T& stepSize)
195 if (std::abs(value - where) <
F_EPSILON * std::abs(stepSize))
207 std::memcpy(x, &a,
sizeof(x));
208 x[1] =
static_cast<std::int32_t
>(b * (x[1] - 1072632447) + 1072632447);
211 std::memcpy(&d, x,
sizeof(d));
218constexpr T
sign(T val)
noexcept
220 return val >= 0 ? 1 : -1;
227 return std::sqrt(std::abs(val)) *
sign(val);
233 return std::pow(std::abs(v), e) *
sign(v);
243 using namespace std::numbers;
246 const float mmax = std::max(std::abs(min), std::abs(max));
247 const float val = value * (max - min) + min;
248 float result =
signedPowf(val / mmax, e_v<float>) * mmax;
249 return std::isnan(result) ? 0 : result;
251 float result = std::pow(value, e_v<float>) * (max - min) + min;
252 return std::isnan(result) ? 0 : result;
259 constexpr auto inv_e =
static_cast<float>(1.0 / std::numbers::e);
260 const float valueLimited = std::clamp(value, min, max);
261 const float val = (valueLimited - min) / (max - min);
264 const float mmax = std::max(std::abs(min), std::abs(max));
265 float result =
signedPowf(valueLimited / mmax, inv_e) * mmax;
266 return std::isnan(result) ? 0 : result;
268 float result = std::pow(val, inv_e) * (max - min) + min;
269 return std::isnan(result) ? 0 : result;
274template<
typename T>
requires std::is_arithmetic_v<T>
277 using F_T = std::conditional_t<std::is_floating_point_v<T>, T,
float>;
278 return std::exp(std::numbers::ln10_v<F_T> * x);
283template<
typename T>
requires std::is_arithmetic_v<T>
286 using F_T = std::conditional_t<std::is_floating_point_v<T>, T,
float>;
287 constexpr auto inv_ln10 =
static_cast<F_T
>(1.0 / std::numbers::ln10);
288 return std::log(x) * inv_ln10;
315 return amp == 0.0f ? -INFINITY :
ampToDbfs(amp);
324 return std::isinf(dbfs) ? 0.0f :
dbfsToAmp(dbfs);
335 int asInt =
static_cast<int>(std::round(f));
344 for (
int i = 1; i < 10; ++i)
347 if (asInt >= power) { ++digits; }
359 T
const dx = x2 - x1;
362 m_a = (y2 - y1) / dx;
379inline __m128 fastExp(__m128 x)
383 const __m128 a = _mm_set1_ps (12102203.0f);
384 const __m128i m = _mm_set1_epi32 (0xff800000);
385 const __m128 ttm23 = _mm_set1_ps (1.1920929e-7f);
386 const __m128 c0 = _mm_set1_ps (0.3371894346f);
387 const __m128 c1 = _mm_set1_ps (0.657636276f);
388 const __m128 c2 = _mm_set1_ps (1.00172476f);
390 t = _mm_cvtps_epi32 (_mm_mul_ps (a, x));
391 j = _mm_and_si128 (t, m);
392 t = _mm_sub_epi32 (t, j);
393 f = _mm_mul_ps (ttm23, _mm_cvtepi32_ps (t));
395 p = _mm_mul_ps (p, f);
396 p = _mm_add_ps (p, c1);
397 p = _mm_mul_ps (p, f);
398 p = _mm_add_ps (p, c2);
399 r = _mm_castsi128_ps (_mm_add_epi32 (j, _mm_castps_si128 (p)));
405inline __m128 fastLog(__m128 a)
407 __m128i aInt = _mm_castps_si128(a);
408 __m128i e = _mm_sub_epi32(aInt, _mm_set1_epi32(0x3f2aaaab));
409 e = _mm_and_si128(e, _mm_set1_epi32(0xff800000));
410 __m128i subtr = _mm_sub_epi32(aInt, e);
411 __m128 m = _mm_castsi128_ps(subtr);
412 __m128 i = _mm_mul_ps(_mm_cvtepi32_ps(e), _mm_set1_ps(1.19209290e-7f));
413 __m128 f = _mm_sub_ps(m, _mm_set1_ps(1.0f));
414 __m128 s = _mm_mul_ps(f, f);
415 __m128 r = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(0.230836749f), f), _mm_set1_ps(-0.279208571f));
416 __m128 t = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(0.331826031f), f), _mm_set1_ps(-0.498910338f));
417 r = _mm_add_ps(_mm_mul_ps(r, s), t);
418 r = _mm_add_ps(_mm_mul_ps(r, s), f);
419 r = _mm_add_ps(_mm_mul_ps(i, _mm_set1_ps(0.693147182f)), r);
423inline __m128 sse2Abs(__m128 x)
425 return _mm_and_ps(x, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)));
428inline __m128 sse2Floor(__m128 x)
430 __m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(x));
431 __m128 needs_correction = _mm_cmplt_ps(x, t);
432 return _mm_sub_ps(t, _mm_and_ps(needs_correction, _mm_set1_ps(1.0f)));
435inline __m128 sse2Round(__m128 x)
437 __m128 sign_mask = _mm_cmplt_ps(x, _mm_setzero_ps());
438 __m128 bias_pos = _mm_set1_ps(0.5f);
439 __m128 bias_neg = _mm_set1_ps(-0.5f);
440 __m128 bias = _mm_or_ps(_mm_and_ps(sign_mask, bias_neg), _mm_andnot_ps(sign_mask, bias_pos));
441 __m128 y = _mm_add_ps(x, bias);
442 return _mm_cvtepi32_ps(_mm_cvttps_epi32(y));
LinearMap(T x1, T y1, T x2, T y2)
Definition lmms_math.h:357
T map(T x) const
Definition lmms_math.h:366
T m_a
Definition lmms_math.h:372
T m_b
Definition lmms_math.h:373
Definition RemotePluginBase.cpp:34
float linearToLogScale(float min, float max, float value)
Scales value from logarithmic to linear. Value should be in min-max range.
Definition lmms_math.h:257
float safeAmpToDbfs(float amp)
Converts linear amplitude (0-1.0) to dBFS scale. Handles zeroes as -inf.
Definition lmms_math.h:313
auto fastPow10f(T x)
Definition lmms_math.h:275
float dbfsToAmp(float dbfs)
Converts dBFS-scale to linear amplitude with 0dBFS = 1.0.
Definition lmms_math.h:304
T fastRandInc(T upper) noexcept
Returns a pseudorandom number within [0, upper] (inclusive upper bound).
Definition lmms_math.h:126
int numDigitsAsInt(float f)
Definition lmms_math.h:330
float signedPowf(float v, float e)
Exponential function that deals with negative bases.
Definition lmms_math.h:231
float sqrt_neg(float val)
if val >= 0.0f, returns sqrt(val), else: -sqrt(-val)
Definition lmms_math.h:225
float logToLinearScale(float min, float max, float value)
Scales value from linear to logarithmic.
Definition lmms_math.h:241
double fastPow(double a, double b)
Source: http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/.
Definition lmms_math.h:202
static void roundAt(T &value, const T &where, const T &stepSize)
Round value to where depending on step size.
Definition lmms_math.h:193
auto absFraction(std::floating_point auto x) noexcept
Returns the wrapped fractional part of a float, a value between 0.0f and 1.0f.
Definition lmms_math.h:80
auto fastLog10f(T x)
Definition lmms_math.h:284
float ampToDbfs(float amp)
Converts linear amplitude (>0-1.0) to dBFS scale.
Definition lmms_math.h:295
float safeDbfsToAmp(float dbfs)
Converts dBFS-scale to linear amplitude with 0dBFS = 1.0. Handles infinity as zero.
Definition lmms_math.h:322
int fastRand() noexcept
Returns a pseudorandom integer within [0, 32768).
Definition lmms_math.h:88
constexpr float F_EPSILON
Definition lmms_constants.h:35
constexpr T sign(T val) noexcept
returns +1 if val >= 0, else -1
Definition lmms_math.h:218
bool approximatelyEqual(float x, float y) noexcept
Definition lmms_math.h:48
auto fraction(std::floating_point auto x) noexcept
Returns the fractional part of a float, a value between -1.0f and 1.0f.
Definition lmms_math.h:63
bool oneIn(unsigned chance) noexcept
Returns true one in chance times at random.
Definition lmms_math.h:188