FastLED 3.10.6
Loading...
Searching...
No Matches

◆ divideWhiteQ16()

i64 fl::anonymous_namespace{white_allocation.cpp.hpp}::divideWhiteQ16 ( i32 numerator,
i32 denominator )

(numerator << 16) / denominator as s16.16, kept in i64.

Named for this file because .cpp.hpp files share a translation unit under the unity build, so an anonymous namespace does not isolate it.

The shift happens in i64: a numerator near i32's range shifted left by 16 needs 47 bits. The result stays there too, and is deliberately not clamped.

An earlier revision clamped it to full drive and argued the clamp was decision-preserving – a bound outside +/-1.0 either does not bind or means infeasible, so the min and max that follow reach the same verdict either way. The argument does not hold: it turns a lower bound of "w >= 6.64", which no drive can satisfy, into "w >= 1.0", which an upper bound of exactly 1.0 then meets, so the interval collapses to a single point instead of being empty.

That is latent here rather than a live bug, and it is worth being precise about why. The drives are at_zero - level * per_white, which reproduce the target for any level – that is an identity, not a property of the level – so the real feasibility test is the range check on the drives at the end, and it rejects these targets whether or not the bound was clamped. A sweep of 300 000 random targets finds no difference in what this function returns.

It is still wrong to leave. The bound is consumed as an interval, and any caller that uses the interval for something other than picking one of its two ends inherits the collapse – which is exactly how it was found, by work on a two-white allocation that bisects over totals. i64 costs nothing: the comparisons that follow are between values the caller already holds, and the chosen level is inside [0, full] before narrowing.

Definition at line 76 of file white_allocation.cpp.hpp.

76 {
77 const i64 scaled = static_cast<i64>(numerator) * 65536;
78 return scaled / static_cast<i64>(denominator);
79}
fl::i64 i64
Definition stdint.h:221

References divideWhiteQ16(), and fl::FL_NO_EXCEPT.

Referenced by divideWhiteQ16().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: