kopia lustrzana https://github.com/kosme/arduinoFFT
Use better sqrtf approximation (precise, no divisions)
rodzic
6df8d2d70f
commit
3e73c9884b
|
@ -392,16 +392,16 @@ private:
|
||||||
0.0000239684};
|
0.0000239684};
|
||||||
#endif
|
#endif
|
||||||
static constexpr T _WindowCompensationFactors[10] = {
|
static constexpr T _WindowCompensationFactors[10] = {
|
||||||
2, /* rectangle (Box car) */
|
1.0000000000 * 2.0, // rectangle (Box car)
|
||||||
1.8549343278 * 2, /* hamming */
|
1.8549343278 * 2.0, // hamming
|
||||||
1.8554726898 * 2, /* hann */
|
1.8554726898 * 2.0, // hann
|
||||||
2.0039186079 * 2, /* triangle (Bartlett) */
|
2.0039186079 * 2.0, // triangle (Bartlett)
|
||||||
2.8163172034 * 2, /* nuttall */
|
2.8163172034 * 2.0, // nuttall
|
||||||
2.367347436 * 2, /* blackman */
|
2.3673474360 * 2.0, // blackman
|
||||||
2.7557840395 * 2, /* blackman nuttall */
|
2.7557840395 * 2.0, // blackman nuttall
|
||||||
2.7929062517 * 2, /* blackman harris*/
|
2.7929062517 * 2.0, // blackman harris
|
||||||
3.5659039231 * 2, /* flat top */
|
3.5659039231 * 2.0, // flat top
|
||||||
1.5029392863 * 2 /* welch */
|
1.5029392863 * 2.0 // welch
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mathematial constants
|
// Mathematial constants
|
||||||
|
@ -419,24 +419,27 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FFT_SQRT_APPROXIMATION
|
#ifdef FFT_SQRT_APPROXIMATION
|
||||||
|
// Fast inverse square root aka "Quake 3 fast inverse square root", multiplied by x.
|
||||||
|
// Uses one iteration of Halley's method for precision.
|
||||||
|
// See: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
|
||||||
|
// And: https://github.com/HorstBaerbel/approx
|
||||||
template<typename V = T>
|
template<typename V = T>
|
||||||
static inline V sqrt_internal(typename std::enable_if<std::is_same<V, float>::value, V>::type x)
|
static inline V sqrt_internal(typename std::enable_if<std::is_same<V, float>::value, V>::type x)
|
||||||
{
|
{
|
||||||
|
union // get bits for float value
|
||||||
union {
|
{
|
||||||
int i;
|
|
||||||
float x;
|
float x;
|
||||||
|
int32_t i;
|
||||||
} u;
|
} u;
|
||||||
u.x = x;
|
u.x = x;
|
||||||
u.i = (1 << 29) + (u.i >> 1) - (1 << 22);
|
u.i = 0x5f375a86 - (u.i >> 1); // gives initial guess y0. use 0x5fe6ec85e7de30da for double
|
||||||
// Two Babylonian Steps (simplified from:)
|
float xu = x * u.x;
|
||||||
// u.x = 0.5f * (u.x + x/u.x);
|
float xu2 = xu * u.x;
|
||||||
// u.x = 0.5f * (u.x + x/u.x);
|
u.x = (0.125 * 3.0) * xu * (5.0 - xu2 * ((10.0 / 3.0) - xu2)); // Halley's method, repeating increases accuracy
|
||||||
u.x = u.x + x / u.x;
|
|
||||||
u.x = 0.25f * u.x + x / u.x;
|
|
||||||
return u.x;
|
return u.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At least on the ESP32, the approximation is not faster, so we use the standard function
|
||||||
template<typename V = T>
|
template<typename V = T>
|
||||||
static inline V sqrt_internal(typename std::enable_if<!std::is_same<V, float>::value, V>::type x)
|
static inline V sqrt_internal(typename std::enable_if<!std::is_same<V, float>::value, V>::type x)
|
||||||
{
|
{
|
||||||
|
|
Ładowanie…
Reference in New Issue