From 1a8aaa3b26feba106259b6842ad9f8998fb3233d Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 26 Nov 2024 20:32:39 +0100 Subject: [PATCH] Speed improvements, commented legacy _t trig functions - speed improvement: by default M_TWOPI is treated as a double float - directly calling sin16_t in cos_approx() saves a lot of overhead --- wled00/wled_math.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/wled00/wled_math.cpp b/wled00/wled_math.cpp index a191968e1..583381d66 100644 --- a/wled00/wled_math.cpp +++ b/wled00/wled_math.cpp @@ -10,14 +10,17 @@ //#define WLED_DEBUG_MATH -#define modd(x, y) ((x) - (int)((x) / (y)) * (y)) - -// Note: cos_t, sin_t and tan_t are very accurate but may be slow +// Note: cos_t, sin_t and tan_t are very accurate but slow // the math.h functions use several kB of flash and are to be avoided if possible // sin16_t / cos16_t are faster and much more accurate than the fastled variants // sin_approx and cos_approx are float wrappers for sin16_t/cos16_t and have an accuracy better than +/-0.0015 compared to sinf() // sin8_t / cos8_t are fastled replacements and use sin16_t / cos16_t. Slightly slower than fastled version but very accurate + +// Taylor series approximations, replaced with Bhaskara I's approximation +/* +#define modd(x, y) ((x) - (int)((x) / (y)) * (y)) + float cos_t(float phi) { float x = modd(phi, M_TWOPI); @@ -54,6 +57,7 @@ float tan_t(float x) { #endif return res; } +*/ // 16-bit, integer based Bhaskara I's sine approximation: 16*x*(pi - x) / (5*pi^2 - 4*x*(pi - x)) // input is 16bit unsigned (0-65535), output is 16bit signed (-32767 to +32767) @@ -85,17 +89,18 @@ uint8_t cos8_t(uint8_t theta) { return sin8_t(theta + 64); //cos(x) = sin(x+pi/2) } -float sin_approx(float theta) -{ - uint16_t scaled_theta = (int)(theta * (0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) +float sin_approx(float theta) { + uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) int32_t result = sin16_t(scaled_theta); float sin = float(result) / 0x7FFF; return sin; } -float cos_approx(float theta) -{ - return sin_approx(theta + M_PI_2); +float cos_approx(float theta) { + uint16_t scaled_theta = (int)(theta * (float)(0xFFFF / M_TWOPI)); // note: do not cast negative float to uint! cast to int first (undefined on C3) + int32_t result = sin16_t(scaled_theta + 16384); + float cos = float(result) / 0x7FFF; + return cos; } float tan_approx(float x) {