|
FastLED 3.10.6
|
A 64/32 -> 32 division built from 32-bit divides.
Q16.16 division is (a << 16) / b, and with a a full-range 32-bit value the numerator genuinely needs 48 bits – narrowing it would silently overflow, which is worse than being slow. So the width is not the problem; what the width costs is.
A target with a 32-bit hardware divider and no 64-bit one has to call into libgcc for that division. Measured on the toolchain the RP2350 core ships, for Cortex-M33 at -Os:
(i64)a * 65536 / b | 10 instructions, then a call to __aeabi_ldivmod |
__aeabi_ldivmod | 34 instructions, tail-calling __divdi3 (230) |
__udivdi3 (the unsigned worker) | 184 instructions, 19 backward branches |
| this | 62 instructions inline, two udiv, no call |
FastLED#4307 measured the runtime cost of that call on hardware: division on s16x16 ran 47x slower than on s8x8, whose 32-bit intermediate lowers to a single SDIV, and 36x slower than scalar float.
Definition in file wide_divide.h.
Include dependency graph for wide_divide.h:
This graph shows which files directly or indirectly include this file:Go to the source code of this file.
Namespaces | |
| namespace | fl |
| Base definition for an LED controller. | |
| namespace | fl::detail |
Compile-time linker keep-alive hook for a single fl::Bus. | |
Macros | |
| #define | FL_FIXED_POINT_DIVIDE_INLINE FASTLED_FORCE_INLINE |
constexpr where the language allows it, always force-inlined. | |
| #define | FL_FIXED_POINT_NARROW_DIVIDE 0 |
| 1 when the target divides 32 bits in hardware but not 64. | |
Functions | |
| FL_FIXED_POINT_DIVIDE_INLINE u32 | fl::divide64By32 (u32 hi, u32 lo, u32 divisor) FL_NO_EXCEPT |
(hi:lo) / divisor, for a quotient that fits 32 bits. | |
| FL_FIXED_POINT_DIVIDE_INLINE int | fl::detail::fixedPointLeadingZeros (u32 value) FL_NO_EXCEPT |
| Leading zeros of a non-zero 32-bit value; 32 for zero. | |