Replace Mixbox with FilamentMixer integration

This commit is contained in:
Justin Hayes
2026-02-11 11:29:51 -05:00
parent 4fea9f5d2c
commit 33ae311ade
7 changed files with 990 additions and 9 deletions

View File

@@ -189,6 +189,8 @@ Orca Slicer includes a pressure advance calibration pattern test adapted from An
The Bambu networking plugin is based on non-free libraries from BambuLab. It is optional to the Orca Slicer and provides extended functionalities for Bambulab printer users. The Bambu networking plugin is based on non-free libraries from BambuLab. It is optional to the Orca Slicer and provides extended functionalities for Bambulab printer users.
Filament color blending uses a FilamentMixer-based implementation and does not include Mixbox source code, binaries, or data files.
# Feedback & Contribution # Feedback & Contribution
We greatly value feedback and contributions from our users. Your feedback will help us to further develop Full Spectrum for our community. We greatly value feedback and contributions from our users. Your feedback will help us to further develop Full Spectrum for our community.
- To submit a bug or feature request, file an issue in GitHub Issues. - To submit a bug or feature request, file an issue in GitHub Issues.

View File

@@ -285,6 +285,9 @@ set(lisbslic3r_sources
MinimumSpanningTree.hpp MinimumSpanningTree.hpp
MixedFilament.cpp MixedFilament.cpp
MixedFilament.hpp MixedFilament.hpp
filament_mixer.cpp
filament_mixer.h
filament_mixer_model.h
miniz_extension.cpp miniz_extension.cpp
miniz_extension.hpp miniz_extension.hpp
ModelArrange.cpp ModelArrange.cpp

View File

@@ -1,4 +1,5 @@
#include "MixedFilament.hpp" #include "MixedFilament.hpp"
#include "filament_mixer.h"
#include <algorithm> #include <algorithm>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
@@ -980,6 +981,55 @@ const MixedFilament *MixedFilamentManager::mixed_filament_from_id(unsigned int f
return idx >= 0 ? &m_mixed[size_t(idx)] : nullptr; return idx >= 0 ? &m_mixed[size_t(idx)] : nullptr;
} }
// Blend N colours using weighted pairwise FilamentMixer blending.
std::string MixedFilamentManager::blend_color_multi(
const std::vector<std::pair<std::string, int>> &color_percents)
{
if (color_percents.empty())
return "#000000";
if (color_percents.size() == 1)
return color_percents.front().first;
struct WeightedColor {
RGB color;
int pct;
};
std::vector<WeightedColor> colors;
colors.reserve(color_percents.size());
int total_pct = 0;
for (const auto &[hex, pct] : color_percents) {
if (pct <= 0)
continue;
colors.push_back({parse_hex_color(hex), pct});
total_pct += pct;
}
if (colors.empty() || total_pct <= 0)
return "#000000";
unsigned char r = static_cast<unsigned char>(colors.front().color.r);
unsigned char g = static_cast<unsigned char>(colors.front().color.g);
unsigned char b = static_cast<unsigned char>(colors.front().color.b);
int accumulated_pct = colors.front().pct;
for (size_t i = 1; i < colors.size(); ++i) {
const auto &next = colors[i];
const int new_total = accumulated_pct + next.pct;
if (new_total <= 0)
continue;
const float t = static_cast<float>(next.pct) / static_cast<float>(new_total);
filament_mixer_lerp(
r, g, b,
static_cast<unsigned char>(next.color.r),
static_cast<unsigned char>(next.color.g),
static_cast<unsigned char>(next.color.b),
t, &r, &g, &b);
accumulated_pct = new_total;
}
return rgb_to_hex({int(r), int(g), int(b)});
}
std::string MixedFilamentManager::blend_color(const std::string &color_a, std::string MixedFilamentManager::blend_color(const std::string &color_a,
const std::string &color_b, const std::string &color_b,
int ratio_a, int ratio_b) int ratio_a, int ratio_b)
@@ -1035,17 +1085,15 @@ void MixedFilamentManager::refresh_display_colors(const std::vector<std::string>
if (it != gradient_ids.end()) if (it != gradient_ids.end())
++counts[size_t(it - gradient_ids.begin())]; ++counts[size_t(it - gradient_ids.begin())];
} }
std::vector<std::pair<std::string, int>> color_percents;
std::string blended = filament_colours[gradient_ids.front() - 1]; color_percents.reserve(gradient_ids.size());
int accum = std::max(1, counts.front()); for (size_t i = 0; i < gradient_ids.size(); ++i) {
for (size_t i = 1; i < gradient_ids.size(); ++i) {
const int wi = std::max(0, counts[i]); const int wi = std::max(0, counts[i]);
if (wi == 0) if (wi == 0)
continue; continue;
blended = blend_color(blended, filament_colours[gradient_ids[i] - 1], accum, wi); color_percents.emplace_back(filament_colours[gradient_ids[i] - 1], wi);
accum += wi;
} }
mf.display_color = blended; mf.display_color = blend_color_multi(color_percents);
continue; continue;
} }
if (mf.component_a == 0 || mf.component_b == 0 || if (mf.component_a == 0 || mf.component_b == 0 ||
@@ -1081,4 +1129,3 @@ std::vector<std::string> MixedFilamentManager::display_colors() const
} }
} // namespace Slic3r } // namespace Slic3r

View File

