Boosted / overdrive solver. This remains useful as an optional visual policy, but it is deliberately distinct from wx_lp_legacy. The non-overdriven residual boundary gives the chromaticity-preserving W limit; overdrive_ratio then moves W toward 1.0 and accepts the corresponding drift toward the W diode.
| 787 | // chromaticity-preserving W limit; overdrive_ratio then moves W toward 1.0 and |
| 788 | // accepts the corresponding drift toward the W diode. |
| 789 | void solve_wx_overdrive(const ProfileCache& cache, float s_r, float s_g, |
| 790 | float s_b, float overdrive_ratio, |
| 791 | float out_rgbw[4]) FL_NOEXCEPT { |
| 792 | zero4(out_rgbw); |
| 793 | |
| 794 | const float value = max3f(s_r, s_g, s_b); |
| 795 | if (value <= 1e-9f) { |
| 796 | return; |
| 797 | } |
| 798 | |
| 799 | // Boosted/overdrive is a distinct visual policy, but it still must keep |
| 800 | // native single/dual topology authority. Single axes stay exact; dual |
| 801 | // edges stay locked to RG/RB/GB through the measured two-emitter solve. |
| 802 | if (is_native_input_gamut(*cache.profile)) { |
| 803 | const int n_active = count_active_channels(s_r, s_g, s_b); |
| 804 | if (n_active == 1) { |
| 805 | native_single_identity(s_r, s_g, s_b, out_rgbw); |
| 806 | return; |
| 807 | } |
| 808 | if (n_active == 2) { |
| 809 | solve_native_dual_edge_fixed_topology(cache, s_r, s_g, |
| 810 | s_b, out_rgbw); |
| 811 | return; |
| 812 | } |
| 813 | } |
| 814 | |
| 815 | // Solve the full-chroma endpoint first and scale value later. This keeps |
| 816 | // boosted mode from flattening fixed-hue HSV value ramps into repeated |
| 817 | // saturated endpoint tuples. |
| 818 | const float c_r = s_r / value; |
| 819 | const float c_g = s_g / value; |
| 820 | const float c_b = s_b / value; |
| 821 | |
| 822 | float X_t[3]; |
| 823 | source_rgb_to_XYZ(cache, c_r, c_g, c_b, X_t); |
| 824 | |
| 825 | float xy_t[2]; |
| 826 | project_to_hull(cache, X_t, xy_t); |
| 827 | |
| 828 | float a[3]; |
| 829 | matvec3(cache.P_RGB_inv, X_t, a); |
| 830 | const float* d = cache.d_W; |
| 831 | |
| 832 | float w_strict = 1.0f; |
| 833 | for (int i = 0; i < 3; ++i) { |
| 834 | if (d[i] > 1e-9f && a[i] >= 0.0f) { |
| 835 | const float lim = a[i] / d[i]; |
| 836 | if (lim < w_strict) { |
| 837 | w_strict = lim; |
| 838 | } |
| 839 | } |
| 840 | } |
| 841 | w_strict = fl::clamp(w_strict, 0.0f, 1.0f); |
| 842 | |
| 843 | const float rho = fl::clamp(overdrive_ratio, 0.0f, 1.0f); |
| 844 | float w = w_strict + rho * (1.0f - w_strict); |
| 845 | w = fl::clamp(w, 0.0f, 1.0f); |
| 846 |
no test coverage detected