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

◆ divideCoefficientQ16()

i64 fl::anonymous_namespace{device_solve.cpp.hpp}::divideCoefficientQ16 ( i64 cofactor_q32,
i64 determinant_q48 )

round(cofactor_q32 * 2^32 / determinant_q48), in s16.16, without a 128-bit intermediate.

The obvious form is (cofactor << 32) / determinant, which is what the host study computes with unbounded integers. A target without __int128 cannot form that numerator: the cofactor is already Q32, and 32 more bits puts it past i64 for any matrix that matters.

So each of the 32 doublings is spent where there is room – on the numerator while it still fits, on the denominator otherwise. Both raise the quotient by the same factor, so the only loss is what halving the denominator rounds away, and the determinant carries far more bits than a s16.16 answer needs.

Checked against the exact divide over ci/color_fixed_inverse_study.py's corpus, six degrees of primary collapse, and 20,000 random primary sets: zero disagreement, and 72% of coefficients needed at least one denominator halving, up to 11 – so the staged path is the one being exercised, not a branch nothing reaches.

Definition at line 112 of file device_solve.cpp.hpp.

112 {
113 i64 numerator = cofactor_q32;
114 i64 denominator = determinant_q48;
115 // Safe to negate: `sumFitsI64` refuses a determinant of i64's minimum, so
116 // the caller cannot pass the one value this would be undefined for.
117 if (denominator < 0) {
118 numerator = -numerator;
119 denominator = -denominator;
120 }
121 constexpr i64 kHalfMax = kI64Max / 2;
122 for (int spent = 0; spent < 32; ++spent) {
123 const i64 magnitude = numerator < 0 ? -numerator : numerator;
124 if (magnitude <= kHalfMax) {
125 numerator *= 2;
126 } else {
127 denominator = (denominator + 1) / 2;
128 }
129 }
130 return roundedDivI64(numerator, denominator);
131}
i64 roundedDivI64(i64 numerator, i64 denominator) FL_NO_EXCEPT
Nearest integer, halves away from zero.
fl::i64 i64
Definition stdint.h:221

References divideCoefficientQ16(), fl::FL_NO_EXCEPT, kI64Max, and roundedDivI64().

Referenced by divideCoefficientQ16().

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