VCV Rack API v2
Loading...
Searching...
No Matches
approx.hpp
Go to the documentation of this file.
1#pragma once
2#include <dsp/common.hpp>
3
4
5namespace rack {
6namespace dsp {
7
8
9/*
10Glossary:
11https://en.wikipedia.org/wiki/Taylor_series
12https://en.wikipedia.org/wiki/Chebyshev_polynomials
13https://en.wikipedia.org/wiki/Pad%C3%A9_approximant
14https://en.wikipedia.org/wiki/Horner%27s_method
15https://en.wikipedia.org/wiki/Estrin%27s_scheme
16https://en.wikipedia.org/wiki/CORDIC
17*/
18
19
23template <typename T, size_t N>
24T polyDirect(const T (&a)[N], T x) {
25 T y = 0;
26 T xn = 1;
27 for (size_t n = 0; n < N; n++) {
28 y += a[n] * xn;
29 xn *= x;
30 }
31 return y;
32}
33
38template <typename T, size_t N>
39T polyHorner(const T (&a)[N], T x) {
40 if (N == 0)
41 return 0;
42
43 T y = a[N - 1];
44 for (size_t n = 1; n < N; n++) {
45 y = a[N - 1 - n] + y * x;
46 }
47 return y;
48}
49
54template <typename T, size_t N>
55T polyEstrin(const T (&a)[N], T x) {
56 if (N == 0)
57 return 0;
58 if (N == 1)
59 return a[0];
60
61 const size_t M = (N + 1) / 2;
62 T b[M];
63 for (size_t i = 0; i < M; i++) {
64 b[i] = a[2 * i];
65 if (2 * i + 1 < N)
66 b[i] += a[2 * i + 1] * x;
67 }
68 return polyEstrin(b, x * x);
69}
70
71
76template <typename T>
77T exp2Floor(T x, T* xf);
78
79template <>
80inline float exp2Floor(float x, float* xf) {
81 x += 127;
82 // x should be positive now, so this always truncates towards -inf.
83 int32_t xi = x;
84 if (xf)
85 *xf = x - xi;
86 // Set mantissa of float
87 union {
88 float yi;
89 int32_t yii;
90 };
91 yii = xi << 23;
92 return yi;
93}
94
95template <>
97 x += 127;
98 simd::int32_4 xi = x;
99 if (xf)
100 *xf = x - simd::float_4(xi);
101 simd::int32_4 yii = xi << 23;
102 return simd::float_4::cast(yii);
103}
104
106template <typename T>
107T approxExp2Floor(T x, T* xf) {
108 return exp2Floor(x, xf);
109}
110
111
117template <typename T>
119 T xf;
120 T yi = exp2Floor(x, &xf);
121
122 const T a[] = {
123 1.0,
124 0.69315169353961,
125 0.2401595990753,
126 0.055817908652,
127 0.008991698010,
128 0.001879100722,
129 };
130 T yf = polyHorner(a, xf);
131 return yi * yf;
132}
133
135template <typename T>
137 return exp2_taylor5(x);
138}
139
140
141} // namespace dsp
142} // namespace rack
T approxExp2Floor(T x, T *xf)
Deprecated alias of exp2Floor()
Definition approx.hpp:107
T approxExp2_taylor5(T x)
Deprecated alias of exp2_taylor5()
Definition approx.hpp:136
T polyEstrin(const T(&a)[N], T x)
Evaluates a polynomial with coefficients a[n] at x.
Definition approx.hpp:55
T polyDirect(const T(&a)[N], T x)
Evaluates a polynomial with coefficients a[n] at x.
Definition approx.hpp:24
T exp2_taylor5(T x)
Returns 2^x with at most 6e-06 relative error.
Definition approx.hpp:118
T exp2Floor(T x, T *xf)
Returns 2^floor(x).
T polyHorner(const T(&a)[N], T x)
Evaluates a polynomial with coefficients a[n] at x.
Definition approx.hpp:39
Vector< float, 4 > float_4
Definition Vector.hpp:340
Root namespace for the Rack API.
Definition AudioDisplay.hpp:9
Wrapper for __m128 representing an aligned vector of 4 single-precision float values.
Definition Vector.hpp:34
static Vector cast(Vector< int32_t, 4 > a)
Definition Vector.hpp:163
Definition Vector.hpp:108