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

◆ emitterColumnQ16()

bool fl::anonymous_namespace{device_solve.cpp.hpp}::emitterColumnQ16 ( const i32(&) xy[2],
i32 luminance,
i64(&) column[3] )

One emitter's XYZ column at its own luminance, all in s16.16.

xyY_to_XYZ is x * Y * inv_y, which C++ groups left to right and so scales before it divides. This divides first, deliberately: in fixed point x * Y discards low bits the divide would have used. Measured against the float derivation over the study's corpus and four luminance sets, the worst coefficient error is 2899 ULP dividing first against 7363 scaling first, and the colour figure is the same either way. See ci/color_fixed_profile_study.py.

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

159 {
160 const i32 x = xy[0];
161 const i32 y = xy[1];
162 // The float guard rejects a `y` at or below 1e-6; in Q16 anything under
163 // half a step quantises to zero, and dividing by it is the failure the
164 // float path cannot have.
165 if (y <= 0 || luminance <= 0 || x <= 0) {
166 return false;
167 }
168 if (static_cast<i64>(x) + static_cast<i64>(y) > kQ16One) {
169 // Outside the CIE simplex, so z would be negative for a physical
170 // emitter.
171 return false;
172 }
173 const i64 z = kQ16One - static_cast<i64>(x) - static_cast<i64>(y);
174 const i64 x_over_y = roundedDivideQ16(static_cast<i64>(x) * kQ16One, y);
175 const i64 z_over_y = roundedDivideQ16(z * kQ16One, y);
176 column[0] = roundedDivideQ16(x_over_y * luminance, kQ16One);
177 column[1] = luminance;
178 column[2] = roundedDivideQ16(z_over_y * luminance, kQ16One);
179 for (int i = 0; i < 3; ++i) {
180 // The inverse works in i32, so a column that does not fit is refused
181 // here rather than wrapped on the way in.
182 if (column[i] > 2147483647LL || column[i] < -2147483648LL) {
183 return false;
184 }
185 }
186 return true;
187}
int y
Definition simple.h:93
int x
Definition simple.h:92
uint32_t z[NUM_LAYERS]
Definition Fire2023.h:93
unsigned int xy(unsigned int x, unsigned int y)
i64 roundedDivideQ16(i64 numerator, i64 denominator) FL_NO_EXCEPT
Nearest integer of numerator / denominator, halves away from zero.
fl::i64 i64
Definition stdint.h:221

References emitterColumnQ16(), fl::FL_NO_EXCEPT, kQ16One, roundedDivideQ16(), fl::x, xy(), fl::y, and z.

Referenced by emitterColumnQ16().

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