-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Experimental: Use fast_powf instead of powf for better performance in PID #11408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: maintenance-10.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -105,6 +105,71 @@ float acos_approx(float x) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Fast power approximation for positive base values. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Uses bit manipulation via the identity: x^y = 2^(y * log2(x)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Optimized for embedded systems - approximately 5-10x faster than powf(). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Accuracy: ~1-3% error for typical ranges, sufficient for TPA calculations. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Note: Only valid for base > 0. Returns 0 for invalid inputs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| float fast_powf(float base, float exp) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Handle common special cases for maximum speed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (exp == 0.0f) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 1.0f; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (exp == 1.0f) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return base; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (base <= 0.0f) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0.0f; // Invalid input | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (exp == 2.0f) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return base * base; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (exp == 0.5f) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fast_fsqrtf(base); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // For general case, use bit manipulation approximation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Based on: x^y = 2^(y * log2(x)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Using IEEE 754 floating point representation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| union { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| float f; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int32_t i; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } u; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| u.f = base; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Extract and compute: log2(x) ≈ (mantissa bits - 127) + normalized_mantissa | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // IEEE 754: float = 2^(exponent-127) * (1 + mantissa/2^23) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // log2(x) ≈ (exponent - 127) + (mantissa / 2^23) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Fast approximation: just use the exponent bits for log2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // More accurate version includes mantissa contribution | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int32_t exp_bits = (u.i >> 23) & 0xFF; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int32_t mant_bits = u.i & 0x7FFFFF; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // log2(base) approximation with mantissa correction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| float log2_base = (float)(exp_bits - 127) + (float)mant_bits / 8388608.0f; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+137
to
+155
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Using IEEE 754 floating point representation | |
| union { | |
| float f; | |
| int32_t i; | |
| } u; | |
| u.f = base; | |
| // Extract and compute: log2(x) ≈ (mantissa bits - 127) + normalized_mantissa | |
| // IEEE 754: float = 2^(exponent-127) * (1 + mantissa/2^23) | |
| // log2(x) ≈ (exponent - 127) + (mantissa / 2^23) | |
| // Fast approximation: just use the exponent bits for log2 | |
| // More accurate version includes mantissa contribution | |
| int32_t exp_bits = (u.i >> 23) & 0xFF; | |
| int32_t mant_bits = u.i & 0x7FFFFF; | |
| // log2(base) approximation with mantissa correction | |
| float log2_base = (float)(exp_bits - 127) + (float)mant_bits / 8388608.0f; | |
| // Use standard library log2f for accurate log2(base) | |
| union { | |
| float f; | |
| int32_t i; | |
| } u; | |
| // Compute log2(base) accurately using libm | |
| float log2_base = log2f(base); | |
Copilot
AI
Mar 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result_exp_frac can be negative when result_exp < 0 (which happens for base<1, common in airspeed scaling). The 2^x polynomial is documented as valid for x in [0,1], but the current int-cast decomposition allows frac outside that domain, which can increase error and introduce discontinuities around integer boundaries. Consider decomposing result_exp using floor (so 0<=frac<1) or otherwise ensuring the polynomial’s input range matches its documented validity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fast_powf() is new math behavior in a file that already has unit tests (src/test/unit/maths_unittest.cc). Please add coverage that checks fast_powf against powf() across the expected domain (e.g., base in ~[0.015, 60] and exp in ~[0, 2]) with an explicit acceptable error bound, so future changes don’t silently degrade PID scaling.