FastLED 3.10.6
Loading...
Searching...
No Matches
wide_divide.h File Reference

Detailed Description

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 "fl/stl/int.h"
#include "fl/stl/compiler_control.h"
#include "fl/stl/noexcept.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.