Evaluate Fit — Control Systems/Curve Fitting
Control_Systems/Curve_Fitting/Evaluate_Fit · 2 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text
Description#
The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.
Evaluate Fit
Control Systems / Curve Fitting
Evaluates a polynomial whose coefficients arrive on a port:
y = c₀·xL−1 + c₁·xL−2
+ … + cL−1, entry by entry over x, with the
coefficients in descending powers. This is MATLAB's polyval
with the first argument taken from a signal.
It is the reading half of Curve Fitting: wire Polynomial Fit into c to read a fit that is recomputed every sample, or put Fit Derivative or Fit Integral in between to read the slope or the area instead.
Ports
- c – the coefficients, descending powers, as a vector of L entries: a column [L,1] or a row [1,L]. A scalar is a constant polynomial, and the output is then that constant everywhere.
- x – where to read the curve. Any size [m,n], applied entry by entry, so one block can read the same curve at several points at once.
- y – the value, of the same size as x. The block never reshapes a signal; the coefficient port does not affect the output's size.
Parameters
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. There is nothing to tune, so nothing is exposed as a parameter on the generated core – the coefficients are a signal, not a setting.
Every target evaluates by Horner's rule – the nested form
((c₀x + c₁)x + c₂)x + c₃ – and not by
summing powers. The two are not the same computation in floating point, so this
is what keeps the ten targets agreeing with each other and with this block's own
simulation.
The three HDL targets are simulation-only. Horner needs nothing but
multiplies and adds, which the Q16.16 datapath has, but a polynomial multiplies
the signal by itself once per order and that format saturates at ±32768
while resolving only 1.5×10⁻⁵ – and here the coefficients
are a signal, so their magnitude is not known at export time and no
scaling can be folded in to compensate. The generated cores convert at the port
boundary and evaluate in real arithmetic: correct in simulation, but
not offered as synthesizable. Base Blocks / Polynomial makes the same
call for the first of those two reasons.
Simulink bridge
None (Support::None). Simulink's own Polynomial block
takes its coefficients as a dialog parameter, so it cannot represent this block
– a mapping onto it would silently drop the port that makes this block
different. polyval itself is a MATLAB function with no library path
a diagram could name, and the Curve Fitting Toolbox ships no Simulink library at
all. The bridge reports this block rather than dropping it silently, and it
therefore has no parity testbench; code export verification still covers
it across all ten languages. For a diagram that must cross with constant
coefficients, use Base Blocks / Polynomial, which is bridged.
Notes
- Algebraic, with no state: the output depends only on the current inputs.
- Use Base Blocks / Polynomial instead whenever the curve is fixed. That block inlines its coefficients, costs less in every target, and is bridged to Simulink. This one exists for a curve that changes every sample, which is the one thing a dialog parameter cannot hold.
- Reading outside the window is allowed and is not checked. Polynomial Fit writes its curve on x = −i·h with the newest sample at x = 0, so a negative x reads back into the window and a positive x extrapolates past its end – one-step prediction is exactly x = +h. Extrapolation is a legitimate use and also where a high-degree fit goes wrong fastest: the error grows like xL−1.
- Horner's rule, in all ten targets. Not an optimization – it is what keeps the ten exports agreeing with each other and with this block.
- No state space. The relation is linear in the coefficients but polynomial in x, so the block carries none and model reduction correctly reports it as unmergeable. Fabricating a feed-through would let a reduction replace a curve with a straight line.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Curve_Fitting/Evaluate_Fit |
| family | Control_Systems/Curve_Fitting |
| solver environment class | ICoreBlock_0_Control_Systems_1_Curve_Fitting_2_Evaluate_Fit |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Curve_Fitting/Evaluate_Fit/ICoreBlock_0_Control_Systems_1_Curve_Fitting_2_Evaluate_Fit.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Curve_Fitting/Evaluate_Fit/ICoreBlock_0_Control_Systems_1_Curve_Fitting_2_Evaluate_Fit.h |
| default size on canvas | 110 × 76 px |
| ports at insert | 2 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | c |
| 2 | in | ICoreDouble | x |
| 3 | out | ICoreDouble | y |
Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.
Configuration variables#
No config variable beyond the Sampling Time (s) every block carries.
Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.
Simulink bridge#
| support | Support::None |
| Simulink path | — |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
Caveat (shown to the user): Simulink's Polynomial block takes its coefficients as a DIALOG PARAMETER, so it cannot represent a block whose coefficients arrive on a port -- a mapping onto it would silently drop what makes this block different; polyval itself is a MATLAB function with no library path. For constant coefficients use Control_Systems/Base_Blocks/Polynomial, which is bridged
Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h
Description vs code#
The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:
B0no sample under docs/generated/samples/ — nothing to cross-check (P8.1)
The verdict above is
tools/docs/check_block_descriptions.py(P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.
File banner (developer view)#
The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).
Evaluate Fit -- polyval with the coefficients on a WIRE y = c0*x^(L-1) + ... + c(L-1), entry by entry over x, with c DESCENDING and arriving on a port rather than out of a config. See the header for why that is a different block from Base_Blocks/Polynomial rather than a duplicate of it.
Every target nests -- Horner's rule -- and every target reads the SAME coefficient entries in the SAME order, because the two are not the same computation in floating point and the ten exported cores are compared against the C++ relation below.
Verified against R2026a: polyval([0.18018728956228861 0.97582972582972149 0.99028980278979795 -0.12171717171717268], -0.7) reports -0.39856770833333272.
Sample results#
No sample run is committed for this block. Samples come from the headless harness (DOCS_PLAN.md P8.1) into docs/generated/samples/; until one exists this block's behaviour is witnessed by the parity and export-verification suites, not by a plot here.