@@ -5,12 +5,13 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <cstdint> #include <cstdint>
#include <utility>
namespace Slic3r { namespace Slic3r {
// Represents a virtual "mixed" filament created from physical filaments // Represents a virtual "mixed" filament created from physical filaments
// (layer cadence and/or same-layer interleaved stripe distribution). The display // (layer cadence and/or same-layer interleaved stripe distribution). The display
// colour uses an RYB pigment-style blend so // colour uses a FilamentMixer-based multi-color blend (and RYB pair blend) so
// pair previews better match expected print mixing (for example Blue+Yellow // pair previews better match expected print mixing (for example Blue+Yellow
// -> Green, Red+Yellow -> Orange, Red+Blue -> Purple). // -> Green, Red+Yellow -> Orange, Red+Blue -> Purple).
struct MixedFilament struct MixedFilament
@@ -152,6 +153,11 @@ public:
// m_mixed. Virtual IDs enumerate enabled mixed rows only. // m_mixed. Virtual IDs enumerate enabled mixed rows only.
int mixed_index_from_filament_id(unsigned int filament_id, size_t num_physical) const; int mixed_index_from_filament_id(unsigned int filament_id, size_t num_physical) const;
// Blend N colours using weighted FilamentMixer blending.
// color_percents: vector of (hex_color, percent) where percents sum to 100.
static std::string blend_color_multi(
const std::vector<std::pair<std::string, int>> &color_percents);
const MixedFilament *mixed_filament_from_id(unsigned int filament_id, size_t num_physical) const; const MixedFilament *mixed_filament_from_id(unsigned int filament_id, size_t num_physical) const;
// Compute a display colour by blending in RYB pigment space. // Compute a display colour by blending in RYB pigment space.

View File

@@ -0,0 +1,81 @@
#include "filament_mixer.h"
#include <algorithm>
#include <cmath>
#include "filament_mixer_model.h"
namespace Slic3r {
namespace {
inline float clamp01(float x)
{
return std::max(0.0f, std::min(1.0f, x));
}
inline float srgb_to_linear(float x)
{
return (x >= 0.04045f) ? std::pow((x + 0.055f) / 1.055f, 2.4f) : x / 12.92f;
}
inline float linear_to_srgb(float x)
{
return (x >= 0.0031308f) ? (1.055f * std::pow(x, 1.0f / 2.4f) - 0.055f) : (12.92f * x);
}
inline unsigned char to_u8(float x)
{
const float clamped = clamp01(x);
return static_cast<unsigned char>(clamped * 255.0f + 0.5f);
}
inline float to_f01(unsigned char x)
{
return static_cast<float>(x) / 255.0f;
}
} // namespace
void filament_mixer_lerp(unsigned char r1, unsigned char g1, unsigned char b1,
unsigned char r2, unsigned char g2, unsigned char b2,
float t,
unsigned char* out_r, unsigned char* out_g, unsigned char* out_b)
{
::filament_mixer::lerp(r1, g1, b1, r2, g2, b2, t, out_r, out_g, out_b);
}
void filament_mixer_lerp_float(float r1, float g1, float b1,
float r2, float g2, float b2,
float t,
float* out_r, float* out_g, float* out_b)
{
unsigned char ur = 0, ug = 0, ub = 0;
filament_mixer_lerp(to_u8(r1), to_u8(g1), to_u8(b1),
to_u8(r2), to_u8(g2), to_u8(b2),
t, &ur, &ug, &ub);
*out_r = to_f01(ur);
*out_g = to_f01(ug);
*out_b = to_f01(ub);
}
void filament_mixer_lerp_linear_float(float r1, float g1, float b1,
float r2, float g2, float b2,
float t,
float* out_r, float* out_g, float* out_b)
{
const float sr1 = linear_to_srgb(clamp01(r1));
const float sg1 = linear_to_srgb(clamp01(g1));
const float sb1 = linear_to_srgb(clamp01(b1));
const float sr2 = linear_to_srgb(clamp01(r2));
const float sg2 = linear_to_srgb(clamp01(g2));
const float sb2 = linear_to_srgb(clamp01(b2));
float out_sr = 0.0f, out_sg = 0.0f, out_sb = 0.0f;
filament_mixer_lerp_float(sr1, sg1, sb1, sr2, sg2, sb2, t, &out_sr, &out_sg, &out_sb);
*out_r = srgb_to_linear(clamp01(out_sr));
*out_g = srgb_to_linear(clamp01(out_sg));
*out_b = srgb_to_linear(clamp01(out_sb));
}
} // namespace Slic3r

View File

@@ -0,0 +1,23 @@
#ifndef SLIC3R_FILAMENT_MIXER_H
#define SLIC3R_FILAMENT_MIXER_H
namespace Slic3r {
void filament_mixer_lerp(unsigned char r1, unsigned char g1, unsigned char b1,
unsigned char r2, unsigned char g2, unsigned char b2,
float t,
unsigned char* out_r, unsigned char* out_g, unsigned char* out_b);
void filament_mixer_lerp_float(float r1, float g1, float b1,
float r2, float g2, float b2,
float t,
float* out_r, float* out_g, float* out_b);
void filament_mixer_lerp_linear_float(float r1, float g1, float b1,
float r2, float g2, float b2,
float t,
float* out_r, float* out_g, float* out_b);
} // namespace Slic3r
#endif

View File

@@ -0,0 +1,819 @@
/*
* FilamentMixer — Header-only C++ pigment color mixer
*
* Filament mixer implementation using a degree-4 polynomial regression
* trained to approximate Mixbox behavior (Mean Delta-E ~2.07).
* This library does not include Mixbox source code, binaries, or data files.
*
* Usage:
* #include "filament_mixer_model.h"
*
* unsigned char r, g, b;
* filament_mixer::lerp(0, 33, 133, 252, 211, 0, 0.5f, &r, &g, &b);
* // r=47, g=141, b=56 (blue + yellow → green)
*
* No dependencies beyond the C++ standard library.
*
* MIT License
*
* Copyright (c) 2026 Justin Hayes
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef FILAMENT_MIXER_H
#define FILAMENT_MIXER_H
#include <algorithm>
#include <cmath>
#include <cstdint>
namespace filament_mixer {
namespace detail {
// BEGIN AUTO-GENERATED COEFFICIENTS
// Auto-generated by scripts/export_poly_coefficients.py
// Do not edit manually.
// Degree-4 polynomial, 330 features, 7 inputs
static const int POLY_DEGREE = 4;
static const int N_FEATURES = 330;
static const int N_INPUTS = 7;
static const int POWERS[330][7] = {
{0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1},
{2, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 0, 0, 0},
{1, 0, 1, 0, 0, 0, 0},
{1, 0, 0, 1, 0, 0, 0},
{1, 0, 0, 0, 1, 0, 0},
{1, 0, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 0, 0, 1},
{0, 2, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 0, 0, 0},
{0, 1, 0, 1, 0, 0, 0},
{0, 1, 0, 0, 1, 0, 0},
{0, 1, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 1},
{0, 0, 2, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0},
{0, 0, 1, 0, 1, 0, 0},
{0, 0, 1, 0, 0, 1, 0},
{0, 0, 1, 0, 0, 0, 1},
{0, 0, 0, 2, 0, 0, 0},
{0, 0, 0, 1, 1, 0, 0},
{0, 0, 0, 1, 0, 1, 0},
{0, 0, 0, 1, 0, 0, 1},
{0, 0, 0, 0, 2, 0, 0},
{0, 0, 0, 0, 1, 1, 0},
{0, 0, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 0, 2, 0},
{0, 0, 0, 0, 0, 1, 1},
{0, 0, 0, 0, 0, 0, 2},
{3, 0, 0, 0, 0, 0, 0},
{2, 1, 0, 0, 0, 0, 0},
{2, 0, 1, 0, 0, 0, 0},
{2, 0, 0, 1, 0, 0, 0},
{2, 0, 0, 0, 1, 0, 0},
{2, 0, 0, 0, 0, 1, 0},
{2, 0, 0, 0, 0, 0, 1},
{1, 2, 0, 0, 0, 0, 0},
{1, 1, 1, 0, 0, 0, 0},
{1, 1, 0, 1, 0, 0, 0},
{1, 1, 0, 0, 1, 0, 0},
{1, 1, 0, 0, 0, 1, 0},
{1, 1, 0, 0, 0, 0, 1},
{1, 0, 2, 0, 0, 0, 0},
{1, 0, 1, 1, 0, 0, 0},
{1, 0, 1, 0, 1, 0, 0},
{1, 0, 1, 0, 0, 1, 0},
{1, 0, 1, 0, 0, 0, 1},
{1, 0, 0, 2, 0, 0, 0},
{1, 0, 0, 1, 1, 0, 0},
{1, 0, 0, 1, 0, 1, 0},
{1, 0, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 2, 0, 0},
{1, 0, 0, 0, 1, 1, 0},
{1, 0, 0, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 2, 0},
{1, 0, 0, 0, 0, 1, 1},
{1, 0, 0, 0, 0, 0, 2},
{0, 3, 0, 0, 0, 0, 0},
{0, 2, 1, 0, 0, 0, 0},
{0, 2, 0, 1, 0, 0, 0},
{0, 2, 0, 0, 1, 0, 0},
{0, 2, 0, 0, 0, 1, 0},
{0, 2, 0, 0, 0, 0, 1},
{0, 1, 2, 0, 0, 0, 0},
{0, 1, 1, 1, 0, 0, 0},
{0, 1, 1, 0, 1, 0, 0},
{0, 1, 1, 0, 0, 1, 0},
{0, 1, 1, 0, 0, 0, 1},
{0, 1, 0, 2, 0, 0, 0},
{0, 1, 0, 1, 1, 0, 0},
{0, 1, 0, 1, 0, 1, 0},
{0, 1, 0, 1, 0, 0, 1},
{0, 1, 0, 0, 2, 0, 0},
{0, 1, 0, 0, 1, 1, 0},
{0, 1, 0, 0, 1, 0, 1},
{0, 1, 0, 0, 0, 2, 0},
{0, 1, 0, 0, 0, 1, 1},
{0, 1, 0, 0, 0, 0, 2},
{0, 0, 3, 0, 0, 0, 0},
{0, 0, 2, 1, 0, 0, 0},
{0, 0, 2, 0, 1, 0, 0},
{0, 0, 2, 0, 0, 1, 0},
{0, 0, 2, 0, 0, 0, 1},
{0, 0, 1, 2, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0},
{0, 0, 1, 1, 0, 1, 0},
{0, 0, 1, 1, 0, 0, 1},
{0, 0, 1, 0, 2, 0, 0},
{0, 0, 1, 0, 1, 1, 0},
{0, 0, 1, 0, 1, 0, 1},
{0, 0, 1, 0, 0, 2, 0},
{0, 0, 1, 0, 0, 1, 1},
{0, 0, 1, 0, 0, 0, 2},
{0, 0, 0, 3, 0, 0, 0},
{0, 0, 0, 2, 1, 0, 0},
{0, 0, 0, 2, 0, 1, 0},
{0, 0, 0, 2, 0, 0, 1},
{0, 0, 0, 1, 2, 0, 0},
{0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 1, 1, 0, 1},
{0, 0, 0, 1, 0, 2, 0},
{0, 0, 0, 1, 0, 1, 1},
{0, 0, 0, 1, 0, 0, 2},
{0, 0, 0, 0, 3, 0, 0},
{0, 0, 0, 0, 2, 1, 0},
{0, 0, 0, 0, 2, 0, 1},
{0, 0, 0, 0, 1, 2, 0},
{0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 1, 0, 2},
{0, 0, 0, 0, 0, 3, 0},
{0, 0, 0, 0, 0, 2, 1},
{0, 0, 0, 0, 0, 1, 2},
{0, 0, 0, 0, 0, 0, 3},
{4, 0, 0, 0, 0, 0, 0},
{3, 1, 0, 0, 0, 0, 0},
{3, 0, 1, 0, 0, 0, 0},
{3, 0, 0, 1, 0, 0, 0},
{3, 0, 0, 0, 1, 0, 0},
{3, 0, 0, 0, 0, 1, 0},
{3, 0, 0, 0, 0, 0, 1},
{2, 2, 0, 0, 0, 0, 0},
{2, 1, 1, 0, 0, 0, 0},
{2, 1, 0, 1, 0, 0, 0},
{2, 1, 0, 0, 1, 0, 0},
{2, 1, 0, 0, 0, 1, 0},
{2, 1, 0, 0, 0, 0, 1},
{2, 0, 2, 0, 0, 0, 0},
{2, 0, 1, 1, 0, 0, 0},
{2, 0, 1, 0, 1, 0, 0},
{2, 0, 1, 0, 0, 1, 0},
{2, 0, 1, 0, 0, 0, 1},
{2, 0, 0, 2, 0, 0, 0},
{2, 0, 0, 1, 1, 0, 0},
{2, 0, 0, 1, 0, 1, 0},
{2, 0, 0, 1, 0, 0, 1},
{2, 0, 0, 0, 2, 0, 0},
{2, 0, 0, 0, 1, 1, 0},
{2, 0, 0, 0, 1, 0, 1},
{2, 0, 0, 0, 0, 2, 0},
{2, 0, 0, 0, 0, 1, 1},
{2, 0, 0, 0, 0, 0, 2},
{1, 3, 0, 0, 0, 0, 0},
{1, 2, 1, 0, 0, 0, 0},
{1, 2, 0, 1, 0, 0, 0},
{1, 2, 0, 0, 1, 0, 0},
{1, 2, 0, 0, 0, 1, 0},
{1, 2, 0, 0, 0, 0, 1},
{1, 1, 2, 0, 0, 0, 0},
{1, 1, 1, 1, 0, 0, 0},
{1, 1, 1, 0, 1, 0, 0},
{1, 1, 1, 0, 0, 1, 0},
{1, 1, 1, 0, 0, 0, 1},
{1, 1, 0, 2, 0, 0, 0},
{1, 1, 0, 1, 1, 0, 0},
{1, 1, 0, 1, 0, 1, 0},
{1, 1, 0, 1, 0, 0, 1},
{1, 1, 0, 0, 2, 0, 0},
{1, 1, 0, 0, 1, 1, 0},
{1, 1, 0, 0, 1, 0, 1},
{1, 1, 0, 0, 0, 2, 0},
{1, 1, 0, 0, 0, 1, 1},
{1, 1, 0, 0, 0, 0, 2},
{1, 0, 3, 0, 0, 0, 0},
{1, 0, 2, 1, 0, 0, 0},
{1, 0, 2, 0, 1, 0, 0},
{1, 0, 2, 0, 0, 1, 0},
{1, 0, 2, 0, 0, 0, 1},
{1, 0, 1, 2, 0, 0, 0},
{1, 0, 1, 1, 1, 0, 0},
{1, 0, 1, 1, 0, 1, 0},
{1, 0, 1, 1, 0, 0, 1},
{1, 0, 1, 0, 2, 0, 0},
{1, 0, 1, 0, 1, 1, 0},
{1, 0, 1, 0, 1, 0, 1},
{1, 0, 1, 0, 0, 2, 0},
{1, 0, 1, 0, 0, 1, 1},
{1, 0, 1, 0, 0, 0, 2},
{1, 0, 0, 3, 0, 0, 0},
{1, 0, 0, 2, 1, 0, 0},
{1, 0, 0, 2, 0, 1, 0},
{1, 0, 0, 2, 0, 0, 1},
{1, 0, 0, 1, 2, 0, 0},
{1, 0, 0, 1, 1, 1, 0},
{1, 0, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 0, 2, 0},
{1, 0, 0, 1, 0, 1, 1},
{1, 0, 0, 1, 0, 0, 2},
{1, 0, 0, 0, 3, 0, 0},
{1, 0, 0, 0, 2, 1, 0},
{1, 0, 0, 0, 2, 0, 1},
{1, 0, 0, 0, 1, 2, 0},
{1, 0, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 1, 0, 2},
{1, 0, 0, 0, 0, 3, 0},
{1, 0, 0, 0, 0, 2, 1},
{1, 0, 0, 0, 0, 1, 2},
{1, 0, 0, 0, 0, 0, 3},
{0, 4, 0, 0, 0, 0, 0},
{0, 3, 1, 0, 0, 0, 0},
{0, 3, 0, 1, 0, 0, 0},
{0, 3, 0, 0, 1, 0, 0},
{0, 3, 0, 0, 0, 1, 0},
{0, 3, 0, 0, 0, 0, 1},
{0, 2, 2, 0, 0, 0, 0},
{0, 2, 1, 1, 0, 0, 0},
{0, 2, 1, 0, 1, 0, 0},
{0, 2, 1, 0, 0, 1, 0},
{0, 2, 1, 0, 0, 0, 1},
{0, 2, 0, 2, 0, 0, 0},
{0, 2, 0, 1, 1, 0, 0},
{0, 2, 0, 1, 0, 1, 0},
{0, 2, 0, 1, 0, 0, 1},
{0, 2, 0, 0, 2, 0, 0},
{0, 2, 0, 0, 1, 1, 0},
{0, 2, 0, 0, 1, 0, 1},
{0, 2, 0, 0, 0, 2, 0},
{0, 2, 0, 0, 0, 1, 1},
{0, 2, 0, 0, 0, 0, 2},
{0, 1, 3, 0, 0, 0, 0},
{0, 1, 2, 1, 0, 0, 0},
{0, 1, 2, 0, 1, 0, 0},
{0, 1, 2, 0, 0, 1, 0},
{0, 1, 2, 0, 0, 0, 1},
{0, 1, 1, 2, 0, 0, 0},
{0, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 1, 0, 1, 0},
{0, 1, 1, 1, 0, 0, 1},
{0, 1, 1, 0, 2, 0, 0},
{0, 1, 1, 0, 1, 1, 0},
{0, 1, 1, 0, 1, 0, 1},
{0, 1, 1, 0, 0, 2, 0},
{0, 1, 1, 0, 0, 1, 1},
{0, 1, 1, 0, 0, 0, 2},
{0, 1, 0, 3, 0, 0, 0},
{0, 1, 0, 2, 1, 0, 0},
{0, 1, 0, 2, 0, 1, 0},
{0, 1, 0, 2, 0, 0, 1},
{0, 1, 0, 1, 2, 0, 0},
{0, 1, 0, 1, 1, 1, 0},
{0, 1, 0, 1, 1, 0, 1},
{0, 1, 0, 1, 0, 2, 0},
{0, 1, 0, 1, 0, 1, 1},
{0, 1, 0, 1, 0, 0, 2},
{0, 1, 0, 0, 3, 0, 0},
{0, 1, 0, 0, 2, 1, 0},
{0, 1, 0, 0, 2, 0, 1},
{0, 1, 0, 0, 1, 2, 0},
{0, 1, 0, 0, 1, 1, 1},
{0, 1, 0, 0, 1, 0, 2},
{0, 1, 0, 0, 0, 3, 0},
{0, 1, 0, 0, 0, 2, 1},
{0, 1, 0, 0, 0, 1, 2},
{0, 1, 0, 0, 0, 0, 3},
{0, 0, 4, 0, 0, 0, 0},
{0, 0, 3, 1, 0, 0, 0},
{0, 0, 3, 0, 1, 0, 0},
{0, 0, 3, 0, 0, 1, 0},
{0, 0, 3, 0, 0, 0, 1},
{0, 0, 2, 2, 0, 0, 0},
{0, 0, 2, 1, 1, 0, 0},
{0, 0, 2, 1, 0, 1, 0},
{0, 0, 2, 1, 0, 0, 1},
{0, 0, 2, 0, 2, 0, 0},
{0, 0, 2, 0, 1, 1, 0},
{0, 0, 2, 0, 1, 0, 1},
{0, 0, 2, 0, 0, 2, 0},
{0, 0, 2, 0, 0, 1, 1},
{0, 0, 2, 0, 0, 0, 2},
{0, 0, 1, 3, 0, 0, 0},
{0, 0, 1, 2, 1, 0, 0},
{0, 0, 1, 2, 0, 1, 0},
{0, 0, 1, 2, 0, 0, 1},
{0, 0, 1, 1, 2, 0, 0},
{0, 0, 1, 1, 1, 1, 0},
{0, 0, 1, 1, 1, 0, 1},
{0, 0, 1, 1, 0, 2, 0},
{0, 0, 1, 1, 0, 1, 1},
{0, 0, 1, 1, 0, 0, 2},
{0, 0, 1, 0, 3, 0, 0},
{0, 0, 1, 0, 2, 1, 0},
{0, 0, 1, 0, 2, 0, 1},
{0, 0, 1, 0, 1, 2, 0},
{0, 0, 1, 0, 1, 1, 1},
{0, 0, 1, 0, 1, 0, 2},
{0, 0, 1, 0, 0, 3, 0},
{0, 0, 1, 0, 0, 2, 1},
{0, 0, 1, 0, 0, 1, 2},
{0, 0, 1, 0, 0, 0, 3},
{0, 0, 0, 4, 0, 0, 0},
{0, 0, 0, 3, 1, 0, 0},
{0, 0, 0, 3, 0, 1, 0},
{0, 0, 0, 3, 0, 0, 1},
{0, 0, 0, 2, 2, 0, 0},
{0, 0, 0, 2, 1, 1, 0},
{0, 0, 0, 2, 1, 0, 1},
{0, 0, 0, 2, 0, 2, 0},
{0, 0, 0, 2, 0, 1, 1},
{0, 0, 0, 2, 0, 0, 2},
{0, 0, 0, 1, 3, 0, 0},
{0, 0, 0, 1, 2, 1, 0},
{0, 0, 0, 1, 2, 0, 1},
{0, 0, 0, 1, 1, 2, 0},
{0, 0, 0, 1, 1, 1, 1},
{0, 0, 0, 1, 1, 0, 2},
{0, 0, 0, 1, 0, 3, 0},
{0, 0, 0, 1, 0, 2, 1},
{0, 0, 0, 1, 0, 1, 2},
{0, 0, 0, 1, 0, 0, 3},
{0, 0, 0, 0, 4, 0, 0},
{0, 0, 0, 0, 3, 1, 0},
{0, 0, 0, 0, 3, 0, 1},
{0, 0, 0, 0, 2, 2, 0},
{0, 0, 0, 0, 2, 1, 1},
{0, 0, 0, 0, 2, 0, 2},
{0, 0, 0, 0, 1, 3, 0},
{0, 0, 0, 0, 1, 2, 1},
{0, 0, 0, 0, 1, 1, 2},
{0, 0, 0, 0, 1, 0, 3},
{0, 0, 0, 0, 0, 4, 0},
{0, 0, 0, 0, 0, 3, 1},
{0, 0, 0, 0, 0, 2, 2},
{0, 0, 0, 0, 0, 1, 3},
{0, 0, 0, 0, 0, 0, 4}
};
static const double COEF[330][3] = {
{8.70954844857314666e-12, 1.27926950848359881e-09, -2.06865474316332923e-09},
{1.05783308354771544e+00, -8.02119209663359686e-03, -7.88705651445470723e-02},
{1.35905954452774837e-02, 8.71267975138422468e-01, 1.04898760410704936e-01},
{-4.16452026099768252e-02, 1.75465381596434100e-02, 1.00224594702931546e+00},
{4.50321316661211821e-02, -7.11409155427628892e-02, 3.91232300778902690e-03},
{1.76675507851922452e-02, -1.32709276116036640e-01, 6.36935270589509828e-02},
{-5.23434830565911030e-02, 3.77681739012521722e-02, -2.08691145087504179e-02},
{-2.33722556520224792e-03, -1.57542611462692145e-03, -3.05158628452478807e-03},
{-8.87678609044812990e-04, 3.83194388837734693e-04, 1.37779212442523083e-03},
{-2.11519042076831979e-03, 5.82337362515735358e-04, 2.24055108941204821e-04},
{4.61545125563611917e-04, 7.72869451707915893e-04, -1.10800630143346882e-03},
{1.05937484157345879e-03, -3.14448681732842211e-04, -1.75129182446198098e-03},
{1.49045689016363055e-03, -2.09220860101674106e-04, 5.93100338908187697e-04},
{-3.51246656293852696e-04, -8.20743017485394289e-04, 5.71854064480802862e-04},
{-9.18204643629581319e-01, -2.27788122702773155e-01, 6.39980793022790623e-02},
{9.24243491377523679e-05, 7.32841332381495400e-04, -1.55219718415109450e-03},
{7.13695056804217989e-04, -8.46467621879685712e-05, 6.50202947442505750e-04},
{1.66640864747485983e-03, -1.24492362771216523e-04, 2.68236502346156410e-04},
{-7.20253644860527516e-04, 7.81434220384157334e-04, 1.12661089007361367e-03},
{-6.83033334365238206e-05, 7.27742627159490762e-04, -1.78048843835204584e-03},
{-3.13431571993316588e-02, -8.57604034845650287e-01, -2.57225920656276863e-01},
{-6.47867200595898341e-05, -1.16688982572457655e-03, 1.14174511750260031e-03},
{-5.00713925613324338e-04, -6.87598082111323477e-04, 6.20598069880440176e-04},
{-8.56716727659588957e-05, 9.74478786593559361e-04, -1.65892838405139512e-03},
{6.53468478750158263e-04, 7.51662000672516676e-04, -6.73196326298856570e-04},
{-4.42539011000103941e-02, -2.01965359697350230e-02, -9.94663493761314355e-01},
{-7.39107395392403087e-04, 5.28870828612476996e-04, 1.00947183860234540e-03},
{-2.06577300933763214e-03, 9.60215813758718011e-04, -3.27993888180819421e-04},
{3.47783280638377555e-04, 8.41824316850705743e-04, -8.87458944147930993e-04},
{1.20960551709587905e+00, -7.07660818059813873e-02, -8.56332806008946491e-03},
{2.11116509318935269e-04, 7.68490846994171776e-04, -1.63228995491542417e-03},
{6.47698075356516103e-04, -4.20589129268072884e-04, 1.18354001300614896e-03},
{-2.78795945253848716e-02, 1.22199201000304547e+00, -2.07383075858847743e-01},
{-5.32457386680677347e-05, -9.58027320315790677e-04, 9.89667309649038679e-04},
{-9.03932426306289782e-02, -4.00969232187064692e-02, 1.26285611182120072e+00},
{-2.19453630740322871e-03, -1.21893190049422620e-03, -1.92293368093085417e-03},
{1.72950845415964505e-06, -8.93952511560151819e-09, -6.14874900641340649e-06},
{8.02644554976326974e-06, -6.42543741723487294e-06, -6.07103419227907060e-06},
{3.20307552755319525e-06, -4.83533743093466500e-06, 9.13563764113473065e-07},
{-2.18105804067510178e-06, 6.19595552598436322e-07, 5.21392855381760945e-06},
{-2.43310123604345563e-06, 2.17201813434465818e-06, 1.94098874242362718e-07},
{-1.56293672065252465e-06, 3.95256011818110372e-06, 1.68792962079201969e-06},
{-1.37567295252127852e-03, 3.59746071987262106e-04, 7.38927139000157259e-05},
{4.27822004137219658e-06, -8.80187479967658548e-07, 2.29453131891411977e-06},
{7.68758937964332534e-06, 2.40909410585557829e-07, 4.69351234070854509e-06},
{-2.87166709944317033e-06, 7.60223902901142716e-07, 4.57864913314467992e-06},
{-4.01295140267654560e-06, 2.65929275888376483e-06, -2.36575067819565221e-06},
{2.32693030513910805e-07, 2.28814396769890308e-06, 1.83526107699893970e-07},
{-2.18213927011287265e-03, 1.65013083920367864e-03, 2.31992998847323087e-04},
{-7.70829764693697905e-06, 4.23888841240673345e-07, 7.30018322002944087e-06},
{-1.23111329452911533e-06, 1.50076529718910084e-06, -1.91139744928209288e-06},
{-1.68872756433485760e-06, 1.03254236824697979e-06, -1.72081108163607555e-06},
{1.64276928199709460e-06, -4.96350219553231067e-07, -1.46349385185670297e-06},
{1.12731767057843682e-03, 5.03104281148445223e-04, 1.36398977654308994e-03},
{-1.05449609518089293e-06, -4.06952115309007489e-07, 3.53062441379482783e-06},
{-1.98745923822574166e-06, 4.98021943693208180e-07, 3.92645061370218429e-06},
{-1.55569377977005097e-07, -4.00262856484093037e-07, -2.49609122397048688e-06},
{2.18005022830924673e-03, -4.10275057064835439e-05, -2.59776311836759947e-04},
{5.41337439827552225e-07, -1.88603932528607146e-06, -2.06428606152470051e-06},
{-6.03243799807140491e-06, -3.75067864464502022e-06, -3.05702776851046742e-06},
{2.30038011634901016e-03, -1.32581161861259635e-03, -1.07680096899188406e-03},
{4.46773877910556887e-06, 1.85008408528524772e-08, -2.72851357570281713e-06},
{-1.49177636513049289e-03, -1.91426739654176659e-04, -1.71206384332753194e-03},
{2.31661325589237743e-02, 2.26540538563063554e-01, 5.42330337046266139e-02},
{-1.40563059963100256e-06, -4.50551806294901061e-06, 8.87542894832671347e-06},
{-1.66780916452391459e-06, 4.12065434881171526e-06, -3.55865035776836702e-06},
{2.71536622051954390e-07, -3.08564858926584692e-06, -1.52164363662402047e-06},
{2.66659632027280158e-06, -1.19436686895073481e-06, -3.25738306279285683e-06},
{-1.43666282346327501e-06, -2.51923473623639690e-06, 5.21205120344175876e-06},
{2.82954522469612199e-04, -1.59147454710008968e-03, 1.27685773978167098e-03},
{-3.99471240294241303e-06, 9.97323772325767188e-08, -5.28196823261495307e-06},
{-6.39858432699424995e-06, -4.59897864440506933e-06, -2.39736149785715891e-06},
{2.89457420106498109e-06, -3.10427512149489757e-06, 9.75553221437691631e-07},
{-8.96518259720091581e-07, -5.53996694461914366e-06, 1.03733964032237669e-05},
{8.82130497168875905e-04, -2.33618402105562365e-03, 1.35100410641244379e-03},
{-2.14088521029685841e-06, 2.59005410360388117e-06, -9.78713171504927426e-08},
{-4.50668337071552516e-06, 3.58808570076458002e-06, -1.56159349007541082e-06},
{-1.52345101244247272e-06, 2.21066768791959578e-06, -2.19555898547246775e-06},
{2.07334042074768356e-03, -1.56333498489329517e-03, -5.53762940364141767e-04},
{2.22151748134440108e-06, -4.74729938900429749e-07, -3.46744150304684889e-06},
{2.95389009221172505e-06, -2.96312023445686329e-06, -9.00385068308695580e-07},
{-6.47780848348620771e-04, 2.38772263398574292e-03, -8.93908589731968019e-04},
{9.69501567645025819e-07, 2.41432205872957328e-06, 5.56908291093893837e-07},
{-6.33392066185247586e-04, 2.38613844267241120e-03, -1.05383725637261472e-03},
{6.76250135616376785e-02, -5.57799579151454852e-02, 1.83393652374666566e-01},
{3.53986894266120067e-06, 5.92996717102502093e-06, -7.32378536156402804e-06},
{5.69667193362453916e-06, 1.20219201908705218e-06, -4.56663805956276925e-06},
{7.11494218295222192e-07, 2.93069858359131137e-06, 1.23210839732268429e-07},
{-3.41917893741799928e-06, -1.47435291776966751e-06, 1.07397354370819542e-06},
{7.30931882734254710e-04, 1.15433149094644884e-03, -2.40026982569019722e-03},
{-1.22780859907432871e-06, 2.29287908084027789e-06, 1.84270754640877832e-06},
{7.71579140080615178e-07, 2.92378122615943208e-06, -1.91800935486416413e-07},
{-3.76107279903559188e-07, -1.83159743461489867e-06, 8.17089655984204466e-07},
{-1.10830882430058061e-03, -5.10908079549339251e-04, -1.77835176235151705e-03},
{-1.26839781743699406e-06, -2.86942252006448415e-06, 4.47464983859263005e-06},
{-1.44518716284694482e-06, -7.03360635528004451e-06, 1.04898109513258675e-05},
{-4.98687888007460470e-04, 1.86990180752567262e-03, -1.24341018156770089e-03},
{-2.90479801332704790e-06, -9.24272269110706229e-07, 7.56354222045119151e-07},
{-1.16451534008294149e-03, -2.34216801827852273e-03, 4.91479264672447288e-03},
{-7.70970926241258958e-02, 9.35855573900774423e-02, 1.50623807158846906e-01},
{1.14039905307547484e-06, -1.80664235182388840e-07, -5.15527441317074897e-06},
{7.50559587697416375e-06, -6.23982034686780714e-06, -5.01245198064126721e-06},
{2.37840954889385892e-06, -4.15663063190341991e-06, 1.93118829429697603e-06},
{-1.54903048110950777e-03, 2.65832194444263125e-04, 5.34401520444913940e-04},
{4.00040634507183718e-06, -2.43965474694277443e-06, 2.88683251413283937e-06},
{7.72301916160400559e-06, -9.54300275625495457e-07, 5.50777546561020959e-06},
{-2.28103126593574368e-03, 1.02658341009706066e-03, 1.22010567464172614e-03},
{-6.32818026002207601e-06, 9.83088209200334157e-07, 5.24316808343458507e-06},
{1.37175660779395581e-03, 4.01188715721313943e-04, 7.59370199245276625e-04},
{-3.33184694847917573e-01, 7.82846225823195241e-02, -9.94270054263078074e-02},
{-1.70108770909324636e-06, -5.10749831734438279e-06, 9.80267482880020635e-06},
{-1.79301365419055891e-06, 4.44839673308561508e-06, -3.83837422072638712e-06},
{1.71911692904483371e-04, -1.56077480341044431e-03, 1.30725115579017584e-03},
{-3.55763938679129477e-06, 1.20558966207589408e-06, -5.94340114624253291e-06},
{1.02325453537648178e-03, -1.52640960762801372e-03, 3.10973117856692537e-04},
{3.81842873295820109e-03, -3.02114884453467680e-01, 2.78264587142456665e-01},
{3.46123498726202961e-06, 5.05929187103208375e-06, -6.85764673719752027e-06},
{4.47228353489932293e-04, 9.60672217798415784e-04, -2.19382758010531077e-03},
{2.22711833124298791e-01, -4.14141995162802465e-02, -4.27998216564745015e-01},
{-1.78271151817048783e-03, -9.81039111371464307e-04, -1.37513011841553174e-03},
{3.35305394560947434e-10, -1.26710751613412498e-09, 3.54248685940916630e-09},
{-9.26917423371698135e-09, 6.21190912597491263e-09, 1.86942252233812667e-08},
{-1.56687696151180944e-09, -5.44315731376698864e-09, 1.93822974337010123e-09},
{7.52897716393974292e-10, -3.48923168136394679e-10, -5.94217786087369859e-10},
{2.52116855170569920e-10, -2.48216903975251313e-09, 1.01699001303634518e-09},
{3.72215577457146729e-09, 4.51910314724912610e-10, -6.15361639422218332e-09},
{-2.62088816666700142e-07, 3.23631086683010168e-07, 8.85302852722882894e-07},
{-1.30537319842360944e-08, 1.46808588619151692e-08, 2.67574040702101001e-09},
{-1.23991327621864045e-08, 2.61298349069072344e-08, -4.58919307373337193e-09},
{5.03079244928983371e-09, -6.73783119575777079e-10, -1.13935871848269699e-08},
{9.09065785148488459e-09, -1.04304054004966673e-08, -3.23123813816827976e-09},
{9.55627910137479830e-10, -1.41129563591135820e-08, -1.75594400131373618e-09},
{-1.05549669436946769e-07, 8.47284096194811896e-08, 6.70761880091491625e-07},
{-5.92079330008488114e-10, 6.31702118392141188e-09, -4.51534448719925763e-09},
{-1.04033970327321867e-09, 4.67775485013532943e-09, 2.79348504744758586e-09},
{5.38758108958869997e-09, -9.55380699552144108e-09, 6.16488249338686956e-11},
{1.12057409185073453e-09, -3.00645183748393663e-09, -2.14940637510707688e-09},
{-6.27004681934967278e-07, 8.59159786402940127e-07, 2.73192537668387470e-07},
{7.36784189214745311e-10, -8.12761968838060511e-10, -2.43226564583531868e-09},
{1.25546123497244366e-09, -6.98609614602219153e-10, -5.29894812750786315e-09},
{-8.88351475714088679e-10, 1.37132565025677167e-09, 1.92497813869541012e-09},
{6.10992637326349119e-07, -6.13496367368217277e-07, -2.19901889726877020e-06},
{-8.59090437677068053e-11, 2.72772732179404898e-09, 1.54554039011323141e-09},
{-4.58798915525804318e-10, 4.54384851966693759e-09, 3.63189350816028877e-09},
{9.93115786933340683e-08, 1.63700862245048928e-07, -1.71397937400244449e-07},
{-1.62985361318312982e-09, -3.10762126448649312e-09, 1.76193495557419588e-09},
{6.27207737564569601e-07, -1.49343052365004934e-06, 8.16168870109573730e-08},
{1.42518738380244172e-03, -3.47531891583186285e-04, -2.98661838800559913e-04},
{8.98157254125564464e-09, -8.24242643235328920e-09, -5.34769730234363472e-09},
{-2.17776999489327494e-08, -4.47141107473569832e-09, -1.10218517090920898e-08},
{3.19614509858290319e-09, -3.32861183754973311e-09, 9.92016746526047655e-11},
{-2.91660393059167689e-09, 5.59829099744391101e-09, 1.70080685646389895e-09},
{1.22479524179014421e-09, 9.20737683318684219e-09, -1.10618757209746121e-10},
{7.70594587548882257e-09, -1.33267446898667659e-06, 4.52812675308736368e-07},
{9.46080642993951670e-09, -1.95483249032513129e-08, -1.23592694620255905e-08},
{-2.02330094345448686e-09, 1.18198534293512125e-10, 2.34746776184291406e-09},
{4.00839940406516604e-09, -4.80716730311137042e-09, 5.25802457129742606e-09},
{-2.53115202408782380e-09, 2.05563177591017165e-10, 5.46003270374129102e-09},
{3.24841319972028232e-08, -1.24284705839720552e-06, 4.97326549863015555e-07},
{1.37729661009444726e-09, -1.67903983772088594e-09, -5.62083748989472554e-09},
{-3.53256937590806785e-10, 4.49320892992322030e-09, -4.02300486673778934e-09},
{2.48976475547557641e-09, -6.97256366533061112e-09, 1.43185084622299286e-09},
{-4.38617299338556199e-09, 9.45081248826811111e-08, -2.91197460585562728e-07},
{3.24429103026879773e-09, -1.71647943601749287e-09, 2.71076100455402980e-09},
{3.86933235105302309e-09, -2.82628156988984358e-09, 8.24455756442965537e-09},
{-7.46614068323353530e-07, 1.27696340529665289e-06, 6.88413034833322557e-07},
{-5.78118683480788320e-09, 1.34319005917760137e-09, -1.15898873831454807e-09},
{4.42686972671260670e-07, 6.41810588767341775e-07, -1.16058405342719939e-08},
{2.24399192788231686e-03, -1.35129336477888174e-03, -7.39944244498236844e-04},
{7.47869199901884940e-09, -2.68762612165573955e-09, -7.41584788022109365e-09},
{1.80867308283150230e-09, -2.21500551234043996e-09, 1.86995768869380186e-09},
{-5.05514829302056157e-09, 4.74048706539109688e-09, 2.52998993977016085e-09},
{1.32441967115592973e-09, 5.70339246663831290e-09, 7.13448300437846683e-10},
{1.19767475292940212e-06, 6.72445227582811568e-07, -1.97500319605841551e-06},
{-1.70612399208458498e-09, 1.07145120553653328e-09, 1.73225882249550267e-09},
{1.15369127445807962e-09, -5.80362996549510513e-09, 9.33515653667171819e-10},
{3.38692740520230018e-09, 3.72531013675958533e-09, -3.18062756687886861e-09},
{1.14787653780236421e-06, -1.84917201319622368e-06, -2.44834286920736499e-07},
{1.45558928799083276e-09, 1.12720083267348059e-09, 9.00940544390493869e-10},
{2.09654001104286891e-09, 4.92913422578400429e-09, 3.04938074791039071e-10},
{3.54033623213741155e-07, 1.07259516691213860e-06, -6.03027205987524684e-07},
{-2.72038239157446071e-09, -1.60070143945256760e-09, 6.03853855807301443e-10},
{-2.03235662485238069e-06, -1.03151962834260348e-06, 1.99637918628457062e-06},
{-1.26261175077493210e-03, -4.98503988506484859e-04, -1.03875859619143593e-03},
{6.43182729298530376e-10, 8.01776645076301975e-10, -1.83589794755523172e-09},
{4.01805119037978997e-09, -5.63673552278487477e-10, -1.09102650663883693e-08},
{-1.48648961195707585e-09, 5.01067861508053269e-09, 2.99132781045319263e-09},
{-8.91404754824534629e-07, 7.49163968581634775e-07, 2.12542215183124383e-06},
{2.38642574451608525e-09, -3.47605810802065207e-09, 3.86935566920598717e-10},
{-2.80031986488182838e-09, -4.25160427697246490e-11, 2.24182921879090280e-09},
{-1.26991357818351247e-07, -1.45348284568834647e-07, 5.68792533226815389e-07},
{1.39227229745131353e-09, -1.84849578699353145e-09, 2.24967258190267305e-09},
{-1.15462500328497586e-06, 1.84347590761761086e-06, 3.64918716654494962e-07},
{-2.09357112083411985e-03, 1.60820400301404873e-05, 2.27418117008655948e-04},
{-1.04484803378768198e-08, 4.86043558178828050e-09, 2.00996588123336650e-09},
{1.44040971927772432e-08, 1.42223015309195233e-09, 1.99778974613318283e-09},
{-1.62414574166394599e-07, -1.31976785339561840e-06, 4.43918084507000099e-07},
{3.73061943836905385e-09, 1.00036822436866402e-08, -1.05450977117005351e-09},
{-2.06551932971539565e-07, -9.72167971235462190e-07, 4.28861904300768815e-07},
{-2.16051814014425313e-03, 1.48780488507118812e-03, 7.79940397419977911e-04},
{-4.80544204428667854e-09, -1.09870773590259319e-09, 6.58876991984844174e-09},
{1.31575045692056136e-06, 4.32430764481131318e-07, -1.55255090541518703e-06},
{1.28823975640215602e-03, 4.04521283440268135e-04, 1.76186984141882253e-03},
{-1.09767251093991436e-01, -4.94112205838347640e-02, -5.43102978164306804e-02},
{7.93691223854864347e-10, 1.54639511196208446e-08, -1.71518303448969789e-08},
{2.56523843833456056e-09, -2.31047392329486456e-09, -4.29758133398648601e-09},
{-9.87725901069325118e-09, 4.28127375218245732e-09, 2.02888056355376989e-09},
{3.21762172461603768e-10, -5.82937505211322815e-09, 3.88293127512318037e-09},
{1.63250610252241302e-09, -7.02161705168347083e-09, 3.46592492032893329e-09},
{-1.44272117683086343e-07, -4.40408510988914148e-07, 5.92746408872857344e-07},
{2.71961467235293242e-09, -1.47466668633244868e-08, 2.89637452632884873e-08},
{1.47637712476396399e-08, 1.16406781783262581e-09, 2.04904540557215853e-09},
{-5.53709807865621073e-09, 7.05512286092169205e-09, 1.56159114805820565e-09},
{5.29268649740455288e-09, 2.10616986628942016e-08, -3.03219004488264332e-08},
{1.79978890693655025e-07, 7.95085399132693105e-07, -4.78366567607801940e-07},
{-4.03847393894152251e-10, 2.90357085597214848e-09, 1.12992165623992946e-09},
{2.99031871486832301e-09, -1.37951879780606745e-09, 2.41048263988075107e-09},
{1.26882357398550027e-09, 1.30631467101793852e-09, 7.99574240151201820e-10},
{-1.41169562567489137e-08, 1.27148955713198356e-06, -2.89386439707162157e-07},
{-2.68794415198003733e-09, 8.73673404455654889e-10, 2.89557382238125882e-09},
{-4.90264437380538709e-09, 1.89207244316591527e-09, 2.25393465003165261e-09},
{-3.58274654665979853e-08, 2.91386646529383231e-07, -4.98477764412919022e-08},
{1.65722165851311942e-09, -1.11673743863338615e-09, -4.14131162695952071e-09},
{-1.47751280626939874e-07, -2.41471865000848773e-07, -8.53552350049691100e-07},
{-2.24352957583577790e-04, 1.60900273524284708e-03, -1.32260753549593617e-03},
{2.05497643901431104e-09, 1.38702982710459111e-08, -3.09887516689033582e-09},
{3.39770491949997755e-09, 9.41613393506957053e-09, -7.09844738544518350e-10},
{7.86209687630989862e-10, 1.93556837224662104e-10, -6.58630930350234678e-09},
{-6.86841181152253455e-10, -5.57194149153339424e-09, 1.41214109156129197e-09},
{2.59516074158083754e-07, 1.30703181255419770e-06, -4.02454784192984860e-07},
{-5.79425202262839889e-10, 4.05071760856134944e-09, 3.02384985106929349e-09},
{4.00677924866643664e-09, -2.25614611715219127e-09, 7.52819043214891792e-09},
{2.34003759425061020e-09, 5.27462258592681366e-09, -2.05723854618256041e-10},
{2.29340174767722615e-07, 1.05507868574435809e-06, -4.45904844964539748e-07},
{-3.91634245866523401e-09, 1.07849931763048801e-09, 1.85542686770290288e-09},
{-6.62166513287765213e-09, 3.86355018811013196e-09, -1.87861701195224384e-09},
{1.32112240848469842e-07, 4.39339645861430705e-08, -1.59384598983486336e-06},
{2.02488462108796341e-09, -1.48427112267590644e-09, -4.32055485832805175e-09},
{-4.27701540045566375e-07, -1.46229443391283215e-06, -2.38186369433401879e-07},
{-9.86744509368740232e-04, 1.91104095070606826e-03, -8.17774843405986713e-04},
{2.06891823117949514e-10, -2.64060942556376688e-09, 1.86419366055012858e-09},
{8.33785634979378187e-09, -1.00697171434571686e-08, -2.84106664583116952e-09},
{5.07057938692323518e-09, -9.56246298811080919e-09, -6.33399999117045809e-11},
{-6.78808357162941078e-08, -2.21612941845184680e-07, 9.42031624998063144e-08},
{-3.04300065007145903e-09, 5.64120231083542478e-09, 1.65718606892628628e-09},
{3.76240642807612602e-09, -4.58941407446844529e-09, 5.06162500801821125e-09},
{7.25149885354159363e-07, -1.18149759075966698e-06, -6.82406347277120240e-07},
{-4.84358128605144600e-09, 4.56893046833772853e-09, 2.67044331092591847e-09},
{-2.54939737986958903e-07, -1.06106228658746360e-06, 5.04013386790069795e-07},
{-2.17097468872509735e-03, 1.41624400187313607e-03, 8.11305605779899562e-04},
{2.24635331169675823e-10, -6.02144184513875302e-09, 4.15827878380570226e-09},
{-4.55408258326350790e-09, 6.20319154376325343e-09, 2.08760821823750220e-09},
{2.10871853867367065e-07, -4.29346688506603014e-07, 1.15683623843482186e-07},
{1.00732072683129559e-09, 3.88267751283422058e-11, -6.73798626615873530e-09},
{5.34506627847264326e-09, -8.01262819982717645e-08, 1.60888846226225901e-06},
{5.83419066552946048e-04, -2.36474094848551555e-03, 8.79373865688287898e-04},
{-4.85158746510450101e-10, -6.78789624508624456e-09, 4.95385649168511577e-09},
{3.47485142271342085e-07, 5.60944792101468470e-07, -4.35887910682497548e-07},
{5.75824910919892421e-04, -2.18618554413632388e-03, 1.22736498224538170e-03},
{-2.51838883195707221e-02, -8.23487774284355212e-02, 3.33658831723806573e-02},
{-8.70167529698484543e-09, -1.37080219501928280e-08, 1.80728228771354082e-08},
{-4.67111571644807100e-09, -2.72041008123058425e-09, 7.06648883852523113e-09},
{7.26183221906172727e-10, -6.77816339167414128e-09, 4.52883232651690726e-09},
{5.28852302228433047e-09, 6.47161005340457507e-09, -8.67298467766008940e-09},
{-2.25465519365641853e-07, -6.46057585221293529e-07, 3.48151143400587948e-07},
{-1.30051025504229756e-09, -3.25062288891730944e-09, 2.01775679498084060e-09},
{-5.12724809831333062e-09, 9.33902577666956280e-10, -6.96327353416625883e-10},
{-3.10810940873373909e-09, -7.49756534634826721e-10, 6.87357185058523612e-10},
{-1.52109221995821997e-06, -4.22908767925417317e-07, 1.38629667568307413e-06},
{1.42955317028459206e-09, -7.02968461219199980e-10, -3.81617160094549490e-09},
{2.53707400921232562e-09, -1.60727622877665510e-09, -4.18765366827500429e-09},
{-2.14750738948554787e-07, -6.40554276953864132e-07, 3.76128531993924486e-07},
{3.83073214815787821e-09, 4.50296289838947317e-10, 2.29523194894554194e-09},
{4.76340728555735282e-07, 6.83235613037347367e-07, -4.72205395646296822e-07},
{-6.10651996176347607e-04, -1.06790499934057291e-03, 2.29083496655867842e-03},
{3.95497823379997726e-09, 1.38236928154400474e-09, -6.26218820548585242e-09},
{1.11904936705986557e-09, -1.37869946362223494e-08, -9.34049783699042457e-10},
{1.25499246411697740e-09, -2.73635453185150368e-09, -2.91506864740637139e-09},
{-3.59882924006599270e-07, 1.32511373732895413e-06, -1.55110207063907657e-07},
{1.07068498511608823e-09, 8.92087770321126072e-09, 2.62826524433101838e-10},
{-2.69316546841480431e-09, 9.61138280075601870e-10, 5.19946977139973399e-09},
{-5.92563579700916554e-07, -1.05071339539294234e-06, 1.56249964602256375e-07},
{1.32198180180509439e-09, 5.16087961255351502e-09, 8.46339526239248130e-10},
{2.07323220008381881e-06, 1.02309267446332522e-06, -2.07661522726165781e-06},
{1.31402366846389393e-03, 3.78229792813366064e-04, 1.77496793932758741e-03},
{8.59301428624004160e-10, -6.83071707530125138e-09, 3.36249680876754553e-09},
{5.27310424491833629e-09, 2.09999085065692981e-08, -3.10459945807028959e-08},
{-8.88666080375855039e-08, 4.60897593930476024e-07, 7.41576575386676540e-07},
{-4.85540663230921155e-10, -5.58243438975036810e-09, 7.40450811775872353e-10},
{4.03141117225058743e-07, 1.52035531639227450e-06, 9.06206514897367477e-08},
{5.61075629915620496e-04, -2.05847905628765053e-03, 1.12849817492909434e-03},
{5.11216541321246609e-09, 7.26292920250060092e-09, -8.97145741030058730e-09},
{-4.26211688914213127e-07, -7.03366608210270750e-07, 6.27995585866791828e-07},
{1.15309052943982646e-03, 2.34474318844151959e-03, -4.91856748507475423e-03},
{1.01104427799588961e-01, -4.22361682938472982e-02, -1.88750007538552200e-01},
{3.94738332298860684e-10, -7.81372397340440727e-10, 4.06815717224340290e-09},
{-8.61483928638051566e-09, 5.37427180535843263e-09, 1.81738104426676372e-08},
{-8.48011268844706123e-10, -5.33803143354383280e-09, 2.99703953494934172e-10},
{3.89154099408092063e-07, -2.44166311268514957e-07, -8.03240371135063858e-07},
{-1.20249536439409610e-08, 1.48908931921210019e-08, 1.88292573199966284e-09},
{-1.16401289163015065e-08, 2.57866422936903206e-08, -5.27022399332555125e-09},
{1.37065399911928676e-07, 2.16494406102361175e-08, -7.63924557662179482e-07},
{-6.94754161319199870e-10, 6.65038621394664631e-09, -4.31779645371221932e-09},
{4.72542155592614588e-07, -7.58546986886782931e-07, -2.35913417925837088e-07},
{1.46133817312113241e-03, -3.25193103208258009e-04, -3.06625181254991741e-04},
{9.35794082672593210e-09, -7.92923574022275091e-09, -5.41426242728348939e-09},
{-2.15279239157428748e-08, -4.16754339024882903e-09, -1.12896482995505920e-08},
{2.60645369870582400e-10, 1.44616071127263122e-06, -3.63334053799999057e-07},
{9.17105741349288905e-09, -2.02295233654725681e-08, -1.20002956877085509e-08},
{-1.27759226226098477e-07, 1.28193771791124470e-06, -5.83097827522305323e-07},
{2.26880791869919426e-03, -1.34042850080092401e-03, -7.65092051285704835e-04},
{7.03374036792325796e-09, -2.53508958270032281e-09, -7.66132998708535240e-09},
{-9.71978722189015265e-07, -5.57836512454779054e-07, 1.96329328074063003e-06},
{-1.26115140811304343e-03, -4.81792074617704632e-04, -1.06803272537897391e-03},
{1.19419564863885497e-01, 5.07766738901840875e-02, 4.87642090320925953e-02},
{1.14090414893297520e-09, 1.56073433760228752e-08, -1.78054684078429726e-08},
{3.03285130343056153e-09, -1.58615337531031741e-09, -4.94928394101368241e-09},
{2.64483280249840080e-07, 2.97155396291660413e-07, -5.41608085095034164e-07},
{2.68757552324139226e-09, -1.41400907649469332e-08, 2.93255796729452456e-08},
{-2.11094617584561828e-07, -6.56355695552793272e-07, 3.72180321686621518e-07},
{-2.55073452371079590e-04, 1.57943859317488818e-03, -1.29154484940938240e-03},
{1.40049266628139435e-09, 1.40747080656922208e-08, -2.58792021839981956e-09},
{-2.12330362681090179e-07, -1.30522733223815968e-06, 5.84417623253341567e-07},
{-9.33144849909676392e-04, 1.90305575962152547e-03, -8.35564417983726418e-04},
{1.81624805201406961e-02, 6.84911174969819458e-02, -2.28291882522520390e-02},
{-8.25231299961259879e-09, -1.40227519596081152e-08, 1.78809529925716415e-08},
{1.90689491530449118e-07, 7.01057736002264065e-07, -4.26430629252294580e-07},
{-5.85146839837499930e-04, -1.07311215649546045e-03, 2.31986890222730339e-03},
{-1.05962397073886522e-01, 5.51532131360410807e-02, 1.87542648909451215e-01},
{-1.37499370823599516e-03, -8.49619409242363438e-04, -1.18180356709159952e-03}
};
static const double INTERCEPT[3] = {
-1.29208772400146188e+00,
6.62251952866635918e+00,
-1.35908984683965173e-01
};
// END AUTO-GENERATED COEFFICIENTS
inline void compute_poly_features(const double x[7], double out[330]) {
for (int i = 0; i < N_FEATURES; ++i) {
double val = 1.0;
for (int j = 0; j < N_INPUTS; ++j) {
if (POWERS[i][j] != 0) {
double base = x[j];
int exp = POWERS[i][j];
// Fast integer exponentiation (max exp = 4)
double p = 1.0;
for (int e = 0; e < exp; ++e)
p *= base;
val *= p;
}
}
out[i] = val;
}
}
} // namespace detail
struct RGB {
unsigned char r, g, b;
};
/**
* Mix two RGB colors using polynomial pigment mixing.
*
* This performs polynomial pigment-style RGB interpolation.
*
* @param r1,g1,b1 First color (0-255)
* @param r2,g2,b2 Second color (0-255)
* @param t Mixing ratio: 0.0 = all color1, 1.0 = all color2
* @param out_r,out_g,out_b Output color (0-255)
*/
inline void lerp(unsigned char r1, unsigned char g1, unsigned char b1,
unsigned char r2, unsigned char g2, unsigned char b2,
float t,
unsigned char* out_r, unsigned char* out_g, unsigned char* out_b) {
// Clamp t
if (t <= 0.0f) {
*out_r = r1; *out_g = g1; *out_b = b1;
return;
}
if (t >= 1.0f) {
*out_r = r2; *out_g = g2; *out_b = b2;
return;
}
double x[7] = {
static_cast<double>(r1), static_cast<double>(g1), static_cast<double>(b1),
static_cast<double>(r2), static_cast<double>(g2), static_cast<double>(b2),
static_cast<double>(t)
};
double features[330];
detail::compute_poly_features(x, features);
// Dot product: features @ COEF + INTERCEPT
for (int c = 0; c < 3; ++c) {
double sum = detail::INTERCEPT[c];
for (int i = 0; i < detail::N_FEATURES; ++i) {
sum += features[i] * detail::COEF[i][c];
}
// Clamp to [0, 255] and truncate (matches numpy astype(int) behavior)
int val = static_cast<int>(sum);
if (val < 0) val = 0;
if (val > 255) val = 255;
if (c == 0) *out_r = static_cast<unsigned char>(val);
else if (c == 1) *out_g = static_cast<unsigned char>(val);
else *out_b = static_cast<unsigned char>(val);
}
}
/**
* Convenience overload returning an RGB struct.
*/
inline RGB lerp(unsigned char r1, unsigned char g1, unsigned char b1,
unsigned char r2, unsigned char g2, unsigned char b2,
float t) {
RGB result;
lerp(r1, g1, b1, r2, g2, b2, t, &result.r, &result.g, &result.b);
return result;
}
} // namespace filament_mixer
#endif // FILAMENT_MIXER_H